A guest placed on a VLAN runs its own networkd, which default-enables
systemd-resolved. That conflicts with the nested-container default of
inheriting the host's resolv.conf, so its toplevel failed to build; keep the
guest's own resolver with networking.useHostResolvConf = false.
The same guest's container enslaves its veth to the VLAN bridge at start,
but the container backend orders the unit only after the network is up, not
after that specific bridge exists — a race the veth enslavement could lose.
Order container@<name> after the br-vlan<id> device so the bridge is there
first.
Both were surfaced by a VM integration test that was explored and then
dropped as not worth its regression cost; the task file records the call.
Add a `nesting` placement field to the Host-side guest interface, a bool
off by default. On, it grants the guest's container the prerequisites its
interior needs to run Podman and other OCI containers: the `CAP_NET_ADMIN`
capability an OCI runtime uses to build its bridges and firewall rules,
and the `/dev/net/tun` and `/dev/fuse` device nodes it reaches for to
network those containers and back their overlay storage. Off, both the
capability and device lists are empty, so a non-nesting guest is untouched.
cgroup delegation, the other nested prerequisite, the NixOS container
backend already grants every container unconditionally, so the Skeleton
records it with an absence pointer rather than re-emitting it.
Add a nesting-sample guest whose interior defines an `oci-containers`
workload on Podman, and enable it on neogaia with `nesting` on, so the
path builds end to end through the Host's `nix flake check` — which pulls
in podman and the generated container unit for the nested system.
Give the Host-side placement a `limits` field — `memory`, `cpu`, and
`tasksMax` — that caps the guest's `container@<name>.service` unit via
`MemoryMax`, `CPUQuota`, and `TasksMax`, uncapped by default so an unset
limit contributes no key and systemd keeps its default.
Add an `autoStart` placement option, on by default, driving the
container's boot-start so a Host can define a guest without starting it
at boot.
Give neogaia's skeleton guest modest demonstrative caps.
Add a `secrets` placement option to the guest builder: a list of secret
names. The host declares each as one of its own sops secrets, so the host
is the sole decryptor from the sops files it already holds, and the
decrypted file is bind-mounted into the guest read-only at the same
`/run/secrets/<name>` path it occupies on a host. A service inside the
guest reads its credentials at a predictable location while the guest
carries no age key and decrypts nothing itself.
Ownership needs no new code: the container already runs in the host's uid
and gid space one to one, so the decrypted file's host owner is its owner
inside the guest.
Assert that no in-guest path is claimed by both a mount and a secret, so
the attribute-set merge fails loudly rather than resolving a collision
silently in the secret's favour.
Add a `mounts` placement option to the guest builder: a Host maps guest
interior paths to host paths, each read-write by default or read-only per
mount, realized as the nested container's bind mounts. A guest sees exactly the
data it should, at any granularity from a single folder to a whole pool.
Pin the container to the host's uid and gid space with `privateUsers = "no"`,
so a guest process writing as the shared storage group lands on a bind-mounted
pool as that same group without permission juggling.
A guest sets `vlan` to attach to its host's `br-vlan<id>` bridge, `mac`
to reuse an existing address (else a stable one is derived from its
namespace path and read back via `nix eval`), and `address` for a static
IP (else DHCP). The MAC and address are pinned inside the guest by its
own networkd, the only stable MAC pin for a nested container. A guest
naming a VLAN its host has not declared fails the build with an
actionable message.
The `br-vlan<id>` naming moves into a shared `bridgeName` in the lib, so
the bridge a guest attaches to and the bridge the host emits have one
source.
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.
Add Stylix as a flake input and a desktop theming module that resolves a
single Nord base16 scheme across the graphical surface: GTK, Qt, cursor,
and the system monospace font, plus a static Nord wallpaper drawn as a
Polar Night gradient.
Scope the theming to the graphical layer alone. The Stylix targets for
fish (at both system and home-manager level), tmux, and nixvim stay off
so the terminal tools keep their hand-written themes.
Each held one default.nix, so the directory added a level to descend without
grouping anything. They are now lib.nix and system.nix beside flake.nix, which
reads as the flake's own scaffolding.
The shared base config's reference to the shared secrets file was relative to
the directory it sat in, so it moves with the file.
Verified to build the same system toplevel as before the move.