[GH-ISSUE #778] '404 Page Not Found' error on Pangolin frontend - after switching to Wildcard certificates #8391

Closed
opened 2026-04-30 04:09:58 -05:00 by GiteaMirror · 3 comments
Owner

Originally created by @BlackrazorNZ on GitHub (May 24, 2025).
Original GitHub issue: https://github.com/fosrl/pangolin/issues/778

Hi,

While it works flawlessly on HTTPS certificates, I'm having a pig of a time getting Pangolin working with DNS challenge certificates. It got so frustrating that I destroyed and rebuilt my entire Pangolin VPS from scratch so that setting up DNS challenge for wildcard could be the first thing I did after completing the Pangolin install and setting up a Site - I've not even created any Resources yet.

The DNS challenge attempt via Cloudfare seems to work fine (and I can verify seperately that the Cloudflare DNS API call is working correctly as it generates a DNS challenge cert almost instantly in NGINX Proxy Manager), but any attempt to access the Pangolin frontend is met with a 404 error.

Given that I've followed the instructions in the Pangolin Docs to the letter, I'm stumped as to where to go here. I have changed nothing post-install apart from the exact changes recommended in the documentation for wildcard certs. If I revert the changes (via a backup of the config directory etc) it starts working again immediately, albeit via HTTPS certificate.

Any advice on what could be wrong? I've spent 5 hours on this now just trying to debug the issue. Relevant (redacted) files below.

docker-compose.yml :

name: pangolin
services:
  pangolin:
    image: fosrl/pangolin:1.4.0
    container_name: pangolin
    restart: unless-stopped
    volumes:
      - ./config:/app/config
    healthcheck:
      test: ["CMD", "curl", "-f", "http://localhost:3001/api/v1/"]
      interval: "10s"
      timeout: "10s"
      retries: 15

  gerbil:
    image: fosrl/gerbil:1.0.0
    container_name: gerbil
    restart: unless-stopped
    depends_on:
      pangolin:
        condition: service_healthy
    command:
      - --reachableAt=http://gerbil:3003
      - --generateAndSaveKeyTo=/var/config/key
      - --remoteConfig=http://pangolin:3001/api/v1/gerbil/get-config
      - --reportBandwidthTo=http://pangolin:3001/api/v1/gerbil/receive-bandwidth
    volumes:
      - ./config/:/var/config
    cap_add:
      - NET_ADMIN
      - SYS_MODULE
    ports:
      - 51820:51820/udp
      - 443:443 # Port for traefik because of the network_mode
      - 80:80 # Port for traefik because of the network_mode

  traefik:
    image: traefik:v3.4.0
    container_name: traefik
    restart: unless-stopped
    network_mode: service:gerbil # Ports appear on the gerbil service
    depends_on:
      pangolin:
        condition: service_healthy
    command:
      - --configFile=/etc/traefik/traefik_config.yml
  # Add the environment variables for your DNS provider.
    environment:
      CLOUDFLARE_DNS_API_TOKEN: "[MY-CLOUDFLARE-TOKEN-HERE]"
    volumes:
      - ./config/traefik:/etc/traefik:ro # Volume to store the Traefik configuration
      - ./config/letsencrypt:/letsencrypt # Volume to store the Let's Encrypt certificates
      - ./config/traefik/logs:/var/log/traefik # Volume to store Traefik logs

networks:
  default:
    driver: bridge
    name: pangolin

traefik_config.yml (from config/traefik):

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.1.0"

log:
  level: "DEBUG"
  format: "common"

certificatesResolvers:
  letsencrypt:
    acme:
#      httpChallenge:
#        entryPoint: web
      dnsChallenge:
        provider: "cloudflare"
      email: "it@[MYDOMAIN]"
      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

dynamic_config.yml (from config/traefik):

http:
  middlewares:
    redirect-to-https:
      redirectScheme:
        scheme: https

  routers:
    # HTTP to HTTPS redirect router
    main-app-router-redirect:
      rule: "Host(`pangolin.[MYDOMAIN]`)"
      service: next-service
      entryPoints:
        - web
      middlewares:
        - redirect-to-https

    # Next.js router (handles everything except API and WebSocket paths)
    next-router:
      rule: "Host(`pangolin.[MYDOMAIN]`) && !PathPrefix(`/api/v1`)"
      service: next-service
      entryPoints:
        - websecure
      tls:
        certResolver: letsencrypt
    domains:
      - main: "[MYDOMAIN]"
        sans:
          - "*.[MYDOMAIN]"

    # API router (handles /api/v1 paths)
    api-router:
      rule: "Host(`pangolin.[MYDOMAIN]`) && PathPrefix(`/api/v1`)"
      service: api-service
      entryPoints:
        - websecure
      tls:
        certResolver: letsencrypt

    # WebSocket router
    ws-router:
      rule: "Host(`pangolin.[MYDOMAIN]`)"
      service: api-service
      entryPoints:
        - websecure
      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

config.yml (from config):

# To see all available options, please visit the docs:
# https://docs.fossorial.io/Pangolin/Configuration/config

app:
    dashboard_url: "https://pangolin.[MYDOMAIN]"
    log_level: "info"
    save_logs: false

domains:
    domain1:
        base_domain: "[MYDOMAIN]"
        cert_resolver: "letsencrypt"

server:
    external_port: 3000
    internal_port: 3001
    next_port: 3002
    internal_hostname: "pangolin"
    session_cookie_name: "p_session_token"
    resource_access_token_param: "p_token"
    resource_access_token_headers:
        id: "P-Access-Token-Id"
        token: "P-Access-Token"
    resource_session_request_param: "p_session_request"
    secret: [MYSECRET]
    cors:
        origins: ["https://pangolin.[MYDOMAIN]"]
        methods: ["GET", "POST", "PUT", "DELETE", "PATCH"]
        headers: ["X-CSRF-Token", "Content-Type"]
        credentials: false

traefik:
    cert_resolver: "letsencrypt"
    http_entrypoint: "web"
    https_entrypoint: "websecure"

gerbil:
    start_port: 51820
    base_endpoint: "pangolin.[MYDOMAIN]"
    use_subdomain: false
    block_size: 24
    site_block_size: 30
    subnet_group: 100.89.137.0/20

rate_limits:
    global:
        window_minutes: 1
        max_requests: 500

users:
    server_admin:
        email: "it@[MYDOMAIN]"
        password: "[MYPASSWORD]"

flags:
    require_email_verification: false
    disable_signup_without_invite: true
    disable_user_create_org: true
    allow_raw_resources: true
    allow_base_domain_resources: true
    prefer_wildcard_cert: true #Added per instruction on the Pangolin Docs

acme.json (from config/letsencrypt):

{
  "letsencrypt": {
    "Account": {
      "Email": "it@[MYDOMAIN]",
      "Registration": {
        "body": {
          "status": "valid",
          "contact": [
            "mailto:it@[MYDOMAIN]"
          ]
        },
        "uri": "https://acme-v02.api.letsencrypt.org/acme/acct/2417999267"
      },
      "PrivateKey": "[PRIVATE-KEY]",
      "KeyType": "4096"
    },
    "Certificates": [
      {
        "domain": {
          "main": "pangolin.[MYDOMAIN]"
        },
        "certificate": "[CERTIFICATE]",
        "key": "[KEY]]",
        "Store": "default"
      }
    ]
  }
}
Originally created by @BlackrazorNZ on GitHub (May 24, 2025). Original GitHub issue: https://github.com/fosrl/pangolin/issues/778 Hi, While it works flawlessly on HTTPS certificates, I'm having a pig of a time getting Pangolin working with DNS challenge certificates. It got so frustrating that I destroyed and rebuilt my entire Pangolin VPS from scratch so that setting up DNS challenge for wildcard could be the first thing I did after completing the Pangolin install and setting up a Site - I've not even created any Resources yet. The DNS challenge attempt via Cloudfare seems to work fine (and I can verify seperately that the Cloudflare DNS API call is working correctly as it generates a DNS challenge cert almost instantly in NGINX Proxy Manager), but any attempt to access the Pangolin frontend is met with a 404 error. Given that I've followed the instructions in the Pangolin Docs to the letter, I'm stumped as to where to go here. I have changed nothing post-install apart from the exact changes recommended in the documentation for wildcard certs. If I revert the changes (via a backup of the config directory etc) it starts working again immediately, albeit via HTTPS certificate. Any advice on what could be wrong? I've spent 5 hours on this now just trying to debug the issue. Relevant (redacted) files below. docker-compose.yml : ``` name: pangolin services: pangolin: image: fosrl/pangolin:1.4.0 container_name: pangolin restart: unless-stopped volumes: - ./config:/app/config healthcheck: test: ["CMD", "curl", "-f", "http://localhost:3001/api/v1/"] interval: "10s" timeout: "10s" retries: 15 gerbil: image: fosrl/gerbil:1.0.0 container_name: gerbil restart: unless-stopped depends_on: pangolin: condition: service_healthy command: - --reachableAt=http://gerbil:3003 - --generateAndSaveKeyTo=/var/config/key - --remoteConfig=http://pangolin:3001/api/v1/gerbil/get-config - --reportBandwidthTo=http://pangolin:3001/api/v1/gerbil/receive-bandwidth volumes: - ./config/:/var/config cap_add: - NET_ADMIN - SYS_MODULE ports: - 51820:51820/udp - 443:443 # Port for traefik because of the network_mode - 80:80 # Port for traefik because of the network_mode traefik: image: traefik:v3.4.0 container_name: traefik restart: unless-stopped network_mode: service:gerbil # Ports appear on the gerbil service depends_on: pangolin: condition: service_healthy command: - --configFile=/etc/traefik/traefik_config.yml # Add the environment variables for your DNS provider. environment: CLOUDFLARE_DNS_API_TOKEN: "[MY-CLOUDFLARE-TOKEN-HERE]" volumes: - ./config/traefik:/etc/traefik:ro # Volume to store the Traefik configuration - ./config/letsencrypt:/letsencrypt # Volume to store the Let's Encrypt certificates - ./config/traefik/logs:/var/log/traefik # Volume to store Traefik logs networks: default: driver: bridge name: pangolin ``` traefik_config.yml (from config/traefik): ``` 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.1.0" log: level: "DEBUG" format: "common" certificatesResolvers: letsencrypt: acme: # httpChallenge: # entryPoint: web dnsChallenge: provider: "cloudflare" email: "it@[MYDOMAIN]" 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 ``` dynamic_config.yml (from config/traefik): ``` http: middlewares: redirect-to-https: redirectScheme: scheme: https routers: # HTTP to HTTPS redirect router main-app-router-redirect: rule: "Host(`pangolin.[MYDOMAIN]`)" service: next-service entryPoints: - web middlewares: - redirect-to-https # Next.js router (handles everything except API and WebSocket paths) next-router: rule: "Host(`pangolin.[MYDOMAIN]`) && !PathPrefix(`/api/v1`)" service: next-service entryPoints: - websecure tls: certResolver: letsencrypt domains: - main: "[MYDOMAIN]" sans: - "*.[MYDOMAIN]" # API router (handles /api/v1 paths) api-router: rule: "Host(`pangolin.[MYDOMAIN]`) && PathPrefix(`/api/v1`)" service: api-service entryPoints: - websecure tls: certResolver: letsencrypt # WebSocket router ws-router: rule: "Host(`pangolin.[MYDOMAIN]`)" service: api-service entryPoints: - websecure 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 ``` config.yml (from config): ``` # To see all available options, please visit the docs: # https://docs.fossorial.io/Pangolin/Configuration/config app: dashboard_url: "https://pangolin.[MYDOMAIN]" log_level: "info" save_logs: false domains: domain1: base_domain: "[MYDOMAIN]" cert_resolver: "letsencrypt" server: external_port: 3000 internal_port: 3001 next_port: 3002 internal_hostname: "pangolin" session_cookie_name: "p_session_token" resource_access_token_param: "p_token" resource_access_token_headers: id: "P-Access-Token-Id" token: "P-Access-Token" resource_session_request_param: "p_session_request" secret: [MYSECRET] cors: origins: ["https://pangolin.[MYDOMAIN]"] methods: ["GET", "POST", "PUT", "DELETE", "PATCH"] headers: ["X-CSRF-Token", "Content-Type"] credentials: false traefik: cert_resolver: "letsencrypt" http_entrypoint: "web" https_entrypoint: "websecure" gerbil: start_port: 51820 base_endpoint: "pangolin.[MYDOMAIN]" use_subdomain: false block_size: 24 site_block_size: 30 subnet_group: 100.89.137.0/20 rate_limits: global: window_minutes: 1 max_requests: 500 users: server_admin: email: "it@[MYDOMAIN]" password: "[MYPASSWORD]" flags: require_email_verification: false disable_signup_without_invite: true disable_user_create_org: true allow_raw_resources: true allow_base_domain_resources: true prefer_wildcard_cert: true #Added per instruction on the Pangolin Docs ``` acme.json (from config/letsencrypt): ``` { "letsencrypt": { "Account": { "Email": "it@[MYDOMAIN]", "Registration": { "body": { "status": "valid", "contact": [ "mailto:it@[MYDOMAIN]" ] }, "uri": "https://acme-v02.api.letsencrypt.org/acme/acct/2417999267" }, "PrivateKey": "[PRIVATE-KEY]", "KeyType": "4096" }, "Certificates": [ { "domain": { "main": "pangolin.[MYDOMAIN]" }, "certificate": "[CERTIFICATE]", "key": "[KEY]]", "Store": "default" } ] } } ```
Author
Owner

@BlackrazorNZ commented on GitHub (May 24, 2025):

A log dump from 'docker compose logs -f' follows, approximately 2 minutes after bringing the docker stack up:

traefik   | 2025-05-24T01:36:12Z INF github.com/traefik/traefik/v3/cmd/traefik/traefik.go:105 > Traefik version 3.4.0 built on 2025-05-05T13:50:06Z version=3.4.0
traefik   | 2025-05-24T01:36:12Z DBG github.com/traefik/traefik/v3/cmd/traefik/traefik.go:112 > Static configuration loaded [json] staticConfiguration={"api":{"basePath":"/","dashboard":true,"insecure":true},"certificatesResolvers":{"letsencrypt":{"acme":{"caServer":"https://acme-v02.api.letsencrypt.org/directory","certificatesDuration":2160,"dnsChallenge":{"provider":"cloudflare"},"email":"it@[MYDOMAIN]","keyType":"RSA4096","storage":"/letsencrypt/acme.json"}}},"entryPoints":{"traefik":{"address":":8080","forwardedHeaders":{},"http":{"maxHeaderBytes":1048576,"sanitizePath":true},"http2":{"maxConcurrentStreams":250},"transport":{"lifeCycle":{"graceTimeOut":"10s"},"respondingTimeouts":{"idleTimeout":"3m0s","readTimeout":"1m0s"}},"udp":{"timeout":"3s"}},"web":{"address":":80","forwardedHeaders":{},"http":{"maxHeaderBytes":1048576,"sanitizePath":true},"http2":{"maxConcurrentStreams":250},"transport":{"lifeCycle":{"graceTimeOut":"10s"},"respondingTimeouts":{"idleTimeout":"3m0s","readTimeout":"1m0s"}},"udp":{"timeout":"3s"}},"websecure":{"address":":443","forwardedHeaders":{},"http":{"maxHeaderBytes":1048576,"sanitizePath":true,"tls":{"certResolver":"letsencrypt"}},"http2":{"maxConcurrentStreams":250},"transport":{"lifeCycle":{"graceTimeOut":"10s"},"respondingTimeouts":{"idleTimeout":"3m0s","readTimeout":"30m0s"}},"udp":{"timeout":"3s"}}},"experimental":{"plugins":{"badger":{"moduleName":"github.com/fosrl/badger","settings":{},"version":"v1.1.0"}}},"global":{"checkNewVersion":true},"log":{"format":"common","level":"DEBUG"},"providers":{"file":{"filename":"/etc/traefik/dynamic_config.yml","watch":true},"http":{"endpoint":"http://pangolin:3001/api/v1/traefik-config","pollInterval":"5s","pollTimeout":"5s"},"providersThrottleDuration":"2s"},"serversTransport":{"insecureSkipVerify":true,"maxIdleConnsPerHost":200},"tcpServersTransport":{"dialKeepAlive":"15s","dialTimeout":"30s"}}
traefik   | 2025-05-24T01:36:12Z INF github.com/traefik/traefik/v3/cmd/traefik/traefik.go:631 > 
traefik   | Stats collection is disabled.
traefik   | Help us improve Traefik by turning this feature on :)
traefik   | More details on: https://doc.traefik.io/traefik/contributing/data-collection/
traefik   | 
traefik   | 2025-05-24T01:36:12Z INF github.com/traefik/traefik/v3/cmd/traefik/traefik.go:239 > Loading plugins... plugins=["badger"]
traefik   | 2025-05-24T01:36:12Z DBG github.com/traefik/traefik/v3/pkg/plugins/plugins.go:30 > Loading of plugin: badger: github.com/fosrl/badger@v1.1.0
traefik   | 2025-05-24T01:36:12Z DBG github.com/hashicorp/go-retryablehttp@v0.7.7/client.go:661 > Performing request method=GET url=https://plugins.traefik.io/public/download/github.com/fosrl/badger/v1.1.0
traefik   | 2025-05-24T01:36:12Z DBG github.com/hashicorp/go-retryablehttp@v0.7.7/client.go:661 > Performing request method=GET url=https://plugins.traefik.io/public/validate/github.com/fosrl/badger/v1.1.0
traefik   | 2025-05-24T01:36:13Z INF github.com/traefik/traefik/v3/cmd/traefik/traefik.go:249 > Plugins loaded. plugins=["badger"]
traefik   | 2025-05-24T01:36:13Z INF github.com/traefik/traefik/v3/pkg/server/configurationwatcher.go:73 > Starting provider aggregator *aggregator.ProviderAggregator
traefik   | 2025-05-24T01:36:13Z DBG github.com/traefik/traefik/v3/pkg/server/server_entrypoint_tcp.go:224 > Starting TCP Server entryPointName=web
traefik   | 2025-05-24T01:36:13Z DBG github.com/traefik/traefik/v3/pkg/server/server_entrypoint_tcp.go:224 > Starting TCP Server entryPointName=traefik
traefik   | 2025-05-24T01:36:13Z DBG github.com/traefik/traefik/v3/pkg/server/server_entrypoint_tcp.go:224 > Starting TCP Server entryPointName=websecure
traefik   | 2025-05-24T01:36:13Z INF github.com/traefik/traefik/v3/pkg/provider/aggregator/aggregator.go:202 > Starting provider *file.Provider
traefik   | 2025-05-24T01:36:13Z DBG github.com/traefik/traefik/v3/pkg/provider/aggregator/aggregator.go:203 > *file.Provider provider configuration config={"filename":"/etc/traefik/dynamic_config.yml","watch":true}
traefik   | 2025-05-24T01:36:13Z DBG github.com/traefik/traefik/v3/pkg/provider/file/file.go:122 > add watcher on: /etc/traefik
traefik   | 2025-05-24T01:36:13Z DBG github.com/traefik/traefik/v3/pkg/provider/file/file.go:122 > add watcher on: /etc/traefik/dynamic_config.yml
traefik   | 2025-05-24T01:36:13Z ERR github.com/traefik/traefik/v3/pkg/provider/file/file.go:105 > Error while building configuration (for the first time) error="field not found, node: [0]" providerName=file
traefik   | 2025-05-24T01:36:13Z INF github.com/traefik/traefik/v3/pkg/provider/aggregator/aggregator.go:202 > Starting provider *traefik.Provider
traefik   | 2025-05-24T01:36:13Z DBG github.com/traefik/traefik/v3/pkg/provider/aggregator/aggregator.go:203 > *traefik.Provider provider configuration config={}
traefik   | 2025-05-24T01:36:13Z INF github.com/traefik/traefik/v3/pkg/provider/aggregator/aggregator.go:202 > Starting provider *http.Provider
traefik   | 2025-05-24T01:36:13Z DBG github.com/traefik/traefik/v3/pkg/provider/aggregator/aggregator.go:203 > *http.Provider provider configuration config={"endpoint":"http://pangolin:3001/api/v1/traefik-config","pollInterval":"5s","pollTimeout":"5s"}
traefik   | 2025-05-24T01:36:13Z INF github.com/traefik/traefik/v3/pkg/provider/aggregator/aggregator.go:202 > Starting provider *acme.ChallengeTLSALPN
traefik   | 2025-05-24T01:36:13Z DBG github.com/traefik/traefik/v3/pkg/provider/aggregator/aggregator.go:203 > *acme.ChallengeTLSALPN provider configuration config={}
traefik   | 2025-05-24T01:36:13Z INF github.com/traefik/traefik/v3/pkg/provider/aggregator/aggregator.go:202 > Starting provider *acme.Provider
traefik   | 2025-05-24T01:36:13Z DBG github.com/traefik/traefik/v3/pkg/provider/aggregator/aggregator.go:203 > *acme.Provider provider configuration config={"HTTPChallengeProvider":{},"ResolverName":"letsencrypt","TLSChallengeProvider":{},"caServer":"https://acme-v02.api.letsencrypt.org/directory","certificatesDuration":2160,"dnsChallenge":{"provider":"cloudflare"},"email":"it@[MYDOMAIN]","keyType":"RSA4096","storage":"/letsencrypt/acme.json","store":{}}
traefik   | 2025-05-24T01:36:13Z DBG github.com/traefik/traefik/v3/pkg/provider/acme/provider.go:234 > Attempt to renew certificates "720h0m0s" before expiry and check every "24h0m0s" acmeCA=https://acme-v02.api.letsencrypt.org/directory providerName=letsencrypt.acme
traefik   | 2025-05-24T01:36:13Z INF github.com/traefik/traefik/v3/pkg/provider/acme/provider.go:890 > Testing certificate renew... acmeCA=https://acme-v02.api.letsencrypt.org/directory providerName=letsencrypt.acme
traefik   | 2025-05-24T01:36:13Z DBG github.com/traefik/traefik/v3/pkg/server/configurationwatcher.go:227 > Configuration received config={"http":{"middlewares":{"dashboard_redirect":{"redirectRegex":{"permanent":true,"regex":"^(http:\\/\\/(\\[[\\w:.]+\\]|[\\w\\._-]+)(:\\d+)?)\\/$","replacement":"${1}/dashboard/"}},"dashboard_stripprefix":{"stripPrefix":{"prefixes":["/dashboard/","/dashboard"]}}},"models":{"websecure":{"observability":{},"tls":{"certResolver":"letsencrypt"}}},"routers":{"api":{"entryPoints":["traefik"],"priority":9223372036854775806,"rule":"PathPrefix(`/api`)","ruleSyntax":"default","service":"api@internal"},"dashboard":{"entryPoints":["traefik"],"middlewares":["dashboard_redirect@internal","dashboard_stripprefix@internal"],"priority":9223372036854775805,"rule":"PathPrefix(`/`)","ruleSyntax":"default","service":"dashboard@internal"}},"serversTransports":{"default":{"insecureSkipVerify":true,"maxIdleConnsPerHost":200}},"services":{"api":{},"dashboard":{},"noop":{}}},"tcp":{"serversTransports":{"default":{"dialKeepAlive":"15s","dialTimeout":"30s"}}},"tls":{},"udp":{}} providerName=internal
traefik   | 2025-05-24T01:36:13Z DBG github.com/traefik/traefik/v3/pkg/server/configurationwatcher.go:227 > Configuration received config={"http":{},"tcp":{},"tls":{},"udp":{}} providerName=letsencrypt.acme
traefik   | 2025-05-24T01:36:13Z DBG github.com/traefik/traefik/v3/pkg/server/configurationwatcher.go:227 > Configuration received config={"http":{},"tcp":{},"tls":{},"udp":{}} providerName=http
traefik   | 2025-05-24T01:36:14Z DBG github.com/traefik/traefik/v3/pkg/tls/tlsmanager.go:321 > No default certificate, fallback to the internal generated certificate tlsStoreName=default
traefik   | 2025-05-24T01:36:14Z DBG github.com/traefik/traefik/v3/pkg/middlewares/stripprefix/strip_prefix.go:32 > Creating middleware entryPointName=traefik middlewareName=dashboard_stripprefix@internal middlewareType=StripPrefix routerName=dashboard@internal
traefik   | 2025-05-24T01:36:14Z DBG github.com/traefik/traefik/v3/pkg/middlewares/observability/middleware.go:33 > Adding tracing to middleware entryPointName=traefik middlewareName=dashboard_stripprefix@internal routerName=dashboard@internal
traefik   | 2025-05-24T01:36:14Z DBG github.com/traefik/traefik/v3/pkg/middlewares/redirect/redirect_regex.go:17 > Creating middleware entryPointName=traefik middlewareName=dashboard_redirect@internal middlewareType=RedirectRegex routerName=dashboard@internal
traefik   | 2025-05-24T01:36:14Z DBG github.com/traefik/traefik/v3/pkg/middlewares/redirect/redirect_regex.go:18 > Setting up redirection from ^(http:\/\/(\[[\w:.]+\]|[\w\._-]+)(:\d+)?)\/$ to ${1}/dashboard/ entryPointName=traefik middlewareName=dashboard_redirect@internal middlewareType=RedirectRegex routerName=dashboard@internal
traefik   | 2025-05-24T01:36:14Z DBG github.com/traefik/traefik/v3/pkg/middlewares/observability/middleware.go:33 > Adding tracing to middleware entryPointName=traefik middlewareName=dashboard_redirect@internal routerName=dashboard@internal
traefik   | 2025-05-24T01:36:14Z DBG github.com/traefik/traefik/v3/pkg/middlewares/recovery/recovery.go:25 > Creating middleware entryPointName=traefik middlewareName=traefik-internal-recovery middlewareType=Recovery
traefik   | 2025-05-24T01:36:14Z DBG github.com/traefik/traefik/v3/pkg/tls/certificate.go:132 > Adding certificate for domain(s) pangolin.[MYDOMAIN]
traefik   | 2025-05-24T01:36:14Z DBG github.com/traefik/traefik/v3/pkg/tls/tlsmanager.go:321 > No default certificate, fallback to the internal generated certificate tlsStoreName=default
traefik   | 2025-05-24T01:36:14Z DBG github.com/traefik/traefik/v3/pkg/middlewares/stripprefix/strip_prefix.go:32 > Creating middleware entryPointName=traefik middlewareName=dashboard_stripprefix@internal middlewareType=StripPrefix routerName=dashboard@internal
traefik   | 2025-05-24T01:36:14Z DBG github.com/traefik/traefik/v3/pkg/middlewares/observability/middleware.go:33 > Adding tracing to middleware entryPointName=traefik middlewareName=dashboard_stripprefix@internal routerName=dashboard@internal
traefik   | 2025-05-24T01:36:14Z DBG github.com/traefik/traefik/v3/pkg/middlewares/redirect/redirect_regex.go:17 > Creating middleware entryPointName=traefik middlewareName=dashboard_redirect@internal middlewareType=RedirectRegex routerName=dashboard@internal
traefik   | 2025-05-24T01:36:14Z DBG github.com/traefik/traefik/v3/pkg/middlewares/redirect/redirect_regex.go:18 > Setting up redirection from ^(http:\/\/(\[[\w:.]+\]|[\w\._-]+)(:\d+)?)\/$ to ${1}/dashboard/ entryPointName=traefik middlewareName=dashboard_redirect@internal middlewareType=RedirectRegex routerName=dashboard@internal
traefik   | 2025-05-24T01:36:14Z DBG github.com/traefik/traefik/v3/pkg/middlewares/observability/middleware.go:33 > Adding tracing to middleware entryPointName=traefik middlewareName=dashboard_redirect@internal routerName=dashboard@internal
traefik   | 2025-05-24T01:36:14Z DBG github.com/traefik/traefik/v3/pkg/middlewares/recovery/recovery.go:25 > Creating middleware entryPointName=traefik middlewareName=traefik-internal-recovery middlewareType=Recovery
gerbil    | INFO: 2025/05/24 01:36:11 Fetching remote config from http://pangolin:3001/api/v1/gerbil/get-config
gerbil    | INFO: 2025/05/24 01:36:11 Created WireGuard interface wg0
gerbil    | INFO: 2025/05/24 01:36:11 Assigned IP address 100.89.128.1/24 to interface wg0
gerbil    | INFO: 2025/05/24 01:36:11 Attempting to delete existing MSS clamping rule for chain INPUT
gerbil    | INFO: 2025/05/24 01:36:11 Attempting to delete existing MSS clamping rule for chain OUTPUT
gerbil    | INFO: 2025/05/24 01:36:11 Attempting to delete existing MSS clamping rule for chain FORWARD
gerbil    | INFO: 2025/05/24 01:36:11 Adding MSS clamping rule for chain INPUT
gerbil    | INFO: 2025/05/24 01:36:11 Successfully added and verified MSS clamping rule for chain INPUT
gerbil    | INFO: 2025/05/24 01:36:11 Adding MSS clamping rule for chain OUTPUT
gerbil    | INFO: 2025/05/24 01:36:11 Successfully added and verified MSS clamping rule for chain OUTPUT
gerbil    | INFO: 2025/05/24 01:36:11 Adding MSS clamping rule for chain FORWARD
gerbil    | INFO: 2025/05/24 01:36:11 Successfully added and verified MSS clamping rule for chain FORWARD
gerbil    | INFO: 2025/05/24 01:36:11 WireGuard interface wg0 created and configured
gerbil    | INFO: 2025/05/24 01:36:11 Peer 8JnmHPHVT0eM/HtuJpATMYdGZZeMNNLmJ+wmfjsF10E= added successfully
gerbil    | INFO: 2025/05/24 01:36:11 Starting server on :3003
pangolin  | 
pangolin  | > @fosrl/pangolin@0.0.0 start
pangolin  | > NODE_OPTIONS=--enable-source-maps NODE_ENV=development ENVIRONMENT=prod sh -c 'node dist/migrations.mjs && node dist/server.mjs'
pangolin  | 
pangolin  | Starting migrations from version 1.4.0
pangolin  | Migrations to run: 
pangolin  | All migrations completed successfully
pangolin  | 2025-05-24T01:36:05.293Z [warn]: Email SMTP configuration is missing. Emails will not be sent.
pangolin  | 2025-05-24T01:36:06.744Z [info]: API server is running on http://localhost:3000
pangolin  | 2025-05-24T01:36:06.744Z [info]: Internal server is running on http://localhost:3001
pangolin  | 2025-05-24T01:36:07.584Z [info]: Next.js server is running on http://localhost:3002

