/ modules / nixos / services / caddy.nix
caddy.nix
  1  {
  2    lib,
  3    config,
  4    ...
  5  }:
  6  {
  7    # NOTE: enormous thanks to blog post: aottr.dev/posts/2024/08/homelab-setting-up-caddy-reverse-proxy-with-ssl-on-nixos/
  8    # certloc = "/var/lib/acme/openws.org";
  9    # # NOTE: TLS disabled as https is handled by cloudflare tunnel
 10    # tlsConfig = ''
 11    #   # tls ${certloc}/cert.pem ${certloc}/key.pem {
 12    #   #   protocols tls1.3
 13    #   # }
 14    # '';
 15  
 16    services.caddy = {
 17      email = config.security.acme.defaults.email;
 18      enable = config.networking.hostName == "framework-desktop";
 19  
 20      globalConfig = ''
 21        metrics {
 22          per_host
 23        }
 24  
 25        servers {
 26          # Cloudflare IP ranges from https://www.cloudflare.com/en-gb/ips/
 27          trusted_proxies static 173.245.48.0/20 103.21.244.0/22 103.22.200.0/22 103.31.4.0/22 141.101.64.0/18 108.162.192.0/18 190.93.240.0/20 188.114.96.0/20 197.234.240.0/22 198.41.128.0/17 162.158.0.0/15 104.16.0.0/13 104.24.0.0/14 172.64.0.0/13 131.0.72.0/22 2400:cb00::/32 2606:4700::/32 2803:f800::/32 2405:b500::/32 2405:8100::/32 2a06:98c0::/29 2c0f:f248::/32
 28  
 29          # Use CF-Connecting-IP to determine the client IP instead of XFF
 30          # https://caddyserver.com/docs/caddyfile/options#client-ip-headers
 31          client_ip_headers CF-Connecting-IP
 32        }
 33      '';
 34  
 35      virtualHosts = lib.mkMerge [
 36        (lib.concatMapAttrs
 37          (
 38            domain: hosts:
 39            lib.mapAttrs' (
 40              name: upstream:
 41              lib.nameValuePair "http://${name}.${domain}" {
 42                extraConfig = ''
 43                  reverse_proxy ${upstream}
 44                '';
 45              }
 46            ) hosts
 47          )
 48          {
 49            "openws.org" = {
 50              penpot = ":81";
 51              admin = ":1212";
 52              excalidraw = ":81";
 53              registry = ":5000";
 54              rpi5 = "rpi5-8:7681";
 55              emacs = "rpi5-8:7682";
 56              neovim = "rpi5-8:7683";
 57              freebsd = "msi-ge76:7681";
 58              mirror = config.services.anubis.instances.mirror.settings.TARGET;
 59            };
 60  
 61            "apidaesystems.ca" = {
 62              crm = ":81";
 63              portal = ":81";
 64              sentry = ":81";
 65              supabase = ":81";
 66              minio = "rpi5-16";
 67              horizon = "rpi5-8";
 68              registry = "rpi5-16";
 69              admin = "rpi5-16:3000";
 70              rutx11 = "100.111.144.127";
 71              ceratina = "http://rutx11:3000";
 72              halow = "http://halowlink2-6c7f";
 73            };
 74          }
 75        )
 76        # (lib.concatMapAttrs
 77        #   (
 78        #     domain: hosts:
 79        #     lib.mapAttrs' (
 80        #       name: upstream:
 81        #       lib.nameValuePair "http://${name}.${domain}" {
 82        #         extraConfig = ''
 83        #           reverse_proxy ${upstream} {
 84        #             transport http {
 85        #               tls_insecure_skip_verify
 86        #             }
 87        #           }
 88        #         '';
 89        #       }
 90        #     ) hosts
 91        #   )
 92        #   {
 93        #     "openws.org" = {
 94        #       proxmox = ":8006";
 95        #     };
 96        #   }
 97        # )
 98        (lib.mapAttrs'
 99          (
100            name: upstream:
101            lib.nameValuePair "http://${name}" {
102              extraConfig = ''
103                reverse_proxy ${upstream} {
104                  header_up X-Forwarded-For {client_ip}
105                  header_up X-Real-IP {client_ip}
106                  header_up X-Http-Version {http.request.proto}
107                }
108              '';
109            }
110          )
111          {
112            "microvisor.systems" = "http://10.0.0.236";
113            "tandemrobotics.ca" = config.services.anubis.instances.tandemrobotics.settings.BIND;
114          }
115        )
116        {
117          "http://manzikert.ca".extraConfig = "reverse_proxy :81";
118          "http://www.manzikert.ca".extraConfig = "reverse_proxy :81";
119          "http://apidaesystems.ca".extraConfig = "redir https://www.apidaesystems.ca";
120  
121          "http://openws.org".extraConfig = ''
122            reverse_proxy http://${config.services.anubis.instances.homepage-dashboard.settings.BIND} {
123              header_up X-Forwarded-For {client_ip}
124              header_up X-Real-IP {client_ip}
125              header_up X-Http-Version {http.request.proto}
126            }
127          ''
128          + lib.optionalString config.services.grafana.enable ''
129            handle /grafana* {
130              reverse_proxy :${toString config.services.grafana.settings.server.http_port}
131            }
132          ''
133          + lib.optionalString config.services.plantuml-server.enable ''
134            handle /plantuml* {
135              reverse_proxy :${toString config.services.plantuml-server.listenPort}
136            }
137          '';
138  
139          "http://docs.openws.org" = {
140            extraConfig = ''
141              root * /var/www/html/dist
142              try_files {path} /index.html
143              file_server
144              header {
145                Strict-Transport-Security "max-age=31536000; includeSubDomains; preload"
146                X-Frame-Options "DENY"
147                X-Content-Type-Options "nosniff"
148              }
149            '';
150          };
151        }
152        (lib.optionalAttrs config.services.open-webui.enable {
153          "http://ai.openws.org".extraConfig = ''
154            reverse_proxy :${toString config.services.open-webui.port} {
155              header_up X-Forwarded-For {client_ip}
156              header_up X-Real-IP {client_ip}
157              header_up X-Http-Version {http.request.proto}
158            }
159          '';
160        })
161        (lib.optionalAttrs config.services.ttyd.enable {
162          "http://demo.openws.org".extraConfig = ''
163            reverse_proxy :${toString config.services.ttyd.port} {
164              header_up X-Forwarded-For {client_ip}
165              header_up X-Real-IP {client_ip}
166              header_up X-Http-Version {http.request.proto}
167            }
168          '';
169        })
170        (lib.optionalAttrs config.services.anki-sync-server.enable {
171          "http://anki.microvisor.dev".extraConfig =
172            "reverse_proxy :${toString config.services.anki-sync-server.port}";
173        })
174      ];
175    };
176  }