{ config, lib, pkgs, ... }: let atriDotDad = "atri.dad"; atashDotDev = "atash.dev"; matrixDomain = "matrix.${atriDotDad}"; matrixRtcDomain = "matrixrtc.${atriDotDad}"; upstream = "lloyd.tadpole-pain.ts.net"; streamPorts = [ 69 420 25565 25566 25567 ]; wellKnownServer = builtins.toJSON { "m.server" = "${matrixDomain}:443"; }; wellKnownClient = builtins.toJSON { "m.homeserver" = { base_url = "https://${matrixDomain}"; }; "org.matrix.msc4143.rtc_foci" = [ { type = "livekit"; livekit_service_url = "https://${matrixDomain}/livekit/jwt"; } ]; }; mkProxy = port: '' reverse_proxy http://${upstream}:${toString port} ''; aiBotsMatcher = '' @fuckai { header_regexp User-Agent "(?i)(GPTBot|ChatGPT-User|OAI-SearchBot|ChatGPT-Browser|ClaudeBot|Claude-Web|Claude-SearchBot|anthropic-ai|Anthropic-Claude|xAI-Bot|DeepseekBot|Google-Extended|Gemini-Ai|Gemini-Deep-Research|Google-CloudVertexBot|Google-NotebookLM|GoogleAgent-Mariner|Bard-Ai|FacebookBot|Meta-ExternalAgent|meta-webindexer|Applebot-Extended|bingbot|CCBot|PerplexityBot|Perplexity-User|Bytespider|Diffbot|Amazonbot|cohere-ai|Cohere-Command|YouBot|Omgilibot|ImagesiftBot|AI2Bot|Andibot|bigsur.ai|Brightbot|TerraCotta|Character-AI|Devin|Crawlspace|DuckAssistBot|FirecrawlAgent|Groq-Bot|HuggingFace-Bot|IbouBot|MistralAI-User|Replicate-Bot|RunPod-Bot|TimpiBot|Together-Bot|Kangaroo Bot|PanguBot|Cotoyogi|Webzio-Extended)" } abort @fuckai ''; mkSocatService = port: proto: lib.nameValuePair "socat-${proto}-${toString port}" { description = "Socat ${proto} proxy for port ${toString port}"; after = [ "network-online.target" "tailscaled.service" ]; wants = [ "network-online.target" ]; wantedBy = [ "multi-user.target" ]; serviceConfig = { ExecStart = "${pkgs.socat}/bin/socat ${lib.toUpper proto}-LISTEN:${toString port},fork,reuseaddr ${lib.toUpper proto}:${upstream}:${toString port}"; Restart = "on-failure"; RestartSec = "5s"; DynamicUser = true; AmbientCapabilities = [ "CAP_NET_BIND_SERVICE" ]; }; }; in { services.caddy = { enable = true; email = "me@${atriDotDad}"; extraConfig = '' ${atriDotDad} { ${aiBotsMatcher} handle /.well-known/matrix/server { header Content-Type application/json header X-Content-Type-Options nosniff respond `${wellKnownServer}` 200 } handle /.well-known/matrix/client { header Content-Type application/json header Access-Control-Allow-Origin "*" header Vary Origin header X-Content-Type-Options nosniff respond `${wellKnownClient}` 200 } handle { reverse_proxy http://${upstream}:3000 } } analytics.${atriDotDad} { ${aiBotsMatcher} ${mkProxy 30060} } archive.${atriDotDad} { ${aiBotsMatcher} ${mkProxy 30288} } ascently.${atriDotDad} { ${aiBotsMatcher} ${mkProxy 8838} } chef.${atriDotDad} { ${aiBotsMatcher} ${mkProxy 30111} } democlimb.${atriDotDad} { ${aiBotsMatcher} ${mkProxy 8008} } fedi.${atriDotDad} { ${aiBotsMatcher} ${mkProxy 8181} } gist.${atriDotDad} { ${aiBotsMatcher} ${mkProxy 1227} } git.${atriDotDad} { ${aiBotsMatcher} ${mkProxy 30010} } links.${atriDotDad} { ${aiBotsMatcher} ${mkProxy 30243} } memos.${atriDotDad} { ${aiBotsMatcher} ${mkProxy 30311} } mermaid.${atriDotDad} { ${aiBotsMatcher} ${mkProxy 8280} } msrc.${atriDotDad} { ${aiBotsMatcher} ${mkProxy 3311} } openclimb.${atriDotDad} { ${aiBotsMatcher} ${mkProxy 1337} } photos.${atriDotDad} { ${aiBotsMatcher} ${mkProxy 30041} } pods.${atriDotDad} { ${aiBotsMatcher} ${mkProxy 30067} } requests.${atriDotDad} { ${aiBotsMatcher} ${mkProxy 30042} } s3.${atriDotDad} { ${aiBotsMatcher} ${mkProxy 30188} } search.${atriDotDad} { ${aiBotsMatcher} ${mkProxy 30053} } vault.${atriDotDad} { ${aiBotsMatcher} ${mkProxy 30032} } vids.${atriDotDad} { ${aiBotsMatcher} ${mkProxy 31008} } music.${atriDotDad} { ${aiBotsMatcher} ${mkProxy 30043} } books.${atriDotDad} { ${aiBotsMatcher} ${mkProxy 31067} } tv.${atriDotDad} { ${aiBotsMatcher} request_body { max_size 20GB } reverse_proxy http://${upstream}:30013 { flush_interval -1 } } ${matrixDomain} { request_body { max_size 100MB } handle_path /livekit/jwt/* { @allowed path /sfu/get /get_token /healthz handle @allowed { reverse_proxy http://[::1]:${toString config.services.lk-jwt-service.port} } handle { respond 404 } } handle { reverse_proxy http://[::1]:6167 } } ${matrixRtcDomain} { reverse_proxy http://[::1]:${toString config.services.livekit.settings.port} { flush_interval -1 } } ripkyle.org { ${aiBotsMatcher} ${mkProxy 4321} } ${atashDotDev} { ${aiBotsMatcher} ${mkProxy 6969} } chronus.${atashDotDev} { ${aiBotsMatcher} ${mkProxy 7337} } ''; }; systemd.services = lib.listToAttrs ( (map (port: mkSocatService port "tcp") streamPorts) ++ (map (port: mkSocatService port "udp") streamPorts) ); networking.firewall = { allowedTCPPorts = [ 80 443 ] ++ streamPorts; allowedUDPPorts = streamPorts; }; }