<!-- gh-comment-id:2906307872 --> @BlackrazorNZ commented on GitHub (May 24, 2025): A log dump from 'docker compose logs -f' follows, approximately 2 minutes after bringing the docker stack up: ``` traefik | 2025-05-24T01:36:12Z INF github.com/traefik/traefik/v3/cmd/traefik/traefik.go:105 > Traefik version 3.4.0 built on 2025-05-05T13:50:06Z version=3.4.0 traefik | 2025-05-24T01:36:12Z DBG github.com/traefik/traefik/v3/cmd/traefik/traefik.go:112 > Static configuration loaded [json] staticConfiguration={"api":{"basePath":"/","dashboard":true,"insecure":true},"certificatesResolvers":{"letsencrypt":{"acme":{"caServer":"https://acme-v02.api.letsencrypt.org/directory","certificatesDuration":2160,"dnsChallenge":{"provider":"cloudflare"},"email":"it@[MYDOMAIN]","keyType":"RSA4096","storage":"/letsencrypt/acme.json"}}},"entryPoints":{"traefik":{"address":":8080","forwardedHeaders":{},"http":{"maxHeaderBytes":1048576,"sanitizePath":true},"http2":{"maxConcurrentStreams":250},"transport":{"lifeCycle":{"graceTimeOut":"10s"},"respondingTimeouts":{"idleTimeout":"3m0s","readTimeout":"1m0s"}},"udp":{"timeout":"3s"}},"web":{"address":":80","forwardedHeaders":{},"http":{"maxHeaderBytes":1048576,"sanitizePath":true},"http2":{"maxConcurrentStreams":250},"transport":{"lifeCycle":{"graceTimeOut":"10s"},"respondingTimeouts":{"idleTimeout":"3m0s","readTimeout":"1m0s"}},"udp":{"timeout":"3s"}},"websecure":{"address":":443","forwardedHeaders":{},"http":{"maxHeaderBytes":1048576,"sanitizePath":true,"tls":{"certResolver":"letsencrypt"}},"http2":{"maxConcurrentStreams":250},"transport":{"lifeCycle":{"graceTimeOut":"10s"},"respondingTimeouts":{"idleTimeout":"3m0s","readTimeout":"30m0s"}},"udp":{"timeout":"3s"}}},"experimental":{"plugins":{"badger":{"moduleName":"github.com/fosrl/badger","settings":{},"version":"v1.1.0"}}},"global":{"checkNewVersion":true},"log":{"format":"common","level":"DEBUG"},"providers":{"file":{"filename":"/etc/traefik/dynamic_config.yml","watch":true},"http":{"endpoint":"http://pangolin:3001/api/v1/traefik-config","pollInterval":"5s","pollTimeout":"5s"},"providersThrottleDuration":"2s"},"serversTransport":{"insecureSkipVerify":true,"maxIdleConnsPerHost":200},"tcpServersTransport":{"dialKeepAlive":"15s","dialTimeout":"30s"}} traefik | 2025-05-24T01:36:12Z INF github.com/traefik/traefik/v3/cmd/traefik/traefik.go:631 > traefik | Stats collection is disabled. traefik | Help us improve Traefik by turning this feature on :) traefik | More details on: https://doc.traefik.io/traefik/contributing/data-collection/ traefik | traefik | 2025-05-24T01:36:12Z INF github.com/traefik/traefik/v3/cmd/traefik/traefik.go:239 > Loading plugins... plugins=["badger"] traefik | 2025-05-24T01:36:12Z DBG github.com/traefik/traefik/v3/pkg/plugins/plugins.go:30 > Loading of plugin: badger: github.com/fosrl/badger@v1.1.0 traefik | 2025-05-24T01:36:12Z DBG github.com/hashicorp/go-retryablehttp@v0.7.7/client.go:661 > Performing request method=GET url=https://plugins.traefik.io/public/download/github.com/fosrl/badger/v1.1.0 traefik | 2025-05-24T01:36:12Z DBG github.com/hashicorp/go-retryablehttp@v0.7.7/client.go:661 > Performing request method=GET url=https://plugins.traefik.io/public/validate/github.com/fosrl/badger/v1.1.0 traefik | 2025-05-24T01:36:13Z INF github.com/traefik/traefik/v3/cmd/traefik/traefik.go:249 > Plugins loaded. plugins=["badger"] traefik | 2025-05-24T01:36:13Z INF github.com/traefik/traefik/v3/pkg/server/configurationwatcher.go:73 > Starting provider aggregator *aggregator.ProviderAggregator traefik | 2025-05-24T01:36:13Z DBG github.com/traefik/traefik/v3/pkg/server/server_entrypoint_tcp.go:224 > Starting TCP Server entryPointName=web traefik | 2025-05-24T01:36:13Z DBG github.com/traefik/traefik/v3/pkg/server/server_entrypoint_tcp.go:224 > Starting TCP Server entryPointName=traefik traefik | 2025-05-24T01:36:13Z DBG github.com/traefik/traefik/v3/pkg/server/server_entrypoint_tcp.go:224 > Starting TCP Server entryPointName=websecure traefik | 2025-05-24T01:36:13Z INF github.com/traefik/traefik/v3/pkg/provider/aggregator/aggregator.go:202 > Starting provider *file.Provider traefik | 2025-05-24T01:36:13Z DBG github.com/traefik/traefik/v3/pkg/provider/aggregator/aggregator.go:203 > *file.Provider provider configuration config={"filename":"/etc/traefik/dynamic_config.yml","watch":true} traefik | 2025-05-24T01:36:13Z DBG github.com/traefik/traefik/v3/pkg/provider/file/file.go:122 > add watcher on: /etc/traefik traefik | 2025-05-24T01:36:13Z DBG github.com/traefik/traefik/v3/pkg/provider/file/file.go:122 > add watcher on: /etc/traefik/dynamic_config.yml traefik | 2025-05-24T01:36:13Z ERR github.com/traefik/traefik/v3/pkg/provider/file/file.go:105 > Error while building configuration (for the first time) error="field not found, node: [0]" providerName=file traefik | 2025-05-24T01:36:13Z INF github.com/traefik/traefik/v3/pkg/provider/aggregator/aggregator.go:202 > Starting provider *traefik.Provider traefik | 2025-05-24T01:36:13Z DBG github.com/traefik/traefik/v3/pkg/provider/aggregator/aggregator.go:203 > *traefik.Provider provider configuration config={} traefik | 2025-05-24T01:36:13Z INF github.com/traefik/traefik/v3/pkg/provider/aggregator/aggregator.go:202 > Starting provider *http.Provider traefik | 2025-05-24T01:36:13Z DBG github.com/traefik/traefik/v3/pkg/provider/aggregator/aggregator.go:203 > *http.Provider provider configuration config={"endpoint":"http://pangolin:3001/api/v1/traefik-config","pollInterval":"5s","pollTimeout":"5s"} traefik | 2025-05-24T01:36:13Z INF github.com/traefik/traefik/v3/pkg/provider/aggregator/aggregator.go:202 > Starting provider *acme.ChallengeTLSALPN traefik | 2025-05-24T01:36:13Z DBG github.com/traefik/traefik/v3/pkg/provider/aggregator/aggregator.go:203 > *acme.ChallengeTLSALPN provider configuration config={} traefik | 2025-05-24T01:36:13Z INF github.com/traefik/traefik/v3/pkg/provider/aggregator/aggregator.go:202 > Starting provider *acme.Provider traefik | 2025-05-24T01:36:13Z DBG github.com/traefik/traefik/v3/pkg/provider/aggregator/aggregator.go:203 > *acme.Provider provider configuration config={"HTTPChallengeProvider":{},"ResolverName":"letsencrypt","TLSChallengeProvider":{},"caServer":"https://acme-v02.api.letsencrypt.org/directory","certificatesDuration":2160,"dnsChallenge":{"provider":"cloudflare"},"email":"it@[MYDOMAIN]","keyType":"RSA4096","storage":"/letsencrypt/acme.json","store":{}} traefik | 2025-05-24T01:36:13Z DBG github.com/traefik/traefik/v3/pkg/provider/acme/provider.go:234 > Attempt to renew certificates "720h0m0s" before expiry and check every "24h0m0s" acmeCA=https://acme-v02.api.letsencrypt.org/directory providerName=letsencrypt.acme traefik | 2025-05-24T01:36:13Z INF github.com/traefik/traefik/v3/pkg/provider/acme/provider.go:890 > Testing certificate renew... acmeCA=https://acme-v02.api.letsencrypt.org/directory providerName=letsencrypt.acme traefik | 2025-05-24T01:36:13Z DBG github.com/traefik/traefik/v3/pkg/server/configurationwatcher.go:227 > Configuration received config={"http":{"middlewares":{"dashboard_redirect":{"redirectRegex":{"permanent":true,"regex":"^(http:\\/\\/(\\[[\\w:.]+\\]|[\\w\\._-]+)(:\\d+)?)\\/$","replacement":"${1}/dashboard/"}},"dashboard_stripprefix":{"stripPrefix":{"prefixes":["/dashboard/","/dashboard"]}}},"models":{"websecure":{"observability":{},"tls":{"certResolver":"letsencrypt"}}},"routers":{"api":{"entryPoints":["traefik"],"priority":9223372036854775806,"rule":"PathPrefix(`/api`)","ruleSyntax":"default","service":"api@internal"},"dashboard":{"entryPoints":["traefik"],"middlewares":["dashboard_redirect@internal","dashboard_stripprefix@internal"],"priority":9223372036854775805,"rule":"PathPrefix(`/`)","ruleSyntax":"default","service":"dashboard@internal"}},"serversTransports":{"default":{"insecureSkipVerify":true,"maxIdleConnsPerHost":200}},"services":{"api":{},"dashboard":{},"noop":{}}},"tcp":{"serversTransports":{"default":{"dialKeepAlive":"15s","dialTimeout":"30s"}}},"tls":{},"udp":{}} providerName=internal traefik | 2025-05-24T01:36:13Z DBG github.com/traefik/traefik/v3/pkg/server/configurationwatcher.go:227 > Configuration received config={"http":{},"tcp":{},"tls":{},"udp":{}} providerName=letsencrypt.acme traefik | 2025-05-24T01:36:13Z DBG github.com/traefik/traefik/v3/pkg/server/configurationwatcher.go:227 > Configuration received config={"http":{},"tcp":{},"tls":{},"udp":{}} providerName=http traefik | 2025-05-24T01:36:14Z DBG github.com/traefik/traefik/v3/pkg/tls/tlsmanager.go:321 > No default certificate, fallback to the internal generated certificate tlsStoreName=default traefik | 2025-05-24T01:36:14Z DBG github.com/traefik/traefik/v3/pkg/middlewares/stripprefix/strip_prefix.go:32 > Creating middleware entryPointName=traefik middlewareName=dashboard_stripprefix@internal middlewareType=StripPrefix routerName=dashboard@internal traefik | 2025-05-24T01:36:14Z DBG github.com/traefik/traefik/v3/pkg/middlewares/observability/middleware.go:33 > Adding tracing to middleware entryPointName=traefik middlewareName=dashboard_stripprefix@internal routerName=dashboard@internal traefik | 2025-05-24T01:36:14Z DBG github.com/traefik/traefik/v3/pkg/middlewares/redirect/redirect_regex.go:17 > Creating middleware entryPointName=traefik middlewareName=dashboard_redirect@internal middlewareType=RedirectRegex routerName=dashboard@internal traefik | 2025-05-24T01:36:14Z DBG github.com/traefik/traefik/v3/pkg/middlewares/redirect/redirect_regex.go:18 > Setting up redirection from ^(http:\/\/(\[[\w:.]+\]|[\w\._-]+)(:\d+)?)\/$ to ${1}/dashboard/ entryPointName=traefik middlewareName=dashboard_redirect@internal middlewareType=RedirectRegex routerName=dashboard@internal traefik | 2025-05-24T01:36:14Z DBG github.com/traefik/traefik/v3/pkg/middlewares/observability/middleware.go:33 > Adding tracing to middleware entryPointName=traefik middlewareName=dashboard_redirect@internal routerName=dashboard@internal traefik | 2025-05-24T01:36:14Z DBG github.com/traefik/traefik/v3/pkg/middlewares/recovery/recovery.go:25 > Creating middleware entryPointName=traefik middlewareName=traefik-internal-recovery middlewareType=Recovery traefik | 2025-05-24T01:36:14Z DBG github.com/traefik/traefik/v3/pkg/tls/certificate.go:132 > Adding certificate for domain(s) pangolin.[MYDOMAIN] traefik | 2025-05-24T01:36:14Z DBG github.com/traefik/traefik/v3/pkg/tls/tlsmanager.go:321 > No default certificate, fallback to the internal generated certificate tlsStoreName=default traefik | 2025-05-24T01:36:14Z DBG github.com/traefik/traefik/v3/pkg/middlewares/stripprefix/strip_prefix.go:32 > Creating middleware entryPointName=traefik middlewareName=dashboard_stripprefix@internal middlewareType=StripPrefix routerName=dashboard@internal traefik | 2025-05-24T01:36:14Z DBG github.com/traefik/traefik/v3/pkg/middlewares/observability/middleware.go:33 > Adding tracing to middleware entryPointName=traefik middlewareName=dashboard_stripprefix@internal routerName=dashboard@internal traefik | 2025-05-24T01:36:14Z DBG github.com/traefik/traefik/v3/pkg/middlewares/redirect/redirect_regex.go:17 > Creating middleware entryPointName=traefik middlewareName=dashboard_redirect@internal middlewareType=RedirectRegex routerName=dashboard@internal traefik | 2025-05-24T01:36:14Z DBG github.com/traefik/traefik/v3/pkg/middlewares/redirect/redirect_regex.go:18 > Setting up redirection from ^(http:\/\/(\[[\w:.]+\]|[\w\._-]+)(:\d+)?)\/$ to ${1}/dashboard/ entryPointName=traefik middlewareName=dashboard_redirect@internal middlewareType=RedirectRegex routerName=dashboard@internal traefik | 2025-05-24T01:36:14Z DBG github.com/traefik/traefik/v3/pkg/middlewares/observability/middleware.go:33 > Adding tracing to middleware entryPointName=traefik middlewareName=dashboard_redirect@internal routerName=dashboard@internal traefik | 2025-05-24T01:36:14Z DBG github.com/traefik/traefik/v3/pkg/middlewares/recovery/recovery.go:25 > Creating middleware entryPointName=traefik middlewareName=traefik-internal-recovery middlewareType=Recovery gerbil | INFO: 2025/05/24 01:36:11 Fetching remote config from http://pangolin:3001/api/v1/gerbil/get-config gerbil | INFO: 2025/05/24 01:36:11 Created WireGuard interface wg0 gerbil | INFO: 2025/05/24 01:36:11 Assigned IP address 100.89.128.1/24 to interface wg0 gerbil | INFO: 2025/05/24 01:36:11 Attempting to delete existing MSS clamping rule for chain INPUT gerbil | INFO: 2025/05/24 01:36:11 Attempting to delete existing MSS clamping rule for chain OUTPUT gerbil | INFO: 2025/05/24 01:36:11 Attempting to delete existing MSS clamping rule for chain FORWARD gerbil | INFO: 2025/05/24 01:36:11 Adding MSS clamping rule for chain INPUT gerbil | INFO: 2025/05/24 01:36:11 Successfully added and verified MSS clamping rule for chain INPUT gerbil | INFO: 2025/05/24 01:36:11 Adding MSS clamping rule for chain OUTPUT gerbil | INFO: 2025/05/24 01:36:11 Successfully added and verified MSS clamping rule for chain OUTPUT gerbil | INFO: 2025/05/24 01:36:11 Adding MSS clamping rule for chain FORWARD gerbil | INFO: 2025/05/24 01:36:11 Successfully added and verified MSS clamping rule for chain FORWARD gerbil | INFO: 2025/05/24 01:36:11 WireGuard interface wg0 created and configured gerbil | INFO: 2025/05/24 01:36:11 Peer 8JnmHPHVT0eM/HtuJpATMYdGZZeMNNLmJ+wmfjsF10E= added successfully gerbil | INFO: 2025/05/24 01:36:11 Starting server on :3003 pangolin | pangolin | > @fosrl/pangolin@0.0.0 start pangolin | > NODE_OPTIONS=--enable-source-maps NODE_ENV=development ENVIRONMENT=prod sh -c 'node dist/migrations.mjs && node dist/server.mjs' pangolin | pangolin | Starting migrations from version 1.4.0 pangolin | Migrations to run: pangolin | All migrations completed successfully pangolin | 2025-05-24T01:36:05.293Z [warn]: Email SMTP configuration is missing. Emails will not be sent. pangolin | 2025-05-24T01:36:06.744Z [info]: API server is running on http://localhost:3000 pangolin | 2025-05-24T01:36:06.744Z [info]: Internal server is running on http://localhost:3001 pangolin | 2025-05-24T01:36:07.584Z [info]: Next.js server is running on http://localhost:3002 ```
Author
Owner

