2014-10-22
Installing NixOS on Linode with Encrypted Partitions
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./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:
nixpkgs.config.allowUnfree = true;