diff --git a/excellon/config.scm b/excellon/config.scm index 187eac8..34b6202 100644 --- a/excellon/config.scm +++ b/excellon/config.scm @@ -39,22 +39,50 @@ (service oci-container-service-type (list + ;; (oci-container-configuration + ;; (image "localhost:5000/caddy:latest") + ;; (provision "caddy") + ;; (respawn? #t) + ;; (network "sandbox") + ;; (ports '( + ;; ("80" . "80") + ;; ("443" . "443"))) + ;; (environment (list + ;; '("NAMECHEAP_API_KEY" . "0e6cd6e2f5044d08a63b9ae05bd1938d") + ;; '("NAMECHEAP_API_USER" . "bakeley") + ;; '("NAMECHEAP_CLIENT_IP" . "172.56.94.158") + ;; '("PUBLIC_IP" . "172.56.94.158"))) + ;; (volumes (list + ;; '("/data/docker/volumes/caddy/Caddyfile" . "/etc/caddy/Caddyfile") + ;; '("/data/docker/volumes/caddy/data" . "/data") + ;; '("/data/docker/volumes/caddy/config" . "/config")))) + (oci-container-configuration - (image "ghcr.io/caddybuilds/caddy-namecheap:latest") - (provision "caddy") - (respawn? #t) + (image "docker.io/fosrl/pangolin:1.14.1") + (provision "pangolin") (network "sandbox") - (ports '( - ("80" . "80") - ("443" . "443"))) - (environment (list - '("NAMECHEAP_API_KEY" . "af43a35060854eb98fd0c0837113a384") - '("NAMECHEAP_API_USER" . "bakeley") - '("PUBLIC_IP" . "70.112.209.162"))) + (respawn? #t) (volumes (list - '("/data/docker/volumes/caddy/Caddyfile" . "/etc/caddy/Caddyfile") - '("/data/docker/volumes/caddy/data" . "/data") - '("/data/docker/volumes/caddy/config" . "/config")))) + '("/data/docker/volumes/pangolin/config" . "/app/config")))) + + (oci-container-configuration + (image "docker.io/traefik:v3.6") + (provision "traefik") + (network "sandbox") + (respawn? #t) + (requirement '(pangolin)) + (environment (list + '("NAMECHEAP_API_KEY" . "0e6cd6e2f5044d08a63b9ae05bd1938d") + '("NAMECHEAP_API_USER" . "bakeley"))) + (ports '( + ("443" . "443") + ("80" . "80"))) + (volumes (list + '("/data/docker/volumes/pangolin/config/traefik" . "/etc/traefik") + '("/data/docker/volumes/pangolin/config/letsencrypt" . "/letsencrypt") + '("/data/docker/volumes/pangolin/config/logs" . "/var/log/traefik"))) + (command '( + "--configFile" "/etc/traefik/traefik_config.yml"))) (oci-container-configuration (image "docker.io/actualbudget/actual-server:latest") diff --git a/excellon/pangolin/config.yml b/excellon/pangolin/config.yml new file mode 100644 index 0000000..0652163 --- /dev/null +++ b/excellon/pangolin/config.yml @@ -0,0 +1,33 @@ +# To see all available options, please visit the docs: +# https://docs.pangolin.net/ + +gerbil: + start_port: 51820 + base_endpoint: "pangolin.akeley.tech" + +app: + dashboard_url: "https://pangolin.akeley.tech" + log_level: "info" + telemetry: + anonymous_usage: true + +domains: + domain1: + base_domain: "akeley.tech" + cert_resolver: "letsencrypt" + prefer_wildcard_cert: true + +server: + secret: "AOUhb0auR2dxUzsYFoIK8n0JtTDshQSh" + cors: + origins: ["https://pangolin.akeley.tech"] + methods: ["GET", "POST", "PUT", "DELETE", "PATCH"] + allowed_headers: ["X-CSRF-Token", "Content-Type"] + credentials: false + + +flags: + require_email_verification: false + disable_signup_without_invite: true + disable_user_create_org: false + allow_raw_resources: true diff --git a/excellon/pangolin/traefik/dynamic_config.yml b/excellon/pangolin/traefik/dynamic_config.yml new file mode 100644 index 0000000..c1c8d6e --- /dev/null +++ b/excellon/pangolin/traefik/dynamic_config.yml @@ -0,0 +1,77 @@ +http: + middlewares: + badger: + plugin: + badger: + disableForwardAuth: true + redirect-to-https: + redirectScheme: + scheme: https + + routers: + # HTTP to HTTPS redirect router + main-app-router-redirect: + rule: "Host(`pangolin.akeley.tech`)" + service: next-service + entryPoints: + - web + middlewares: + - redirect-to-https + - badger + + # Next.js router (handles everything except API and WebSocket paths) + next-router: + rule: "Host(`pangolin.akeley.tech`) && !PathPrefix(`/api/v1`)" + service: next-service + entryPoints: + - websecure + middlewares: + - badger + tls: + certResolver: letsencrypt + + # API router (handles /api/v1 paths) + api-router: + rule: "Host(`pangolin.akeley.tech`) && PathPrefix(`/api/v1`)" + service: api-service + entryPoints: + - websecure + middlewares: + - badger + tls: + certResolver: letsencrypt + domains: + - main: "akeley.tech" + sans: + - "*.akeley.tech" + + # WebSocket router + ws-router: + rule: "Host(`pangolin.akeley.tech`)" + service: api-service + entryPoints: + - websecure + middlewares: + - badger + tls: + certResolver: letsencrypt + + services: + next-service: + loadBalancer: + servers: + - url: "http://pangolin:3002" # Next.js server + + api-service: + loadBalancer: + servers: + - url: "http://pangolin:3000" # API/WebSocket server + +tcp: + serversTransports: + pp-transport-v1: + proxyProtocol: + version: 1 + pp-transport-v2: + proxyProtocol: + version: 2 diff --git a/excellon/pangolin/traefik/traefik_config.yml b/excellon/pangolin/traefik/traefik_config.yml new file mode 100644 index 0000000..6790a55 --- /dev/null +++ b/excellon/pangolin/traefik/traefik_config.yml @@ -0,0 +1,51 @@ +api: + insecure: true + dashboard: true + +providers: + http: + endpoint: "http://pangolin:3001/api/v1/traefik-config" + pollInterval: "5s" + file: + filename: "/etc/traefik/dynamic_config.yml" + +experimental: + plugins: + badger: + moduleName: "github.com/fosrl/badger" + version: "v1.3.1" + +log: + level: "INFO" + format: "common" + maxSize: 100 + maxBackups: 3 + maxAge: 3 + compress: true + +certificatesResolvers: + letsencrypt: + acme: + dnsChallenge: + provider: "namecheap" + email: "barton@akeley.tech" + storage: "/letsencrypt/acme.json" + caServer: "https://acme-v02.api.letsencrypt.org/directory" + +entryPoints: + web: + address: ":80" + websecure: + address: ":443" + transport: + respondingTimeouts: + readTimeout: "30m" + http: + tls: + certResolver: "letsencrypt" + +serversTransport: + insecureSkipVerify: true + +ping: + entryPoint: "web"