@kmanwar89 commented on GitHub (May 26, 2025):

Hey there, not a pangolin expert but I just spent a few hours last night on this (though my issue was caused by something else)

I didn't notice any difference in using the prefer_wildcard_certs flag in my testing, nor did I need to specify the domains/sans field (though I did this one anyways).

What stood out to me in the output you shared is this line:

traefik | 2025-05-24T01:36:14Z DBG github.com/traefik/traefik/v3/pkg/tls/tlsmanager.go:321 > No default certificate, fallback to the internal generated certificate tlsStoreName=default

Your config looks almost identical to my working wildcard + Pangolin setup. For troubleshooting, I would try the following:

  1. Edit your config/traefik/traefik_config.yml file to increase the verbosity of logging and follow the logs using docker compose logs -f in a second terminal window. Under the log section, change level: INFO to level: DEBUG.
  2. Delete your old certs (from config/letsencrypt) by deleting that acme.json file.
  3. Add the staging letsencrypt URL (caServer: https://acme-staging-v02.api.letsencrypt.org/directory) so you don't inadvertently hit the rate limit while troubleshooting this. If it works, you should have your acme.json file populated again (mine was about 40k file size from about 6 domains) and if you go to a website, it'll show a cert error, and the cert will show Lets Encrypt Staging.

I think because you already have certs, net-new ones aren't being requested. I got this from the 'Verify it works' section of the doc page on this topic

Good luck!

<!-- gh-comment-id:2909853829 --> @kmanwar89 commented on GitHub (May 26, 2025): Hey there, not a pangolin expert but I just spent a few hours last night on this (though my issue was caused by something else) I didn't notice any difference in using the `prefer_wildcard_certs` flag in my testing, nor did I need to specify the domains/sans field (though I did this one anyways). What stood out to me in the output you shared is this line: `traefik | 2025-05-24T01:36:14Z DBG github.com/traefik/traefik/v3/pkg/tls/tlsmanager.go:321 > No default certificate, fallback to the internal generated certificate tlsStoreName=default` Your config looks almost identical to my working wildcard + Pangolin setup. For troubleshooting, I would try the following: 1. Edit your `config/traefik/traefik_config.yml` file to increase the verbosity of logging and follow the logs using `docker compose logs -f` in a second terminal window. Under the `log` section, change `level: INFO` to `level: DEBUG`. 2. Delete your old certs (from `config/letsencrypt`) by deleting that `acme.json` file. 3. Add the `staging` letsencrypt URL (`caServer: https://acme-staging-v02.api.letsencrypt.org/directory`) so you don't inadvertently hit the rate limit while troubleshooting this. If it works, you should have your `acme.json` file populated again (mine was about 40k file size from about 6 domains) and if you go to a website, it'll show a cert error, and the cert will show Lets Encrypt Staging. I think because you already have certs, net-new ones aren't being requested. I got this from the 'Verify it works' section of the [doc page on this topic](https://docs.fossorial.io/Pangolin/Configuration/wildcard-certs#verify-it-works) Good luck!
Author
Owner

@BlackrazorNZ commented on GitHub (May 27, 2025):

Closing this one, figured it out with assistance from the Discord group. The issue is that the 'domains' value in dynamic_config.yml was incorrectly indented, and needs to be formatted so that the 'domains' is indented to align with 'certResolver' like so:

    certResolver: letsencrypt
    domains:
      - main: "[MYDOMAIN]" 
        sans: "*.[MYDOMAIN]"
<!-- gh-comment-id:2914431074 --> @BlackrazorNZ commented on GitHub (May 27, 2025): Closing this one, figured it out with assistance from the Discord group. The issue is that the 'domains' value in `dynamic_config.yml` was incorrectly indented, and needs to be formatted so that the 'domains' is indented to align with 'certResolver' like so: certResolver: letsencrypt domains: - main: "[MYDOMAIN]" sans: "*.[MYDOMAIN]"
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: github-starred/pangolin#8391