January 19, 2015

Deploying NixOS on a 256 RAM VPS

I’d like to share with my experiences of migration from Debian 7.7 to NixOS 14.12.

I use 256mb RAM KVM-based VPS from RamNode

Before I opened a ticket ID: 399523 to the RamNode support asking to add a NixOS installation ISO for mounting, I needed to use available SystemRescCd image.

Boot: System Rescue (sysresccd), default boot options

Use VNC to get control over the termainal

It’s more comfortable to install the system via ssh, not VNC. So we’ll setup root password and connect to our running SystemRescCd VPS

sysresccd ~ # passwd root

Okay, we are in and now we can start our process of NixOS installation. First we’ll prepare the environment and the storage. VPS gives us 30 GB HDD available at /dev/sda

my-laptop $ ssh root@ipv4-of-your-vps
sysresccd ~ # bash
sysresccd ~ # export LANG=POSIX
sysresccd ~ # export LC_ALL=POSIX

sysresccd ~ # fdisk /dev/sda

I’ve created 512MB swap partition /dev/sda1. However, based on my recent experience, it’s better to at least create it 1GB big as nix-env -i may require more than 700 MB of RAM when it builds a package.

And the rest of a disk space is for /dev/sda2. Usually I use LVM, but this time I didn’t want to bother, but rather have NixOS up & running ASAP :-)

sysresccd ~ # fdisk -l /dev/sda

Disk /dev/sda: 32.2 GB, 32212254720 bytes
255 heads, 63 sectors/track, 3916 cylinders, total 62914560 sectors
Units = sectors of 1 * 512 = 512 bytes
Sector size (logical/physical): 512 bytes / 512 bytes
I/O size (minimum/optimal): 512 bytes / 512 bytes
Disk identifier: 0xa3f12756

   Device Boot      Start         End      Blocks   Id  System
/dev/sda1            2048     1050623      524288   82  Linux swap / Solaris
/dev/sda2         1050624    62914559    30931968   83  Linux

It says that for installation minimum required RAM space should be at least 768MB. Setting up a Linux swap area at /dev/sda1 and activating it.

sysresccd ~ # mkswap /dev/sda1
sysresccd ~ # swapon /dev/sda1

Creating EXT4 FS over /dev/sda2 with the nixos label and mounting it

sysresccd ~ # mkfs.ext4 -j -L nixos /dev/sda2
sysresccd ~ # mount LABEL=nixos /mnt

To install NixOS from another running Linux, we will need to prepare the Nix environment. SystemRescCd doesn’t have any large enough partition (max ~120mb), so I mount tmpfs to /var/empty directory which gives me a pseudo-fs with 256mb space.

sysresccd ~ # mount -t tmpfs -o size=256M tmpfs /var/empty

Create a user/group which we will use for NixOS installation/build.

sysresccd ~ # groupadd -r -g 30000 nixbld
sysresccd ~ # useradd -c "Nix build user 1" -u 30001 -d /var/empty -g nixbld -G nixbld -M -N -r -s "$(which nologin)" nixbld1
sysresccd ~ # usermod -s "$(which bash)" nixbld1
sysresccd ~ # mkdir -m 0755 /mnt/nixtmp && chown nixbld1:nixbld /mnt/nixtmp
sysresccd ~ # ln -sv /mnt/nixtmp /nix
`/nix' -> `/mnt/nixtmp'

Switch to the nixbld1 user and install the Nix environment.

sysresccd ~ # su - nixbld1
nixbld1@sysresccd ~ $ export LANG=POSIX
nixbld1@sysresccd ~ $ export LC_ALL=POSIX
nixbld1@sysresccd ~ $ export NIX_IGNORE_SYMLINK_STORE=1
nixbld1@sysresccd ~ $ bash <(curl https://nixos.org/nix/install)

nixbld1@sysresccd ~ $ . /var/empty/.nix-profile/etc/profile.d/nix.sh
nixbld1@sysresccd ~ $ nix-channel --remove nixpkgs
nixbld1@sysresccd ~ $ nix-channel --add http://nixos.org/channels/nixos-14.12 nixos
nixbld1@sysresccd ~ $ nix-channel --update

nixbld1@sysresccd ~ $ cat <<EOF > configuration.nix
{ fileSystems."/" = {};
  boot.loader.grub.enable = false;
}
EOF

nixbld1@sysresccd ~ $ export NIX_PATH=nixpkgs=/var/empty/.nix-defexpr/channels/nixos:nixos=/var/empty/.nix-defexpr/channels/nixos/nixos
nixbld1@sysresccd ~ $ export NIXOS_CONFIG=/var/empty/configuration.nix
nixbld1@sysresccd ~ $ nix-env -i -A config.system.build.nixos-install -A config.system.build.nixos-option -A config.system.build.nixos-generate-config -f "<nixos>"

nixbld1@sysresccd ~ $ exit
sysresccd ~ # . /var/empty/.nix-profile/etc/profile.d/nix.sh
sysresccd ~ # nixos-generate-config --root /mnt

We are almost done! Time to configure your NixOS configuration file. Based on how you will set it, the system you will get.

sysresccd ~ # nano -w /mnt/etc/nixos/configuration.nix

Usually it is enough to set there only the following parameters

  boot.loader.grub.device = "/dev/sda";
  networking.hostName = "mynixos";

  services.openssh.enable = true;

  users.extraUsers.user1 = {
    isNormalUser = true;
    uid = 1000;
    home = "/home/user1";
    extraGroups = [ "wheel" ];
  };

Finally, setup the NixOS!

sysresccd ~ # unset NIXOS_CONFIG
sysresccd ~ # export NIX_PATH=nixpkgs=/var/empty/.nix-defexpr/channels/nixos:nixos=/var/empty/.nix-defexpr/channels/nixos/nixos
sysresccd ~ # nixos-install

At this point we are almost done. If you want to log-in to your NixOS, do not forget to set the password for your user and root if you would like.

sysresccd ~ # ls -latrh /nix/store/*/bin/bash
-rwxr-xr-x 1 nixbld1 nixbld 801K Jan  1  1970 /nix/store/r5sxfcwq9324xvcd1z312kb9kkddqvld-bash-4.3-p30/bin/bash

sysresccd ~ # nixos-install --chroot /nix/store/r5sxfcwq9324xvcd1z312kb9kkddqvld-bash-4.3-p30/bin/bash
(chroot) passwd root
(chroot) passwd user1
(chroot) exit

sysresccd ~ # usermod -s "$(which nologin)" nixbld1
sysresccd ~ # rm /nix
sysresccd ~ # rm -rf /mnt/nixtmp
sysresccd ~ # umount /mnt
sysresccd ~ # swapoff /dev/sda1
sysresccd ~ # sysctl -w vm.drop_caches=3
sysresccd ~ # sync
sysresccd ~ # shutdown -r now

Once you boot your NixOS, don’t forget to check the journal for errors, warnings, etc.. and update the system.

my-laptop ~ $ ssh user1@my-vps
[user1@mynixos:~]$ sudo su -

[root@mynixos:~]# journalctl -b -p crit
[root@mynixos:~]# journalctl -b -p warning

[root@mynixos:~]# nix-channel --update
[root@mynixos:~]# nixos-rebuild switch --upgrade

[root@mynixos:~]# nix-env -u '*'

For the rest, here is the NixOS Manual ;-)

Good luck & Have fun!