NixOS is a Linux distribution that is configured using a functional language in a declarative way.
Iâve been using it here at Brightbox as my main development machine for several months now and whilst it has some rough edges, it has some compelling features to look at.
It is possible to use it on Brightbox but there is a bit of work involved.
This post is for those who are curious about NixOS and want a brief introduction and for those who already use NixOS but didnât realise how to get it running on Brightbox.
Nix is a package manager for Linux, OS X and other Unix systems. It uses a functional language to create reproducible, isolated versions of packages that do not change once built.
As many of the build inputs as possible are fixed so that the exact same piece of software can be rebuilt given the same parameters. This also allows using prebuilt binary packages from trustworthy sources.
It uses symlinks to perform atomic upgrades and rollbacks in a similar way to Capistrano deployments. The symlinks are managed by Nix and allow you to have multiple profiles, each with a different view of the system and itâs software.
Due to this isolation, you can run multiple versions of libraries, applications or services on one system alongside each other without having to resort to using containers.
Think of it as a system wide chruby
where you can run nix-shell
and be in
Bash with the exact libraries and version of languages you need to develop and
test.
NixOS is a Linux distribution that builds on Nix that allows you to declare what the desired state of the system should be. Unlike something like Puppet or Chef, the system itself can do this.
As well as declaring which packages you want available, one or more config files can specify which services to run, which kernel modules to blacklist, containers to run, disks to mount and some other 3000 documented options.
It also includes the same atomic upgrades and rollbacks that nix does but on a system level. You can rebuild a system and it will causes any altered services to restart and they pick up new version of servers and configs immediately.
When you make a change to the system, it can even automatically create a new GRUB entry for it. So you can switch back to earlier generations in case something went wrong.
Thanks to Rob Vermass and other members of the community, there has been the means to build an image for Brightbox for the last year (since version 15.09).
Using the nix-build
tool NixOS (or any Linux system with Nix) you can build a
QCOW2 image based on a NixOS configuration.
Youâll need access to a Linux machine with Nix installed for this. So this means thereâs a bit of bootstrapping.
Whilst OS X supports Nix, the x86_64-darwin
platform can not build the images
you need to upload.
You can either install Nix on an existing Linux system or create a Cloud Server to use.
You can install Nix following their
installation guide. That should give you
the nix-build
command and a copy of Nixpkgs
that you need.
The command is a bit more complicated than it should be. You have to tell it the following things:
config.system.build.brightboxImage
x86_64-linux
We can set the configuration file a number of ways. To keep things simple weâll
use the NIXOS_CONFIG
environment setting.
Weâll start simple and try to build that as is.
$ export NIXOS_CONFIG=~/.nix-defexpr/channels/nixpkgs/nixos/modules/virtualisation/brightbox-config.nix
$ nix-build ~/.nix-defexpr/channels/nixpkgs/nixos \
-A config.system.build.brightboxImage \
--argstr system x86_64-linux
The build command will create an result/nixos.qcow2
image in the working
directory. This can be uploaded and registered in your accountâs image
library and used to build new servers.
Create a cloud server using your new image. If you donât have IPv6, then map a
Cloud IP so you can access it and you can log in as root
. It should
automatically pick up the SSH keys registered to the account using cloud-init
.
You can now use NixOS as normal.
$ ssh root@public.srv-d3fs2.gb1.brightbox.com
[root@srv-d3fs2:~]# nixos-version
16.09pre88945.5120af0 (Flounder)
[root@srv-fbppf:~]# cat /etc/nixos/configuration.nix
{ config, pkgs, modulesPath, ... }:
{
imports = [ "${modulesPath}/virtualisation/brightbox-image.nix" ];
}
/etc/nixos/configuration.nix
is the file that defines the NixOS system. The
default file inherits the brightbox-image module which in turn inherits various
settings for a headless server running under virtualisation.
After the image is build, there is one more job to do. Nix uses Nixpkgs, which is the collection of definitions for packages and a NixOS system.
At the moment, it is not yet connected to a âchannelâ which is where the latest version of these are downloaded from.
[root@srv-fbppf:~]# nixos-rebuild switch --upgrade
This downloads the latest version of Nixpkgs and switches the system to be using it. It also sets up the environment to allow future rebuilds to find the packages without needing extra command line args.
NixOS has a substantial list of configurable options you can tweak to set up a system.
Be aware however that the online documentation runs close to the latest version so some setting may not be available unless you are using your own checkout of Nixpkgs on the master branch.
So letâs set up a webserver. Update /etc/nixos/configuration.nix
to be:
{ config, pkgs, modulesPath, ... }:
{
imports = [ "${modulesPath}/virtualisation/brightbox-image.nix" ];
networking.firewall.allowedTCPPorts = [ 80 ];
services = {
lighttpd = {
enable = true;
};
};
}
We need something to serve from the server so lets create a file and tell NixOS to switch to the new configuration.
[root@srv-fbppf:~]# mkdir -p /srv/www
[root@srv-fbppf:~]# echo hello >> /srv/www/index.html
[root@srv-fbppf:~]# nixos-rebuild switch
building Nix...
building the system configuration...fyppn6nyr387c6mcrww44mzjd-vconsole.confâ
these derivations will be built:v3s33drxsazwagdqm59ygg3923yzp-vlock.pamâ
/nix/store/y7sdfs7cipqw2pz1f7swanmkfabdnpc1-system-path.drv-unit-systemd-vcon /nix/store/zbqqi20hda0q9mzwvbx1d1r2m04rhm1g-dbus-conf.drv
/nix/store/2grckp2wy4m482s7ls49s86a5vbxmnjw-unit-dbus.service.drv.pamâ
/nix/store/2s2lgv7apxic7yb425syhwkxx3xphi7l-unit-polkit.service.drvunitsâ
/nix/store/9x620l3rkfmhh87w259xnnpf4hvassb5-firewall-start.drvcreensaver.pamâ
/nix/store/2vr12m0jm5w0z5ygpl5f4lkl8ydv4vmv-firewall-reload.drvâ
/nix/store/5r1ami1qd7w9c0lj5b9xdy6ygplls2gh-lighttpd.conf.drvixos-system-unna /nix/store/9dfkzr76m3m7pjn1lf23zmzkjm0aw4id-unit-lighttpd.service.drv
/nix/store/zbxs8557qck12ws3is2m4lvs2lijmfds-unit-firewall.service.drv
/nix/store/sii9s784hgwhg900ik1aly5f6414cxjp-system-units.drvrvice, kmod-stati /nix/store/j4krbskh09svlnxmc3msbg7qjz78kasn-etc.drvork-setup.service, nginx.s /nix/store/xzxp08dv516mvig2hx09bh2y8fpcvsmy-users-groups.json.drvrnald.servic /nix/store/kvqzlki1ys3x6iq1cf0j79pxn0zq5wv8-nixos-system-unnamed-16.09pre89188.f25006b.drvmd-tmpfiles-setup-dev.service, systemd-udev-trigger.service, systethese paths will be fetched (0.22 MiB download, 0.90 MiB unpacked):
/nix/store/hzdykwhy13gj9qs7b54c79c7scmfjfcq-lighttpd-1.4.40ivated by:
building path(s) â/nix/store/y9gpy3a3113zjd8a9g25sn1ydgv8labw-users-groups.jsonâarning: Stopping systemd-journald.service, but it can still be activated by:
fetching path â/nix/store/hzdykwhy13gj9qs7b54c79c7scmfjfcq-lighttpd-1.4.40â...
systemd-journald-dev-log.socket
*** Downloading âhttps://cache.nixos.org/nar/02mfxl8bbmzhj8dra2mk1iah3hdjbsca8gd15iq66dpa1vpwlzr9.nar.xzâ (signed by âcache.nixos.org-1â) to â/nix/store/hzdykwhy13gj9qs7b54c79c7scmfjfcq-lighttpd-1.4.40â...
% Total % Received % Xferd Average Speed Time Time Time Current
Dload Upload Total Spent Left Speedst100 227k 100 227k 0 0 1749k 0 --:--:-- --:--:-- --:--:-- 1767krvice, systemd-update-utmp.service, systemd-user-sessions.service, user@0.servicbuilding path(s) â/nix/store/xi1kmhv7din74vgq418rv6wpwkw93h5r-firewall-startâ
building path(s) â/nix/store/g1i15pbc7vbmrrfxlzfmn9r6i1s9p9c0-lighttpd.confâ
building path(s) â/nix/store/kkpw534nh89j2lsvcfivyad8amp0lcb8-firewall-reloadâ
building path(s) â/nix/store/hlhs4gbfi3xv9gqcvbhya7ja1p8rg1z4-system-pathâ
created 3009 symlinks in user environment1/conf.d/60-nixos-generic-alias.confâ.install-info: warning: no info dir entry in `/nix/store/hlhs4gbfi3xv9gqcvbhya7ja1p8rg1z4-system-path/share/info/time.info'conf.d/99-user.confâ...
building path(s) â/nix/store/1fg4wg50a7mnc762jsyylhxjmx5gfcdr-unit-firewall.serviceâing group ânginxâ
building path(s) â/nix/store/c6fdpwj7arg5wgvsjqvr6xfsskmb9bs6-dbus-confâ
building path(s) â/nix/store/5kjpb33vcwdcpa160n320qk02mfl6mzl-unit-lighttpd.serviceâding the following units: dbus.service, dev-hugepages.mount, dev-mqueue.mobuilding path(s) â/nix/store/2d3kfvbg47p1gh267fs0ja9ik3iqp4in-unit-dbus.serviceâestarting the following units: dhcpcd.service, sshd.service, systemd-logind.sebuilding path(s) â/nix/store/lng22apqwim953gbx5wapfb3n3vcgr94-unit-polkit.serviceârting the following units: audit.service, fetch-ec2-data.service, kmod-statibuilding path(s) â/nix/store/7lhfzxndnddh6p1sj6d5w2mw0ks522g7-system-unitsâ-daebuilding path(s) â/nix/store/rac1l547i4dqyrxg343n357rkgrz8pny-etcâ systemd-modubuilding path(s) â/nix/store/q38ic52y324ypk0lb98sv6n0fii01n9x-nixos-system-unnamed-16.09pre89188.f25006bâe, systemd-udev-trigger.service, systemd-udevd.servicupdating GRUB 2 menu...up.service
activating the configuration...
setting up /etc...
reloading the following units: dbus.service, firewall.service
the following new units were started: lighttpd.service
Now each change in the system has created derivations which are exact instructions in how to create a package or file. It then builds theses packages and versioned file of that part of the configuration. lighttpd itself has already been built so it is downloaded from the trusted NixOS sources.
The new state of the system is prepared and then when the symlinks are setup and switched the services that have been touched are restarted.
You can visit the Cloud IP of the server and you should see âhelloâ or whatever
you put in /srv/www/index.html
.
Wait, we didnât want a web server.
[root@srv-fbppf:~]# nixos-rebuild switch --rollback
switching from generation 3 to 2
updating GRUB 2 menu...
stopping the following units: lighttpd.service
activating the configuration...
setting up /etc...
removing group âlighttpdâ
removing user âlighttpdâ
reloading the following units: dbus.service, firewall.service
This switches back to the 2nd generation of our system. The 1st generation was
the one before we first ran nixos-rebuild switch --update
fresh from our
uploaded image. The 2nd generation had the updates.
Switching back didnât involved any downloads or rebuilding since the Nix store kept the old version of all the files and packages. The rollback was pretty managed by shutting off lighttpd, changing a symlink and restarting.
Try the web page again and the firewall will be blocking you, and there isnât a web server listening anymore anyway.
Now next time we try to rebuild it will try to recreate the system in
/etc/nixos/configuration.nix
which will turn the webserver back on.
However /srv/www/index.html
still exists on the system. So there there is a
mix of the declarative system and still some âimperativeâ parts to be aware of.
NixOS is trying something different in the Linux distribution space and itâs not going to be suitable for everyone.
The documentation and UX of the tools is a bit rough and is being worked on by the community. The Nix language itself has a learning curve as well.
If you have to manage your own development machine then the ability to pull in
software, into an isolated shell and not pollute your normal shell is pleasing
different to a world of homebrew
, RVM and most package managers.
If a system update goes bad, most times a rollback can fix it. Including kernel panics during startup.
Having a local checkout of Nixpkgs allows developers to use tools like
git-bisect
to find where a problem was introduced to a system. You can rebase
you customisations, test them and move on without waiting for a PR to be
reviewed and accepted.
Itâs certainly worth having a look at and if you are already a NixOS user, now you can try running it on Brightbox as well.
You can sign up for Brightbox in just a couple of minutes and use your ÂŁ50 free credit to play with NixOS on an SSD Cloud Server.