Configuring NixOS for Impermanence
After reading posts from both Graham Christensen and Elis Hirwing about the idea of impermanence in NixOS I decided to try setting it up on my homelab. The basic idea is that we configure the system to use a temporary file system, where everything is wiped after a reboot, unless specified otherwise.
One of the major benefits of this kind of setup is that it forces you to properly declare the configuration, as everything will break after a reboot otherwise.
Initial Setup
For the initial installation of NixOS I followed Elis' walk through (linked above) and configured root using a temporary file system. Once this was complete I added the nix community tool impermanence to /etc/nixos/configuration.nix
to allow for a declarative configuration going forward.
# /etc/nixos/configuration.nix
{ ... }:
let
impermanence = builtins.fetchTarball {
url = "https://github.com/nix-community/impermanence/archive/master.tar.gz";
};
in
{
imports = [
./hardware-configuration.nix # should be present by default
"${impermanence}/nixos.nix"
];
}
Configuring Persistence
With the above complete I was able to configure directories I needed to persist from within /etc/nixos/configuration.nix
.
# /etc/nixos/configuration.nix
{ ... }:
{
environment = {
persistence."/nix/persist" = {
directories = [
"/etc/nixos" # configuration files
"/srv" # service data
"/var/log" # where journald dumps logs
"/var/lib" # system service persistant data
"/data" # where I store local media
];
files = [
"/etc/machine-id" # ensures logs are retained after reboot
"/users/admin" # directory where I store passwordFile for user
];
};
etc = {
# ensures SSH keys can be correctly generated
"ssh/ssh_host_rsa_key".source = "/nix/persist/etc/ssh/ssh_host_rsa_key";
"ssh/ssh_host_rsa_key.pub".source = "/nix/persist/etc/ssh/ssh_host_rsa_key.pub";
"ssh/ssh_host_ed25519_key".source = "/nix/persist/etc/ssh/ssh_host_ed25519_key";
"ssh/ssh_host_ed25519_key.pub".source = "/nix/persist/etc/ssh/ssh_host_ed25519_key.pub";
};
};
}
Initially I ran into issues configuring Tailscale as I would be logged out after each reboot, I found persisting /var/lib
fixed the issue as it ensures the Tailscale state, located at /var/lib/tailscale/tailscale.state
, is always available.
I setup /srv
as the directory I keep data relating to other services I run on the machine, for services which allow me to specify it.
Managing Users
You may have noticed in the configuration above I also persist /users/admin
, this allows me to store a hashed password for the user inside of the directory, which is read from within /etc/nixos/configuration.nix
. The alternative is to either include a password directly, which would then be available for everyone to see in the nix store, or to add a temporary password and change it on each reboot:
# /etc/nixos/configuration.nix
{ ... }:
{}
users = {
mutableUsers = false;
users = {
admin = {
isNormalUser = true;
home = "/home/admin";
# generate with: nix-shell --run 'mkpasswd -m SHA-512 -s' -p mkpasswd
passwordFile = "/nix/persist/users/admin";
extraGroups = [ "wheel" ];
};
};
};