Table of Contents
List of Examples
/dev/sda (MBR)/dev/sda (UEFI)/dev/sdaemacs.nix)configuration.nix~/.config/nixpkgs/config.nixmkEnableOption usagemkPackageOption usagemkPackageOption with explicit default and examplemkPackageOption with additional description textservices.xserver.displayManager.enable in the gdm moduleservices.xserver.displayManager.enable in the sddm moduletypes.anythingsettings optionsettings attributepassthru.tests to make (openssh.tests.overrideAttrs f).tests.nixos coherentThis manual describes how to install, use and extend NixOS, a Linux distribution based on the purely functional package management system Nix, that is composed using modules and packages defined in the Nixpkgs project.
Additional information regarding the Nix package manager and the Nixpkgs project can be found in respectively the Nix manual and the Nixpkgs manual.
If you encounter problems, please report them on the Discourse, the Matrix room, or on the #nixos channel on Libera.Chat. Alternatively, consider contributing to this manual. Bugs should be reported in NixOS’ GitHub issue tracker.
Commands prefixed with # have to be run as root, either requiring to login as root user or temporarily switching to it using sudo for example.
This section describes how to obtain, install, and configure NixOS for first-time use.
NixOS ISO images can be downloaded from the NixOS download page. Follow the instructions in the section called “Booting from a USB flash drive” to create a bootable USB flash drive.
If you have a very old system that can’t boot from USB, you can burn the image to an empty CD. NixOS might not work very well on such systems.
As an alternative to installing NixOS yourself, you can get a running NixOS system through several other means:
Using virtual appliances in Open Virtualization Format (OVF) that can be imported into VirtualBox. These are available from the NixOS download page.
Using AMIs for Amazon’s EC2. To find one for your region, please refer to the download page.
Using NixOps, the NixOS-based cloud deployment tool, which allows you to provision VirtualBox and EC2 NixOS instances from declarative specifications. Check out the NixOps homepage for details.
Table of Contents
To begin the installation, you have to boot your computer from the install drive.
Plug in the install drive. Then turn on or restart your computer.
Open the boot menu by pressing the appropriate key, which is usually shown on the display on early boot. Select the USB flash drive (the option usually contains the word “USB”). If you choose the incorrect drive, your computer will likely continue to boot as normal. In that case restart your computer and pick a different drive.
The key to open the boot menu is different across computer brands and even models. It can be F12, but also F1, F9, F10, Enter, Del, Esc or another function key. If you are unsure and don’t see it on the early boot screen, you can search online for your computers brand, model followed by “boot from usb”. The computer might not even have that feature, so you have to go into the BIOS/UEFI settings to change the boot order. Again, search online for details about your specific computer model.
For Apple computers with Intel processors press and hold the ⌥ (Option or Alt) key until you see the boot menu. On Apple silicon press and hold the power button.
If your computer supports both BIOS and UEFI boot, choose the UEFI option. You will likely need to disable “Secure Boot” to use the UEFI option. The exact steps vary by device manufacturer but generally “Secure Boot” will be listed under “Boot”, “Security” or “Advanced” in the BIOS/UEFI menu.
If you use a CD for the installation, the computer will probably boot from it automatically. If not, choose the option containing the word “CD” from the boot menu.
Shortly after selecting the appropriate boot drive, you should be presented with a menu with different installer options. Leave the default and wait (or press Enter to speed up).
The graphical images will start their corresponding desktop environment and the graphical installer, which can take some time. The minimal images will boot to a command line. You have to follow the instructions in the section called “Manual Installation” there.
The graphical installer is recommended for desktop users and will guide you through the installation.
In the “Welcome” screen, you can select the language of the Installer and the installed system.
Leaving the language as “American English” will make it easier to search for error messages in a search engine or to report an issue.
Next you should choose your location to have the timezone set correctly. You can actually click on the map!
The installer will use an online service to guess your location based on your public IP address.
Then you can select the keyboard layout. The default keyboard model should work well with most desktop keyboards. If you have a special keyboard or notebook, your model might be in the list. Select the language you are most comfortable typing in.
On the “Users” screen, you have to type in your display name, login name and password. You can also enable an option to automatically login to the desktop.
Then you have the option to choose a desktop environment. If you want to create a custom setup with a window manager, you can select “No desktop”.
If you don’t have a favorite desktop and don’t know which one to choose, you can stick to either GNOME or Plasma. They have a quite different design, so you should choose whichever you like better. They are both popular choices and well tested on NixOS.
You have the option to allow unfree software in the next screen.
The easiest option in the “Partitioning” screen is “Erase disk”, which will delete all data from the selected disk and install the system on it. Also select “Swap (with Hibernation)” in the dropdown below it. You have the option to encrypt the whole disk with LUKS.
At the top left you see if the Installer was booted with BIOS or UEFI. If you know your system supports UEFI and it shows “BIOS”, reboot with the correct option.
Make sure you have selected the correct disk at the top and that no valuable data is still on the disk! It will be deleted when formatting the disk.
Check the choices you made in the “Summary” and click “Install”.
The installation takes about 15 minutes. The time varies based on the selected desktop environment, internet connection speed and disk write speed.
When the install is complete, remove the USB flash drive and reboot into your new system!
NixOS can be installed on BIOS or UEFI systems. The procedure for a UEFI installation is broadly the same as for a BIOS installation. The differences are mentioned in the following steps.
The NixOS manual is available by running nixos-help in the command line
or from the application menu in the desktop environment.
To have access to the command line on the graphical images, open Terminal (GNOME) or Konsole (Plasma) from the application menu.
You are logged-in automatically as nixos. The nixos user account has
an empty password so you can use sudo without a password:
$ sudo -i
You can use loadkeys to switch to your preferred keyboard layout.
(We even provide neo2 via loadkeys de neo!)
If the text is too small to be legible, try setfont ter-v32n to
increase the font size.
To install over a serial port connect with 115200n8 (e.g.
picocom -b 115200 /dev/ttyUSB0). When the bootloader lists boot
entries, select the serial console boot entry.
The boot process should have brought up networking (check ip a). Networking is necessary for the installer, since it will
download lots of stuff (such as source tarballs or Nixpkgs channel
binaries). It’s best if you have a DHCP server on your network.
Otherwise configure networking manually using ip.
You can configure the network, Wi-Fi included, through NetworkManager.
Using the nmtui program, you can do so even in a non-graphical session.
If you prefer to configure the network manually, disable NetworkManager with
systemctl stop NetworkManager.
If you would like to continue the installation from a different machine
you can use activated SSH daemon. You need to copy your ssh key to
either /home/nixos/.ssh/authorized_keys or
/root/.ssh/authorized_keys (Tip: For installers with a modifiable
filesystem such as the sd-card installer image a key can be manually
placed by mounting the image on a different machine). Alternatively you
must set a password for either root or nixos with passwd to be
able to login.
The NixOS installer doesn’t do any partitioning or formatting, so you need to do that yourself.
The NixOS installer ships with multiple partitioning tools. The examples
below use parted, but also provides fdisk, gdisk, cfdisk, and
cgdisk.
Use the command ‘lsblk’ to find the name of your ‘disk’ device.
The recommended partition scheme differs depending if the computer uses Legacy Boot or UEFI.
Here’s an example partition scheme for UEFI, using /dev/sda as the
device.
You can safely ignore parted’s informational message about needing to
update /etc/fstab.
Create a GPT partition table.
# parted /dev/sda -- mklabel gpt
Add the root partition. This will fill the disk except for the end part, where the swap will live, and the space left in front (512MiB) which will be used by the boot partition.
# parted /dev/sda -- mkpart root ext4 512MB -8GB
Next, add a swap partition. The size required will vary according to needs, here a 8GB one is created.
# parted /dev/sda -- mkpart swap linux-swap -8GB 100%
The swap partition size rules are no different than for other Linux distributions.
Finally, the boot partition. NixOS by default uses the ESP (EFI system partition) as its /boot partition. It uses the initially reserved 512MiB at the start of the disk.
# parted /dev/sda -- mkpart ESP fat32 1MB 512MB
# parted /dev/sda -- set 3 esp on
In case you decided to not create a swap partition, replace 3 by 2. To be sure of the id number of ESP, run parted --list.
Once complete, you can follow with the section called “Formatting”.
Here’s an example partition scheme for Legacy Boot, using /dev/sda as
the device.
You can safely ignore parted’s informational message about needing to
update /etc/fstab.
Create a MBR partition table.
# parted /dev/sda -- mklabel msdos
Add the root partition. This will fill the disk except for the end part, where the swap will live.
# parted /dev/sda -- mkpart primary 1MB -8GB
Set the root partition’s boot flag to on. This allows the disk to be booted from.
# parted /dev/sda -- set 1 boot on
Finally, add a swap partition. The size required will vary according to needs, here a 8GB one is created.
# parted /dev/sda -- mkpart primary linux-swap -8GB 100%
The swap partition size rules are no different than for other Linux distributions.
Once complete, you can follow with the section called “Formatting”.
Use the following commands:
For initialising Ext4 partitions: mkfs.ext4. It is recommended
that you assign a unique symbolic label to the file system using the
option -L label, since this makes the file system configuration
independent from device changes. For example:
# mkfs.ext4 -L nixos /dev/sda1
For creating swap partitions: mkswap. Again it’s recommended to
assign a label to the swap partition: -L label. For example:
# mkswap -L swap /dev/sda2
UEFI systems
For creating boot partitions: mkfs.fat. Again it’s recommended
to assign a label to the boot partition: -n label. For
example:
# mkfs.fat -F 32 -n boot /dev/sda3
For creating LVM volumes, the LVM commands, e.g., pvcreate,
vgcreate, and lvcreate.
For creating software RAID devices, use mdadm.
Mount the target file system on which NixOS should be installed on
/mnt, e.g.
# mount /dev/disk/by-label/nixos /mnt
UEFI systems
Mount the boot file system on /mnt/boot, e.g.
# mkdir -p /mnt/boot
# mount -o umask=077 /dev/disk/by-label/boot /mnt/boot
If your machine has a limited amount of memory, you may want to
activate swap devices now (swapon device).
The installer (or rather, the build actions that it
may spawn) may need quite a bit of RAM, depending on your
configuration.
# swapon /dev/sda2
You now need to create a file /mnt/etc/nixos/configuration.nix
that specifies the intended configuration of the system. This is
because NixOS has a declarative configuration model: you create or
edit a description of the desired configuration of your system, and
then NixOS takes care of making it happen. The syntax of the NixOS
configuration file is described in Configuration Syntax,
while a list of available configuration options appears in
Appendix A. A minimal example is shown in
Example: NixOS Configuration.
This command accepts an optional --flake option, to also generate a
flake.nix file, if you want to set up a flake-based configuration.
The command nixos-generate-config can generate an initial
configuration file for you:
# nixos-generate-config --root /mnt
You should then edit /mnt/etc/nixos/configuration.nix to suit your
needs:
# nano /mnt/etc/nixos/configuration.nix
If you’re using the graphical ISO image, other editors may be
available (such as vim). If you have network access, you can also
install other editors – for instance, you can install Emacs by
running nix-env -f '<nixpkgs>' -iA emacs.
You must set the option boot.loader.grub.device to
specify on which disk the GRUB boot loader is to be installed.
Without it, NixOS cannot boot.
If there are other operating systems running on the machine before
installing NixOS, the boot.loader.grub.useOSProber
option can be set to true to automatically add them to the grub
menu.
You must select a boot-loader, either systemd-boot or GRUB. The recommended
option is systemd-boot: set the option boot.loader.systemd-boot.enable
to true. nixos-generate-config should do this automatically
for new configurations when booted in UEFI mode.
You may want to look at the options starting with
boot.loader.efi and
boot.loader.systemd-boot
as well.
If you want to use GRUB, set boot.loader.grub.device to nodev and
boot.loader.grub.efiSupport to true.
With systemd-boot, you should not need any special configuration to detect
other installed systems. With GRUB, set boot.loader.grub.useOSProber
to true, but this will only detect windows partitions, not other Linux
distributions. If you dual boot another Linux distribution, use systemd-boot
instead.
If you need to configure networking for your machine the
configuration options are described in Networking. In
particular, while wifi is supported on the installation image, it is
not enabled by default in the configuration generated by
nixos-generate-config.
Another critical option is fileSystems, specifying the file
systems that need to be mounted by NixOS. However, you typically
don’t need to set it yourself, because nixos-generate-config sets
it automatically in /mnt/etc/nixos/hardware-configuration.nix from
your currently mounted file systems. (The configuration file
hardware-configuration.nix is included from configuration.nix
and will be overwritten by future invocations of
nixos-generate-config; thus, you generally should not modify it.)
Additionally, you may want to look at Hardware configuration for
known-hardware at this
point or after installation.
Depending on your hardware configuration or type of file system, you
may need to set the option boot.initrd.kernelModules to include
the kernel modules that are necessary for mounting the root file
system, otherwise the installed system will not be able to boot. (If
this happens, boot from the installation media again, mount the
target file system on /mnt, fix /mnt/etc/nixos/configuration.nix
and rerun nixos-install.) In most cases, nixos-generate-config
will figure out the required modules.
Do the installation:
# nixos-install
This will install your system based on the configuration you
provided. If anything fails due to a configuration problem or any
other issue (such as a network outage while downloading binaries
from the NixOS binary cache), you can re-run nixos-install after
fixing your configuration.nix.
If you opted for a flake-based configuration, you will need to pass the
--flake here as well and specify the name of the configuration as used in
the flake.nix file. For the default generated flake, this is nixos.
# nixos-install --flake 'path/to/flake.nix#nixos'
As the last step, nixos-install will ask you to set the password
for the root user, e.g.
setting root password...
New password: ***
Retype new password: ***
If you have a user account declared in your configuration.nix and plan to log in using this user, set a password before rebooting, e.g. for the alice user:
# nixos-enter --root /mnt -c 'passwd alice'
For unattended installations, it is possible to use
nixos-install --no-root-passwd in order to disable the password
prompt entirely.
If everything went well:
# reboot
You should now be able to boot into the installed NixOS. The GRUB boot menu shows a list of available configurations (initially just one). Every time you change the NixOS configuration (see Changing Configuration), a new item is added to the menu. This allows you to easily roll back to a previous configuration if something goes wrong.
Use your declared user account to log in.
If you didn’t declare one, you should still be able to log in using the root user.
Some graphical display managers such as SDDM do not allow root login by default, so you might need to switch to TTY.
Refer to User Management for details on declaring user accounts.
You may also want to install some software. This will be covered in Package Management.
To summarise, Example: Commands for Installing NixOS on /dev/sda
shows a typical sequence of commands for installing NixOS on an empty hard
drive (here /dev/sda). Example: NixOS Configuration shows a
corresponding configuration Nix expression.
/dev/sda (MBR)# parted /dev/sda -- mklabel msdos
# parted /dev/sda -- mkpart primary 1MB -8GB
# parted /dev/sda -- mkpart primary linux-swap -8GB 100%
/dev/sda (UEFI)# parted /dev/sda -- mklabel gpt
# parted /dev/sda -- mkpart root ext4 512MB -8GB
# parted /dev/sda -- mkpart swap linux-swap -8GB 100%
# parted /dev/sda -- mkpart ESP fat32 1MB 512MB
# parted /dev/sda -- set 3 esp on
/dev/sdaWith a partitioned disk.
# mkfs.ext4 -L nixos /dev/sda1
# mkswap -L swap /dev/sda2
# swapon /dev/sda2
# mkfs.fat -F 32 -n boot /dev/sda3 # (for UEFI systems only)
# mount /dev/disk/by-label/nixos /mnt
# mkdir -p /mnt/boot # (for UEFI systems only)
# mount -o umask=077 /dev/disk/by-label/boot /mnt/boot # (for UEFI systems only)
# nixos-generate-config --root /mnt
# nano /mnt/etc/nixos/configuration.nix
# nixos-install
# reboot
{ config, pkgs, ... }: {
imports = [
# Include the results of the hardware scan.
./hardware-configuration.nix
];
boot.loader.grub.device = "/dev/sda"; # (for BIOS systems only)
boot.loader.systemd-boot.enable = true; # (for UEFI systems only)
# Note: setting fileSystems is generally not
# necessary, since nixos-generate-config figures them out
# automatically in hardware-configuration.nix.
#fileSystems."/".device = "/dev/disk/by-label/nixos";
# Enable the OpenSSH server.
services.sshd.enable = true;
}
The image has to be written verbatim to the USB flash drive for it to be bootable on UEFI and BIOS systems. Here are the recommended tools to do that.
Etcher is a popular and user-friendly tool. It works on Linux, Windows and macOS.
Download it from balena.io, start the program, select the downloaded NixOS ISO, then select the USB flash drive and flash it.
Etcher reports errors and usage statistics by default, which can be disabled in the settings.
An alternative is USBImager, which is very simple and does not connect to the internet. Download the version with write-only (wo) interface for your system. Start the program, select the image, select the USB flash drive and click “Write”.
Plug in the USB flash drive.
Find the corresponding device with lsblk. You can distinguish them by
their size.
Make sure all partitions on the device are properly unmounted. Replace sdX
with your device (e.g. sdb).
sudo umount /dev/sdX*
Then use the dd utility to write the image to the USB flash drive.
sudo dd bs=4M conv=fsync oflag=direct status=progress if=<path-to-image> of=/dev/sdX
Plug in the USB flash drive.
Find the corresponding device with diskutil list. You can distinguish them
by their size.
Make sure all partitions on the device are properly unmounted. Replace diskX
with your device (e.g. disk1).
diskutil unmountDisk diskX
Then use the dd utility to write the image to the USB flash drive.
sudo dd if=<path-to-image> of=/dev/rdiskX bs=4m
After dd completes, a GUI dialog “The disk
you inserted was not readable by this computer” will pop up, which can
be ignored.
Using the ‘raw’ rdiskX device instead of diskX with dd completes in
minutes instead of hours.
Eject the disk when it is finished.
diskutil eject /dev/diskX
Advanced users may wish to install NixOS using an existing PXE or iPXE setup.
These instructions assume that you have an existing PXE or iPXE infrastructure and want to add the NixOS installer as another option. To build the necessary files from your current version of nixpkgs, you can run:
nix-build -A netboot.x86_64-linux '<nixpkgs/nixos/release.nix>'
This will create a result directory containing:
bzImage – the Linux kernel
initrd – the initrd file
netboot.ipxe – an example ipxe script demonstrating the appropriate kernel command line arguments for this image
If you’re using plain PXE, configure your boot loader to use the
bzImage and initrd files and have it provide the same kernel command
line arguments found in netboot.ipxe.
If you’re using iPXE, depending on how your HTTP/FTP/etc. server is
configured you may be able to use netboot.ipxe unmodified, or you may
need to update the paths to the files to match your server’s directory
layout.
In the future we may begin making these files available as build products from hydra at which point we will update this documentation with instructions on how to obtain them either for placing on a dedicated TFTP server or to boot them directly over the internet.
In some cases, your system might already be booted into/preinstalled with another Linux distribution, and booting NixOS by attaching an installation image is quite a manual process.
This is particularly useful for (cloud) providers where you can’t boot a custom image, but get some Debian or Ubuntu installation.
In these cases, it might be easier to use kexec to “jump into NixOS” from the
running system, which only assumes bash and kexec to be installed on the
machine.
Note that kexec may not work correctly on some hardware, as devices are not fully re-initialized in the process. In practice, this however is rarely the case.
To build the necessary files from your current version of nixpkgs, you can run:
nix-build -A kexec.x86_64-linux '<nixpkgs/nixos/release.nix>'
This will create a result directory containing the following:
bzImage (the Linux kernel)
initrd (the initrd file)
kexec-boot (a shellscript invoking kexec)
These three files are meant to be copied over to the other already running Linux Distribution.
Note its symlinks pointing elsewhere, so cd in, and use
scp * root@$destination to copy it over, rather than rsync.
Once you finished copying, execute kexec-boot on the destination, and after
some seconds, the machine should be booting into an (ephemeral) NixOS
installation medium.
In case you want to describe your own system closure to kexec into, instead of
the default installer image, you can build your own configuration.nix:
{ modulesPath, ... }:
{
imports = [ (modulesPath + "/installer/netboot/netboot-minimal.nix") ];
services.openssh.enable = true;
users.users.root.openssh.authorizedKeys.keys = [ "my-ssh-pubkey" ];
}
nix-build '<nixpkgs/nixos>' \
--arg configuration ./configuration.nix
--attr config.system.build.kexecTree
Make sure your configuration.nix does still import netboot-minimal.nix (or
netboot-base.nix).
Installing NixOS into a VirtualBox guest is convenient for users who want to try NixOS without installing it on bare metal. If you want to set up a VirtualBox guest, follow these instructions:
Add a New Machine in VirtualBox with OS Type “Linux / Other Linux”
Base Memory Size: 768 MB or higher.
New Hard Disk of 10 GB or higher.
Mount the CD-ROM with the NixOS ISO (by clicking on CD/DVD-ROM)
Click on Settings / System / Processor and enable PAE/NX
Click on Settings / System / Acceleration and enable “VT-x/AMD-V” acceleration
Click on Settings / Display / Screen and select VMSVGA as Graphics Controller
Save the settings, start the virtual machine, and continue installation like normal
There are a few modifications you should make in configuration.nix. Enable booting:
{ boot.loader.grub.device = "/dev/sda"; }
Also remove the fsck that runs at startup. It will always fail to run,
stopping your boot until you press *.
{ boot.initrd.checkJournalingFS = false; }
Shared folders can be given a name and a path in the host system in the
VirtualBox settings (Machine / Settings / Shared Folders, then click on
the “Add” icon). Add the following to the
/etc/nixos/configuration.nix to auto-mount them. If you do not add
"nofail", the system will not boot properly.
{ config, pkgs, ... }:
{
fileSystems."/virtualboxshare" = {
fsType = "vboxsf";
device = "nameofthesharedfolder";
options = [
"rw"
"nofail"
];
};
}
The folder will be available directly under the root directory.
Because Nix (the package manager) & Nixpkgs (the Nix packages collection) can both be installed on any (most?) Linux distributions, they can be used to install NixOS in various creative ways. You can, for instance:
Install NixOS on another partition, from your existing Linux distribution (without the use of a USB or optical device!)
Install NixOS on the same partition (in place!), from your existing
non-NixOS Linux distribution using NIXOS_LUSTRATE.
Install NixOS on your hard drive from the Live CD of any Linux distribution.
The first steps to all these are the same:
Install the Nix package manager:
Short version:
$ curl -L https://nixos.org/nix/install | sh
$ . $HOME/.nix-profile/etc/profile.d/nix.sh # …or open a fresh shell
More details in the Nix manual
Switch to the NixOS channel:
If you’ve just installed Nix on a non-NixOS distribution, you will
be on the nixpkgs channel by default.
$ nix-channel --list
nixpkgs https://channels.nixos.org/nixpkgs-unstable
As that channel gets released without running the NixOS tests, it
will be safer to use the nixos-* channels instead:
$ nix-channel --add https://channels.nixos.org/nixos-<version> nixpkgs
Where <version> corresponds to the latest version available on channels.nixos.org.
You may want to throw in a nix-channel --update for good measure.
Install the NixOS installation tools:
You’ll need nixos-generate-config and nixos-install, but this
also makes some man pages and nixos-enter available, just in case
you want to chroot into your NixOS partition. NixOS installs these
by default, but you don’t have NixOS yet…
$ nix-env -f '<nixpkgs>' -iA nixos-install-tools
The following 5 steps are only for installing NixOS to another
partition. For installing NixOS in place using NIXOS_LUSTRATE,
skip ahead.
Prepare your target partition:
At this point it is time to prepare your target partition. Please refer to the partitioning, file-system creation, and mounting steps of Installing NixOS
If you’re about to install NixOS in place using NIXOS_LUSTRATE
there is nothing to do for this step.
Generate your NixOS configuration:
$ sudo `which nixos-generate-config` --root /mnt
You’ll probably want to edit the configuration files. Refer to the
nixos-generate-config step in Installing NixOS for more
information.
Consider setting up the NixOS bootloader to give you the ability to
boot on your existing Linux partition. For instance, if you’re
using GRUB and your existing distribution is running Ubuntu, you may
want to add something like this to your configuration.nix:
{
boot.loader.grub.extraEntries = ''
menuentry "Ubuntu" {
search --set=ubuntu --fs-uuid 3cc3e652-0c1f-4800-8451-033754f68e6e
configfile "($ubuntu)/boot/grub/grub.cfg"
}
'';
}
(You can find the appropriate UUID for your partition in
/dev/disk/by-uuid)
Create the nixbld group and user on your original distribution:
$ sudo groupadd -g 30000 nixbld
$ sudo useradd -u 30000 -g nixbld -G nixbld nixbld
Download/build/install NixOS:
Once you complete this step, you might no longer be able to boot on existing systems without the help of a rescue USB drive or similar.
On some distributions there are separate PATHS for programs intended
only for root. In order for the installation to succeed, you might
have to use PATH="$PATH:/usr/sbin:/sbin" in the following command.
$ sudo PATH="$PATH" `which nixos-install` --root /mnt
Again, please refer to the nixos-install step in
Installing NixOS for more information.
That should be it for installation to another partition!
Optionally, you may want to clean up your non-NixOS distribution:
$ sudo userdel nixbld
$ sudo groupdel nixbld
If you do not wish to keep the Nix package manager installed either,
run something like sudo rm -rv ~/.nix-* /nix and remove the line
that the Nix installer added to your ~/.profile.
The following steps are only for installing NixOS in place using
NIXOS_LUSTRATE:
Generate your NixOS configuration:
$ sudo `which nixos-generate-config`
Note that this will place the generated configuration files in
/etc/nixos. You’ll probably want to edit the configuration files.
Refer to the nixos-generate-config step in
Installing NixOS for more information.
On UEFI systems, check that your /etc/nixos/hardware-configuration.nix did the right thing with the EFI System Partition.
In NixOS, by default, both systemd-boot and grub expect it to be mounted on /boot.
However, the configuration generator bases its fileSystems configuration on the current mount points at the time it is run.
If the current system and NixOS’s bootloader configuration don’t agree on where the EFI System Partition is to be mounted, you’ll need to manually alter the mount point in hardware-configuration.nix before building the system closure.
The lustrate process will not work if the boot.initrd.systemd.enable option is set to true.
If you want to use this option, wait until after the first boot into the NixOS system to enable it and rebuild.
You’ll likely want to set a root password for your first boot using
the configuration files because you won’t have a chance to enter a
password until after you reboot. You can initialize the root password
to an empty one with this line: (and of course don’t forget to set
one once you’ve rebooted or to lock the account with
sudo passwd -l root if you use sudo)
{ users.users.root.initialHashedPassword = ""; }
Build the NixOS closure and install it in the system profile:
$ nix-env -p /nix/var/nix/profiles/system -f '<nixpkgs/nixos>' -I nixos-config=/etc/nixos/configuration.nix -iA system
Change ownership of the /nix tree to root (since your Nix install
was probably single user):
$ sudo chown -R 0:0 /nix
Set up the /etc/NIXOS and /etc/NIXOS_LUSTRATE files:
/etc/NIXOS officializes that this is now a NixOS partition (the
bootup scripts require its presence).
/etc/NIXOS_LUSTRATE tells the NixOS bootup scripts to move
everything that’s in the root partition to /old-root. This will
move your existing distribution out of the way in the very early
stages of the NixOS bootup. There are exceptions (we do need to keep
NixOS there after all), so the NixOS lustrate process will not
touch:
The /nix directory
The /boot directory
Any file or directory listed in /etc/NIXOS_LUSTRATE (one per
line)
The act of “lustrating” refers to the wiping of the existing distribution.
Creating /etc/NIXOS_LUSTRATE can also be used on NixOS to remove
all mutable files from your root partition (anything that’s not in
/nix or /boot gets “lustrated” on the next boot.
lustrate /ˈlʌstreɪt/ verb.
purify by expiatory sacrifice, ceremonial washing, or some other ritual action.
Let’s create the files:
$ sudo touch /etc/NIXOS
$ sudo touch /etc/NIXOS_LUSTRATE
Let’s also make sure the NixOS configuration files are kept once we reboot on NixOS:
$ echo etc/nixos | sudo tee -a /etc/NIXOS_LUSTRATE
Finally, install NixOS’s boot system, backing up the current boot system’s files in the process.
The details of this step can vary depending on the bootloader configuration in NixOS and the bootloader in use by the current system.
The commands below should work for:
BIOS systems.
UEFI systems where both the current system and NixOS mount the EFI System Partition on /boot.
Both systemd-boot and grub expect this by default in NixOS, but other distributions vary.
Once you complete this step, your current distribution will no longer be bootable! If you didn’t get all the NixOS configuration right, especially those settings pertaining to boot loading and root partition, NixOS may not be bootable either. Have a USB rescue device ready in case this happens.
On UEFI systems, anything on the EFI System Partition will be removed by these commands, such as other coexisting OS’s bootloaders.
$ sudo mkdir /boot.bak && sudo mv /boot/* /boot.bak &&
sudo NIXOS_INSTALL_BOOTLOADER=1 /nix/var/nix/profiles/system/bin/switch-to-configuration boot
Cross your fingers, reboot, hopefully you should get a NixOS prompt!
In other cases, most commonly where the EFI System Partition of the current system is instead mounted on /boot/efi, the goal is to:
Make sure /boot (and the EFI System Partition, if mounted elsewhere) are mounted how the NixOS configuration would mount them.
Clear them of files related to the current system, backing them up outside of /boot.
NixOS will move the backups into /old-root along with everything else when it first boots.
Instruct the NixOS closure built earlier to install its bootloader with:
sudo NIXOS_INSTALL_BOOTLOADER=1 /nix/var/nix/profiles/system/bin/switch-to-configuration boot
If for some reason you want to revert to the old distribution, you’ll need to boot on a USB rescue disk and do something along these lines:
# mkdir root
# mount /dev/sdaX root
# mkdir root/nixos-root
# mv -v root/* root/nixos-root/
# mv -v root/nixos-root/old-root/* root/
# mv -v root/boot.bak root/boot # We had renamed this by hand earlier
# umount root
# reboot
This may work as is or you might also need to reinstall the boot loader.
And of course, if you’re happy with NixOS and no longer need the old distribution:
sudo rm -rf /old-root
It’s also worth noting that this whole process can be automated. This is especially useful for Cloud VMs, where provider do not provide NixOS. For instance, nixos-infect uses the lustrate process to convert Digital Ocean droplets to NixOS from other distributions automatically.
To install NixOS behind a proxy, do the following before running
nixos-install.
Update proxy configuration in /mnt/etc/nixos/configuration.nix to
keep the internet accessible after reboot.
{
networking.proxy.default = "http://user:password@proxy:port/";
networking.proxy.noProxy = "127.0.0.1,localhost,internal.domain";
}
Setup the proxy environment variables in the shell where you are
running nixos-install.
# proxy_url="http://user:password@proxy:port/"
# export http_proxy="$proxy_url"
# export HTTP_PROXY="$proxy_url"
# export https_proxy="$proxy_url"
# export HTTPS_PROXY="$proxy_url"
If you are switching networks with different proxy configurations, use
the specialisation option in configuration.nix to switch proxies at
runtime. Refer to Appendix A for more information.
The file /etc/nixos/configuration.nix contains the current
configuration of your machine. Whenever you’ve changed
something in that file, you should do
# nixos-rebuild switch
to build the new configuration, make it the default configuration for booting, and try to realise the configuration in the running system (e.g., by restarting system services).
This command doesn’t start/stop user services
automatically. nixos-rebuild only runs a daemon-reload for each user with running
user services.
These commands must be executed as root, so you should either run them
from a root shell or by prefixing them with sudo -i.
You can also do
# nixos-rebuild test
to build the configuration and switch the running system to it, but without making it the boot default. So if (say) the configuration locks up your machine, you can just reboot to get back to a working configuration.
There is also
# nixos-rebuild boot
to build the configuration and make it the boot default, but not switch to it now (so it will only take effect after the next reboot).
You can make your configuration show up in a different submenu of the GRUB 2 boot screen by giving it a different profile name, e.g.
# nixos-rebuild switch -p test
which causes the new configuration (and previous ones created using
-p test) to show up in the GRUB submenu “NixOS - Profile ‘test’”.
This can be useful to separate test configurations from “stable”
configurations.
A repl, or read-eval-print loop, is also available. You can inspect your configuration and use the Nix language with
# nixos-rebuild repl
Your configuration is loaded into the config variable. Use tab for autocompletion, use the :r command to reload the configuration files. See :? or nix repl in the Nix manual to learn more.
Finally, you can do
$ nixos-rebuild build
to build the configuration but nothing more. This is useful to see whether everything compiles cleanly.
If you have a machine that supports hardware virtualisation, you can also test the new configuration in a sandbox by building and running a QEMU virtual machine that contains the desired configuration. Just do
$ nixos-rebuild build-vm
$ ./result/bin/run-*-vm
The VM does not have any data from your host system, so your existing
user accounts and home directories will not be available unless you have
set mutableUsers = false. Another way is to temporarily add the
following to your configuration:
{ users.users.your-user.initialHashedPassword = "test"; }
Important: delete the $hostname.qcow2 file if you have started the virtual machine at least once without the right users, otherwise the changes will not get picked up. You can forward ports on the host to the guest. For instance, the following will forward host port 2222 to guest port 22 (SSH):
$ QEMU_NET_OPTS="hostfwd=tcp:127.0.0.1:2222-:22" ./result/bin/run-*-vm
allowing you to log in via SSH (assuming you have set the appropriate passwords or SSH authorized keys):
$ ssh -p 2222 localhost
Such port forwardings connect via the VM’s virtual network interface.
Thus they cannot connect to ports that are only bound to the VM’s
loopback interface (127.0.0.1), and the VM’s NixOS firewall
must be configured to allow these connections.
Table of Contents
The best way to keep your NixOS installation up to date is to use one of
the NixOS channels. A channel is a Nix mechanism for distributing Nix
expressions and associated binaries. The NixOS channels are updated
automatically from NixOS’s Git repository after certain tests have
passed and a selection of packages has been built successfully
(see nixos/release-combined.nix and nixos/release-small.nix).
These channels are:
Stable channels, such as nixos-25.11.
These only get conservative bug fixes and package upgrades. For
instance, a channel update may cause the Linux kernel on your system
to be upgraded from 4.19.34 to 4.19.38 (a minor bug fix), but not
from 4.19.x to 4.20.x (a major change that has the potential to break things).
Stable channels are generally maintained until the next stable
branch is created.
The unstable channel, nixos-unstable.
This corresponds to NixOS’s main development branch, and may thus see
radical changes between channel updates. It’s not recommended for
production systems.
Small channels, such as nixos-25.11-small
or nixos-unstable-small.
These are identical to the stable and unstable channels described above,
except that they contain fewer binary packages. This means they get updated
faster than the regular channels (for instance, when a critical security patch
is committed to NixOS’s source tree), but may require more packages to be
built from source than usual. They’re mostly intended for server environments
and as such contain few GUI applications.
To see what channels are available, go to https://channels.nixos.org. (Note that the URIs of the various channels redirect to a directory that contains the channel’s latest version and includes ISO images and VirtualBox appliances.) Please note that during the release process, channels that are not yet released will be present here as well. See the Getting NixOS page https://nixos.org/download/ to find the newest supported stable release.
When you first install NixOS, you’re automatically subscribed to the
NixOS channel that corresponds to your installation source. For
instance, if you installed from a 25.11 ISO, you will be subscribed to
the nixos-25.11 channel. To see which NixOS channel you’re subscribed
to, run the following as root:
# nix-channel --list | grep nixos
nixos https://channels.nixos.org/nixos-unstable
To switch to a different NixOS channel, do
# nix-channel --add https://channels.nixos.org/channel-name nixos
(Be sure to include the nixos parameter at the end.) For instance, to
use the NixOS 25.05 stable channel:
# nix-channel --add https://channels.nixos.org/nixos-25.11 nixos
If you have a server, you may want to use the “small” channel instead:
# nix-channel --add https://channels.nixos.org/nixos-25.11-small nixos
And if you want to live on the bleeding edge:
# nix-channel --add https://channels.nixos.org/nixos-unstable nixos
You can then upgrade NixOS to the latest version in your chosen channel by running
# nixos-rebuild switch --upgrade
which is equivalent to the more verbose nix-channel --update nixos; nixos-rebuild switch.
Channels are set per user. This means that running nix-channel --add
as a non root user (or without sudo) will not affect
configuration in /etc/nixos/configuration.nix
It is generally safe to switch back and forth between channels. The only exception is that a newer NixOS may also have a newer Nix version, which may involve an upgrade of Nix’s database schema. This cannot be undone easily, so in that case you will not be able to go back to your original channel.
You can keep a NixOS system up-to-date automatically by adding the
following to configuration.nix:
{
system.autoUpgrade.enable = true;
system.autoUpgrade.allowReboot = true;
}
This enables a periodically executed systemd service named
nixos-upgrade.service. If the allowReboot option is false, it runs
nixos-rebuild switch --upgrade to upgrade NixOS to the latest version
in the current channel. (To see when the service runs, see systemctl list-timers.)
If allowReboot is true, then the system will automatically reboot if
the new generation contains a different kernel, initrd or kernel
modules. You can also specify a channel explicitly, e.g.
{ system.autoUpgrade.channel = "https://channels.nixos.org/nixos-25.11"; }
Table of Contents
Default live installer configurations are available inside nixos/modules/installer/cd-dvd.
For building other system images, see Building Images with nixos-rebuild build-image.
You have two options:
Use any of those default configurations as is
Combine them with (any of) your host config(s)
System images, such as the live installer ones, know how to enforce configuration settings on which they immediately depend in order to work correctly.
However, if you are confident, you can opt to override those
enforced values with mkForce.
To build an ISO image for the channel nixos-unstable:
$ git clone https://github.com/NixOS/nixpkgs.git
$ cd nixpkgs/nixos
$ git switch nixos-unstable
$ nix-build -A config.system.build.isoImage -I nixos-config=modules/installer/cd-dvd/installation-cd-minimal.nix default.nix
To check the content of an ISO image, mount it like so:
# mount -o loop -t iso9660 ./result/iso/nixos-image-25.05pre-git-x86_64-linux.iso /mnt/iso
If you need additional (non-distributable) drivers or firmware in the installer, you might want to extend these configurations.
For example, to build the GNOME graphical installer ISO, but with support for
certain WiFi adapters present in some MacBooks, you can create the following
file at modules/installer/cd-dvd/installation-cd-graphical-gnome-macbook.nix:
{ config, ... }:
{
imports = [ ./installation-cd-graphical-gnome.nix ];
boot.initrd.kernelModules = [ "wl" ];
boot.kernelModules = [
"kvm-intel"
"wl"
];
boot.extraModulePackages = [ config.boot.kernelPackages.broadcom_sta ];
}
Then build it like in the example above:
$ git clone https://github.com/NixOS/nixpkgs.git
$ cd nixpkgs/nixos
$ export NIXPKGS_ALLOW_UNFREE=1
$ nix-build -A config.system.build.isoImage -I nixos-config=modules/installer/cd-dvd/installation-cd-graphical-gnome-macbook.nix default.nix
The config value enforcement is implemented via mkImageMediaOverride = mkOverride 60;
and therefore primes over simple value assignments, but also yields to mkForce.
This property allows image designers to implement in semantically correct ways those configuration values upon which the correct functioning of the image depends.
For example, the iso base image overrides those file systems which it needs at a minimum for correct functioning, while the installer base image overrides the entire file system layout because there can’t be any other guarantees on a live medium than those given by the live medium itself. The latter is especially true before formatting the target block device(s). On the other hand, the netboot iso only overrides its minimum dependencies since netboot images are always made-to-target.
nixos-rebuild build-image Nixpkgs contains a variety of modules to build custom images for different virtualization platforms and cloud providers, such as e.g. amazon-image.nix and proxmox-lxc.nix.
While those can be imported directly, system.build.images provides an attribute set mapping variant names to image derivations. Available variants are defined - end extendable - in image.modules, an attribute set mapping variant names to NixOS modules.
All of those images can be built via both, their system.build.image attribute and the nixos-rebuild build-image command.
For example, to build an Amazon image from your existing NixOS configuration, run:
$ nixos-rebuild build-image --image-variant amazon
[...]
Done. The disk image can be found in /nix/store/[hash]-nixos-image-amazon-25.05pre-git-x86_64-linux/nixos-image-amazon-25.05pre-git-x86_64-linux.vpc
To get a list of all variants available, run nixos-rebuild build-image without arguments.
The image.modules option can be used to set specific options per image variant, in a similar fashion as specialisations for generic NixOS configurations.
E.g. images for the cloud provider Linode use grub2 as a bootloader by default. If you are using systemd-boot on other platforms and want to disable it for Linode only, you could use the following options:
{
image.modules.linode = {
boot.loader.systemd-boot.enable = lib.mkForce false;
};
}
systemd-repart Table of Contents
You can build disk images in NixOS with the image.repart option provided by
the module image/repart.nix. This module uses systemd-repart to build the
images and exposes it’s entire interface via the repartConfig option.
An example of how to build an image:
{ config, modulesPath, ... }:
{
imports = [ "${modulesPath}/image/repart.nix" ];
image.repart = {
name = "image";
partitions = {
"esp" = {
contents = {
# ...
};
repartConfig = {
Type = "esp";
# ...
};
};
"root" = {
storePaths = [ config.system.build.toplevel ];
repartConfig = {
Type = "root";
Label = "nixos";
# ...
};
};
};
};
}
If you want to rewrite Nix store paths, e.g., to remove the /nix/store prefix
or to nest it below a parent path, you can do that through the
nixStorePrefix option.
You can define a partition that only contains the Nix store and then mount it
under /nix/store. Because the /nix/store part of the paths is already
determined by the mount point, you have to set nixStorePrefix = "/" so
that /nix/store is stripped from the paths before copying them into the image.
{
fileSystems."/nix/store".device = "/dev/disk/by-partlabel/nix-store";
image.repart.partitions = {
"store" = {
storePaths = [ config.system.build.toplevel ];
nixStorePrefix = "/";
repartConfig = {
Type = "linux-generic";
Label = "nix-store";
# ...
};
};
};
}
Alternatively, you can create a Btrfs subvolume /@nix-store containing the
Nix store and mount it on /nix/store:
{
fileSystems."/" = {
device = "/dev/disk/by-partlabel/root";
fsType = "btrfs";
options = [ "subvol=/@" ];
};
fileSystems."/nix/store" = {
device = "/dev/disk/by-partlabel/root";
fsType = "btrfs";
options = [ "subvol=/@nix-store" ];
};
image.repart.partitions = {
"root" = {
storePaths = [ config.system.build.toplevel ];
nixStorePrefix = "/@nix-store";
repartConfig = {
Type = "root";
Label = "root";
Format = "btrfs";
Subvolumes = "/@ /@nix-store";
MakeDirectories = "/@ /@nix-store";
# ...
};
};
};
}
The image/repart.nix module can also be used to build self-contained software
appliances.
The generation based update mechanism of NixOS is not suited for appliances.
Updates of appliances are usually either performed by replacing the entire
image with a new one or by updating partitions via an A/B scheme. See the
Chrome OS update process for an example of how to achieve
this. The appliance image built in the following example does not contain a
configuration.nix and thus you will not be able to call nixos-rebuild from
this system. Furthermore, it uses a Unified Kernel Image.
let
pkgs = import <nixpkgs> { };
efiArch = pkgs.stdenv.hostPlatform.efiArch;
in
(pkgs.nixos [
(
{
config,
lib,
pkgs,
modulesPath,
...
}:
{
imports = [ "${modulesPath}/image/repart.nix" ];
boot.loader.grub.enable = false;
fileSystems."/".device = "/dev/disk/by-label/nixos";
image.repart = {
name = "image";
partitions = {
"esp" = {
contents = {
"/EFI/BOOT/BOOT${lib.toUpper efiArch}.EFI".source =
"${pkgs.systemd}/lib/systemd/boot/efi/systemd-boot${efiArch}.efi";
"/EFI/Linux/${config.system.boot.loader.ukiFile}".source =
"${config.system.build.uki}/${config.system.boot.loader.ukiFile}";
};
repartConfig = {
Type = "esp";
Format = "vfat";
SizeMinBytes = "96M";
};
};
"root" = {
storePaths = [ config.system.build.toplevel ];
repartConfig = {
Type = "root";
Format = "ext4";
Label = "nixos";
Minimize = "guess";
};
};
};
};
}
)
]).image
This chapter describes how to configure various aspects of a NixOS machine through the configuration file /etc/nixos/configuration.nix. As described in Changing the Configuration, changes to this file only take effect after you run nixos-rebuild.
Table of Contents
Table of Contents
The NixOS configuration file /etc/nixos/configuration.nix is actually
a Nix expression, which is the Nix package manager’s purely functional
language for describing how to build packages and configurations. This
means you have all the expressive power of that language at your
disposal, including the ability to abstract over common patterns, which
is very useful when managing complex systems. The syntax and semantics
of the Nix language are fully described in the Nix
manual, but
here we give a short overview of the most important constructs useful in
NixOS configuration files.
The NixOS configuration file generally looks like this:
{ config, pkgs, ... }:
{
# option definitions
}
The first line ({ config, pkgs, ... }:) denotes that this is actually
a function that takes at least the two arguments config and pkgs.
(These are explained later, in chapter Writing NixOS Modules) The
function returns a set of option definitions ({ ... }).
These definitions have the form name = value, where name is the
name of an option and value is its value. For example,
{ config, pkgs, ... }:
{
services.httpd.enable = true;
services.httpd.adminAddr = "[email protected]";
services.httpd.virtualHosts.localhost.documentRoot = "/webroot";
}
defines a configuration with three option definitions that together
enable the Apache HTTP Server with /webroot as the document root.
Sets can be nested, and in fact dots in option names are shorthand for
defining a set containing another set. For instance,
services.httpd.enable defines a set named
services that contains a set named httpd, which in turn contains an
option definition named enable with value true. This means that the
example above can also be written as:
{ config, pkgs, ... }:
{
services = {
httpd = {
enable = true;
adminAddr = "[email protected]";
virtualHosts = {
localhost = {
documentRoot = "/webroot";
};
};
};
};
}
which may be more convenient if you have lots of option definitions that
share the same prefix (such as services.httpd).
NixOS checks your option definitions for correctness. For instance, if
you try to define an option that doesn’t exist (that is, doesn’t have a
corresponding option declaration), nixos-rebuild will give an error
like:
The option `services.httpd.enable' defined in `/etc/nixos/configuration.nix' does not exist.
Likewise, values in option definitions must have a correct type. For
instance, services.httpd.enable must be a Boolean (true or false).
Trying to give it a value of another type, such as a string, will cause
an error:
The option value `services.httpd.enable' in `/etc/nixos/configuration.nix' is not a boolean.
Options have various types of values. The most important are:
Strings are enclosed in double quotes, e.g.
{
networking.hostName = "dexter";
}
Special characters can be escaped by prefixing them with a backslash
(e.g. \").
Multi-line strings can be enclosed in double single quotes, e.g.
{
networking.extraHosts =
''
127.0.0.2 other-localhost
10.0.0.1 server
'';
}
The main difference is that it strips from each line a number of
spaces equal to the minimal indentation of the string as a whole
(disregarding the indentation of empty lines), and that characters
like " and \ are not special (making it more convenient for
including things like shell code). See more info about this in the
Nix manual here.
These can be true or false, e.g.
{
networking.firewall.enable = true;
networking.firewall.allowPing = false;
}
For example,
{
boot.kernel.sysctl."net.ipv4.tcp_keepalive_time" = 60;
}
(Note that here the attribute name net.ipv4.tcp_keepalive_time is
enclosed in quotes to prevent it from being interpreted as a set
named net containing a set named ipv4, and so on. This is
because it’s not a NixOS option but the literal name of a Linux
kernel setting.)
Sets were introduced above. They are name/value pairs enclosed in braces, as in the option definition
{
fileSystems."/boot" =
{ device = "/dev/sda1";
fsType = "ext4";
options = [ "rw" "data=ordered" "relatime" ];
};
}
The important thing to note about lists is that list elements are separated by whitespace, like this:
{
boot.kernelModules = [ "fuse" "kvm-intel" "coretemp" ];
}
List elements can be any other type, e.g. sets:
{
swapDevices = [ { device = "/dev/disk/by-label/swap"; } ];
}
Usually, the packages you need are already part of the Nix Packages
collection, which is a set that can be accessed through the function
argument pkgs. Typical uses:
{
environment.systemPackages =
[ pkgs.thunderbird
pkgs.emacs
];
services.postgresql.package = pkgs.postgresql_14;
}
The latter option definition changes the default PostgreSQL package used by NixOS’s PostgreSQL service to 14.x. For more information on packages, including how to add new ones, see the section called “Adding Custom Packages”.
If you find yourself repeating yourself over and over, it’s time to abstract. Take, for instance, this Apache HTTP Server configuration:
{
services.httpd.virtualHosts = {
"blog.example.org" = {
documentRoot = "/webroot/blog.example.org";
adminAddr = "[email protected]";
forceSSL = true;
enableACME = true;
};
"wiki.example.org" = {
documentRoot = "/webroot/wiki.example.org";
adminAddr = "[email protected]";
forceSSL = true;
enableACME = true;
};
};
}
It defines two virtual hosts with nearly identical configuration; the only difference is the document root directories. To prevent this duplication, we can use a let:
let
commonConfig = {
adminAddr = "[email protected]";
forceSSL = true;
enableACME = true;
};
in
{
services.httpd.virtualHosts = {
"blog.example.org" = (commonConfig // { documentRoot = "/webroot/blog.example.org"; });
"wiki.example.org" = (commonConfig // { documentRoot = "/webroot/wiki.example.org"; });
};
}
The let commonConfig = ... defines a variable named commonConfig. The // operator merges two attribute sets, so the configuration of the second virtual host is the set commonConfig extended with the document root option.
You can write a let wherever an expression is allowed. Thus, you also could have written:
{
services.httpd.virtualHosts =
let
commonConfig = {
# ...
};
in
{
"blog.example.org" = (
commonConfig
// {
# ...
}
);
"wiki.example.org" = (
commonConfig
// {
# ...
}
);
};
}
but not { let commonConfig = ...; in ...; } since attributes (as opposed to attribute values) are not expressions.
Functions provide another method of abstraction. For instance, suppose that we want to generate lots of different virtual hosts, all with identical configuration except for the document root. This can be done as follows:
{
services.httpd.virtualHosts =
let
makeVirtualHost = webroot: {
documentRoot = webroot;
adminAddr = "[email protected]";
forceSSL = true;
enableACME = true;
};
in
{
"example.org" = (makeVirtualHost "/webroot/example.org");
"example.com" = (makeVirtualHost "/webroot/example.com");
"example.gov" = (makeVirtualHost "/webroot/example.gov");
"example.nl" = (makeVirtualHost "/webroot/example.nl");
};
}
Here, makeVirtualHost is a function that takes a single argument webroot and returns the configuration for a virtual host. That function is then called for several names to produce the list of virtual host configurations.
The NixOS configuration mechanism is modular. If your
configuration.nix becomes too big, you can split it into multiple
files. Likewise, if you have multiple NixOS configurations (e.g. for
different computers) with some commonality, you can move the common
configuration into a shared file.
Modules have exactly the same syntax as configuration.nix. In fact,
configuration.nix is itself a module. You can use other modules by
including them from configuration.nix, e.g.:
{ config, pkgs, ... }:
{
imports = [
./vpn.nix
./kde.nix
];
services.httpd.enable = true;
environment.systemPackages = [ pkgs.emacs ];
# ...
}
Here, we include two modules from the same directory, vpn.nix and
kde.nix. The latter might look like this:
{ config, pkgs, ... }:
{
services.xserver.enable = true;
services.displayManager.sddm.enable = true;
services.desktopManager.plasma6.enable = true;
environment.systemPackages = [ pkgs.vim ];
}
Note that both configuration.nix and kde.nix define the option
environment.systemPackages. When multiple modules define an
option, NixOS will try to merge the definitions. In the case of
environment.systemPackages the lists of packages will be
concatenated. The value in configuration.nix is
merged last, so for list-type options, it will appear at the end of the
merged list. If you want it to appear first, you can use mkBefore:
{ boot.kernelModules = mkBefore [ "kvm-intel" ]; }
This causes the kvm-intel kernel module to be loaded before any other
kernel modules.
For other types of options, a merge may not be possible. For instance,
if two modules define services.httpd.adminAddr,
nixos-rebuild will give an error:
The unique option `services.httpd.adminAddr' is defined multiple times, in `/etc/nixos/httpd.nix' and `/etc/nixos/configuration.nix'.
When that happens, it’s possible to force one definition take precedence over the others:
{ services.httpd.adminAddr = pkgs.lib.mkForce "[email protected]"; }
When using multiple modules, you may need to access configuration values
defined in other modules. This is what the config function argument is
for: it contains the complete, merged system configuration. That is,
config is the result of combining the configurations returned by every
module. (If you’re wondering how it’s possible that the (indirect) result
of a function is passed as an input to that same function: that’s
because Nix is a “lazy” language — it only computes values when
they are needed. This works as long as no individual configuration
value depends on itself.)
For example, here is a module that adds some packages to
environment.systemPackages only if
services.xserver.enable is set to true somewhere else:
{ config, pkgs, ... }:
{
environment.systemPackages =
if config.services.xserver.enable then
[
pkgs.firefox
pkgs.thunderbird
]
else
[ ];
}
With multiple modules, it may not be obvious what the final value of a
configuration option is. The command nixos-option allows you to find
out:
$ nixos-option services.xserver.enable
true
$ nixos-option boot.kernelModules
[ "tun" "ipv6" "loop" ... ]
Interactive exploration of the configuration is possible using nix repl, a read-eval-print loop for Nix expressions. A typical use:
$ nix repl '<nixpkgs/nixos>'
nix-repl> config.networking.hostName
"mandark"
nix-repl> map (x: x.hostName) config.services.httpd.virtualHosts
[ "example.org" "example.gov" ]
While abstracting your configuration, you may find it useful to generate modules using code, instead of writing files. The example below would have the same effect as importing a file which sets those options.
{ config, pkgs, ... }:
let
netConfig = hostName: {
networking.hostName = hostName;
networking.useDHCP = false;
};
in
{
imports = [ (netConfig "nixos.localdomain") ];
}
Table of Contents
This section describes how to add additional packages to your system. NixOS has two distinct styles of package management:
Declarative, where you declare what packages you want in your
configuration.nix. Every time you run nixos-rebuild, NixOS will
ensure that you get a consistent set of binaries corresponding to
your specification.
Ad hoc, where you install, upgrade and uninstall packages via the
nix-env command. This style allows mixing packages from different
Nixpkgs versions. It’s the only choice for non-root users.
With declarative package management, you specify which packages you want
on your system by setting the option
environment.systemPackages. For instance, adding the
following line to configuration.nix enables the Mozilla Thunderbird
email application:
{ environment.systemPackages = [ pkgs.thunderbird ]; }
The effect of this specification is that the Thunderbird package from
Nixpkgs will be built or downloaded as part of the system when you run
nixos-rebuild switch.
Some packages require additional global configuration such as D-Bus or
systemd service registration so adding them to
environment.systemPackages might not be sufficient. You are
advised to check the list of options whether a NixOS
module for the package does not exist.
You can get a list of the available packages as follows:
$ nix-env -qaP '*' --description
nixos.firefox firefox-23.0 Mozilla Firefox - the browser, reloaded
...
The first column in the output is the attribute name, such as
nixos.thunderbird.
Note: the nixos prefix tells us that we want to get the package from
the nixos channel and works only in CLI tools. In declarative
configuration, use pkgs prefix (variable).
To “uninstall” a package, remove it from
environment.systemPackages and run nixos-rebuild switch.
The Nixpkgs configuration for a NixOS system is set by the nixpkgs.config option.
{
nixpkgs.config = {
allowUnfree = true;
};
}
This only allows unfree software in the given NixOS configuration.
For users invoking Nix commands such as nix-build, Nixpkgs is configured independently.
See the Nixpkgs manual section on global configuration for details.
Some packages in Nixpkgs have options to enable or disable optional functionality, or change other aspects of the package.
Unfortunately, Nixpkgs currently lacks a way to query available package configuration options.
For example, many packages come with extensions one might add. Examples include:
You can use them like this:
{
environment.systemPackages = with pkgs; [
sl
(pass.withExtensions (
subpkgs: with subpkgs; [
pass-audit
pass-otp
pass-genphrase
]
))
(python3.withPackages (subpkgs: with subpkgs; [ requests ]))
cowsay
];
}
Apart from high-level options, it’s possible to tweak a package in almost arbitrary ways, such as changing or disabling dependencies of a package. For instance, the Emacs package in Nixpkgs by default has a dependency on GTK 2. If you want to build it against GTK 3, you can specify that as follows:
{ environment.systemPackages = [ (pkgs.emacs.override { gtk = pkgs.gtk3; }) ]; }
The function override performs the call to the Nix function that
produces Emacs, with the original arguments amended by the set of
arguments specified by you. So here the function argument gtk gets the
value pkgs.gtk3, causing Emacs to depend on GTK 3. (The parentheses
are necessary because in Nix, function application binds more weakly
than list construction, so without them,