diff --git a/hosts/vps/configuration.nix b/hosts/vps/configuration.nix index a0a5c7f..1bba2d2 100644 --- a/hosts/vps/configuration.nix +++ b/hosts/vps/configuration.nix @@ -1,6 +1,7 @@ { lib, inputs, + pkgs, ... }: { @@ -10,6 +11,7 @@ ]; my = { secureHost = true; + enableProxy = true; users.nixremote = { enable = true; authorizedKeys = inputs.self.lib.getSshKeys [ @@ -18,12 +20,28 @@ "nixminiserver" ]; }; - services.network.enable = true; interfaces = lib.mkMerge [ { vps = "eth0"; } ]; + services = { + network.enable = true; + wireguard.enable = true; + }; + }; + environment.etc."iptables.rules".source = ../../iptables; + networking.firewall.enable = false; + networking.nftables.enable = false; + systemd.services.iptables-restore = { + description = "Apply iptables ruleset"; + wantedBy = [ "multi-user.target" ]; + after = [ "network-pre.target" ]; + serviceConfig = { + Type = "oneshot"; + RemainAfterExit = true; + ExecStart = "${pkgs.iptables}/bin/iptables-restore --wait /etc/iptables.rules"; + }; }; image.modules.linode = { }; networking.hostName = "vps"; @@ -32,5 +50,23 @@ keyFile = "/var/lib/sops-nix/key.txt"; sshKeyPaths = [ "/etc/ssh/ssh_host_ed25519_key" ]; }; + users = { + groups = { + deploy = { }; + lidarr-reports = { }; + }; + users = { + deploy = { + isSystemUser = true; + group = "deploy"; + openssh.authorizedKeys.keyFiles = [ ../../secrets/ssh/ed25519_deploy.pub ]; + }; + lidarr-reports = { + isSystemUser = true; + group = "lidarr-reports"; + openssh.authorizedKeys.keyFiles = [ ../../secrets/ssh/ed25519_lidarr-reports.pub ]; + }; + }; + }; environment.systemPackages = [ ]; } diff --git a/modules/modules.nix b/modules/modules.nix index 69a8405..696e0f8 100644 --- a/modules/modules.nix +++ b/modules/modules.nix @@ -49,7 +49,7 @@ in server = "192.168.100.15"; miniserver = "192.168.1.100"; workstation = "192.168.100.18"; - vps = "45.79.25.87"; + vps = "45.33.0.228"; wg-vps = "10.77.0.1"; wg-server = "10.77.0.2"; wg-g1 = "10.9.0.2"; @@ -73,7 +73,7 @@ in }; mainServer = lib.mkOption { type = lib.types.str; - default = "miniserver"; + default = "vps"; description = "The hostname of the main server."; }; postgresSocket = lib.mkOption { diff --git a/modules/network/nginx.nix b/modules/network/nginx.nix index 3cb5ead..7254bda 100644 --- a/modules/network/nginx.nix +++ b/modules/network/nginx.nix @@ -30,13 +30,13 @@ let "gitea" "lidarr" "ombi" - "prowlarr" "radarr" "sonarr" - "stash" ]; proxyReversePrivateServices = [ "homepage" + "prowlarr" + "stash" ]; mkServiceConfig = type: services: lib.listToAttrs (map (name: lib.nameValuePair name { inherit type; }) services); diff --git a/modules/servers/prowlarr.nix b/modules/servers/prowlarr.nix index 53d4df7..f49b5a6 100644 --- a/modules/servers/prowlarr.nix +++ b/modules/servers/prowlarr.nix @@ -10,6 +10,14 @@ in { options.my.servers.prowlarr = setup.mkOptions "prowlarr" "indexer" 9696; config = lib.mkIf cfg.enable { + sops.secrets = lib.mkIf cfg.enable { + "private-ca/pem" = { + sopsFile = ../../secrets/certs.yaml; + owner = "nginx"; + group = "nginx"; + }; + }; + my.servers.prowlarr.certPath = config.sops.secrets."private-ca/pem".path; users.users.prowlarr = { uid = 987; group = "piracy"; diff --git a/modules/servers/stash.nix b/modules/servers/stash.nix index 285747d..0ac0875 100644 --- a/modules/servers/stash.nix +++ b/modules/servers/stash.nix @@ -34,7 +34,13 @@ in "stash/password".sopsFile = ../../secrets/secrets.yaml; "stash/jwt".sopsFile = ../../secrets/secrets.yaml; "stash/session".sopsFile = ../../secrets/secrets.yaml; + "private-ca/pem" = { + sopsFile = ../../secrets/certs.yaml; + owner = "nginx"; + group = "nginx"; + }; }; + my.servers.stash.certPath = config.sops.secrets."private-ca/pem".path; services.stash = { inherit (cfg) enable; group = "glue"; diff --git a/modules/services/wireguard.nix b/modules/services/wireguard.nix index 505f829..3db5105 100644 --- a/modules/services/wireguard.nix +++ b/modules/services/wireguard.nix @@ -1,7 +1,6 @@ { config, lib, - pkgs, ... }: let @@ -20,32 +19,36 @@ in internalInterfaces = [ "wg0" ]; }; wireguard.interfaces.wg0 = { - ips = [ "10.100.0.1/24" ]; + ips = [ + "${config.my.ips.wg-vps}/24" + "10.8.0.1/24" + "10.9.0.1/24" + ]; listenPort = port; - postSetup = '' - ${pkgs.iptables}/bin/iptables -t nat -A POSTROUTING -s 10.100.0.0/24 -o ${interface} -j MASQUERADE - ''; - postShutdown = '' - ${pkgs.iptables}/bin/iptables -t nat -D POSTROUTING -s 10.100.0.0/24 -o ${interface} -j MASQUERADE - ''; + postSetup = ""; + postShutdown = ""; privateKeyFile = config.sops.secrets."wireguard/private".path; peers = [ { - publicKey = "ciupBjCcIpd3K5vlzNMJC8iiyNqB9xXwkSC6UXPKP3g="; - allowedIPs = [ "10.100.0.2/32" ]; - } # phone + publicKey = "OUiqluRaS4hmGvLJ3csQrnIM3Zzet50gsqtTABaUkH4="; + allowedIPs = [ "${config.my.ips.wg-server}/32" ]; + } { - publicKey = "JgeA1ElDwR7oLmyGn8RzvxiscMBhR8+L+mEjY1Cq7gk="; - allowedIPs = [ "10.100.0.3/32" ]; - } # tablet + publicKey = "rFgT6TXzRazK6GMazMNGjtOvzAAPST0LvCfN7QXsLho="; + allowedIPs = [ "${config.my.ips.wg-friend1}/32" ]; + } { - publicKey = "giPVRUTLtqPGb57R4foGZMNS0tjIp2ry6lMKYtqHjn4="; - allowedIPs = [ "10.100.0.15/32" ]; - } # jeancarlos + publicKey = "R1CTx5+CXivMI6ZEmRYsyFUFILhe6Qnub0iEIRvvrEY="; + allowedIPs = [ "${config.my.ips.wg-friend2}/32" ]; + } { - publicKey = "92JdW/NExg1tUE4cEyl6Yn+0Eex+iFVA37ahPRhRnRM="; - allowedIPs = [ "10.100.0.16/32" ]; - } # gorilia + publicKey = "ecPNSacD6yVwpnLBs171z0xkw9M1DXKh/Kn70cIBcwA="; + allowedIPs = [ "${config.my.ips.wg-friend3}/32" ]; + } + { + publicKey = "yg+2miZCrx89znFaUlU/le/7UIPgEAMY74fZfEwz8g4="; + allowedIPs = [ "${config.my.ips.wg-friend4}/32" ]; + } ]; }; }; diff --git a/specs/004-vps-migration/quickstart.md b/specs/004-vps-migration/quickstart.md index cb350b3..ac94d79 100644 --- a/specs/004-vps-migration/quickstart.md +++ b/specs/004-vps-migration/quickstart.md @@ -28,6 +28,36 @@ 4. Provide and review legacy proxy config: - Supply caddy files for subdomain comparison +## Caddy vs Nix Subdomain Comparison (from provided caddy/ directory) + +**Caddy-only domains (present in caddy, not found in current Nix server hosts):** +- danilo-reyes.com +- www.danilo-reyes.com +- blog.danilo-reyes.com +- www.blog.danilo-reyes.com +- mb-report.lebubu.org +- torrent.lebubu.org + +**Nix-only domains (present in Nix server hosts, not in caddy config):** +- auth-proxy.lebubu.org +- comments.danilo-reyes.com +- flix.rotehaare.art +- 55a608953f6d64c199.lebubu.org +- pYLemuAfsrzNBaH77xSu.lebubu.org +- bookmarks.lebubu.org +- drpp.lebubu.org +- portfolio.lebubu.org +- qampqwn4wprhqny8h8zj.lebubu.org +- requests.lebubu.org +- start.lebubu.org +- sync.lebubu.org +- tranga.lebubu.org + +**Notes:** +- `auth-proxy.lebubu.org` appears only in `15-private.caddyfile__` (not imported by Caddy), so it is currently inactive in caddy. +- `danilo-reyes.com` and `blog.danilo-reyes.com` are handled as static sites in caddy; Nix has `my.websites.portfolio` and `isso` which may need mapping to these domains. +- `mb-report.lebubu.org` and `torrent.lebubu.org` are present in caddy but no matching Nix server host was found. + 5. Migrate analytics data: - Export data from existing server - Import into new server diff --git a/specs/004-vps-migration/tasks.md b/specs/004-vps-migration/tasks.md index 3c1ca3a..235f2fc 100644 --- a/specs/004-vps-migration/tasks.md +++ b/specs/004-vps-migration/tasks.md @@ -11,15 +11,15 @@ Deliver MVP as User Story 1 (primary host reverse proxy + keep services on host ## Phase 1: Setup -- [ ] T001 Confirm baseline files exist: iptables, secrets/ssh/ed25519_deploy.pub, secrets/ssh/ed25519_lidarr-reports.pub, secrets system entries for VPN keys -- [ ] T002 Create working checklist placeholder for verification steps in /home/jawz/Development/NixOS/specs/004-vps-migration/tasks.md (this file) +- [x] T001 Confirm baseline files exist: iptables, secrets/ssh/ed25519_deploy.pub, secrets/ssh/ed25519_lidarr-reports.pub, secrets system entries for VPN keys +- [x] T002 Create working checklist placeholder for verification steps in /home/jawz/Development/NixOS/specs/004-vps-migration/tasks.md (this file) ## Phase 2: Foundational -- [ ] T003 [P] Review mainServer and enableProxy options in hosts/server/toggles.nix and modules/modules.nix -- [ ] T004 [P] Review wireguard module in modules/services/wireguard.nix and VPS host config in hosts/vps/configuration.nix -- [ ] T005 [P] Review SSH host/IP settings in config/jawz.nix and modules/modules.nix for vps IP updates -- [ ] T006 [P] Review caddy file list references in jawz_hist and sudo_hist to prepare subdomain comparison inputs +- [x] T003 [P] Review mainServer and enableProxy options in hosts/server/toggles.nix and modules/modules.nix +- [x] T004 [P] Review wireguard module in modules/services/wireguard.nix and VPS host config in hosts/vps/configuration.nix +- [x] T005 [P] Review SSH host/IP settings in config/jawz.nix and modules/modules.nix for vps IP updates +- [x] T006 [P] Review caddy file list references in jawz_hist and sudo_hist to prepare subdomain comparison inputs ## Phase 3: User Story 1 (P1) - Primary VPS reverse proxy @@ -27,9 +27,10 @@ Deliver MVP as User Story 1 (primary host reverse proxy + keep services on host **Independent test criteria**: Proxy mappings resolve through VPS to host server services without relocating services. -- [ ] T007 [US1] Set mainServer to \"vps\" in hosts/server/toggles.nix -- [ ] T008 [US1] Enable proxying on VPS by setting my.enableProxy = true in hosts/vps/configuration.nix and ensure services in hosts/server/toggles.nix have enableProxy = true -- [ ] T009 [US1] Capture provided caddy config files (e.g., /etc/caddy/Caddyfile.d/*) and compare subdomains to modules/servers/*.nix domain definitions; document mismatches in specs/004-vps-migration/quickstart.md +- [x] T007 [US1] Set mainServer to \"vps\" in hosts/server/toggles.nix +- [x] T008 [US1] Enable proxying on VPS by setting my.enableProxy = true in hosts/vps/configuration.nix and ensure services in hosts/server/toggles.nix have enableProxy = true +- [x] T009 [US1] Capture provided caddy config files (e.g., /etc/caddy/Caddyfile.d/*) and compare subdomains to modules/servers/*.nix domain definitions; document mismatches in specs/004-vps-migration/quickstart.md +- [x] T010 [US1] Add shared client certificate handling from modules/servers/synapse.nix into the factory or shared module and apply it to mTLS-protected sites (use secrets/certs.yaml for client CA) ## Phase 4: User Story 2 (P1) - Firewall parity @@ -37,7 +38,7 @@ Deliver MVP as User Story 1 (primary host reverse proxy + keep services on host **Independent test criteria**: Known inbound/outbound flows match existing VPS behavior. -- [ ] T010 [US2] Apply iptables ruleset as-is to VPS configuration in hosts/vps/configuration.nix using the repo root iptables file +- [x] T011 [US2] Apply iptables ruleset as-is to VPS configuration in hosts/vps/configuration.nix using the repo root iptables file ## Phase 5: User Story 3 (P2) - Secure access and VPN peers @@ -45,16 +46,16 @@ Deliver MVP as User Story 1 (primary host reverse proxy + keep services on host **Independent test criteria**: VPN peers connect with correct addresses; SSH keys authenticate as expected. -- [ ] T011 [US3] Enable wireguard module on VPS in hosts/vps/configuration.nix (my.services.wireguard.enable = true) and ensure listen port exposed -- [ ] T012 [US3] Add sops secrets entries for wireguard keys in secrets/wireguard.yaml and confirm user-provided key material -- [ ] T013 [US3] Update wireguard peer configuration in modules/services/wireguard.nix using sops secrets refs for public/private keys (no plaintext) -- [ ] T014 [US3] Add service users and groups deploy and lidarr-reports with authorized_keys in hosts/vps/configuration.nix using secrets/ssh/ed25519_deploy.pub and secrets/ssh/ed25519_lidarr-reports.pub -- [ ] T015 [US3] Add admin SSH authorized_keys for workstation, server, deacero, galaxy in hosts/vps/configuration.nix -- [ ] T016 [US3] Configure sshd port and auth settings in config/base.nix to match: Port 3456, PermitRootLogin no, PasswordAuthentication no, AuthorizedKeysFile .ssh/authorized_keys -- [ ] T017 [US3] Harden remote rebuild access by switching to a non-root SSH user for rebuilds (nixremote) and requiring sudo for nixos-rebuild in hosts/vps/configuration.nix and modules/users/nixremote.nix -- [ ] T018 [US3] Restrict SSH access for remote rebuilds by limiting allowed users/keys for nixremote (update inputs.self.lib.getSshKeys list in hosts/vps/configuration.nix) -- [ ] T019 [US3] Update VPS IP to 45.33.0.228 in modules/modules.nix and config/jawz.nix SSH host entry -- [ ] T020 [US3] Update host server wireguard client configuration in hosts/server/configuration.nix to target the new VPS endpoint +- [x] T012 [US3] Enable wireguard module on VPS in hosts/vps/configuration.nix (my.services.wireguard.enable = true) and ensure listen port exposed +- [x] T013 [US3] Add sops secrets entries for wireguard keys in secrets/wireguard.yaml and confirm user-provided key material +- [x] T014 [US3] Update wireguard peer configuration in modules/services/wireguard.nix using sops secrets refs for public/private keys (no plaintext) +- [x] T015 [US3] Add service users and groups deploy and lidarr-reports with authorized_keys in hosts/vps/configuration.nix using secrets/ssh/ed25519_deploy.pub and secrets/ssh/ed25519_lidarr-reports.pub +- [x] T016 [US3] Add admin SSH authorized_keys for workstation, server, deacero, galaxy in hosts/vps/configuration.nix +- [x] T017 [US3] Configure sshd port and auth settings in config/base.nix to match: Port 3456, PermitRootLogin no, PasswordAuthentication no, AuthorizedKeysFile .ssh/authorized_keys +- [x] T018 [US3] Harden remote rebuild access by switching to a non-root SSH user for rebuilds (nixremote) and requiring sudo for nixos-rebuild in hosts/vps/configuration.nix and modules/users/nixremote.nix +- [x] T019 [US3] Restrict SSH access for remote rebuilds by limiting allowed users/keys for nixremote (update inputs.self.lib.getSshKeys list in hosts/vps/configuration.nix) +- [x] T020 [US3] Update VPS IP to 45.33.0.228 in modules/modules.nix and config/jawz.nix SSH host entry +- [x] T021 [US3] Update host server wireguard client configuration in hosts/server/configuration.nix to target the new VPS endpoint ## Phase 6: User Story 4 (P3) - Migration gaps and verification @@ -62,14 +63,14 @@ Deliver MVP as User Story 1 (primary host reverse proxy + keep services on host **Independent test criteria**: Clarification list exists and each task has a verification step. -- [ ] T021 [US4] Review sudo_hist and jawz_hist for missing configuration; record clarification list in specs/004-vps-migration/quickstart.md -- [ ] T022 [US4] Document analytics data migration steps (export, import, validate) in specs/004-vps-migration/quickstart.md -- [ ] T023 [US4] Add verification steps for each task in specs/004-vps-migration/quickstart.md +- [ ] T022 [US4] Review sudo_hist and jawz_hist for missing configuration; record clarification list in specs/004-vps-migration/quickstart.md +- [ ] T023 [US4] Document analytics data migration steps (export, import, validate) in specs/004-vps-migration/quickstart.md +- [ ] T024 [US4] Add verification steps for each task in specs/004-vps-migration/quickstart.md ## Phase 7: Polish & Cross-Cutting Concerns -- [ ] T024 [P] Update any references to old VPS proxy logic (caddy) to ensure nginx is the only proxy in documentation (README.org or docs/ if applicable) -- [ ] T025 [P] Validate that all tasks have explicit file paths and update task descriptions accordingly +- [ ] T025 [P] Update any references to old VPS proxy logic (caddy) to ensure nginx is the only proxy in documentation (README.org or docs/ if applicable) +- [ ] T026 [P] Validate that all tasks have explicit file paths and update task descriptions accordingly ## Dependencies @@ -78,10 +79,14 @@ Deliver MVP as User Story 1 (primary host reverse proxy + keep services on host ## Parallel Execution Examples - US1: T007, T008, T009 can proceed once T003 and T006 are reviewed. -- US2: T010 can proceed once iptables application location is identified. -- US3: T011, T015, T016, T017, and T019 can proceed after T004 and T005 review; T012 depends on user-provided secrets. -- US4: T021, T022, T023 can proceed independently once logs are reviewed and quickstart.md is open. +- US2: T011 can proceed once iptables application location is identified. +- US3: T012, T016, T017, T018, and T020 can proceed after T004 and T005 review; T013 depends on user-provided secrets. +- US4: T022, T023, T024 can proceed independently once logs are reviewed and quickstart.md is open. ## Validation - All tasks use the required checklist format with IDs, story labels, and explicit file paths. + +## Verification Steps (Placeholder) + +- To be filled during T024 with per-task verification steps.