refactor: move host configs under hosts/{jupiter,vps}

- git-mv jupiter/ vps/ into hosts/; fix ../ -> ../../ for common/services/secrets
- flake.nix + deploy point at hosts/<config>/
- README structure updated
- verified: jupiter/vps/vbox all eval
This commit is contained in:
erik
2026-07-13 19:34:27 +02:00
parent fb782cb9fe
commit b6c393ff98
12 changed files with 47 additions and 38 deletions
+19 -10
View File
@@ -5,16 +5,25 @@ Flake-based NixOS config. Host: `jupiter` (ZimaBlade, NAS + services).
## Structure
```
flake.nix # inputs (nixpkgs, disko) + nixosConfigurations
jupiter/configuration.nix # real host: imports + bootloader + data mount
jupiter/disk-config.nix # disko: OS-disk partitions + filesystems
jupiter/hardware-configuration.nix # PLACEHOLDER — kernel modules, regenerate on target
jupiter/services.nix # shared: users, ssh, samba, containers, caddy
jupiter/vm.nix # VirtualBox test image (jupiter-vbox)
flake.nix # inputs + nixosConfigurations (jupiter, vps, kexec, ...)
common.nix # shared base: user, ssh, nix, firewall, timezone
services/ # one reusable module per service
samba.nix avahi.nix audiobookshelf.nix containers.nix caddy.nix tailscale.nix
hosts/
jupiter/ # ZimaBlade NAS
configuration.nix # host bits + imports common + the services it runs
disk-config.nix # disko: eMMC partitions
hardware-configuration.nix
secrets.nix # sops-nix wiring
vm.nix # VirtualBox test image (jupiter-vbox)
vps/ # netcup public reverse proxy + tailnet node
configuration.nix disk-config.nix hardware-configuration.nix secrets.nix
secrets/ # age-encrypted sops files (jupiter.yaml, vps.yaml)
scripts/ # deploy, edit_secrets
```
Two configs from one service definition: `jupiter` (real host, disko-partitioned)
and `jupiter-vbox` (test OVA). Both import `services.nix`.
Hosts compose by importing `common.nix` + whichever `services/*` modules they
run. Each service module opens its own firewall ports.
## Test in VirtualBox (no hardware needed)
@@ -35,7 +44,7 @@ an installer, partitions via disko, installs.
> ONLY (by-id). Back up / physically identify the NAS data disk first — it must
> NOT appear in disko. `lsblk -o NAME,SERIAL,SIZE,MODEL` to identify.
1. Set the real OS disk id in `jupiter/disk-config.nix`
1. Set the real OS disk id in `hosts/jupiter/disk-config.nix`
(`ls -l /dev/disk/by-id`), and the data-disk mount in `configuration.nix`.
2. Add your login SSH pubkey to `users.users.darman.openssh.authorizedKeys.keys`.
3. Set the real samba password:
@@ -56,7 +65,7 @@ an installer, partitions via disko, installs.
nix run github:nix-community/nixos-anywhere -- \
--flake .#jupiter \
--extra-files /tmp/extra \
--generate-hardware-config nixos-generate-config ./jupiter/hardware-configuration.nix \
--generate-hardware-config nixos-generate-config ./hosts/jupiter/hardware-configuration.nix \
--target-host root@<zimablade-ip>
```
`--extra-files` plants the host key before first boot (its age identity is
+3 -3
View File
@@ -31,7 +31,7 @@
modules = [
disko.nixosModules.disko
sops-nix.nixosModules.sops
./jupiter/configuration.nix
./hosts/jupiter/configuration.nix
];
};
@@ -42,7 +42,7 @@
modules = [
disko.nixosModules.disko
sops-nix.nixosModules.sops
./vps/configuration.nix
./hosts/vps/configuration.nix
];
};
@@ -52,7 +52,7 @@
jupiter-vbox = nixpkgs.lib.nixosSystem {
inherit system;
specialArgs = { inherit inputs; };
modules = [ ./jupiter/vm.nix ];
modules = [ ./hosts/jupiter/vm.nix ];
};
# Custom kexec installer with our SSH key baked in, for headless install
@@ -6,13 +6,13 @@
./hardware-configuration.nix
./disk-config.nix # disko: OS-disk partitions + filesystems
./secrets.nix # sops-nix: samba password, tailscale key, ...
../common.nix # shared base: user / ssh / nix / firewall
../services/samba.nix
../services/avahi.nix
../services/audiobookshelf.nix
../services/containers.nix
../services/caddy.nix
../services/tailscale.nix
../../common.nix # shared base: user / ssh / nix / firewall
../../services/samba.nix
../../services/avahi.nix
../../services/audiobookshelf.nix
../../services/containers.nix
../../services/caddy.nix
../../services/tailscale.nix
];
# ---- Host identity ----
@@ -1,16 +1,16 @@
{ config, ... }:
# sops-nix secret wiring (real host only; not imported by vm.nix).
# Encrypted values live in ../secrets/jupiter.yaml, decrypted at activation to
# Encrypted values live in ../../secrets/jupiter.yaml, decrypted at activation to
# /run/secrets/<name>.
#
# The host decrypts with its OWN SSH host key (age identity derived via
# ssh-to-age, recipient listed in ../.sops.yaml). The key is pre-generated on
# ssh-to-age, recipient listed in ../../.sops.yaml). The key is pre-generated on
# the laptop and shipped once at install as /etc/ssh/ssh_host_ed25519_key
# (nixos-anywhere --extra-files) — so decryption works on boot #1 and there is
# no separate sops-only key to manage.
{
sops.defaultSopsFile = ../secrets/jupiter.yaml;
sops.defaultSopsFile = ../../secrets/jupiter.yaml;
sops.age.sshKeyPaths = [ "/etc/ssh/ssh_host_ed25519_key" ];
# Decrypts to /run/secrets/samba_password (root-only by default).
+6 -6
View File
@@ -6,12 +6,12 @@
{
imports = [
(modulesPath + "/virtualisation/virtualbox-image.nix")
../common.nix # shared base: user / ssh / nix / firewall
../services/samba.nix
../services/avahi.nix
../services/audiobookshelf.nix
../services/containers.nix
../services/caddy.nix
../../common.nix # shared base: user / ssh / nix / firewall
../../services/samba.nix
../../services/avahi.nix
../../services/audiobookshelf.nix
../../services/containers.nix
../../services/caddy.nix
];
networking.hostName = "jupiter";
@@ -6,9 +6,9 @@
./hardware-configuration.nix
./disk-config.nix # disko: vda partitions + filesystems
./secrets.nix # sops-nix: tailscale authkey
../common.nix # shared base: user / ssh / nix / firewall
../services/caddy.nix
../services/tailscale.nix
../../common.nix # shared base: user / ssh / nix / firewall
../../services/caddy.nix
../../services/tailscale.nix
];
# ---- Boot (UEFI) ----
@@ -37,7 +37,7 @@
networking.nameservers = [ "9.9.9.9" "1.1.1.1" "2620:fe::fe" ];
# firewall (enable + 22), caddy (80/443), tailscale (trust tailscale0 + join
# headscale) come from ../common.nix and ../services/{caddy,tailscale}.nix.
# headscale) come from ../../common.nix and ../../services/{caddy,tailscale}.nix.
# ---- Public reverse proxy vhosts ----
# Caddy gets automatic public HTTPS (Let's Encrypt) for real domains.
+3 -3
View File
@@ -1,11 +1,11 @@
{ config, ... }:
# sops-nix wiring for the VPS. Encrypted values live in ../secrets/vps.yaml,
# decrypted with the VPS's own SSH host key (recipient in ../.sops.yaml).
# sops-nix wiring for the VPS. Encrypted values live in ../../secrets/vps.yaml,
# decrypted with the VPS's own SSH host key (recipient in ../../.sops.yaml).
# The host key is pre-generated on the laptop and shipped at install
# (nixos-anywhere --extra-files -> /etc/ssh/ssh_host_ed25519_key).
{
sops.defaultSopsFile = ../secrets/vps.yaml;
sops.defaultSopsFile = ../../secrets/vps.yaml;
sops.age.sshKeyPaths = [ "/etc/ssh/ssh_host_ed25519_key" ];
sops.secrets.tailscale_authkey = { };
+2 -2
View File
@@ -66,7 +66,7 @@ case "$cmd" in
{ [ -n "$config" ] && [ -n "$host" ]; } || die "usage: ./deploy install <config> <host>"
hostkey="$HOME/.config/homelab/$config/ssh_host_ed25519_key"
[ -f "$hostkey" ] || die "missing host key: $hostkey"
[ -d "./$config" ] || die "no ./$config directory in the repo"
[ -d "./hosts/$config" ] || die "no ./hosts/$config directory in the repo"
# Stage the pre-generated SSH host key so sops can decrypt on boot #1.
stage="$(mktemp -d)"
@@ -78,7 +78,7 @@ case "$cmd" in
nix run github:nix-community/nixos-anywhere -- \
--flake ".#$config" \
--extra-files "$stage" \
--generate-hardware-config nixos-generate-config "./$config/hardware-configuration.nix" \
--generate-hardware-config nixos-generate-config "./hosts/$config/hardware-configuration.nix" \
--target-host "root@$host"
;;