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 <noreply@anthropic.com>
This commit is contained in:
@@ -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
|
flake.nix # nixosConfigurations: real hosts + test/util targets
|
||||||
common.nix # shared base: user darman (key-only ssh), nix settings, firewall :22, tz
|
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/<cat>/*.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/<h>/ # configuration.nix + disk-config.nix (disko) + hardware-configuration.nix + secrets.nix
|
hosts/<h>/ # configuration.nix + disk-config.nix (disko) + hardware-configuration.nix + secrets.nix
|
||||||
secrets/<h>.yaml # sops-nix, age-encrypted per host
|
secrets/<h>.yaml # sops-nix, age-encrypted per host
|
||||||
scripts/deploy # config-agnostic deploy wrapper (all args mandatory)
|
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)
|
.sops.yaml # per-host encryption rules (admin key + each host's key)
|
||||||
```
|
```
|
||||||
|
|
||||||
A host = `common.nix` + the `services/*` modules it imports + its `hosts/<h>/configuration.nix`.
|
A host = `common.nix` + the `services/**` modules it imports + its `hosts/<h>/configuration.nix`.
|
||||||
`services/` modules are engine-agnostic and shared across hosts (e.g. `tailscale.nix`,
|
`services/` modules are engine-agnostic and shared across hosts (e.g. `services/vpn/tailscale.nix`,
|
||||||
`caddy.nix` used by jupiter and neptun).
|
`services/network/caddy.nix` used by jupiter and neptun).
|
||||||
|
|
||||||
## Commands
|
## 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)
|
`/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
|
+ `qemu-user-static-binfmt`, else emulated builds fail with "platform mismatch". Or
|
||||||
build on the Pi with `--build-host darman@<ip>`.
|
build on the Pi with `--build-host darman@<ip>`.
|
||||||
- **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
|
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.pihole-ftl` module **segfaults on the Pi 3B+ aarch64** — do not switch back.
|
||||||
- **`services.unbound.resolveLocalQueries = false`** is required: unbound listens on
|
- **`services.unbound.resolveLocalQueries = false`** is required: unbound listens on
|
||||||
|
|||||||
@@ -73,8 +73,8 @@
|
|||||||
modules = [
|
modules = [
|
||||||
(nixpkgs + "/nixos/modules/virtualisation/qemu-vm.nix")
|
(nixpkgs + "/nixos/modules/virtualisation/qemu-vm.nix")
|
||||||
./common.nix
|
./common.nix
|
||||||
./services/unbound.nix
|
./services/network/unbound.nix
|
||||||
./services/pihole.nix
|
./services/network/pihole.nix
|
||||||
({ lib, ... }: {
|
({ lib, ... }: {
|
||||||
networking.hostName = "mercury-vm";
|
networking.hostName = "mercury-vm";
|
||||||
networking.nameservers = [ "1.1.1.1" "9.9.9.9" ]; # host resolver (not pihole)
|
networking.nameservers = [ "1.1.1.1" "9.9.9.9" ]; # host resolver (not pihole)
|
||||||
|
|||||||
@@ -7,20 +7,20 @@
|
|||||||
./disk-config.nix # disko: OS-disk partitions + filesystems
|
./disk-config.nix # disko: OS-disk partitions + filesystems
|
||||||
./secrets.nix # sops-nix: samba password, tailscale key, ...
|
./secrets.nix # sops-nix: samba password, tailscale key, ...
|
||||||
../../common.nix # shared base: user / ssh / nix / firewall
|
../../common.nix # shared base: user / ssh / nix / firewall
|
||||||
../../services/samba.nix
|
../../services/network/samba.nix
|
||||||
../../services/avahi.nix
|
../../services/network/avahi.nix
|
||||||
../../services/audiobookshelf.nix
|
../../services/media/audiobookshelf.nix
|
||||||
../../services/containers.nix
|
../../services/containers.nix
|
||||||
../../services/caddy.nix
|
../../services/network/caddy.nix
|
||||||
../../services/tailscale.nix
|
../../services/vpn/tailscale.nix
|
||||||
../../services/jellyfin.nix
|
../../services/media/jellyfin.nix
|
||||||
../../services/sabnzbd.nix
|
../../services/media/sabnzbd.nix
|
||||||
../../services/prowlarr.nix
|
../../services/media/prowlarr.nix
|
||||||
../../services/sonarr.nix
|
../../services/media/sonarr.nix
|
||||||
../../services/radarr.nix
|
../../services/media/radarr.nix
|
||||||
../../services/clonarr.nix
|
../../services/media/clonarr.nix
|
||||||
../../services/seerr.nix
|
../../services/media/seerr.nix
|
||||||
../../services/gitea.nix
|
../../services/dev/gitea.nix
|
||||||
];
|
];
|
||||||
|
|
||||||
# sabnzbd's unrar dependency is unfree; scope the allowance to just that
|
# sabnzbd's unrar dependency is unfree; scope the allowance to just that
|
||||||
|
|||||||
@@ -7,11 +7,11 @@
|
|||||||
imports = [
|
imports = [
|
||||||
(modulesPath + "/virtualisation/virtualbox-image.nix")
|
(modulesPath + "/virtualisation/virtualbox-image.nix")
|
||||||
../../common.nix # shared base: user / ssh / nix / firewall
|
../../common.nix # shared base: user / ssh / nix / firewall
|
||||||
../../services/samba.nix
|
../../services/network/samba.nix
|
||||||
../../services/avahi.nix
|
../../services/network/avahi.nix
|
||||||
../../services/audiobookshelf.nix
|
../../services/media/audiobookshelf.nix
|
||||||
../../services/containers.nix
|
../../services/containers.nix
|
||||||
../../services/caddy.nix
|
../../services/network/caddy.nix
|
||||||
];
|
];
|
||||||
|
|
||||||
networking.hostName = "jupiter";
|
networking.hostName = "jupiter";
|
||||||
|
|||||||
@@ -7,8 +7,8 @@
|
|||||||
imports = [
|
imports = [
|
||||||
../../common.nix # shared base: user / ssh / nix / firewall
|
../../common.nix # shared base: user / ssh / nix / firewall
|
||||||
./secrets.nix # sops-nix: darman password (age key on boot part.)
|
./secrets.nix # sops-nix: darman password (age key on boot part.)
|
||||||
../../services/unbound.nix # local recursive resolver (127.0.0.1:5335)
|
../../services/network/unbound.nix # local recursive resolver (127.0.0.1:5335)
|
||||||
../../services/pihole.nix # DNS adblock + DHCP (declarative static leases)
|
../../services/network/pihole.nix # DNS adblock + DHCP (declarative static leases)
|
||||||
];
|
];
|
||||||
|
|
||||||
networking.hostName = "mercury";
|
networking.hostName = "mercury";
|
||||||
|
|||||||
@@ -7,11 +7,11 @@
|
|||||||
./disk-config.nix # disko: vda partitions + filesystems
|
./disk-config.nix # disko: vda partitions + filesystems
|
||||||
./secrets.nix # sops-nix: tailscale authkey
|
./secrets.nix # sops-nix: tailscale authkey
|
||||||
../../common.nix # shared base: user / ssh / nix / firewall
|
../../common.nix # shared base: user / ssh / nix / firewall
|
||||||
../../services/caddy.nix
|
../../services/network/caddy.nix
|
||||||
../../services/tailscale.nix
|
../../services/vpn/tailscale.nix
|
||||||
../../services/zitadel.nix
|
../../services/identity/zitadel.nix
|
||||||
../../services/headscale.nix
|
../../services/vpn/headscale.nix
|
||||||
../../services/headplane.nix
|
../../services/vpn/headplane.nix
|
||||||
];
|
];
|
||||||
|
|
||||||
# ---- Boot (UEFI) ----
|
# ---- Boot (UEFI) ----
|
||||||
@@ -52,7 +52,7 @@
|
|||||||
# TODO: port your other VPS services' vhosts here before deploying.
|
# TODO: port your other VPS services' vhosts here before deploying.
|
||||||
|
|
||||||
# ---- Zitadel (identity/OIDC provider) ----
|
# ---- 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.
|
# TLS and proxies to it.
|
||||||
services.zitadel.settings.ExternalDomain = "auth.mgaction.town";
|
services.zitadel.settings.ExternalDomain = "auth.mgaction.town";
|
||||||
services.caddy.virtualHosts."auth.mgaction.town".extraConfig = ''
|
services.caddy.virtualHosts."auth.mgaction.town".extraConfig = ''
|
||||||
@@ -78,7 +78,7 @@
|
|||||||
|
|
||||||
# ---- Gitea SSH forward ----
|
# ---- Gitea SSH forward ----
|
||||||
# Caddy only proxies HTTP; forward :2222 over the tailnet to gitea's own
|
# 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
|
# `ssh://git@git.mgaction.town:2222/...` works. Also needs a matching
|
||||||
# inbound-2222 rule in netcup's edge firewall panel (not managed by Nix).
|
# inbound-2222 rule in netcup's edge firewall panel (not managed by Nix).
|
||||||
systemd.services.gitea-ssh-forward = {
|
systemd.services.gitea-ssh-forward = {
|
||||||
|
|||||||
@@ -18,7 +18,7 @@
|
|||||||
# bootstrap password is different — services.zitadel.steps would render it
|
# bootstrap password is different — services.zitadel.steps would render it
|
||||||
# into a world-readable store path, so render a FirstInstance steps file
|
# into a world-readable store path, so render a FirstInstance steps file
|
||||||
# from the secret instead and point extraStepsPaths at it (see
|
# 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).
|
# pattern).
|
||||||
sops.secrets.zitadel_master_key = { };
|
sops.secrets.zitadel_master_key = { };
|
||||||
sops.secrets.zitadel_admin_password = { };
|
sops.secrets.zitadel_admin_password = { };
|
||||||
@@ -39,7 +39,7 @@
|
|||||||
|
|
||||||
# Headplane: cookie_secret_path takes a path natively (no store leak).
|
# Headplane: cookie_secret_path takes a path natively (no store leak).
|
||||||
# oidc.client_secret + the headscale API key are still REPLACE_ME
|
# 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.
|
# actually deployed and those get created for real.
|
||||||
sops.secrets.headplane_cookie_secret = { };
|
sops.secrets.headplane_cookie_secret = { };
|
||||||
sops.secrets.headplane_oidc_client_secret = { };
|
sops.secrets.headplane_oidc_client_secret = { };
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{ config, ... }:
|
{ 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
|
# first). Runs as headscale's own OS user so it can restart headscale when
|
||||||
# settings change from the UI.
|
# settings change from the UI.
|
||||||
#
|
#
|
||||||
@@ -9,7 +9,7 @@
|
|||||||
# /admin prefix — Headplane appends that itself, including for the OIDC
|
# /admin prefix — Headplane appends that itself, including for the OIDC
|
||||||
# callback.
|
# 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
|
# and the headscale API key can't be known until Zitadel/headscale are
|
||||||
# actually deployed, so they're placeholders below; direct API-key login
|
# actually deployed, so they're placeholders below; direct API-key login
|
||||||
# still works as a fallback until then. Once live:
|
# still works as a fallback until then. Once live:
|
||||||
@@ -1,7 +1,7 @@
|
|||||||
{ ... }:
|
{ ... }:
|
||||||
|
|
||||||
# Headscale — self-hosted control server for the tailnet. Every host's
|
# 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
|
# (this host). MagicDNS base_domain "hosts.mgaction.town" matches the
|
||||||
# "jupiter.hosts.mgaction.town" names used in this repo's Caddy vhosts
|
# "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.
|
# (e.g. hosts/neptun/configuration.nix) — don't change one without the other.
|
||||||
Reference in New Issue
Block a user