Nixos.org: Unterschied zwischen den Versionen
Marc (Diskussion | Beiträge) (Beispiel Haskell development mit NixOS) |
Marc (Diskussion | Beiträge) |
||
Zeile 2: | Zeile 2: | ||
Paketliste: https://search.nixos.org/packages oder Overlays auf Github (unterschiedliche Qualität) | Paketliste: https://search.nixos.org/packages oder Overlays auf Github (unterschiedliche Qualität) | ||
+ | |||
Webseite: https://nixos.org | Webseite: https://nixos.org | ||
+ | |||
Dokumentation: https://nixos.org/manual/nixos/stable/ | Dokumentation: https://nixos.org/manual/nixos/stable/ | ||
Zeile 603: | Zeile 605: | ||
} | } | ||
</pre> | </pre> | ||
− | |||
== Zusammenfassung: == | == Zusammenfassung: == |
Aktuelle Version vom 26. Mai 2022, 17:01 Uhr
Einführung in nixos.org
Paketliste: https://search.nixos.org/packages oder Overlays auf Github (unterschiedliche Qualität)
Webseite: https://nixos.org
Dokumentation: https://nixos.org/manual/nixos/stable/
Zusammenfassung: Nixos basiert auf dem Nix Paket manager welcher es erlaubt deterministisch also immer gleich Abhängigkeiten zu definieren. Wenn sich eine Abhängigkeit ändert ändert sich der Paktetpfad (ähnlich einem Git-Hash) und alle darauf basierenden Abhängigkeiten bekommen neue Pfade (Versionen). Vorteil: Gleicher Pfad gleiches Verhalten, dh.h auch Bisecting z.B mit git möglich ! Nachteil: Bei kleinen Änderungen muss viel neu heruntergeladen werden.
Pakete werden durch Garbage Collector Roots (Fäden) vor dem Garbage Collector (Müllschlucker) bewart. D.h. solange ein Paket über einen Symlink über eine User Installation oder über eine System-Konfiguration noch erreicht werden kann wird das Paket nicht gelöscht.
PATH etc werden über spezielle User Profiles gemanaged und ersetzen /user/local/bin usw.
Damit sind atomic Upgrades möglich durch switchen von Symlinks.
Nixos erlaubt es ein Paket mit Abhängigkeiten zu archivieren (Nar Archive) und offline woanders zu importieren/installieren.
Auch können Pakete mit Abhängkeiten über nix-store --copy-closure differentiell kopiert werden.
Pakete und Systeme können also ohne das laufende System zu stören auf mehreren PCs verteilt je nach Architektur auf Build-Slaves vorbereitet werden. Jedes Paket wird in einer Sandbox (chroot) installiert, so dass jedes Paket nur seine eigenen Abhängigkeiten sieht. Damit wird erreicht dass jede Installation soweit möglich bis auf Kleinigkeiten wie Zeit bzw CPU Architektur oder RAM Größe das gleiche reproduzierbare Verhalten zeigt.
Zum Beispiel wenn man was unter Ubuntu kompiliert kann das configure Ergebnis von anderen installierten aber nicht relevanten Paketen und Header Dateien abhängen. Dh. 2 Ubuntu Installationen können verschiedenes Verhalten produzieren.
Dadurch dass jedes Paket mit jeder Version seinen eigenen /nix/store/... Namen mit Hash hat kann man mehrere Generationen gleichzeitig auf der gleichen Partition installiert haben und beim Boot-Prozess auswählen welche Version man will. Dann wird /etc/ gemäß des im Store vorbereiteten Systems angepasst. Bootet man eine alte Version mit altem MySQL kann diese allerdings mit einem aktualisierten /var/db/.. mysql Verzeichnis nichts mehr anfangen. Aber deswegen gibt es ja z.B BTRFS.
Am besten erklährt man die Vorteile der configuration.nix welche Hardware Profile laden kann an einem Beispeil, weswegen auch der Installationsprozess eine Hardware Datei und eine Sytem-Configurations-Datei erstellt.
Es demonstriert deutlich wie einfach es ist
- Dokmuentation
- Verhalten
- Software (environment.systemPackages)
- Cron-Jobs z.B. Backups
in wenigen Dateien übersichtlich zu konfigurieren und zu duplizieren aber auch an den PC anzupassen. Leider muss man bei Thunderbird z.B. immer noch manuell Sprachpakete nachintsallieren, weil jene in ~/.thunderbird gespeichert werden.
z.B. können so auch BTRFS Snapshots einmal pro Tag automatisch konfiguriert werden.
Die Installation kann theoretisch vereinfacht werden indem man ein Shell Script mit curl läd welches /etc/nixos/configuration.nix oder module runterläd bzw die Festplatte formatiert.
Durch den inkrementellen Aufbau der Pakete + einrichten von /etc/* beim Booten können auch abgebrochene Installationen fortgesetzt werden. Es werden nur die noch fehlenden noch nicht im /nix/store vorhandenen Pakete identifiziert und installiert.
Gleichzeitig kann man durch sogenannte derivations eigene Software z.B. von Github konfigurieren und installieren.
# beispiel eigenes Software Paket name = mkDerivation { name = "mein-paket-von-github" src = fetchGithub { # z.B. mit nix-prefetch-git holen owner = "..."; name = "..."; hash = ".." }; buildDepends = [ readline ]; meta = { .. } } # fertig details bitte Orignial-Dokumentation nachschauen.
Wenn man also wie hier gezeigt /home und / auf unterschiedlichen BTRFS subvolumes hat kann man System/Home unabhängig bei Bedarf zurücksetzen *EGAL* was der Benutzer gemacht hat. Ausfallzeiten länger als 5min eigentlich kaum möglich ausser man Hardware-Probleme.
Allerdings muss man regelmäßig alte Snapshots löschen (und PC bischen Zeit geben). Das ist aber planbar.
Deswegn ist das alles ein ziemlich idiotensicheres Setup.
Wenn wirklich Interesse besteht müsste man das alles nochmal testen. Aber als Idee / Vorstellung ist dies schonmal gut.
# shell script zum formatieren und installieren von Nixos nach booten von CD DEV=nbd0 ENCRYPT=none SWAP_SIZE=30GiB BOOT_SIZE=512MiB # partition prefix P=p # BOOT_SIZE=1GiB MOUNT_POINT=/mnt set -x parted /dev/${DEV} -- mklabel gpt parted /dev/${DEV} -- mkpart primary $BOOT_SIZE -$SWAP_SIZE parted /dev/${DEV} -- mkpart primary linux-swap -$SWAP_SIZE 100% parted /dev/${DEV} -- mkpart primary 1MiB $BOOT_SIZE -$SWAP_SIZE 100% parted /dev/${DEV} -- mkpart ESP fat32 1MiB $BOOT_SIZE parted /dev/${DEV} -- set 3 boot on case $ENCRYPT in none) mkfs.btrfs /dev/${DEV}${P}1 ROOT_DEVICE=/dev/${DEV}${P}1 ;; luks) MAPPER_NAME=${DEV}${P}1 cryptsetup --verbose --verify-passphrase luksFormat /dev/${DEV}${P}1 cryptsetup luksOpen /dev/${DEV}${P}1 ${MAPPER_NAME} mkfs.btrfs /dev/mapper/${MAPPER_NAME} ROOT_DEVICE=/dev/mapper/${MAPPER_NAME} ;; esac mkswap -L swap /dev/${DEV}${P}2 mkfs.fat -F 32 -n boot /dev/${DEV}${P}3 mount $ROOT_DEVICE $MOUNT_POINT mkdir /mnt/boot mount /dev/${DEV}${P}3 $MOUNT_POINT/boot nixos-generate-config --root $MOUNT_POINT # sed -i 's/# \(boot.loader.grub.device\)/\1/' $MOUNT_POINT/etc/nixos/configuration.nix nixos-install --root $MOUNT_POINT
#configuration.nix {pkgs , config, ...}: let inherit (pkgs) lib; inherit (lib) mkMerge mkOverride; in { imports = [ ./disk-configuration.nix ./shared-configuration.nix ./hardware-configuration.nix ]; config = { boot.loader.grub.configurationName = "x68_64"; }; }
shared-configuration.nix {pkgs , config, ...}: let inherit (pkgs) lib; inherit (lib) mkMerge mkOverride; in { imports = [ ]; config = { nixpkgs.config.allowBroken = true; hardware.pulseaudio.enable = true; networking.networkmanager.enable = true; networking.firewall.enable = true; networking.firewall.allowedTCPPorts = []; # networking.useDHCP = true; programs.bash.promptInit = ""; environment.pathsToLink = ["/"]; environment.sessionVariables = { TERMINFO_DIRS = "/run/current-system/sw/share/terminfo"; }; i18n.defaultLocale = "de_DE.UTF-8"; time.timeZone= "Europe/Berlin"; # services.blueman.enable = true; environment.systemPackages = [ pkgs.iotop pkgs.pciutils pkgs.gwenview pkgs.evince pkgs.okular # pkgs.acroread # ] ++ (attrValues pkgs.plasma5) ++ [ # pkgs.plasma-nm pkgs.bluedevil pkgs.vim pkgs.kate pkgs.firefox # /backup/mount-disk kann durch /volumes ersetzt werden # /backup/references eventuell auf /volumes verschieben ? ( pkgs.writeScriptBin "erstelle-backup-externe-festplatte" '' #!/bin/sh -e set -x mkdir -p /backup/mount-disk mkdir -p /backup/mount-backup mkdir -p /backup/references mount /dev/sda3 /backup/mount-disk mount /dev/disk/by-uuid/1b6a7b15-f6bd-4c0c-b735-aaf928ee79db /backup/mount-backup -o compress=zstd:1 for subvol in home system; do echo backup hup $subvol btrfs-backup-nach.sh "benutzer-backup-$subvol" "/backup/mount-disk/$subvol" "/backup/references/benutzer-backup-$subvol" /backup/mount-backup done umount /backup/mount-disk umount /backup/mount-backup echo "BACKUP FERTIG" '') ( pkgs.writeScriptBin "btrfs-backup-nach.sh" '' #!/bin/sh -e set -o pipefail # mount: mount point # target: the name of the external disk # for each name a reference is kept so that next backup is differential and fast target=$1 mount=''${2:-/backup} # identify that the target destination is the expected one. # this is done by expecting backup-dummy$target filename to be there dummy="$mount/backup-dummy$target" [ -n "target" ] || { echo "usage: ./backup.sh external-disk /backup "; exit 1; } [ -f "$dummy" ] || { echo "$dummy file to identify backup location not found. Shall I touch it? [y/N]" read reply if [ "$reply" == "y" ]; then touch "$dummy" else echo 'failing'; exit 1 fi } backup(){ local name="$1" local from="$2" # where to store subvolumes and keep last for incremental update local dir_in_from="$3" local to="$4" now=$(date '+%Y-%m-%d_%H%M%S') mkdir -p "$dir_in_from" if [ -f "$dir_in_from/last-backup-''${name}" ]; then local last=$(cat "$dir_in_from/last-backup-''${name}" 2>/dev/null || true) echo 'snapshotting from' btrfs subvolume snapshot -r "$from" "$dir_in_from/$name-$now" echo 'updating target' btrfs send -p "$dir_in_from/$last" "$dir_in_from/$name-$now" | btrfs receive "$to" echo 'deleting old reference' btrfs subvolume delete "$dir_in_from/$last" echo "new snapshot is is $name-$now" echo "$name-$now" > "$dir_in_from/last-backup-''${name}" else echo "creating initial snapshot as reference" btrfs subvolume snapshot -r "$from" "$dir_in_from/$name-$now" echo "sending initial data .. might take long" btrfs send "$dir_in_from/$name-$now" | btrfs receive "$to" echo "$name-$now" > "$dir_in_from/last-backup-''${name}" fi } backup "$@" '' ) ( pkgs.writeScriptBin "nixos-aktualisieren" '' #!/bin/sh set -e set -x sudo erstelle-snapshots sudo nix-channel --update sudo nixos-rebuild boot echo 'Aktualisierung fertig bitte neu starten. Thunderbird Extensios -> Deutsche Übersetzungen neu installieren' '' ) ( pkgs.writeScriptBin "erstelle-snapshots" '' #!/bin/sh set -x echo "system" ${pkgs.btrfsProgs}/bin/btrfs subvolume snapshot -r / /subvolumes/system-$(${pkgs.coreutils}/bin/date +'%Y-%m-%d_%H%M%S') echo "home" ${pkgs.btrfsProgs}/bin/btrfs subvolume snapshot -r /home /subvolumes/home-$(${pkgs.coreutils}/bin/date +'%Y-%m-%d_%H%M%S') echo "fertig" '' ) ( pkgs.writeScriptBin "hilfe" '' #!/bin/sh ${pkgs.utillinux}/bin/more <<EOF Bei Problemen -> LUGVS Mailinglist User Linux Group Villingen Schwenningen einmal pro Monat Siehe https://lug-vs.org/lugvswiki/index.php/Hauptseite, Die kennen sich jedoch mit Nixos.org Linux nicht aus Haben auch Mailingliste Chat Hilfe zu Nixos (English) Terminal eingaben irssi Dann eingeben /connect irc.liberachact.net Dann eingeben /join #nixos Remote Desktop sharing (Support) anydesk nutzen System aktualisieren (kann nichts passieren, weil alte Versionen bleiben bestehen) sudo nixos-aktualisieren Eventuell muss bei Thunderbird hinterher Deutsche Sprachpakete neu installiert werden. Backups (gleiche Festplatte mit BTRFS) sudo erstelle-snapshot eingeben Backups liegen unter /subvolumes Schützt nicht vor Festplatten-Crash / versagen Backup externe Festplatte (btrfs send) empfohlen: sudo erstelle-backup-externe-festplatte System aufräumen (alte Versionen löschen - also nur wenn neue Version geht) sudo nix-collect-garbage -d Wenn danach Anwendungen nicht mehr korrekt funktionieren eventuell in ~/.config/* Dateien löschen und erneut probieren (vorher sudo erstelle-snapshot ausführen) iphone mounten (wegen Bildern) google ifuse. z.B. sudo ifuse /mnt Android mounten sudo mtpfs /mnt Drucken -> Cups kann eingerichtet werden. Wenns aber nur 1-2 Seiten sind kurz zu Frau Burger gehen oder zu meiner Mutter, PDF mitbringen. Drucken -> "Print To File" oder "In Datei Drucken" PDF Speicherort angeben. Zum Enrichten langfristig: sudo nano /etc/nixos/shared-configuration.nix dort siehe printing (Treiber müssen hinzugefügt werden) Manuell Backups externes Medium: Externe Festplatte ist besser weil Festplatte kaputt gehen kann (einfach manuell kopieren, gibt auch viele Tools) Beispiel mount /dev/sdb1 /mnt rsync -ra --delete /home/benutzer/ /mnt/backup-home-benutzer/ umount /mnt System-Check smartmontools ist installiert Dateisystem: sudo btrfs scrub start /dev/sda # bischen warten.. # dann immer wieder bis fertig ist: sudo btrfs scrub status /dev/sda Paket-Check sudo nix-store --verify --check-contents Festplatte Eigenauskunft S.M.A.R.T auslesen sudo smartctl -a /dev/sda Die werte sollten über den TRESH werten liegen. Memory (beim booten memtest wählen) Habe-Ich-Internet-Test ping www.gmx.de root werden: sudo anwendung sudo su -> wieder shell USB Stick (oder Kamera) mount /dev/sdb1 /mnt .. Daten kopieren umount /mnt Statt sda1 eventuell sdb2 (zweite Partition) oder sdbX für zweiten USB Stick etc Partitionen (USB Stick) finden: sudo fdisk -l auf Grösse achten Können das auch als Script automatisieren oder udev-rule Programme: audacity: Audio scalc (Tabellen) simpress (Präsentationen) gimp: Bilder Krita: Malen Firefox: Internet Thunderbird: E-Mails Blender: 3d test und 3d Malen, 3d Animation und mehr mplayer/vlc: videos und Mediadateien aufmachen + Streaming EOF '' ) pkgs.irssi pkgs.utillinux pkgs.nettools # pkgs.firefox pkgs.chromium pkgs.libreoffice pkgs.audacity pkgs.krita pkgs.inkscape pkgs.gimp pkgs.thunderbird pkgs.gnome3.nautilus pkgs.ifuse # mount iphone pkgs.mtpfs # mountandroid pkgs.anydesk # Es funktioniert einfach... pkgs.smartmontools pkgs.blender pkgs.mplayer pkgs.vlc ]; services.printing = { enable = true; # drivers = [ pkgs.hlip ]; }; programs.zsh.enable = true; programs.zsh.promptInit = '' if [ "$TERM" != dumb ]; then # prompt walters autoload -U promptinit && promptinit fi ''; users.users.benutzer = { isNormalUser = true; home = "/home/benutzer"; description = "benutzer"; extraGroups = [ "wheel" "networkmanager" ]; # openssh.authorizedKeys.keys = [ "ssh-dss AAAAB3Nza... alice@foobar" ]; }; environment.etc."nix/machines".target = "nix/machines.sample"; fileSystems."/tmp" = { device = "tmpfs"; fsType = "tmpfs"; options = ["size=20000m" "mode=1777"]; }; fonts.fontconfig.enable = true; fonts.enableFontDir = true; fonts.fonts = [ ]; nixpkgs.config.permittedInsecurePackages = [ "openssl-1.0.2u" ]; nixpkgs.config.allowUnfree = true; nixpkgs.config.android_sdk.accept_license = true; nixpkgs.config.ruby.tags = true; # nixpkgs.config.packageOverrides = p: { nix = { package = pkgs.nixUnstable; daemonNiceLevel = 20; useSandbox = true; }; programs.ssh.startAgent = false; programs.gnupg.agent.enable = true; # services.cron.systemCronJobs = # let # backupscript = pkgs.writeScriptBin "backupscript" '' # #!/bin/sh # ${pkgs.btrfsProgs}/bin/btrfs subvolume snapshot / /root/root-of-fs-$(${pkgs.coreutils}/bin/date +'%Y-%m-%d_%H%M%S') # ''; # in # [ # "0 10,15 * * * root ${backupscript}" # ]; services.nfs.server.enable = true; services.ntp.enable = true; # services.openssh = { # enable = true; # allowSFTP = true; # # startOn = "never"; # passwordAuthentication = true; # }; security.sudo = { enable = true; configFile = mkOverride 20 '' root ALL=(ALL) SETENV: ALL benutzer ALL=(ALL) NOPASSWD: ALL # Users in the \"wheel\" group can do anything. # %wheel ALL=(ALL) SETENV: ALL ''; }; documentation.nixos.enable = false; # takes too much time to build services.xserver.enable = true; services.xserver.autorun = true; services.xserver.layout = "de"; services.xserver.wacom.enable = true; services.xserver.enableTCP = true; services.xserver.resolutions = []; # services.xserver.windowManager.default = "wmii"; services.xserver.desktopManager.plasma5.enable = true; services.xserver.desktopManager.lxqt.enable = true; systemd.services.nix-daemon.serviceConfig.IOSchedulingClass = "idle"; systemd.services.nix-daemon.serviceConfig.CPUShares = 123; systemd.services.nix-daemon.serviceConfig.MemoryLimit = "10G"; # users.defaultUserShell = "/var/run/current-system/sw/bin/zsh"; }; }
# hardware-configuration.nix # vom Installationscript erstellt { config, lib, pkgs, ... }: { imports = [ <nixpkgs/nixos/modules/installer/scan/not-detected.nix> ]; boot.initrd.availableKernelModules = [ "btrfs" "ehci_pci" "ahci" "usb_storage" "sd_mod" "sr_mod" "rtsx_usb_sdmmc" ]; boot.kernelParams = [ ]; # boot.kernelPackages = pkgs.linuxPackages_testing; # oder 20 boot.blacklistedKernelModules = [ ]; powerManagement = { enable = true; cpuFreqGovernor = "ondemand"; }; # services.logind.lidSwitch = "ignore"; # services.xserver.videoDrivers = [ "ati_unfree" ]; # boot.kernelPackages = pkgs.linuxPackages_latest; # boot.kernelParams = [ "amd_iommu=pt" "ivrs_ioapic[32]=00:14.0" "iommu=soft" ]; # services.xserver.videoDrivers = [ "amdgpu" ]; # services.xserver.videoDrivers = [ "ati_unfree" ]; hardware.firmware = [pkgs.firmwareLinuxNonfree pkgs.sof-firmware]; hardware.cpu.amd.updateMicrocode = true; hardware.enableAllFirmware = true; # hardware.enableRedistributableFirmware = true; # hardware.opengl.enable = true; # hardware.opengl.driSupport = true; hardware.opengl.driSupport = true; # programs.light.enable = true; }
Zusammenfassung:
Eine fast automatische Installation wäre so möglich:
# iso runterladen # booten # sudo su # automatisch formatieren und configuration.nix Template anlegen DEV=/dev/sda curl https://script-noch-zu-erstellen-was-foramtiert-dann-mounted-dann-configuration.nix-anlegt > /tmp/script . /tmp/script # nixos-hardware-scan # nixos-install .. # shutdown -r now
Das Sytsem hätte dann - lugvs dokumentation mit hilfe-lugvs aufrufbar oder ähnlich auch was vieles weitere erinnert - regelmäßige Snapshots - ein Backup Script für externe Festplatte inkrementell mit BTRFS - einfache Update Scripte um sich selbst solange zu aktualisieren bis sich die
Wörter in configuration.nix verändern. Manchmal kommt was dazu oder wird umbenannt.
Aber ein Crash oder halbfertiges System beim Benutzer (Update-Probleme) sind passieren nicht mehr oder sind zurückstellbar in kalkulierbaren 5 Minuten.
Wie geht nutzt man z.B. Python oder Haskell mit NixOS?
cabal2nix_init(){ local dir=$(basename `pwd`) local defaultGHC=${1:-ghc921} $(nix-build -A cabal2nix $NIXPKGS_ALL)/bin/cabal2nix . > $dir.nix cat > default.nix << EOF { nixpkgs ? import <nixpkgs> {}, compiler ? "${defaultGHC}" }: nixpkgs.haskell.packages.\${compiler}.callPackage ./$dir.nix { } EOF cat > shell.nix << EOF { nixpkgs ? import <nixpkgs> {}, compiler ? "${defaultGHC}" }: (import ./default.nix { inherit nixpkgs compiler; }).env EOF # nix-shell -A env ./default.nix
das cabal2nix_init Script erstellt einige .nix Dateien die dann genutzt werden um die Abhängikgeiten im Store bereitzustellen. Dann kann mit nix-shell eine Shell bereitgestellt werden wo ghc ghc-pkg cabal etc vorhanden sind und jene finden. D.h. einem ./Setup configure && ./Setup build steht nichts mehr im Wege.
Das geht meistens gut - manchmal leider auch nicht.
Ähnliche Tools gibts für Ruby, Python ..
Auf die Art und Weise lassen sich auch derivations generieren so dass man Software über environment.systemPackages schnell installieren kann.
Nach meiner Meinung ist das alles einfacher als Pakete für Debian / Suse bereitzustellen (wenns klappt)