From d7a66f3e3be842a074e4bdb798e0348c468edb50 Mon Sep 17 00:00:00 2001 From: Erik Simon Date: Mon, 20 Jul 2026 06:08:43 +0200 Subject: [PATCH] Reorganize services/ into category subfolders Group service modules by category (media, network, vpn, identity, dev, desktop) to make the growing services/ dir easier to navigate. containers.nix stays at the top level since it's a shared backend, not a single-category service. Co-Authored-By: Claude Sonnet 5 --- CLAUDE.md | 13 ++++++++----- flake.nix | 4 ++-- hosts/jupiter/configuration.nix | 26 ++++++++++++------------- hosts/jupiter/vm.nix | 8 ++++---- hosts/mercury/configuration.nix | 4 ++-- hosts/neptun/configuration.nix | 14 ++++++------- hosts/neptun/secrets.nix | 4 ++-- services/{ => dev}/gitea.nix | 0 services/{ => identity}/zitadel.nix | 0 services/{ => media}/audiobookshelf.nix | 0 services/{ => media}/cinephage.nix | 0 services/{ => media}/clonarr.nix | 0 services/{ => media}/jellyfin.nix | 0 services/{ => media}/mediamanager.nix | 0 services/{ => media}/prowlarr.nix | 0 services/{ => media}/radarr.nix | 0 services/{ => media}/sabnzbd.nix | 0 services/{ => media}/seerr.nix | 0 services/{ => media}/sonarr.nix | 0 services/{ => network}/avahi.nix | 0 services/{ => network}/caddy.nix | 0 services/{ => network}/pihole.nix | 0 services/{ => network}/samba.nix | 0 services/{ => network}/unbound.nix | 0 services/{ => vpn}/headplane.nix | 4 ++-- services/{ => vpn}/headscale.nix | 2 +- services/{ => vpn}/tailscale.nix | 0 27 files changed, 41 insertions(+), 38 deletions(-) rename services/{ => dev}/gitea.nix (100%) rename services/{ => identity}/zitadel.nix (100%) rename services/{ => media}/audiobookshelf.nix (100%) rename services/{ => media}/cinephage.nix (100%) rename services/{ => media}/clonarr.nix (100%) rename services/{ => media}/jellyfin.nix (100%) rename services/{ => media}/mediamanager.nix (100%) rename services/{ => media}/prowlarr.nix (100%) rename services/{ => media}/radarr.nix (100%) rename services/{ => media}/sabnzbd.nix (100%) rename services/{ => media}/seerr.nix (100%) rename services/{ => media}/sonarr.nix (100%) rename services/{ => network}/avahi.nix (100%) rename services/{ => network}/caddy.nix (100%) rename services/{ => network}/pihole.nix (100%) rename services/{ => network}/samba.nix (100%) rename services/{ => network}/unbound.nix (100%) rename services/{ => vpn}/headplane.nix (90%) rename services/{ => vpn}/headscale.nix (90%) rename services/{ => vpn}/tailscale.nix (100%) diff --git a/CLAUDE.md b/CLAUDE.md index df31841..a7d3e0e 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -11,7 +11,10 @@ Pi 3B+ DNS/DHCP, aarch64). See `README.md` for the full install/deploy walkthrou ``` flake.nix # nixosConfigurations: real hosts + test/util targets common.nix # shared base: user darman (key-only ssh), nix settings, firewall :22, tz -services/*.nix # one reusable NixOS module per service; each opens ITS OWN firewall ports +services//*.nix # one reusable NixOS module per service, grouped by category + # (media, network, vpn, identity, dev, desktop); each opens + # ITS OWN firewall ports. services/containers.nix (podman + # backend) stays at the top level, shared across categories. hosts// # configuration.nix + disk-config.nix (disko) + hardware-configuration.nix + secrets.nix secrets/.yaml # sops-nix, age-encrypted per host scripts/deploy # config-agnostic deploy wrapper (all args mandatory) @@ -19,9 +22,9 @@ scripts/edit_secrets .sops.yaml # per-host encryption rules (admin key + each host's key) ``` -A host = `common.nix` + the `services/*` modules it imports + its `hosts//configuration.nix`. -`services/` modules are engine-agnostic and shared across hosts (e.g. `tailscale.nix`, -`caddy.nix` used by jupiter and neptun). +A host = `common.nix` + the `services/**` modules it imports + its `hosts//configuration.nix`. +`services/` modules are engine-agnostic and shared across hosts (e.g. `services/vpn/tailscale.nix`, +`services/network/caddy.nix` used by jupiter and neptun). ## Commands @@ -73,7 +76,7 @@ nix build .#nixosConfigurations.jupiter-vbox.config.system.build.virtualBoxOVA `/etc/nix/nix.custom.conf` (NOT `/etc/nix/nix.conf` — Determinate Nix regenerates that) + `qemu-user-static-binfmt`, else emulated builds fail with "platform mismatch". Or build on the Pi with `--build-host darman@`. -- **pihole on mercury is a CONTAINER** (`services/pihole.nix`, official image, host +- **pihole on mercury is a CONTAINER** (`services/network/pihole.nix`, official image, host networking, caps NET_ADMIN/NET_RAW/SYS_NICE/CHOWN, `FTLCONF_*` env config). The native `services.pihole-ftl` module **segfaults on the Pi 3B+ aarch64** — do not switch back. - **`services.unbound.resolveLocalQueries = false`** is required: unbound listens on diff --git a/flake.nix b/flake.nix index 90163a2..0872256 100644 --- a/flake.nix +++ b/flake.nix @@ -73,8 +73,8 @@ modules = [ (nixpkgs + "/nixos/modules/virtualisation/qemu-vm.nix") ./common.nix - ./services/unbound.nix - ./services/pihole.nix + ./services/network/unbound.nix + ./services/network/pihole.nix ({ lib, ... }: { networking.hostName = "mercury-vm"; networking.nameservers = [ "1.1.1.1" "9.9.9.9" ]; # host resolver (not pihole) diff --git a/hosts/jupiter/configuration.nix b/hosts/jupiter/configuration.nix index 4613348..2734c1b 100644 --- a/hosts/jupiter/configuration.nix +++ b/hosts/jupiter/configuration.nix @@ -7,20 +7,20 @@ ./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/network/samba.nix + ../../services/network/avahi.nix + ../../services/media/audiobookshelf.nix ../../services/containers.nix - ../../services/caddy.nix - ../../services/tailscale.nix - ../../services/jellyfin.nix - ../../services/sabnzbd.nix - ../../services/prowlarr.nix - ../../services/sonarr.nix - ../../services/radarr.nix - ../../services/clonarr.nix - ../../services/seerr.nix - ../../services/gitea.nix + ../../services/network/caddy.nix + ../../services/vpn/tailscale.nix + ../../services/media/jellyfin.nix + ../../services/media/sabnzbd.nix + ../../services/media/prowlarr.nix + ../../services/media/sonarr.nix + ../../services/media/radarr.nix + ../../services/media/clonarr.nix + ../../services/media/seerr.nix + ../../services/dev/gitea.nix ]; # sabnzbd's unrar dependency is unfree; scope the allowance to just that diff --git a/hosts/jupiter/vm.nix b/hosts/jupiter/vm.nix index 98ce261..4b33a32 100644 --- a/hosts/jupiter/vm.nix +++ b/hosts/jupiter/vm.nix @@ -7,11 +7,11 @@ imports = [ (modulesPath + "/virtualisation/virtualbox-image.nix") ../../common.nix # shared base: user / ssh / nix / firewall - ../../services/samba.nix - ../../services/avahi.nix - ../../services/audiobookshelf.nix + ../../services/network/samba.nix + ../../services/network/avahi.nix + ../../services/media/audiobookshelf.nix ../../services/containers.nix - ../../services/caddy.nix + ../../services/network/caddy.nix ]; networking.hostName = "jupiter"; diff --git a/hosts/mercury/configuration.nix b/hosts/mercury/configuration.nix index 9384491..37c404c 100644 --- a/hosts/mercury/configuration.nix +++ b/hosts/mercury/configuration.nix @@ -7,8 +7,8 @@ imports = [ ../../common.nix # shared base: user / ssh / nix / firewall ./secrets.nix # sops-nix: darman password (age key on boot part.) - ../../services/unbound.nix # local recursive resolver (127.0.0.1:5335) - ../../services/pihole.nix # DNS adblock + DHCP (declarative static leases) + ../../services/network/unbound.nix # local recursive resolver (127.0.0.1:5335) + ../../services/network/pihole.nix # DNS adblock + DHCP (declarative static leases) ]; networking.hostName = "mercury"; diff --git a/hosts/neptun/configuration.nix b/hosts/neptun/configuration.nix index d61b0a6..7618381 100644 --- a/hosts/neptun/configuration.nix +++ b/hosts/neptun/configuration.nix @@ -7,11 +7,11 @@ ./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 - ../../services/zitadel.nix - ../../services/headscale.nix - ../../services/headplane.nix + ../../services/network/caddy.nix + ../../services/vpn/tailscale.nix + ../../services/identity/zitadel.nix + ../../services/vpn/headscale.nix + ../../services/vpn/headplane.nix ]; # ---- Boot (UEFI) ---- @@ -52,7 +52,7 @@ # TODO: port your other VPS services' vhosts here before deploying. # ---- Zitadel (identity/OIDC provider) ---- - # Runs locally on neptun (see services/zitadel.nix); Caddy just terminates + # Runs locally on neptun (see services/identity/zitadel.nix); Caddy just terminates # TLS and proxies to it. services.zitadel.settings.ExternalDomain = "auth.mgaction.town"; services.caddy.virtualHosts."auth.mgaction.town".extraConfig = '' @@ -78,7 +78,7 @@ # ---- Gitea SSH forward ---- # Caddy only proxies HTTP; forward :2222 over the tailnet to gitea's own - # SSH server on jupiter (services/gitea.nix), so + # SSH server on jupiter (services/dev/gitea.nix), so # `ssh://git@git.mgaction.town:2222/...` works. Also needs a matching # inbound-2222 rule in netcup's edge firewall panel (not managed by Nix). systemd.services.gitea-ssh-forward = { diff --git a/hosts/neptun/secrets.nix b/hosts/neptun/secrets.nix index 2507985..c992881 100644 --- a/hosts/neptun/secrets.nix +++ b/hosts/neptun/secrets.nix @@ -18,7 +18,7 @@ # bootstrap password is different — services.zitadel.steps would render it # into a world-readable store path, so render a FirstInstance steps file # from the secret instead and point extraStepsPaths at it (see - # services/zitadel.nix and the pihole.env template on mercury for the same + # services/identity/zitadel.nix and the pihole.env template on mercury for the same # pattern). sops.secrets.zitadel_master_key = { }; sops.secrets.zitadel_admin_password = { }; @@ -39,7 +39,7 @@ # Headplane: cookie_secret_path takes a path natively (no store leak). # oidc.client_secret + the headscale API key are still REPLACE_ME - # placeholders (see services/headplane.nix) until Zitadel/headscale are + # placeholders (see services/vpn/headplane.nix) until Zitadel/headscale are # actually deployed and those get created for real. sops.secrets.headplane_cookie_secret = { }; sops.secrets.headplane_oidc_client_secret = { }; diff --git a/services/gitea.nix b/services/dev/gitea.nix similarity index 100% rename from services/gitea.nix rename to services/dev/gitea.nix diff --git a/services/zitadel.nix b/services/identity/zitadel.nix similarity index 100% rename from services/zitadel.nix rename to services/identity/zitadel.nix diff --git a/services/audiobookshelf.nix b/services/media/audiobookshelf.nix similarity index 100% rename from services/audiobookshelf.nix rename to services/media/audiobookshelf.nix diff --git a/services/cinephage.nix b/services/media/cinephage.nix similarity index 100% rename from services/cinephage.nix rename to services/media/cinephage.nix diff --git a/services/clonarr.nix b/services/media/clonarr.nix similarity index 100% rename from services/clonarr.nix rename to services/media/clonarr.nix diff --git a/services/jellyfin.nix b/services/media/jellyfin.nix similarity index 100% rename from services/jellyfin.nix rename to services/media/jellyfin.nix diff --git a/services/mediamanager.nix b/services/media/mediamanager.nix similarity index 100% rename from services/mediamanager.nix rename to services/media/mediamanager.nix diff --git a/services/prowlarr.nix b/services/media/prowlarr.nix similarity index 100% rename from services/prowlarr.nix rename to services/media/prowlarr.nix diff --git a/services/radarr.nix b/services/media/radarr.nix similarity index 100% rename from services/radarr.nix rename to services/media/radarr.nix diff --git a/services/sabnzbd.nix b/services/media/sabnzbd.nix similarity index 100% rename from services/sabnzbd.nix rename to services/media/sabnzbd.nix diff --git a/services/seerr.nix b/services/media/seerr.nix similarity index 100% rename from services/seerr.nix rename to services/media/seerr.nix diff --git a/services/sonarr.nix b/services/media/sonarr.nix similarity index 100% rename from services/sonarr.nix rename to services/media/sonarr.nix diff --git a/services/avahi.nix b/services/network/avahi.nix similarity index 100% rename from services/avahi.nix rename to services/network/avahi.nix diff --git a/services/caddy.nix b/services/network/caddy.nix similarity index 100% rename from services/caddy.nix rename to services/network/caddy.nix diff --git a/services/pihole.nix b/services/network/pihole.nix similarity index 100% rename from services/pihole.nix rename to services/network/pihole.nix diff --git a/services/samba.nix b/services/network/samba.nix similarity index 100% rename from services/samba.nix rename to services/network/samba.nix diff --git a/services/unbound.nix b/services/network/unbound.nix similarity index 100% rename from services/unbound.nix rename to services/network/unbound.nix diff --git a/services/headplane.nix b/services/vpn/headplane.nix similarity index 90% rename from services/headplane.nix rename to services/vpn/headplane.nix index 17389f5..899f4fa 100644 --- a/services/headplane.nix +++ b/services/vpn/headplane.nix @@ -1,6 +1,6 @@ { config, ... }: -# Headplane — web UI for headscale (services/headscale.nix; must be enabled +# Headplane — web UI for headscale (services/vpn/headscale.nix; must be enabled # first). Runs as headscale's own OS user so it can restart headscale when # settings change from the UI. # @@ -9,7 +9,7 @@ # /admin prefix — Headplane appends that itself, including for the OIDC # callback. # -# Auth is Zitadel (services/zitadel.nix) via OIDC. client_id, client_secret, +# Auth is Zitadel (services/identity/zitadel.nix) via OIDC. client_id, client_secret, # and the headscale API key can't be known until Zitadel/headscale are # actually deployed, so they're placeholders below; direct API-key login # still works as a fallback until then. Once live: diff --git a/services/headscale.nix b/services/vpn/headscale.nix similarity index 90% rename from services/headscale.nix rename to services/vpn/headscale.nix index e11879c..8ef3bcd 100644 --- a/services/headscale.nix +++ b/services/vpn/headscale.nix @@ -1,7 +1,7 @@ { ... }: # Headscale — self-hosted control server for the tailnet. Every host's -# services/tailscale.nix points --login-server at https://vpn.mgaction.town +# services/vpn/tailscale.nix points --login-server at https://vpn.mgaction.town # (this host). MagicDNS base_domain "hosts.mgaction.town" matches the # "jupiter.hosts.mgaction.town" names used in this repo's Caddy vhosts # (e.g. hosts/neptun/configuration.nix) — don't change one without the other. diff --git a/services/tailscale.nix b/services/vpn/tailscale.nix similarity index 100% rename from services/tailscale.nix rename to services/vpn/tailscale.nix