Running NixOS in a Linux Container

NixOS Home Page
NixOS Home Page

NixOS is seen as the holy grail of My favorite configuration stack is Ansible + Shell + Alpine management and system administration. It’s what many call a purely functional distribution [pdf]. The state is declarative — entire systems, deployment artifacts, or services can be built from a single file.

Let’s try out NixOS in a Linux Container This is assuming you have a working LXC or LXD setup with networking. NixOS’ Hydra builds provide container images but they don’t seem to Symlinking issues were encountered when extracting the rootfs. for this use case.

Bootstrapping

The best way to get a NixOS root file system is to bootstrap using nixos-generate. This will require a live NixOS environment. Download the latest NixOS minimal image and boot into the live environment using preferred means.

Once inside the live environment, bootstrap a Linux container’s rootfs using nixos-generate.

nixos-generate -f lxc

Once completed, this command will print a path resembling /nix/store/3ipfpzhk4dllwhcnldsbfldi1favyxsm-tarball/nix-support/hydra-build-products. This file contains the location of the rootfs archive.

$ cat /nix/store/3ipfpzhk4dllwhcnldsbfldi1favyxsm-tarball/nix-support/hydra-build-products
file system-tarball /nix/store/3ipfpzhk4dllwhcnldsbfldi1favyxsm-tarball/tarball/nixos-system-x86_64-linux.tar.xz

Save the generated archive nixos-system-x86_64-linux.tar.xz and exit the live environment.

Setup the Linux Container

Now that we have a clean rootfs archive. Create an empty linux container and rootfs directory. Extract nixos-system-x86_64-linux.tar.xz to rootfs.

lxc-create -n nixos -t none
cd /var/lib/lxc/nixos
mkdir rootfs
tar -xvf nixos-system-x86_64-linux.tar.xz -C rootfs/

Let’s massage our This has been tested on Debian and Arch Linux. for NixOS at /var/lib/lxc/nixos/config. Our entry point is /sbin/init and we must mount /proc to run nixos-rebuild.

# Distribution configuration
lxc.include = /usr/share/lxc/config/common.conf
lxc.arch = linux64

# Container specific configuration
lxc.rootfs.path = dir:/var/lib/lxc/nixos/rootfs
lxc.uts.name = nixos

# Network configuration
lxc.net.0.type = veth
lxc.net.0.link = lxcbr0
lxc.net.0.flags = up
lxc.net.0.hwaddr = 00:16:3e:01:77:76
lxc.apparmor.profile = generated
lxc.apparmor.allow_nesting = 1

# NixOS configuration
lxc.init.cmd = /sbin/init
lxc.mount.entry = proc mnt/proc proc create=dir 0 0

Setup and Run NixOS

Now NixOS Container Setup NixOS Container Setup the container and enter the shell using lxc-attach.

lxc-start -n nixos
lxc-attach -n nixos

The default /etc/nixos/configuration.nix is empty. Tell NixOS that we are a container by adding boot.isContainer = true.

{ config, pkgs, ... }:

{
  imports = [  ];
  boot.isContainer = true;
}

Now run a Firewall errors about iptables IPv6 filters mean you either run an old kernel or you need to sudo modprobe ip6table_filter of the system. The upgrade flag is necessary on the first rebuild to download the channels.

 nixos-rebuild switch --upgrade

We now have a base NixOS system in a Linux container. You can build reproducible desktops, servers, deployment artifacts — anything, using your own configuration.nix and consulting the NixOS options index. This approach is so good because when you make something it just works — all the time.

Updated 16 January 2020