{ config, lib, pkgs, ... }: with lib; let primaryIp = "10.0.0.1"; hostname = config.instance.hostname; domSecrets = config.fudo.secrets.files.domain-secrets."${config.instance.local-domain}"; hostSecrets = config.fudo.secrets.host-secrets."${hostname}"; authentikHost = "authentik.fudo.org"; in { config = { networking = { enableIPv6 = true; interfaces = { enp1s0.useDHCP = true; intif0 = { useDHCP = false; ipv4 = { addresses = [{ address = primaryIp; prefixLength = 16; }]; routes = [{ address = "192.168.86.0"; prefixLength = 24; via = "10.0.0.3"; }]; }; }; }; firewall = { # Until it becomes the gateway, this is necessary # enable = mkForce true; allowedTCPPorts = [ 80 443 25565 config.services.murmur.port ]; allowedUDPPorts = [ 25565 34197 ]; }; nat = { enableIPv6 = true; forwardPorts = [ # Minecraft { destination = "10.0.0.12:25555"; proto = "tcp"; sourcePort = 25565; } { destination = "10.0.0.12:25555"; proto = "udp"; sourcePort = 25565; } # Factorio { destination = "10.0.0.12:34197"; proto = "udp"; sourcePort = 34197; } ]; }; }; virtualisation = { podman = { enable = true; dockerSocket.enable = true; autoPrune.enable = true; }; docker.enable = false; oci-containers = { backend = "podman"; containers = { "sea-cam-auth-proxy" = { image = "ghcr.io/goauthentik/proxy"; autoStart = true; environmentFiles = [ hostSecrets.sea-cam-auth-proxy-env.target-file ]; ports = [ "9000:9000" ]; }; "sea-red-auth-proxy" = { image = "ghcr.io/goauthentik/proxy"; autoStart = true; environmentFiles = [ hostSecrets.sea-red-auth-proxy-env.target-file ]; ports = [ "9001:9000" ]; }; }; }; }; fudo = { hosts.fimbria.external-interfaces = [ "enp1s0" ]; client.dns.external-interface = "enp1s0"; local-network.state-directory = "/state/services/local-network"; secrets.host-secrets."${hostname}" = { sea-cam-auth-proxy-env = { source-file = let token = removeSuffix "\n" (readFile domSecrets."seattle-camera-auth-proxy.token"); in pkgs.writeText "sea-cam-auth-proxy.env" '' AUTHENTIK_HOST=https://${authentikHost}/; AUTHENTIK_TOKEN=${token} AUTHENTIK_INSECURE=0 ''; target-file = "/run/sea-cam-auth-proxy/env"; }; sea-red-auth-proxy-env = { source-file = let token = removeSuffix "\n" (readFile domSecrets."seattle-red-auth-proxy.token"); in pkgs.writeText "sea-red-auth-proxy.env" '' AUTHENTIK_HOST=https://${authentikHost}/; AUTHENTIK_TOKEN=${token} AUTHENTIK_INSECURE=0 ''; target-file = "/run/sea-red-auth-proxy/env"; }; }; services = { local-network = { enable = true; internal-interfaces = [ "intif0" ]; external-interface = "enp1s0"; dns-filter-proxy.enable = true; }; metrics = { prometheus.state-directory = "/state/services/prometheus"; }; auth.kerberos.state-directory = "/state/services/heimdal-kdc"; }; }; security.acme.defaults.email = "niten@fudo.org"; systemd.services = { nginx = { after = [ "bind.service" ]; requires = [ "bind.service" ]; }; podman-sea-cam-auth-proxy.after = [ "network-online.service" ]; podman-sea-red-auth-proxy.after = [ "network-online.service" ]; }; services = { ## TODO: enable when ready nginx = { enable = true; recommendedGzipSettings = true; recommendedOptimisation = true; recommendedProxySettings = true; virtualHosts = let authenticatedPassthrough = { target, authPort }: { enableACME = true; forceSSL = true; locations = { "/" = { proxyPass = target; proxyWebsockets = true; extraConfig = '' ############################## # authentik-specific config ############################## auth_request /outpost.goauthentik.io/auth/nginx; error_page 401 = @goauthentik_proxy_signin; auth_request_set $auth_cookie $upstream_http_set_cookie; add_header Set-Cookie $auth_cookie; # translate headers from the outposts back to the actual upstream auth_request_set $authentik_username $upstream_http_x_authentik_username; auth_request_set $authentik_groups $upstream_http_x_authentik_groups; auth_request_set $authentik_email $upstream_http_x_authentik_email; auth_request_set $authentik_name $upstream_http_x_authentik_name; auth_request_set $authentik_uid $upstream_http_x_authentik_uid; proxy_set_header X-authentik-username $authentik_username; proxy_set_header X-authentik-groups $authentik_groups; proxy_set_header X-authentik-email $authentik_email; proxy_set_header X-authentik-name $authentik_name; proxy_set_header X-authentik-uid $authentik_uid; ''; }; "/outpost.goauthentik.io" = { proxyPass = "http://127.0.0.1:${ toString authPort }/outpost.goauthentik.io"; extraConfig = '' proxy_set_header X-Forwarded-Host $host; proxy_set_header X-Original-URL $scheme://$http_host$request_uri; add_header Set-Cookie $auth_cookie; auth_request_set $auth_cookie $upstream_http_set_cookie; proxy_pass_request_body off; proxy_set_header Content-Length ""; ''; }; "@goauthentik_proxy_signin" = { return = "302 /outpost.goauthentik.io/start?rd=$request_uri"; extraConfig = '' add_header Set-Cookie $auth_cookie; internal; ''; }; }; }; in { "sea-home.fudo.link" = { enableACME = true; forceSSL = true; locations."/" = { proxyPass = "http://home-assist.sea.fudo.org/"; extraConfig = '' proxy_http_version 1.1; proxy_set_header Upgrade $http_upgrade; proxy_set_header Connection "Upgrade"; ''; }; }; "sea-cam.fudo.link" = authenticatedPassthrough { target = "http://frigate.sea.fudo.org/"; authPort = 9000; }; "sea-red.fudo.link" = authenticatedPassthrough { target = "http://node-red.sea.fudo.org/"; authPort = 9001; }; "metrics.fudo.link" = { enableACME = true; forceSSL = true; locations."/" = { proxyPass = "http://prometheus.sea.fudo.org"; extraConfig = let trustedNetworkClauses = map (nw: "allow ${nw};") (config.instance.local-networks ++ config.fudo.domains."fudo.org".local-networks); in concatStringsSep "\n" (trustedNetworkClauses ++ [ "deny all;" ]); }; }; "pics.fudo.link" = { enableACME = true; forceSSL = true; locations."/" = { proxyPass = "http://immich.sea.fudo.org/"; proxyWebsockets = true; recommendedProxySettings = true; extraConfig = '' client_max_body_size 1024M; ''; }; }; }; }; murmur = { enable = true; port = 64738; bonjour = true; password = "thelittleschool"; }; openssh = { hostKeys = [ { path = "/state/ssh/ssh_host_ed25519_key"; type = "ed25519"; } { path = "/state/ssh/ssh_host_rsa_key"; type = "rsa"; bits = 4096; } ]; }; }; }; }