Files
dotfiles/system.nix
alexion e7d7eb14e1 feat: introduce guests as nested-container definitions
Add a third auto-loaded kind beside the host and the module: the guest, a
reusable definition under guests/ that a host enables like a module and that
realizes its interior as a systemd-nspawn nested container.

Split the shared base config so a guest can stand on it.
base.nix now holds the substrate both bases share — the primary user,
home-manager, and the unstable/stable overlays.
system.nix keeps the host-only machinery, and a new guest.nix is the slim
guest-base: it imports the full modules tree, pins the interior release, and
auto-enables the toolkit bundle and SSH so any guest is workable on sight.

Give modules.ssh a guest flavor.
A host restores its host keys from secrets as before, while a guest sets
hostKeys.restore = false, names no sops files, and self-generates a host key,
so it holds no age key of its own.

The lib grows a guest helper that declares the guests.<path> namespace with an
enable and a backend field.
Only the container backend is built; microvm is a reserved value that trips a
clear build-time assertion rather than silently building nothing.

A sample guest exercises the whole path, and neogaia enables it, so the guest
interior builds through the existing nix flake check seam.
2026-07-25 13:19:07 -04:00

76 lines
2.8 KiB
Nix

{
config,
lib,
pkgs,
...
}:
# The host base: the host-only machinery a physical machine needs on top of the
# shared base — bootloader, secret decryption, and the maintenance timers.
let
user = config.user;
passwordSecret = "${user.name}-password";
in
{
imports = [ ./base.nix ];
# chaotic's binary cache, so the CachyOS kernel is fetched rather than compiled.
# The `extra-` prefix keeps cache.nixos.org alongside it.
nix.settings.extra-substituters = [ "https://nyx-cache.chaotic.cx/" ];
nix.settings.extra-trusted-public-keys = [
"nyx-cache.chaotic.cx:dJxTrgMC3V3cFfyIiBQDQorG6k1LsqurH/srpMSq7qk="
];
# A month of generations is kept, because on a rolling channel with a
# third-party kernel an old generation is a known-good system to boot when
# an update breaks something.
nix.gc.automatic = true;
nix.gc.dates = "Mon 03:15";
nix.gc.options = "--delete-older-than 30d";
# Deduplication runs on a timer, off the rebuild path, so it never adds
# latency to a `nixos-rebuild switch`.
# It falls on a different day from collection, so the two never contend.
nix.optimise.automatic = true;
nix.optimise.dates = [ "Thu 03:45" ];
# The EFI system partition holds a kernel and an initrd per entry at roughly
# 70 MiB apiece, and is fixed in size.
# An exhausted one fails at bootloader installation, after the build has
# already succeeded.
boot.loader.systemd-boot.configurationLimit = 15;
environment.systemPackages = [ pkgs.git ];
# Caps Lock is a second Escape.
# Shift+Caps Lock still toggles Caps Lock.
services.xserver.xkb.layout = "us";
services.xserver.xkb.options = "caps:escape_shifted_capslock";
# Compile the console keymap from the layout above, so the remap holds on a
# bare TTY and not only under a graphical session.
console.useXkbConfig = true;
# Decryption machinery every host depends on.
# The identity sits on the encrypted root, which is mounted early enough to
# satisfy the secret below.
# Clearing both `sshKeyPaths` defaults keeps the SSH host keys out of the
# decryption path.
sops.defaultSopsFile = ./secrets/shared.yaml;
sops.age.keyFile = "/var/lib/sops-nix/key.txt";
sops.age.sshKeyPaths = [ ];
sops.gnupg.sshKeyPaths = [ ];
# A password set by hand on a running machine otherwise takes precedence.
# That leaves the declared `hashedPasswordFile` below silently inert.
# Root has no declared password and is therefore locked.
# `sudo` from the wheel group is the way in.
users.mutableUsers = false;
# Decrypted in an earlier activation stage than ordinary secrets.
# That is early enough to precede the account that reads it.
sops.secrets.${passwordSecret}.neededForUsers = true;
users.users.${user.name}.hashedPasswordFile = config.sops.secrets.${passwordSecret}.path;
}