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 }