A while back I updated the instructions to install NixOS on Linode on the NixOS Wiki. This post adds to this to include encrypted partitions. It's based on those wiki instructions and my previous post on installing NixOS to an encrypted drive.

Some points to keep in mind when running a Linode with an encrypted drive are:

When you reboot you will need to access the Linode console to enter the password to mount the encrypted partition.

Because the server is located remotely it's possible for Linode or a party in a similar position to trap the console input to capture your password. So while encryption prevents a malicious admin from scanning your disks it won't prevent someone located at Linode from rebooting and capturing the password you enter.

I'm sure there are other weaknesses such as keys existing in memory while the Linode is running. Make sure you are ok with the attack points in this setup.

Boot a Linode into Rescue Mode

First step is to create the Linode as usual. I tested with a $20/month Linode 2048. Create two disk images. They should be:

A boot disk that will be unencrypted. I made this 1GB which is way oversized for what it needs to be but makes math easy.

A root disk that will be encrypted. I made this the remainder of my free disk space.

From the Linode manager choose the option to boot into the new Linode in Rescue mode. Make sure the disks are setup as:

/dev/xvda is the boot disk.

is the boot disk. /dev/xvdb is the root disk.

When the recovery image is booted you can ssh into it with the instructions in the Remote Access tab of the Linode manager under Console Access . This will get you to a root prompt on the Linode to perform the rest of the steps.

Encryption Setup

Perform the following commands to setup the disk encryption:

# cryptsetup luksFormat /dev/xvdb # cryptsetup luksOpen /dev/xvdb enc-pv # pvcreate /dev/mapper/enc-pv # vgcreate vg /dev/mapper/enc-pv # lvcreate -L 1G -n swap vg # lvcreate -l 11525 -n root vg

Note that these operate on the /dev/xvdb disk which is the root disk we created earlier. You will be prompted for a passphrase during the luksFormat and luksOpen commands. Make sure you remember this as this is the passphrase needed when rebooting.

The lvcreate lines create the partitions for swap and root partition. The 1G means a one gigabyte swap file. The 11525 is the extent for the remainder of the disk space. I found this number by initally running lvcreate -L 99G -n root vg which is bigger than the 40GB available on the linode. This gave an error message showing the maximum extent to use which was 11525 for me.

Formatting and Mounting

Format the new partitions with:

# mkfs.ext4 -L boot /dev/xvda # mkfs.ext4 -O dir_index -j -L root /dev/vg/root # mkswap -L swap /dev/vg/swap # swapon /dev/vg/swap

To install NixOS we need to mount the partitions under /mnt :

# mount /dev/vg/root /mnt # mkdir /mnt/boot # mount /dev/xvda /mnt/boot

Installing NixOS

The installation is relatively simple. First install the Nix package manager:

# bash <(curl https://nixos.org/nix/install) # . /root/.nix-profile/etc/profile.d/nix.sh

Set the channel to be NixOS:

# nix-channel --remove nixpkgs # nix-channel --add http://nixos.org/channels/nixos-14.04 nixos # nix-channel --update

Create a default configuration file for some NixOS packages we will need for the install later:

# cat <<EOF > configuration.nix { fileSystems."/" = {}; boot.loader.grub.enable = false; } EOF

Install the NixOS installation software:

# export NIX_PATH=nixpkgs=/root/.nix-defexpr/channels/nixos:nixos=/root/.nix-defexpr/channels/nixos/nixos # export NIXOS_CONFIG=/root/configuration.nix # nix-env -i -A config.system.build.nixos-install \ -A config.system.build.nixos-option \ -A config.system.build.nixos-generate-config \ -f "<nixos>"

Generate a default configuration file for the bootable system:

# nixos-generate-config --root /mnt

This creates a /mnt/etc/nixos/configuration.nix file which should be edited to install the software you want. It also requires some changes for Grub and the disk encryption. Replace the existing section related to Grub 2 in this file with:

# Use the GRUB 1 boot loader. boot.loader.grub = { enable = true; version = 1; extraPerEntryConfig = "root (hd0)"; device = "nodev"; };

For the encryption support add:

boot.initrd.luks.devices = [ { name = "root"; device = "/dev/xvdb"; preLVM = true; } ];

To enable OpenSSH access to the Linode add:

services.openssh.enable = true;

Now run the install:

# nixos-install

This will take some time to download and install things.

Post install

Once nixos-install completes the following commands will need to be run to fixup Grub 1 usage on Linode. This must be done before rebooting:

# mkdir -p /mnt/boot/boot/grub # cd /mnt/boot/boot/grub # ln -sv ../../grub/menu.lst /mnt/boot/boot/grub

First boot

Create a new Configuration Profile in the Linode Manager for the Linode. Set the kernel to pv-grub-x86_64 . Set the disks as they were setup in the Rescue boot. Everything else can be left at the default.

Boot the new Configuration. Now you will need to ssh back into the Linode console so you can enter your passphrase. This will continue the booting process. Login as root . There is no initial password. Set one:

# passwd

By default you won't be able to ssh as root so you should set up a normal user:

# useadd -m myuser # passwd myuser # usermod -a -G wheel myuser

The latter command lets you use sudo as that user. You should now be able to ssh into the Linode with the newly created user.

Customization

These steps install the stable version of NixOS. This does not receive new packages, only updates to existing ones. I like to live on the bleeding edge so I use nixos-unstable . You can switch to this by running the following as root :

# nix-channel --add http://nixos.org/channels/nixos-unstable nixos # nixos-rebuild switch --upgrade

If you prefer vim to nano as an editor, add the following to /etc/nixos/configuration.nix :

environment.systemPackages = with pkgs; [ vim ]; environment.variables.EDITOR = pkgs.lib.mkOverride 0 "vim";

If you need non-free packages, add: