Use proper impermanence in LXC

This commit is contained in:
2026-09-29 16:41:23 +00:00
parent 66e24bc1ed
commit 32062d18ed
3 changed files with 107 additions and 57 deletions
Generated
+68 -11
View File
@@ -113,11 +113,11 @@
"systems": "systems"
},
"locked": {
"lastModified": 1788380457,
"narHash": "sha256-U/nnAFAoT5qZz65hUTxQnhfhTyNcsIKsO16aU5S569w=",
"lastModified": 1790698990,
"narHash": "sha256-3O+rVesesqOhcqbRbBsCKN5Nf+mrQCsF6pIsm7MYORs=",
"ref": "refs/heads/main",
"rev": "d14e934cb708f3c7fe9f84ad0d22f904e7b2da24",
"revCount": 51,
"rev": "23b03a94448be4392b747436b9dc675204dd9f13",
"revCount": 56,
"type": "git",
"url": "https://github.com/futureware-tech/nix.git"
},
@@ -135,11 +135,11 @@
]
},
"locked": {
"lastModified": 1787424939,
"narHash": "sha256-O2tBn84NNuHrnqNVxx/XqsXwfYvS1YwBh+7CBnbCYsk=",
"lastModified": 1790500375,
"narHash": "sha256-XN3sDtn8TU9hAc9xqZ+SqRB/HHm2wjxM6aSWYLJU+oo=",
"owner": "cachix",
"repo": "git-hooks.nix",
"rev": "809414f0cdadf82cf11b06c2b29ba9b3168b3297",
"rev": "a0e4241b51206fbcbf52fd322eb5f0cd80f153c4",
"type": "github"
},
"original": {
@@ -210,6 +210,46 @@
"type": "github"
}
},
"home-manager_2": {
"inputs": {
"nixpkgs": [
"impermanence",
"nixpkgs"
]
},
"locked": {
"lastModified": 1768598210,
"narHash": "sha256-kkgA32s/f4jaa4UG+2f8C225Qvclxnqs76mf8zvTVPg=",
"owner": "nix-community",
"repo": "home-manager",
"rev": "c47b2cc64a629f8e075de52e4742de688f930dc6",
"type": "github"
},
"original": {
"owner": "nix-community",
"repo": "home-manager",
"type": "github"
}
},
"impermanence": {
"inputs": {
"home-manager": "home-manager_2",
"nixpkgs": "nixpkgs"
},
"locked": {
"lastModified": 1769548169,
"narHash": "sha256-03+JxvzmfwRu+5JafM0DLbxgHttOQZkUtDWBmeUkN8Y=",
"owner": "nix-community",
"repo": "impermanence",
"rev": "7b1d382faf603b6d264f58627330f9faa5cba149",
"type": "github"
},
"original": {
"owner": "nix-community",
"repo": "impermanence",
"type": "github"
}
},
"jail-nix": {
"locked": {
"lastModified": 1783532714,
@@ -245,11 +285,11 @@
},
"nixpkgs": {
"locked": {
"lastModified": 1788179007,
"narHash": "sha256-hn1oU2rue2SYK8dAr8+WNZWtbsz1S2W5mnHlSEuh3bo=",
"lastModified": 1768564909,
"narHash": "sha256-Kell/SpJYVkHWMvnhqJz/8DqQg2b6PguxVWOuadbHCc=",
"owner": "nixos",
"repo": "nixpkgs",
"rev": "34ab99075ac4f7e40cf037eef32cb1c360bb85e9",
"rev": "e4bae1bd10c9c57b2cf517953ab70060a828ee6f",
"type": "github"
},
"original": {
@@ -290,6 +330,22 @@
"type": "github"
}
},
"nixpkgs_2": {
"locked": {
"lastModified": 1788179007,
"narHash": "sha256-hn1oU2rue2SYK8dAr8+WNZWtbsz1S2W5mnHlSEuh3bo=",
"owner": "nixos",
"repo": "nixpkgs",
"rev": "34ab99075ac4f7e40cf037eef32cb1c360bb85e9",
"type": "github"
},
"original": {
"owner": "nixos",
"ref": "nixos-unstable",
"repo": "nixpkgs",
"type": "github"
}
},
"root": {
"inputs": {
"crush-src": "crush-src",
@@ -298,9 +354,10 @@
"git-hooks": "git-hooks_2",
"home-manager": "home-manager",
"home-manager-mars": "home-manager-mars",
"impermanence": "impermanence",
"jail-nix": "jail-nix",
"nix-homebrew": "nix-homebrew",
"nixpkgs": "nixpkgs",
"nixpkgs": "nixpkgs_2",
"nixpkgs-mars": "nixpkgs-mars",
"systems": "systems_2",
"vscode-server": "vscode-server"
+6
View File
@@ -23,6 +23,7 @@
inputs.nixpkgs.follows = "nixpkgs-mars";
};
nix-homebrew.url = "github:zhaofengli/nix-homebrew";
impermanence.url = "github:nix-community/impermanence";
git-hooks = {
url = "github:cachix/git-hooks.nix";
inputs.nixpkgs.follows = "nixpkgs";
@@ -142,6 +143,10 @@
system = "x86_64-linux";
specialArgs = {
primaryUser = homeManagerUser;
# /home is the only data-storing mountpoint besides /nix.
persistenceCommon = "/home/persistent";
inherit (inputs) jail-nix;
};
modules = [
@@ -149,6 +154,7 @@
self.nixosModules.linux-headless
self.nixosModules.linux-lxc
self.nixosModules.jailed-agy
inputs.impermanence.nixosModules.impermanence
inputs.fw_nix.nixosModules.nix-gc
inputs.fw_nix.nixosModules.nix-settings
inputs.fw_nix.nixosModules.tools
+33 -46
View File
@@ -2,6 +2,7 @@
modulesPath,
pkgs,
lib,
persistenceCommon,
...
}:
{
@@ -11,59 +12,45 @@
# Disable legacy channel behavior that lxc-container brings in via installer/cd-dvd/channel.nix.
system.installer.channel.enable = false;
# Impermanence setup:
# 1. There's no initrd/stage 1 in LXC container; /sbin/init is invoked after
# LXC finishes setting up special and user-configured filesystems. Any
# options in boot.initrd, as well as neededForBoot fileSystems won't be
# respected.
# 2. Non-boot fileSystems (aka systemd) mount too late for systemd or nixos
# persistence to be instantiated, so we have to create this script below.
# 3. The expectation from host is to mount /home and /nix. Root filesystem
# will also be a disk, as that's Incus requirement; the host should clean
# it up periodically using: "incus rebuild --empty <vm>".
# 4. Since rootfs will be empty after rebuild, you have to point LXC at the
# current init (instead of /sbin/init), by adding to the "config:" section
# in "incus config edit <vm>":
# raw.lxc: lxc.init.cmd = /nix/var/nix/profiles/system/init
system.activationScripts.persistence = {
environment.persistence.${persistenceCommon} = {
directories = [
"/var/lib/systemd"
"/var/lib/nixos"
"/var/lib/docker"
];
files = [
"/etc/machine-id"
];
};
systemd.tmpfiles.rules = [
"d ${persistenceCommon}/etc/ssh 0755 root root -"
];
services.openssh.hostKeys = [
{
path = "${persistenceCommon}/etc/ssh/ssh_host_ed25519_key";
type = "ed25519";
}
];
# rootfs on LXC is also a persistent mountpoint (requirement from Incus), so
# the host should periodically clean it up using: incus rebuild --empty <vm>.
#
# Since rootfs is empty after container rebuild, for the first boot you have
# to point LXC at the current init (instead of /sbin/init), by adding to the
# "config:" section in "incus config edit <vm>":
# raw.lxc: lxc.init.cmd = /nix/var/nix/profiles/system/init
#
# The bootloader installer will later try to symlink it into /sbin/init (which
# is what the next script prepares for), but that will be erased on the next
# container rebuild anyway.
system.activationScripts.bootloader-patch = {
deps = [ "specialfs" ];
text = ''
persist() {
local item="$1"
local constructor="''${item%%:*}"
local target="''${item#*:}"
mkdir -p "$(dirname "$target")"
$constructor "$target"
if ! mountpoint -q "$target"; then
local source="/home/persistent/$target"
mkdir -p "$(dirname "$source")"
$constructor "$source"
mount --bind "$source" "$target"
fi
}
for item in \
"mkdir -p:/var/lib/nixos" \
"mkdir -p:/var/lib/systemd" \
"mkdir -p:/var/lib/docker" \
"touch:/etc/machine-id" \
"touch:/etc/ssh/ssh_host_ed25519_key" \
; do
persist "$item"
done
chmod 0600 /etc/ssh/ssh_host_ed25519_key
# lxc-container.nix installBootloader/installInitScript will attempt to
# symlink /sbin/init, so we have to create the parent directory.
mkdir -p /sbin
'';
};
system.activationScripts.users.deps = [ "persistence" ];
system.activationScripts.users.deps = [ "bootloder-patch" ];
# This is supposed to persist machine-id, but fails.
systemd.services.systemd-machine-id-commit.enable = false;