Running NixOS in a Linux Container
init
and the init
path lxc
expects across multiple
NixOS versions. See this
thread
for a possible fix.
NixOS
is seen as the holy grail of
[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
LXC
or LXD
setup with networking.
LXC
). The NixOS
Hydra
builds
(aarch64
)
provide container images but they don’t seem to
rootfs
(file system).
Bootstrapping
The best way to get a NixOS
root file system is to bootstrap using
nixos-generate
.
This will require a live NixOS
environment or
installing nix
onto your Linux
distribution. Download the latest
NixOS
minimal image and boot
into the live environment using preferred means.
nix-shell
or
flake
configuration.
nix
, bootstrap a Linux
container’s rootfs
using nixos-generate
.
shell
nixos-generate --format lxc
shell
nixos-generate --format lxc --configuration configuration.nix
If the command
nixos-generate
is not found — install nixos-generators
using
nix-env
or
nix-shell
.
shell
nix-env -iA nixos.nixos-generators
shell
nix-shell --packages nixos-generators
Once completed, this command will print a hashed path like
/nix/store/3ipfpzhk4dllwhcnldsbfldi1favyxsm-tarball/nix-support/hydra-build-products
.
This file contains the location of the rootfs
archive.
shell
$ 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
.
shell
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
Debian
and Arch Linux.
NixOS
at /var/lib/lxc/nixos/config
. The entry point is /sbin/init
.
ini
# Distribution configuration
lxc.arch = linux64
lxc.include = /usr/share/lxc/config/common.conf
# Container specific configuration
lxc.uts.name = nixos
lxc.rootfs.path = dir:/var/lib/lxc/nixos/rootfs
# 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
# NixOS configuration
lxc.init.cmd = /sbin/init
Setup and Run NixOS
Now
NixOS
container setup
lxc-attach
.
shell
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
.
nix
{ config, pkgs, ... }:
{
imports = [ ];
boot.isContainer = true;
}
Now run a
iptables
filters for IPv6
mean you either run an old
kernel or you need to sudo
modprobe ip6table_filter
shell
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
great because when you make something it just works — all the time.