NixOS 101
A variant of Linux that uses declarative approach.
Like how Cisco use a single IOS config file to define the function of a switch, router, firewall, NixOS can use a single configuration.nix file to declare all its settings.
Instead of using Puppet or Chef to configure the OS, NixOS natively use its own declarative language to define how the OS is to be configured. Their emphasis is on the "what" of the config instead of the "how".
ie. define that you need an apache httpd server, instead of finding what rpm to install.
But fact is, all the unix admin knowledge is still there, just condensed into a single parameter definition file. eg. enable sshd. use port 22. define user foo. assign the home dir /home/foo. give it /bin/zsh as shell.
I also blogged another reason why declarative OS like NixOS is the right new paradigm.
Terminology
- NixOS - This refers to the Operating System
- Nix - This is the package manager, new as part of the NixOS, but it can be run in other Linux distribution and OS X. Conceptually it is source-based, but it used cached binary to speed installation. Non-root user can install packages, and multiple versions can be maintained. Ref: About Nix
Nix can be installed on Linux, even as normal user! details - Derivation: official name of package in Nix.
Initial install
- Create a bootable USB using Unetbootin based on a live dvd iso. (Unetbootin is like Lili usb creator, but this didn't work as of 2015.09.15 as it didn't know about NixOS yet and used generic Linux, which failed to boot). ref: NixOS wiki
- Pre create the file system on the desired hard drive (fdisk, mkfs, lvm if desired) ref: NixOS manual install page
- mount /dev/sda1 /mnt
- swapon /dev/sda2
- nixos-generate-config --root /mnt
- vi /mnt/etc/nixos/configuration.nix
enable grub boot loader. add additional desired pkg. (nano is avail if vi is not) - cat /mnt/etc/nixos/hardware-config.nix
ensure right disk is defined as device#1. use blkid /dev/sda1 to check disk UID. - nixos-install # this command must somehow be preprogrammed to write to /mnt, and look for configuration.nix rooted in there.
- give a pw for the root acc when prompted. If it didn't ask to set a password, something went wrong and nixos install need to be run again.
- reboot
Basic configuration.nix for a laptop with KDE gui
# Edit this configuration file to define what should be installed on # your system. Help is available in the configuration.nix(5) man page # and in the NixOS manual (accessible by running 'nixos-help'). ## run sudo nixos-rebuild switch ## to apply changes { config, pkgs, ... }: { imports = [ # Include the results of the hardware scan. ./hardware-configuration.nix ]; # Use the GRUB 2 boot loader. boot.loader.grub.enable = true; boot.loader.grub.version = 2; # Define on which hard drive you want to install Grub. # boot.loader.grub.device = "/dev/sda"; ## boot.loader.grub.device = "/dev/sda"; # networking.hostName = "nixos"; # Define your hostname. networking.hostName = "nixon"; # Define your hostname. networking.hostId = "b6e466c1"; networking.firewall.enable = true; networking.firewall.allowPing = true; networking.networkmanager.enable = true; # https://nixos.org/nixos/manual/sec-networking.html#sec-wireless 10.1 #networking.wireless.enable = true; # true means use wpa_supplicant #networking.useDHCP = false; # Don't run dhclient on wlan0, but break DNS networking.wicd.enable = false; # https://nixos.org/wiki/WICD wicd-gtk to run gui client # Select internationalisation properties. # i18n = { # consoleFont = "lat9w-16"; # consoleKeyMap = "us"; # defaultLocale = "en_US.UTF-8"; # }; # List packages installed in system profile. To search by name, run: # $ nix-env -qaP | grep wget # environment.systemPackages = with pkgs; [ # wget # ]; # List services that you want to enable: # Enable the OpenSSH daemon. # services.openssh.enable = true; services.openssh.enable = true; # Enable CUPS to print documents. # services.printing.enable = true; # Enable the X11 windowing system. services.xserver.enable = true; services.xserver.layout = "us"; # services.xserver.xkbOptions = "eurosign:e"; # Enable the KDE Desktop Environment. services.xserver.displayManager.kdm.enable = true; services.xserver.desktopManager.kde4.enable = true; # Define a user account. Don't forget to set a password with 'passwd'. # users.extraUsers.guest = { # isNormalUser = true; # uid = 1000; # }; users.extraUsers.sn = { isNormalUser = true; uid = 1001; home = "/home/sn"; extraGroups = [ "wheel" "networkmanager" ]; openssh.authorizedKeys.keys = [ "ssh-dss AABB... sn@grumpyxmas.com" ]; }; users.extraUsers.sa9 = { isNormalUser = true; uid = 999; home = "/home/sa9"; extraGroups = [ "networkmanager" ]; openssh.authorizedKeys.keys = [ "ssh-dss AABB... sa@grumpyxmas.com" ]; hashedPassword = "testtesttest"; }; # removing a user from the config file will trigger a userdel. #but the home dir remains (understandably don't want to delete files) environment.systemPackages = with pkgs; [ zsh wget htop nmap netcat telnet wireshark-qt vim vimPlugins.ipython vimPlugins.vim-addon-syntax-checker vimPlugins.vim-addon-nix vimNox #vimHugeX python27Packages.ipython python34Packages.ipython gpgme dos2unix bzip2 #gzip avail by def # commenting out pkg will remove the sym links and take them out of the path, # but pkg and executable is actually still avail in /nix/store #gcc34 #gcc44 # automake autoconf cmake gnumake #couchdb # unable to compile :( aws awscli docker kubernetes vagrant # uge # gridengine not yet avail #chromiumWrapper # this doens't seems to exist anymore chromium firefoxWrapper firefox # virtualisation need pkg installed, plus config param (see below) linuxPackages_3_19.virtualboxHardened kde4.networkmanagement kde4.kdemultimedia kde4.kdegraphics kde4.kdeutils kde4.applications #pkgs.kde4.kdegames #pkgs.kde4.kdeedu kde4.kdebindings kde4.kdeaccessibility kde4.kde_baseapps kde4.kactivities kde4.kdeadmin kde4.kdeartwork kde4.kde_base_artwork kde4.kdenetwork kde4.kdepim kde4.kdepimlibs kde4.kdeplasma_addons kde4.kdesdk kde4.kdetoys kde4.kde_wallpapers kde4.kdewebdev kde4.oxygen_icons kde4.kdebase_workspace kde4.kdelibs kde4.kdevelop kde4.kdevplatform kde4.qtcurve kde4.ColorSchemes kde4.desktopthemes kde4.kscreensaver kde4.kwin_styles kde4.partitionManager kde4.qt4 kde4.yakuake kde4.kgpg tightvnc ssvnc xterm x86info binutils ]; # package configuration nixpkgs.config.allowUnfree = true; nixpkgs.config.firefox.enableAdobeFlash = true; # for Firefox nixpkgs.config.chromium.enableAdobeFlash = true; # for Chromium nixpkgs.config.chromium.enablePepperFlash = true; nixpkgs.config.chromium.enablePepperPDF = true; security.sudo.wheelNeedsPassword = false; #security.sudo.extraCOnfig # apparently virtualbox should NOT be added just as a package # https://nixos.org/wiki/Installing_VirtualBox_on_NixOS # but could not get below to work, so just added as a package afterall # run it by calling VirtualBox # virtualisation.virtualbox.host.enable = true; # probably changed to this clause below: # services.virtualboxGuest.enable = true; users.extraGroups.vboxusers.members = [ "sn" ]; # https://nixos.org/wiki/NixOS_and_Xen # virtualisation.xen.enable = true; }This is an example of configuration.nix from my last nixos install.
Basic hardware-configuration.nix
# Do not modify this file! It was generated by 'nixos-generate-config' # and may be overwritten by future invocations. Please make changes # to /etc/nixos/configuration.nix instead. { config, lib, pkgs, ... }: { imports = [This is an example of hardware-configuration.nix from my last nixos install.]; boot.initrd.availableKernelModules = [ "ehci_pci" "ata_piix" "firewire_ohci" "usb_storage" ]; boot.kernelModules = [ "kvm-intel" ]; boot.extraModulePackages = [ ]; fileSystems."/" = ##{ device = "/dev/disk/by-uuid/81c298dc-64e4-4dde-9986-069753dcdece"; { device = "/dev/sda1"; # aka /dev/sda1 label=nixos fsType = "ext4"; }; swapDevices = ##[ { device = "/dev/disk/by-uuid/3a9de093-d26c-464a-b900-0ca5e1243bb8"; } [ { device = "/dev/sda5"; } # aka /dev/sda5 label=swapspace ]; nix.maxJobs = 4; }
One can create many additional *.nix config and import them into the configuration.nix. Some like the modularity of it. The default config separate the hardware into its own specific file.
Other may place a GUI desktop part into its own file, thus easy to trim it out for a headless server.
Beyond that, I personally like one monolithic file, so that it is easy to run a diff between two servers to find what difference have been made that may explain functionality differences.
Other example config:
ordinatechnic
Notes on *.nix config file
There should be a single { config, pkgs, ... }: section. If needed additional clause, change it , but don't add new {section}. eg: { config, lib, pkgs, ... }: .There are a couple of ways to add software package, I like:
environment.systemPackages = with pkgs; [ # it is a semi-colon in there, i do find it weired... kde4.applications kde4.kdeutils firefox vim emacs zsh w3m elinks ];Another format used often in the NixOS manual
environment.systemPackages = [ pkgs.thunderbird pkgs.vim pkgs.emacs pkgs.kde4.pgpg ]; # not sure for pkgs.kde4.pgpgThis is the list of available packages as of 2015.09
Changing config
- sudo vi /etc/nixos/configuration.nix
- sudo nixos-rebuild switch Reboot is NOT needed.
- nixpkgs is for creating new Nix Packages. But sometime may need to refer to it to see what config parameters are exposed for setting in configuration.nix. eg of nixpkgs locations: /nix/store/pilijx70f4bf81w1i01pp63s5lrqlqya-nixos-14.12.875.bb79e19/nixos/nixpkgs ~/.nixpkgs
Update package and OS
nix-channel --update # apt-get update. # run as root for system-wide update (root env is used by everyone) # run as user for personal's env update only. # need to run this at least once to get an initial db, eg use by command-not-found # This update w/in current channel, so just get bug fixes, minor changes. sudo nix-channel --add https://nixos.org/channels/nixos-15.09 nixos # eg upgrade from 14.12 to 15.09 sudo nix-channel --add https://nixos.org/channels/nixos-unstable nixos # bleeding edge nixos-rebuild switch # apt-get upgrade # run this after channel update to update the whole OS (pkg in environment.systemPackages) nixos-rebuild switch --upgrade # ie nix-channel --update nixos; nixos-rebuild switch nix-channel --list # run as root for system-wide config # generally safe to switch back and forth b/w channels, so long as they did not have Nix schema upgrade! nix-store --verify --check-contents # verify all installed packages. eg apt-get check, debsums nix-store --verrify --check-contents --repair # fix/reinstall broken package (ie failed checksum) nix-env -u --keep-going # per-user package upgrade nix-env -u --keep-going -leq # -leq will update if the dependencies are the one that changed nix-channel --list --add https://nixos.org/channels/nixpkgs-unstable # Add additional channel (eg yum repository) --remove CHANNELNAMEref: NixOS manual ch 4 - Upgrade
SW Pakcage Versioning
The configuration.nix file has provision to specify a specific version of the software to install. eg remove software shows an example in using nixpkgs.config.packageOverrides to specify an older version of KDE.However, there may not be any easy provision to switch mix of different software versions and combination at will, as could be done with SoftEnv or modules. Theoretically, the different versions can all just be installed. They are symlinks anyway, so it is just a matter of having a wrapper to change out the links to pick the right versions and combinations into the user's profile.
On the other hand, for shops that setup a large respository of software in a centralized NFS location such as /mnt/programs, and use SoftEnv or Modules to switch between desired version depending on user's desire, Nix/NixOS will not hinter such setup. Such NFS world is essentially a parallel universe :)
As to compiling program from source because Nix didn't provide it, this is still possible, but not as straight forward as say compiling a program in Ubuntu or RedHat. These problems are likely transient as NixOS matures and get wider support from the community. Example complications are:
- Depenencies are no longer in a centralized place such as /lib. One would have to hunt for such location and feed them into ./configure . It is worth noting that the dependencies can still be provided thru Nix, one does not have to install everything from source. It is just that ./configure may need help finding where these dependencies are, since there is no "centralized" LD_LIBRARY_PATH where dependencies would typically be installed in most other Unix OS.
- ./configure may not correctly determine it is running in NixOS, and may use flags designating compilation for a wrong OS Environment. eg, my last compilation of couchdb, I had to seed CFLAGS="-D _DEFAULT_SOURCE" so that configure did not create makefile for BSD.
Ad-hoc package addition
NixOS allows the use of nix-env -i PKGNAME to add package. this is similar to yum install PKGNAME.
But for a declarative OS, I think it is best to put everything in the config file (system-wide configuration.nix or per-user ~/nixpkgs/config.nix..
One nice thing, say for a development machine, user can add their own package without needing root password and so such commands would be run by the user.
nix-env -i PKGNAME # add package, like yum install PKGNAME. nix-env -e PKGNAME # erase package, like rpm -e ... nix-env -u # upgrade all pkg that has update nix-env -q # list packages installed by user and not as root nix-env -q --installed # no diff than above ?? # rpm -qa # no equiv of nix-env -q for root/system-wide settings (as of 8jun2011) nix-store -q --references /var/run/current-system/sw | cut -d'-' -f2- # list all downloaded packages for all user (root and per-user basis), incl deleted pkg (but not yet cleaned/garbage collected) nix-env -qa \* # list avail pkg for install. ie: yum list nix-env -qaP '*' --description # --query --available --attr-path nix-env --rollback # undo last "nix-env -i" (eg user pkg install, could be root if done as sudo and with -p) nix-env -p /nix/var/nix/profiles/system --list-generations # list avail generations (one generation created per each nixos-rebuild) # generation list is also present in grub menu nix-env --delete-generations old # remove sw that is no longer needed to free up space, but can no longer rollback nix-collect-garbage nix-collect-garbage -d nix-search vim nix-install vimCheatsheet says that as a user, can run dpkg -i packagename.deb to add a debian package!! (not sure where files will be installed). Need to have the dpkg command/package installed in NixOS for this.
Per-User package collection
# https://nixos.org/wiki/Cheatsheet # personal's collection, here called 'all' # TBA, was not able to change name to sn-pkg # it is really just like any other pkg # Place file in ~/.nixpkg/config.nix # add the whole collection via nix-env -i all # NOTE: pkg installed on cli via nix-env -i dropbox would # conflict with a dup listed in this file # also, nix-env -q will only show "all" as installed, not the individual pkg. # this is perhaps a problem of treating it as pkg rather than a container, now things are opaque. { packageOverrides = pkgs_: with pkgs_; { all = with pkgs; buildEnv { #sn-pkg = with pkgs; buildEnv { name = "all"; paths = [ #dropbox roxterm transmission vlc w3m tcsh file ]; }; }; }
Commands/Troubleshooting
nixos-rebuild switch # change/update system as per /etc/nixos/configuration.nix nixos-rebuild boot nixos-rebuild switch -p test nixos-rebuild build nixos-rebuild switch --rollback # undo last "nixos-rebuild switch" this will stop service, etc, whatever that were enabled would be reverted back. # but will not rewrite /etc/nixos/configuration.nix (it just uses a diff cached version stored in /nix/store?) # ref https://nixos.org/wiki/Install/remove_software#How_to_roll_back_software nixos-option services.xserver.enable # find out what the config file has resulted. ie, this is a read, not a set. systemctl start apache # start a service (apache daemon), need to run as root, but best to set it perm in configuration.nix systemctl stop apache command-not-found xterm # tell what package to install to provide a given command # DB is updated via nix-channel --update nox xterm # present a list of packages matching the queried command nix-store --query --requisites $(readlink -f /run/current-system) # list package dependencies, eg # apt-cache depends couchdb nix-store --query --references $(which roxterm) # for installed package at user level ?? # list files installed by a pkg, eg dpkg -L nmap ?? # which pkg installed a given file, eg dpkg -S /usr/bin/vim nixos-version # tell version of running os passwd username #
TBA
environment.env # settings for default ?Pros and Cons of NixOS/Nix dogma
- From debian devel:
- Not everything can be functional. solution such as ridding ldcache may make system slow.
- run time and build time dependcies are intermingled.
- Being able to go back to any previous version means never getting ride of any code, even those with security flaws.
- May not be scalable to OS the size of Debian
- From Y combinator
- Idempotency, atomicity
- Why Puppet/Chef/Ansible aren't good enough (and we can do better)
- Chef and Fabric provides Automated Imperative Configuration
- Puppet and Ansible provides Declarative Configuration
- Docker... ??
- NixOS/Nix provides stateless Declarative Config
Reference
- NixOS manual (latest version). The Appendix shows Configuration Options (but for v13.10) for the many packages that are added by Nix and support config directly from the configuration.nix file.
- NixOS 14.04 manual (abbreviated version in single large page, covers firewall, container, troubleshooting, the Config Options appendix, etc. The appendix (Configuration Options) is more current than the wiki page).
- NixOS 14.12 manual.
- NixOS 15.09 manual(beta?).
- NixOS cheatsheet. Also a good comparison of ubuntu commands vs NixOS, and implication of a declarative config OS.
- NixOS bug tracker
- tba
- tba
#
Copyright info about this work
This work is licensed under a Creative Commons Attribution-NonCommercial-ShareAlike2.5 License.
Pocket Sys Admin Survival Guide: for content that I wrote, (CC)
some rights reserved.
2005,2012 Tin Ho [ tin6150 (at) gmail.com ]
Some contents are "cached" here for easy reference. Sources include man pages,
vendor documents, online references, discussion groups, etc. Copyright of those
are obviously those of the vendor and original authors. I am merely caching them here for quick reference and avoid broken URL problems.
Where is PSG hosted these days?
http://tin6150.github.io/psg/psg2.html This new home page at github
http://tiny.cc/tin6150/ New home in 2011.06.
http://tin6150.s3-website-us-west-1.amazonaws.com/psg.html (coming soon)
ftp://sn.is-a-geek.com/psg/psg.html My home "server". Up sporadically.
http://tin6150.github.io/psg/psg.html
http://www.fiu.edu/~tho01/psg/psg.html (no longer updated as of 2007-05)