From d00ff42e8e00b772b50fa2cc97178e113223c79a Mon Sep 17 00:00:00 2001 From: Simon Gardling Date: Wed, 22 Apr 2026 20:48:29 -0400 Subject: [PATCH] site-config: dedupe cross-host values, fix stale dark-reader urls, drop desktop 1g hugepages new site-config.nix holds values previously duplicated across hosts: domain, old_domain, contact_email, timezone, binary_cache (url + pubkey), dns_servers, lan (cidr + gateway), hosts.{muffin,yarn} (ip/alias/ssh_host_key), ssh_keys.{laptop,desktop,ci_deploy}. threaded through specialArgs on all three hosts + home-manager extraSpecialArgs + homeConfigurations.primary + serverLib. service-configs.nix now takes { site_config } as a function arg and drops its https namespace; per-service domains (gitea/matrix/ntfy/mollysocket/livekit/firefox-sync/grafana) are derived from site_config.domain. ~15 service files and 6 vm tests migrated. breakage fixes rolled in: - home/progs/zen/dark-reader.nix: 5 stale *.gardling.com entries in disabledFor rewritten to *.sigkill.computer (caddy 301s the old names so these never fired and the new sigkill urls were getting dark-reader applied) - modules/desktop-common.nix: drop unused hugepagesz=1G/hugepages=3 kernelParams (no consumer on mreow or yarn; xmrig on muffin still reserves its own via services/monero/xmrig.nix) verification: muffin toplevel is bit-identical to pre-refactor baseline. mreow/yarn toplevels differ only in boot.json kernelParams + darkreader storage.js (nix-diff verified). deployGuardTest and fail2banVaultwardenTest (latter exercises site_config.domain via bitwarden.nix) pass. --- flake.nix | 16 ++++++- home/profiles/terminal.nix | 3 +- home/progs/zen/dark-reader.nix | 10 ++-- hosts/muffin/default.nix | 39 ++++++++------- hosts/muffin/service-configs.nix | 21 ++++----- hosts/yarn/default.nix | 15 +++--- lib/default.nix | 3 +- modules/common.nix | 5 ++ modules/desktop-common.nix | 16 ++----- modules/desktop-networkmanager.nix | 7 +-- services/bitwarden.nix | 5 +- services/caddy/caddy.nix | 12 +++-- services/caddy/caddy_senior_project.nix | 3 +- services/graphing-calculator.nix | 3 +- services/harmonia.nix | 3 +- services/jellyfin/jellyfin.nix | 3 +- services/llama-cpp.nix | 7 +-- services/matrix/coturn.nix | 3 +- services/matrix/matrix.nix | 9 ++-- services/minecraft.nix | 3 +- services/ssh.nix | 7 +-- site-config.nix | 63 +++++++++++++++++++++++++ tests/deploy-guard.nix | 4 +- tests/fail2ban/gitea.nix | 5 +- tests/fail2ban/immich.nix | 6 ++- tests/fail2ban/jellyfin.nix | 7 ++- tests/fail2ban/vaultwarden.nix | 7 ++- tests/minecraft.nix | 5 +- 28 files changed, 190 insertions(+), 100 deletions(-) create mode 100644 site-config.nix diff --git a/flake.nix b/flake.nix index ffc62e8..2fa6f42 100644 --- a/flake.nix +++ b/flake.nix @@ -180,17 +180,20 @@ targetPlatform = system; buildPlatform = builtins.currentSystem; }; - serviceConfigs = import ./hosts/muffin/service-configs.nix; + siteConfig = import ./site-config.nix; + serviceConfigs = import ./hosts/muffin/service-configs.nix { site_config = siteConfig; }; serverLib = import ./lib { inherit inputs; lib = nixpkgs-stable.lib; pkgs = serverPkgs; service_configs = serviceConfigs; + site_config = siteConfig; }; testSuite = import ./tests/tests.nix { pkgs = serverPkgs; lib = serverLib; inherit inputs; + site_config = siteConfig; config = self.nixosConfigurations.muffin.config; }; @@ -203,6 +206,7 @@ specialArgs = { inherit inputs username hostname; niri-package = niriPackage; + site_config = siteConfig; }; modules = [ home-manager.nixosModules.home-manager @@ -222,6 +226,7 @@ niri-package = niriPackage; homeDirectory = "/home/${username}"; stateVersion = config.system.stateVersion; + site_config = siteConfig; }; home-manager.users.${username} = import ./hosts/${hostname}/home.nix; } @@ -241,6 +246,7 @@ hostname = "muffin"; eth_interface = "enp4s0"; service_configs = serviceConfigs; + site_config = siteConfig; lib = serverLib; }; modules = [ @@ -349,6 +355,9 @@ ( { ... }: { + home-manager.extraSpecialArgs = { + site_config = siteConfig; + }; home-manager.users.${username} = import ./hosts/muffin/home.nix; } ) @@ -376,6 +385,9 @@ # Ships the shared terminal profile (fish, helix, modern CLI, git). homeConfigurations.primary = home-manager.lib.homeManagerConfiguration { pkgs = desktopPkgs; + extraSpecialArgs = { + site_config = siteConfig; + }; modules = [ ./home/profiles/terminal.nix { @@ -389,7 +401,7 @@ }; deploy.nodes.muffin = { - hostname = "server-public"; + hostname = siteConfig.hosts.muffin.alias; profiles.system = { sshUser = "root"; user = "root"; diff --git a/home/profiles/terminal.nix b/home/profiles/terminal.nix index 9f6d86b..0bfc2f3 100644 --- a/home/profiles/terminal.nix +++ b/home/profiles/terminal.nix @@ -10,6 +10,7 @@ # tools, no GUI-adjacent utilities — those belong in profiles layered on top. { lib, + site_config, pkgs, ... }: @@ -83,7 +84,7 @@ push.autoSetupRemote = true; user = { name = "Simon Gardling"; - email = "titaniumtown@proton.me"; + email = site_config.contact_email; }; }; diff --git a/home/progs/zen/dark-reader.nix b/home/progs/zen/dark-reader.nix index 2218adb..7d74386 100644 --- a/home/progs/zen/dark-reader.nix +++ b/home/progs/zen/dark-reader.nix @@ -68,19 +68,19 @@ in "element.envs.net" "mail.proton.me" "mail.google.com" - "www.gardling.com" + "www.sigkill.computer" "projects.fivethirtyeight.com" "secure.bankofamerica.com" "billpay-ui.bankofamerica.com" "plus.pearson.com" - "immich.gardling.com" + "immich.sigkill.computer" "huggingface.co" "session.masteringphysics.com" "brainly.com" "www.270towin.com" "phet.colorado.edu" "8042-1.portal.athenahealth.com" - "torrent.gardling.com" + "torrent.sigkill.computer" "nssb-p.adm.fit.edu" "mail.openbenchmarking.org" "moneroocean.stream" @@ -89,11 +89,11 @@ in "chat.deepseek.com" "n21.ultipro.com" "www.egaroucid.nyanyan.dev" - "bitmagnet.gardling.com" + "bitmagnet.sigkill.computer" "frame.work" "www.altcancer.net" "jenkins.jpenilla.xyz" - "soulseek.gardling.com" + "soulseek.sigkill.computer" "discord.com" "www.lufthansa.com" "surveys.hyundaicx.com" diff --git a/hosts/muffin/default.nix b/hosts/muffin/default.nix index 90953e4..4c93093 100644 --- a/hosts/muffin/default.nix +++ b/hosts/muffin/default.nix @@ -5,6 +5,7 @@ hostname, username, eth_interface, + site_config, service_configs, options, ... @@ -79,16 +80,22 @@ ]; # Hosts entries for CI/CD deploy targets - networking.hosts."192.168.1.50" = [ "server-public" ]; - networking.hosts."192.168.1.223" = [ "desktop" ]; + networking.hosts.${site_config.hosts.muffin.ip} = [ site_config.hosts.muffin.alias ]; + networking.hosts.${site_config.hosts.yarn.ip} = [ site_config.hosts.yarn.alias ]; - # SSH known_hosts for CI runner (pinned host keys) - environment.etc."ci-known-hosts".text = '' - server-public ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIFMjgaMnE+zS7tL+m5E7gh9Q9U1zurLdmU0qcmEmaucu - 192.168.1.50 ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIFMjgaMnE+zS7tL+m5E7gh9Q9U1zurLdmU0qcmEmaucu - git.sigkill.computer ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIFMjgaMnE+zS7tL+m5E7gh9Q9U1zurLdmU0qcmEmaucu - git.gardling.com ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIFMjgaMnE+zS7tL+m5E7gh9Q9U1zurLdmU0qcmEmaucu - ''; + # SSH known_hosts for CI runner (pinned host keys). All four names resolve to + # the same muffin host and therefore serve the same host key. + environment.etc."ci-known-hosts".text = + let + key = site_config.hosts.muffin.ssh_host_key; + names = [ + site_config.hosts.muffin.alias + site_config.hosts.muffin.ip + "git.${site_config.domain}" + "git.${site_config.old_domain}" + ]; + in + lib.concatMapStrings (n: "${n} ${key}\n") names; services.deployGuard.enable = true; @@ -149,9 +156,6 @@ }; }; - # Set your time zone. - time.timeZone = "America/New_York"; - hardware.graphics = { enable = true; extraPackages = with pkgs; [ @@ -183,10 +187,7 @@ ]; networking = { - nameservers = [ - "1.1.1.1" - "9.9.9.9" - ]; + nameservers = site_config.dns_servers; hostName = hostname; hostId = "0f712d56"; @@ -200,8 +201,7 @@ interfaces.${eth_interface} = { ipv4.addresses = [ { - address = "192.168.1.50"; - # address = "10.1.1.102"; + address = site_config.hosts.muffin.ip; prefixLength = 24; } ]; @@ -213,8 +213,7 @@ ]; }; defaultGateway = { - #address = "10.1.1.1"; - address = "192.168.1.1"; + address = site_config.lan.gateway; interface = eth_interface; }; # TODO! fix this diff --git a/hosts/muffin/service-configs.nix b/hosts/muffin/service-configs.nix index 3f20d4a..e8caa00 100644 --- a/hosts/muffin/service-configs.nix +++ b/hosts/muffin/service-configs.nix @@ -1,3 +1,4 @@ +{ site_config }: rec { zpool_ssds = "tank"; zpool_hdds = "hdds"; @@ -206,15 +207,9 @@ rec { }; }; - https = { - certs = services_dir + "/http_certs"; - domain = "sigkill.computer"; - old_domain = "gardling.com"; # Redirect traffic from old domain - }; - gitea = { dir = services_dir + "/gitea"; - domain = "git.${https.domain}"; + domain = "git.${site_config.domain}"; }; postgres = { @@ -278,19 +273,19 @@ rec { matrix = { dataDir = "/var/lib/continuwuity"; - domain = "matrix.${https.domain}"; + domain = "matrix.${site_config.domain}"; }; ntfy = { - domain = "ntfy.${https.domain}"; + domain = "ntfy.${site_config.domain}"; }; mollysocket = { - domain = "mollysocket.${https.domain}"; + domain = "mollysocket.${site_config.domain}"; }; livekit = { - domain = "livekit.${https.domain}"; + domain = "livekit.${site_config.domain}"; }; syncthing = { @@ -324,12 +319,12 @@ rec { }; firefox_syncserver = { - domain = "firefox-sync.${https.domain}"; + domain = "firefox-sync.${site_config.domain}"; }; grafana = { dir = services_dir + "/grafana"; - domain = "grafana.${https.domain}"; + domain = "grafana.${site_config.domain}"; }; trilium = { diff --git a/hosts/yarn/default.nix b/hosts/yarn/default.nix index 65217fe..e637214 100644 --- a/hosts/yarn/default.nix +++ b/hosts/yarn/default.nix @@ -4,6 +4,7 @@ lib, username, inputs, + site_config, ... }: { @@ -43,8 +44,8 @@ }; ipv4 = { method = "manual"; - address1 = "192.168.1.223/24,192.168.1.1"; - dns = "1.1.1.1;9.9.9.9;"; + address1 = "${site_config.hosts.yarn.ip}/24,${site_config.lan.gateway}"; + dns = lib.concatMapStrings (n: "${n};") site_config.dns_servers; }; ipv6.method = "disabled"; }; @@ -59,12 +60,12 @@ }; users.users.${username}.openssh.authorizedKeys.keys = [ - "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIO4jL6gYOunUlUtPvGdML0cpbKSsPNqQ1jit4E7U1RyH" # laptop + site_config.ssh_keys.laptop ]; users.users.root.openssh.authorizedKeys.keys = [ - "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIO4jL6gYOunUlUtPvGdML0cpbKSsPNqQ1jit4E7U1RyH" # laptop - "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIC5ZYN6idL/w/mUIfPOH1i+Q/SQXuzAMQUEuWpipx1Pc ci-deploy@muffin" + site_config.ssh_keys.laptop + site_config.ssh_keys.ci_deploy ]; programs.steam = { @@ -99,7 +100,7 @@ ] } - STORE_PATH=$(curl -sf --max-time 30 "https://nix-cache.sigkill.computer/deploy/yarn" || true) + STORE_PATH=$(curl -sf --max-time 30 "${site_config.binary_cache.url}/deploy/yarn" || true) if [ -z "$STORE_PATH" ]; then echo "server unreachable" exit 1 @@ -152,7 +153,7 @@ ( final: prev: let - deploy-url = "https://nix-cache.sigkill.computer/deploy/yarn"; + deploy-url = "${site_config.binary_cache.url}/deploy/yarn"; steamos-update-script = final.writeShellScript "steamos-update" '' export PATH=${ diff --git a/lib/default.nix b/lib/default.nix index 413c9c3..5ec3f1e 100644 --- a/lib/default.nix +++ b/lib/default.nix @@ -2,6 +2,7 @@ inputs, pkgs, service_configs, + site_config, lib ? inputs.nixpkgs-stable.lib, ... }: @@ -195,7 +196,7 @@ lib.extend ( assert (subdomain != null) != (domain != null); { config, ... }: let - vhostDomain = if domain != null then domain else "${subdomain}.${service_configs.https.domain}"; + vhostDomain = if domain != null then domain else "${subdomain}.${site_config.domain}"; upstream = if vpn then "${config.vpnNamespaces.wg.namespaceAddress}:${builtins.toString port}" diff --git a/modules/common.nix b/modules/common.nix index db4dd38..0d3fcb5 100644 --- a/modules/common.nix +++ b/modules/common.nix @@ -2,10 +2,15 @@ config, lib, pkgs, + site_config, username, ... }: { + # Shared timezone. Plain priority so it wins against srvos's mkDefault "UTC"; + # mreow overrides via lib.mkForce when travelling. + time.timeZone = site_config.timezone; + # Common Nix daemon settings. Host-specific overrides (binary cache substituters, # gc retention) live in the host's default.nix. nix = { diff --git a/modules/desktop-common.nix b/modules/desktop-common.nix index 26cddd0..e7c303a 100644 --- a/modules/desktop-common.nix +++ b/modules/desktop-common.nix @@ -5,6 +5,7 @@ lib, username, inputs, + site_config, niri-package, ... }: @@ -64,11 +65,11 @@ swapDevices = [ ]; # Desktop-specific Nix cache — muffin serves it, desktops consume. - # Base nix settings (optimise, gc, experimental-features) come from common-nix.nix. + # Base nix settings (optimise, gc, experimental-features) come from common.nix. nix.settings = { - substituters = [ "https://nix-cache.sigkill.computer" ]; + substituters = [ site_config.binary_cache.url ]; trusted-public-keys = [ - "nix-cache.sigkill.computer-1:ONtQC9gUjL+2yNgMWB68NudPySXhyzJ7I3ra56/NPgk=" + site_config.binary_cache.public_key ]; netrc-file = "${../secrets/desktop/nix-cache-netrc}"; }; @@ -337,12 +338,6 @@ "msr" "btusb" ]; - - kernelParams = [ - # 1gb huge pages - "hugepagesz=1G" - "hugepages=3" - ]; }; services = { @@ -381,9 +376,6 @@ }; }; - # EST - time.timeZone = "America/New_York"; - # Select internationalisation properties. i18n.defaultLocale = "en_US.UTF-8"; diff --git a/modules/desktop-networkmanager.nix b/modules/desktop-networkmanager.nix index 428783e..7cb6265 100644 --- a/modules/desktop-networkmanager.nix +++ b/modules/desktop-networkmanager.nix @@ -1,4 +1,4 @@ -{ hostname, ... }: +{ hostname, site_config, ... }: { # speed up boot times (by about three seconds) systemd.services.NetworkManager-wait-online.enable = false; @@ -9,10 +9,7 @@ networkmanager = { enable = true; - appendNameservers = [ - "1.1.1.1" - "9.9.9.9" - ]; + appendNameservers = site_config.dns_servers; wifi = { scanRandMacAddress = true; diff --git a/services/bitwarden.nix b/services/bitwarden.nix index 87547a8..4a6df91 100644 --- a/services/bitwarden.nix +++ b/services/bitwarden.nix @@ -2,6 +2,7 @@ config, lib, pkgs, + site_config, service_configs, ... }: @@ -25,7 +26,7 @@ configurePostgres = true; config = { # Refer to https://github.com/dani-garcia/vaultwarden/blob/main/.env.template - DOMAIN = "https://bitwarden.${service_configs.https.domain}"; + DOMAIN = "https://bitwarden.${site_config.domain}"; SIGNUPS_ALLOWED = false; ROCKET_ADDRESS = "127.0.0.1"; @@ -34,7 +35,7 @@ }; }; - services.caddy.virtualHosts."bitwarden.${service_configs.https.domain}".extraConfig = '' + services.caddy.virtualHosts."bitwarden.${site_config.domain}".extraConfig = '' encode zstd gzip reverse_proxy :${toString config.services.vaultwarden.config.ROCKET_PORT} { diff --git a/services/caddy/caddy.nix b/services/caddy/caddy.nix index 6481c8d..6624fb9 100644 --- a/services/caddy/caddy.nix +++ b/services/caddy/caddy.nix @@ -1,5 +1,6 @@ { config, + site_config, service_configs, pkgs, lib, @@ -42,8 +43,8 @@ let ''; }; - newDomain = service_configs.https.domain; - oldDomain = service_configs.https.old_domain; + newDomain = site_config.domain; + oldDomain = site_config.old_domain; in { imports = [ @@ -54,7 +55,7 @@ in services.caddy = { enable = true; - email = "titaniumtown@proton.me"; + email = site_config.contact_email; # Build with Njalla DNS provider for DNS-01 ACME challenges (wildcard certs) package = pkgs.caddy.withPlugins { @@ -146,8 +147,9 @@ in # defaults: maxretry=5, findtime=10m, bantime=10m # Ignore local network IPs - NAT hairpinning causes all LAN traffic to - # appear from the router IP (192.168.1.1). Banning it blocks all internal access. - ignoreip = "127.0.0.1/8 ::1 192.168.1.0/24"; + # appear from the router IP (site_config.lan.gateway). Banning it + # blocks all internal access. + ignoreip = "127.0.0.1/8 ::1 ${site_config.lan.cidr}"; }; filter.Definition = { # Only match 401s where an Authorization header was actually sent. diff --git a/services/caddy/caddy_senior_project.nix b/services/caddy/caddy_senior_project.nix index 637eafc..b2d4c71 100644 --- a/services/caddy/caddy_senior_project.nix +++ b/services/caddy/caddy_senior_project.nix @@ -2,6 +2,7 @@ config, lib, pkgs, + site_config, service_configs, inputs, ... @@ -32,7 +33,7 @@ let }; in { - services.caddy.virtualHosts."senior-project.${service_configs.https.domain}".extraConfig = '' + services.caddy.virtualHosts."senior-project.${site_config.domain}".extraConfig = '' root * ${hugoWebsite} file_server browse ''; diff --git a/services/graphing-calculator.nix b/services/graphing-calculator.nix index 95aa1e2..1c429ca 100644 --- a/services/graphing-calculator.nix +++ b/services/graphing-calculator.nix @@ -1,4 +1,5 @@ { + site_config, service_configs, inputs, pkgs, @@ -9,7 +10,7 @@ let inputs.ytbn-graphing-software.packages.${pkgs.stdenv.targetPlatform.system}.web; in { - services.caddy.virtualHosts."graphing.${service_configs.https.domain}".extraConfig = '' + services.caddy.virtualHosts."graphing.${site_config.domain}".extraConfig = '' root * ${graphing-calculator} file_server browse ''; diff --git a/services/harmonia.nix b/services/harmonia.nix index 70dd784..93f5a76 100644 --- a/services/harmonia.nix +++ b/services/harmonia.nix @@ -1,6 +1,7 @@ { config, lib, + site_config, service_configs, ... }: @@ -19,7 +20,7 @@ # serve latest deploy store paths (unauthenticated — just a path string) # CI writes to /var/lib/nix-deploy/ after building - services.caddy.virtualHosts."nix-cache.${service_configs.https.domain}".extraConfig = '' + services.caddy.virtualHosts."nix-cache.${site_config.domain}".extraConfig = '' handle_path /deploy/* { root * /var/lib/nix-deploy file_server diff --git a/services/jellyfin/jellyfin.nix b/services/jellyfin/jellyfin.nix index d37df91..5b69768 100644 --- a/services/jellyfin/jellyfin.nix +++ b/services/jellyfin/jellyfin.nix @@ -1,6 +1,7 @@ { pkgs, config, + site_config, service_configs, lib, ... @@ -24,7 +25,7 @@ inherit (service_configs.jellyfin) dataDir cacheDir; }; - services.caddy.virtualHosts."jellyfin.${service_configs.https.domain}".extraConfig = '' + services.caddy.virtualHosts."jellyfin.${site_config.domain}".extraConfig = '' reverse_proxy :${builtins.toString service_configs.ports.private.jellyfin.port} { # Disable response buffering for streaming. Caddy's default partial # buffering delays fMP4-HLS segments and direct-play responses where diff --git a/services/llama-cpp.nix b/services/llama-cpp.nix index ce6de79..7676154 100644 --- a/services/llama-cpp.nix +++ b/services/llama-cpp.nix @@ -1,5 +1,6 @@ { pkgs, + site_config, service_configs, config, inputs, @@ -24,7 +25,7 @@ in # "Invalid API Key" warning has no client IP, and behind Caddy the # llama-server access log only sees 127.0.0.1. Caddy's JSON log has # the real client IP via request.remote_ip. - services.caddy.virtualHosts."llm.${service_configs.https.domain}".extraConfig = '' + services.caddy.virtualHosts."llm.${site_config.domain}".extraConfig = '' log { output file /var/log/caddy/access-llama-cpp.log format json @@ -52,8 +53,8 @@ in # defaults: maxretry=5, findtime=10m, bantime=10m # NAT hairpinning sends LAN traffic via the router IP. Don't ban - # 192.168.1.0/24 or we lock ourselves out. - ignoreip = "127.0.0.1/8 ::1 192.168.1.0/24"; + # our LAN or we lock ourselves out. + ignoreip = "127.0.0.1/8 ::1 ${site_config.lan.cidr}"; }; filter.Definition = { failregex = ''^.*"remote_ip":"".*"status":401.*$''; diff --git a/services/matrix/coturn.nix b/services/matrix/coturn.nix index 4dfd8d3..f6a7432 100644 --- a/services/matrix/coturn.nix +++ b/services/matrix/coturn.nix @@ -1,13 +1,14 @@ { config, lib, + site_config, service_configs, ... }: { services.coturn = { enable = true; - realm = service_configs.https.domain; + realm = site_config.domain; use-auth-secret = true; static-auth-secret-file = config.age.secrets.coturn-auth-secret.path; listening-port = service_configs.ports.public.coturn.port; diff --git a/services/matrix/matrix.nix b/services/matrix/matrix.nix index fea48c3..b85ffff 100644 --- a/services/matrix/matrix.nix +++ b/services/matrix/matrix.nix @@ -1,5 +1,6 @@ { config, + site_config, service_configs, lib, ... @@ -23,7 +24,7 @@ settings.global = { port = [ service_configs.ports.private.matrix.port ]; - server_name = service_configs.https.domain; + server_name = site_config.domain; allow_registration = true; registration_token_file = config.age.secrets.matrix-reg-token.path; @@ -43,14 +44,14 @@ # TURN server config (coturn) turn_secret_file = config.age.secrets.matrix-turn-secret.path; turn_uris = [ - "turn:${service_configs.https.domain}?transport=udp" - "turn:${service_configs.https.domain}?transport=tcp" + "turn:${site_config.domain}?transport=udp" + "turn:${site_config.domain}?transport=tcp" ]; turn_ttl = 86400; }; }; - services.caddy.virtualHosts.${service_configs.https.domain}.extraConfig = lib.mkBefore '' + services.caddy.virtualHosts.${site_config.domain}.extraConfig = lib.mkBefore '' header /.well-known/matrix/* Content-Type application/json header /.well-known/matrix/* Access-Control-Allow-Origin * respond /.well-known/matrix/server `{"m.server": "${service_configs.matrix.domain}:${builtins.toString service_configs.ports.public.https.port}"}` diff --git a/services/minecraft.nix b/services/minecraft.nix index 2882079..834295b 100644 --- a/services/minecraft.nix +++ b/services/minecraft.nix @@ -1,5 +1,6 @@ { pkgs, + site_config, service_configs, lib, config, @@ -177,7 +178,7 @@ }; services.caddy.virtualHosts = lib.mkIf (config.services.caddy.enable) { - "map.${service_configs.https.domain}".extraConfig = '' + "map.${site_config.domain}".extraConfig = '' root * ${service_configs.minecraft.parent_dir}/${service_configs.minecraft.server_name}/squaremap/web file_server browse ''; diff --git a/services/ssh.nix b/services/ssh.nix index e0f2a4f..7aecb47 100644 --- a/services/ssh.nix +++ b/services/ssh.nix @@ -2,6 +2,7 @@ config, lib, pkgs, + site_config, username, ... }: @@ -25,14 +26,14 @@ ]; users.users.${username}.openssh.authorizedKeys.keys = [ - "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIO4jL6gYOunUlUtPvGdML0cpbKSsPNqQ1jit4E7U1RyH" # laptop - "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIBJjT5QZ3zRDb+V6Em20EYpSEgPW5e/U+06uQGJdraxi" # desktop + site_config.ssh_keys.laptop + site_config.ssh_keys.desktop ]; # used for deploying configs to server users.users.root.openssh.authorizedKeys.keys = config.users.users.${username}.openssh.authorizedKeys.keys ++ [ - "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIC5ZYN6idL/w/mUIfPOH1i+Q/SQXuzAMQUEuWpipx1Pc ci-deploy@muffin" + site_config.ssh_keys.ci_deploy ]; } diff --git a/site-config.nix b/site-config.nix new file mode 100644 index 0000000..5c3ee31 --- /dev/null +++ b/site-config.nix @@ -0,0 +1,63 @@ +# Site-wide constants shared across all three hosts and home-manager profiles. +# +# This file is pure data — no package refs, no module config. Import it from +# flake.nix and pass it as the `site_config` specialArg (and extraSpecialArg for +# home-manager). Callers read values; they do not set them. +# +# Adding a value: only add if it's used by ≥2 hosts/modules. Host-specific +# single-use values stay in the host's default.nix. Muffin-only service +# infrastructure (ports, zpool names, hugepage budgets) stays in +# hosts/muffin/service-configs.nix. +rec { + # --- Identity --- + domain = "sigkill.computer"; + old_domain = "gardling.com"; # served by muffin via permanent redirect (services/caddy/caddy.nix) + contact_email = "titaniumtown@proton.me"; + + # All three hosts run on the same timezone. Override per-host via + # lib.mkForce when travelling (see hosts/mreow/default.nix for the pattern). + timezone = "America/New_York"; + + # --- Binary cache (muffin serves via harmonia, desktops consume) --- + binary_cache = { + url = "https://nix-cache.${domain}"; + public_key = "nix-cache.${domain}-1:ONtQC9gUjL+2yNgMWB68NudPySXhyzJ7I3ra56/NPgk="; + }; + + # --- LAN topology --- + dns_servers = [ + "1.1.1.1" + "9.9.9.9" + ]; + + lan = { + cidr = "192.168.1.0/24"; + gateway = "192.168.1.1"; + }; + + # Per-host network info. mreow is laptop-on-DHCP so it has no entry. + hosts = { + muffin = { + ip = "192.168.1.50"; + # Canonical alias used by deploy.sh, CI workflows, and borg backup target. + # Resolves via /etc/hosts on muffin and the desktops' NetworkManager DNS. + alias = "server-public"; + # SSH host key — same key is served for every alias muffin answers to + # (server-public, the IP, git.${domain}, git.${old_domain}). + ssh_host_key = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIFMjgaMnE+zS7tL+m5E7gh9Q9U1zurLdmU0qcmEmaucu"; + }; + yarn = { + ip = "192.168.1.223"; + alias = "desktop"; + }; + }; + + # --- SSH pubkeys --- + # One line per key, referenced by name from services/ssh.nix (muffin) and + # hosts/yarn/default.nix. Rotating a key means changing it here, nowhere else. + ssh_keys = { + laptop = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIO4jL6gYOunUlUtPvGdML0cpbKSsPNqQ1jit4E7U1RyH"; + desktop = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIBJjT5QZ3zRDb+V6Em20EYpSEgPW5e/U+06uQGJdraxi"; + ci_deploy = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIC5ZYN6idL/w/mUIfPOH1i+Q/SQXuzAMQUEuWpipx1Pc ci-deploy@muffin"; + }; +} diff --git a/tests/deploy-guard.nix b/tests/deploy-guard.nix index aa35aad..75c58f3 100644 --- a/tests/deploy-guard.nix +++ b/tests/deploy-guard.nix @@ -12,10 +12,10 @@ ... }: let - baseServiceConfigs = import ../hosts/muffin/service-configs.nix; + baseSiteConfig = import ../site-config.nix; + baseServiceConfigs = import ../hosts/muffin/service-configs.nix { site_config = baseSiteConfig; }; testServiceConfigs = lib.recursiveUpdate baseServiceConfigs { zpool_ssds = ""; - https.domain = "test.local"; }; alwaysOk = pkgs.writeShellApplication { diff --git a/tests/fail2ban/gitea.nix b/tests/fail2ban/gitea.nix index 0f69106..803e15d 100644 --- a/tests/fail2ban/gitea.nix +++ b/tests/fail2ban/gitea.nix @@ -5,7 +5,10 @@ ... }: let - baseServiceConfigs = import ../../hosts/muffin/service-configs.nix; + baseSiteConfig = import ../../site-config.nix; + baseServiceConfigs = import ../../hosts/muffin/service-configs.nix { + site_config = baseSiteConfig; + }; testServiceConfigs = lib.recursiveUpdate baseServiceConfigs { zpool_ssds = ""; gitea = { diff --git a/tests/fail2ban/immich.nix b/tests/fail2ban/immich.nix index 29f08b9..bf04d85 100644 --- a/tests/fail2ban/immich.nix +++ b/tests/fail2ban/immich.nix @@ -5,10 +5,12 @@ ... }: let - baseServiceConfigs = import ../../hosts/muffin/service-configs.nix; + baseSiteConfig = import ../../site-config.nix; + baseServiceConfigs = import ../../hosts/muffin/service-configs.nix { + site_config = baseSiteConfig; + }; testServiceConfigs = lib.recursiveUpdate baseServiceConfigs { zpool_ssds = ""; - https.domain = "test.local"; ports.private.immich = { port = 2283; proto = "tcp"; diff --git a/tests/fail2ban/jellyfin.nix b/tests/fail2ban/jellyfin.nix index 98a509d..bf24b04 100644 --- a/tests/fail2ban/jellyfin.nix +++ b/tests/fail2ban/jellyfin.nix @@ -5,10 +5,12 @@ ... }: let - baseServiceConfigs = import ../../hosts/muffin/service-configs.nix; + baseSiteConfig = import ../../site-config.nix; + baseServiceConfigs = import ../../hosts/muffin/service-configs.nix { + site_config = baseSiteConfig; + }; testServiceConfigs = lib.recursiveUpdate baseServiceConfigs { zpool_ssds = ""; - https.domain = "test.local"; jellyfin = { dataDir = "/var/lib/jellyfin"; cacheDir = "/var/cache/jellyfin"; @@ -33,6 +35,7 @@ let (import ../../services/jellyfin/jellyfin.nix { inherit config pkgs; lib = testLib; + site_config = baseSiteConfig; service_configs = testServiceConfigs; }) ]; diff --git a/tests/fail2ban/vaultwarden.nix b/tests/fail2ban/vaultwarden.nix index 2d49522..361069f 100644 --- a/tests/fail2ban/vaultwarden.nix +++ b/tests/fail2ban/vaultwarden.nix @@ -5,10 +5,12 @@ ... }: let - baseServiceConfigs = import ../../hosts/muffin/service-configs.nix; + baseSiteConfig = import ../../site-config.nix; + baseServiceConfigs = import ../../hosts/muffin/service-configs.nix { + site_config = baseSiteConfig; + }; testServiceConfigs = lib.recursiveUpdate baseServiceConfigs { zpool_ssds = ""; - https.domain = "test.local"; }; testLib = lib.extend ( @@ -28,6 +30,7 @@ let (import ../../services/bitwarden.nix { inherit config pkgs; lib = testLib; + site_config = baseSiteConfig; service_configs = testServiceConfigs; }) ]; diff --git a/tests/minecraft.nix b/tests/minecraft.nix index 1e59125..69b5477 100644 --- a/tests/minecraft.nix +++ b/tests/minecraft.nix @@ -6,10 +6,10 @@ ... }: let - baseServiceConfigs = import ../hosts/muffin/service-configs.nix; + baseSiteConfig = import ../site-config.nix; + baseServiceConfigs = import ../hosts/muffin/service-configs.nix { site_config = baseSiteConfig; }; testServiceConfigs = lib.recursiveUpdate baseServiceConfigs { zpool_ssds = ""; - https.domain = "test.local"; minecraft.parent_dir = "/var/lib/minecraft"; minecraft.memory = rec { heap_size_m = 1000; @@ -31,6 +31,7 @@ testPkgs.testers.runNixOSTest { node.specialArgs = { inherit inputs lib; + site_config = baseSiteConfig; service_configs = testServiceConfigs; username = "testuser"; };