Skip to content

Standalone Traefik mode: /api/v1/traefik-config still fetches Pangolin and returns 500 when active_data_source=traefik #107

@smoochy

Description

@smoochy

Summary

In my setup, Middleware Manager is configured to use standalone Traefik with active_data_source=traefik and no Pangolin present.

Codex found that GET /api/v1/traefik-config still appears to go through Pangolin fetch logic and returns 500 Internal Server Error when Pangolin is absent, even though Traefik itself is reachable and the loaded plugins are active.

This causes Traefik's HTTP provider to stay in a retry loop and makes the Middleware Manager state misleading.

Environment

  • Middleware Manager: v4.5.0
  • Traefik: v3.6.12
  • Deployment mode: standalone Traefik
  • Active data source in config/UI: traefik
  • Pangolin: not present in my setup
Traefik compose.yaml from my setup
services:
  traefik:
    container_name: traefik
    image: traefik:v3.6.12@sha256:171c9c3565b29f6c133f1c1b43c5d4e5853415198e9e1078c001f8702ff66aec
    logging:
      driver: "json-file"
      options:
        max-file: "10"
        max-size: "100m"
    restart: unless-stopped

    # Network
    networks:
      smoonet:
    # Ports (host binding)
    ports:
      - "443:443/tcp" # HTTPS
      - "444:444/tcp" # TCP (your custom)
      - "8080:8080/tcp" # Dashboard
      - "80:80/tcp" # HTTP
      - "81:81/tcp" # Additional HTTP
    # Volumes
    volumes:
      - /mnt/user/appdata/traefik:/etc/traefik # Config, certs, acme.json

    # Environment variables
    environment:
      - CF_DNS_API_TOKEN=${CF_DNS_API_TOKEN} # Cloudflare API token (sensitive!)
      - DOCKER_HOST=tcp://dockerproxy:2375 # Docker socket proxy
      - HOST_CONTAINERNAME=traefik
      - HOST_HOSTNAME=smooRAID
      - HOST_OS=Unraid
      - TZ=Europe/Berlin
    # Resource limits
    deploy:
      resources:
        limits:
          pids: 2048
    ## Start Traefik Config
    labels:
      - traefik.enable=true
      - traefik.http.middlewares.crowdsec-bouncer.plugin.bouncer.enabled=true
      - traefik.http.middlewares.crowdsec-bouncer.plugin.bouncer.crowdsecmode=stream
      - traefik.http.middlewares.crowdsec-bouncer.plugin.bouncer.crowdseclapischeme=http
      - traefik.http.middlewares.crowdsec-bouncer.plugin.bouncer.crowdseclapihost=crowdsec:8080
      - traefik.http.middlewares.crowdsec-bouncer.plugin.bouncer.crowdseclapipath=/
      - traefik.http.middlewares.crowdsec-bouncer.plugin.bouncer.crowdseclapikey=${CROWDSEC_TRAEFIK_BOUNCER_API_KEY}
      - traefik.http.middlewares.crowdsec-bouncer.plugin.bouncer.forwardedheaderstrustedips=${CROWDSEC_FORWARDED_HEADERS_TRUSTED_IPS}
      # # Internal
      - traefik.http.routers.${SERVICE}-internal.entrypoints=websecure-internal
      - traefik.http.routers.${SERVICE}-internal.middlewares=chain-internal@file
      - traefik.http.routers.${SERVICE}-internal.priority=5000
      - traefik.http.routers.${SERVICE}-internal.rule=Host(`${TRAEFIK_EXTERNAL_URL}`)
      - traefik.http.routers.${SERVICE}-internal.service=${SERVICE}
      - traefik.http.routers.${SERVICE}-internal.tls=true
      # # External
      - traefik.http.routers.${SERVICE}-external.entrypoints=websecure-external
      - traefik.http.routers.${SERVICE}-external.middlewares=chain-external@file
      - traefik.http.routers.${SERVICE}-external.priority=10
      - traefik.http.routers.${SERVICE}-external.rule=Host(`${TRAEFIK_EXTERNAL_URL}`)
      - traefik.http.routers.${SERVICE}-external.service=${SERVICE}
      - traefik.http.routers.${SERVICE}-external.tls=true
      # # HTTP-Header
      - traefik.http.routers.${SERVICE}-bypass.entrypoints=websecure-external
      - traefik.http.routers.${SERVICE}-bypass.middlewares=chain-external-bypass@file
      - traefik.http.routers.${SERVICE}-bypass.priority=2500
      - traefik.http.routers.${SERVICE}-bypass.rule=Host(`${TRAEFIK_EXTERNAL_URL}`) && Header(`${SPECIAL_HEADER_NAME}`, `${SPECIAL_HEADER_SECRET}`)
      - traefik.http.routers.${SERVICE}-bypass.service=${SERVICE}
      - traefik.http.routers.${SERVICE}-bypass.tls=true
      # Service port (must match the port Komodo listens on INSIDE the container)
      - traefik.docker.network=smoonet
      - traefik.http.services.${SERVICE}.loadbalancer.server.url=${TRAEFIK_INTERNAL_URL}
      ## End Traefik Config
      - com.smoochy.komodo.restore_stack=traefik
      - net.unraid.docker.icon=https://raw.githubusercontent.com/ibracorp/unraid-templates/master/traefik/traefik.png
      - net.unraid.docker.webui=${TRAEFIK_INTERNAL_URL}
  geoipupdate:
    container_name: geoipupdate
    image: ghcr.io/maxmind/geoipupdate:v7.1.1@sha256:faecdca22579730ab0b7dea5aa9af350bb3c93cb9d39845c173639ead30346d2
    restart: unless-stopped

    # Network
    networks:
      smoonet:

    # Volumes
    volumes:
      - /mnt/user/appdata/traefik-dashboard/data/geoip/:/usr/share/GeoIP:rw

    # Environment variables
    environment:
      - GEOIPUPDATE_ACCOUNT_ID=${GEOIPUPDATE_ACCOUNT_ID}
      - GEOIPUPDATE_EDITION_IDS=GeoLite2-City GeoLite2-Country
      - GEOIPUPDATE_FREQUENCY=24
      - GEOIPUPDATE_LICENSE_KEY=${GEOIPUPDATE_LICENSE_KEY}
      - HOST_CONTAINERNAME=geoipupdate
      - HOST_HOSTNAME=smooRAID
      - HOST_OS=Unraid
      - TZ=Europe/Berlin

    # Resource limits
    deploy:
      resources:
        limits:
          pids: 2048
    labels:
      - com.smoochy.komodo.restore_stack=traefik
      - net.unraid.docker.icon=https://raw.githubusercontent.com/tritones/unraid-templates/main/templates/img/geoipupdate.png
  traefik-middleware-manager:
    container_name: traefik-middleware-manager
    image: hhftechnology/middleware-manager:v4.5.0@sha256:96099c3e069f24800e9b7f8ffa43e359b90c54d73961681825fd51d3cfdc1e49
    restart: unless-stopped

    # Network
    networks:
      smoonet:
    # Ports
    ports:
      - "3456:3456/tcp" # Middleware Manager UI
    # Volumes
    volumes:
      - /mnt/user/appdata/traefik/middleware-manager/data:/data:rw
      - /mnt/user/appdata/traefik/middleware-manager/config:/app/config:rw
      - /mnt/user/appdata/traefik/rules:/conf:rw
      - /mnt/user/appdata/traefik:/etc/traefik:rw

    # Environment variables
    environment:
      - ACTIVE_DATA_SOURCE=traefik
      - DB_PATH=/data/middleware.db
      - HOST_CONTAINERNAME=${TRAEFIK_MIDDLEWARE_MANAGER_SERVICE}
      - HOST_HOSTNAME=smooRAID
      - HOST_OS=Unraid
      - PORT=3456
      - TRAEFIK_API_URL=http://traefik:8080
      - TRAEFIK_CONF_DIR=/conf
      - TRAEFIK_STATIC_CONFIG_PATH=/etc/traefik/traefik.yml
      - TZ=Europe/Berlin

    # Resource limits
    deploy:
      resources:
        limits:
          pids: 2048
    ## Start Traefik Config
    labels:
      - traefik.enable=true
      # # Internal
      - traefik.http.routers.${TRAEFIK_MIDDLEWARE_MANAGER_SERVICE}-internal.entrypoints=websecure-internal
      - traefik.http.routers.${TRAEFIK_MIDDLEWARE_MANAGER_SERVICE}-internal.middlewares=chain-internal@file
      - traefik.http.routers.${TRAEFIK_MIDDLEWARE_MANAGER_SERVICE}-internal.priority=5000
      - traefik.http.routers.${TRAEFIK_MIDDLEWARE_MANAGER_SERVICE}-internal.rule=Host(`${TRAEFIK_MIDDLEWARE_MANAGER_EXTERNAL_URL}`)
      - traefik.http.routers.${TRAEFIK_MIDDLEWARE_MANAGER_SERVICE}-internal.service=${TRAEFIK_MIDDLEWARE_MANAGER_SERVICE}
      - traefik.http.routers.${TRAEFIK_MIDDLEWARE_MANAGER_SERVICE}-internal.tls=true
      # # External
      - traefik.http.routers.${TRAEFIK_MIDDLEWARE_MANAGER_SERVICE}-external.entrypoints=websecure-external
      - traefik.http.routers.${TRAEFIK_MIDDLEWARE_MANAGER_SERVICE}-external.middlewares=chain-external@file
      - traefik.http.routers.${TRAEFIK_MIDDLEWARE_MANAGER_SERVICE}-external.priority=10
      - traefik.http.routers.${TRAEFIK_MIDDLEWARE_MANAGER_SERVICE}-external.rule=Host(`${TRAEFIK_MIDDLEWARE_MANAGER_EXTERNAL_URL}`)
      - traefik.http.routers.${TRAEFIK_MIDDLEWARE_MANAGER_SERVICE}-external.service=${TRAEFIK_MIDDLEWARE_MANAGER_SERVICE}
      - traefik.http.routers.${TRAEFIK_MIDDLEWARE_MANAGER_SERVICE}-external.tls=true
      # # HTTP-Header
      - traefik.http.routers.${TRAEFIK_MIDDLEWARE_MANAGER_SERVICE}-bypass.entrypoints=websecure-external
      - traefik.http.routers.${TRAEFIK_MIDDLEWARE_MANAGER_SERVICE}-bypass.middlewares=chain-external-bypass@file
      - traefik.http.routers.${TRAEFIK_MIDDLEWARE_MANAGER_SERVICE}-bypass.priority=2500
      - traefik.http.routers.${TRAEFIK_MIDDLEWARE_MANAGER_SERVICE}-bypass.rule=Host(`${TRAEFIK_MIDDLEWARE_MANAGER_EXTERNAL_URL}`) && Header(`${SPECIAL_HEADER_NAME}`, `${SPECIAL_HEADER_SECRET}`)
      - traefik.http.routers.${TRAEFIK_MIDDLEWARE_MANAGER_SERVICE}-bypass.service=${TRAEFIK_MIDDLEWARE_MANAGER_SERVICE}
      - traefik.http.routers.${TRAEFIK_MIDDLEWARE_MANAGER_SERVICE}-bypass.tls=true
      # Service port (Middleware Manager runs on 3456)
      - traefik.docker.network=smoonet
      - traefik.http.services.${TRAEFIK_MIDDLEWARE_MANAGER_SERVICE}.loadbalancer.server.url=${TRAEFIK_MIDDLEWARE_MANAGER_INTERNAL_URL}
      ## End Traefik Config
      - com.smoochy.komodo.restore_stack=traefik
      - net.unraid.docker.icon=https://github.com/hhftechnology.png
      - net.unraid.docker.webui=${TRAEFIK_MIDDLEWARE_MANAGER_INTERNAL_URL}
  traefik-log-dashboard:
    container_name: traefik-log-dashboard
    depends_on:
      - traefik
      - traefik-log-dashboard-agent
    image: hhftechnology/traefik-log-dashboard:3.0.0@sha256:b9a8e6a3a2d7261526975beac67e605111f0d03aedf646016d9d230bef24c016
    restart: unless-stopped

    # Network
    networks:
      smoonet:
    # Ports
    ports:
      - "5101:3000/tcp" # Dashboard UI
    # Volumes
    volumes:
      - /mnt/user/appdata/traefik-dashboard/data/dashboard/:/data:rw
      - /mnt/user/appdata/traefik-dashboard/data/geoip/:/geoip:ro

    # Environment variables
    environment:
      - AGENT_1_NAME=smooRaid
      - AGENT_1_TOKEN=${TRAEFIK_LOG_AGENT_TOKEN}
      - AGENT_1_URL=http://traefik-log-dashboard-agent:5000
      - DASHBOARD_AGENTS_ENV_ONLY=true
      - DASHBOARD_MAX_LOGS_DISPLAY=500
      - GEOIP_LOCAL_DB_PATH=/geoip/GeoLite2-City.mmdb
      # Accounts are not free, hence disabled
      #- GEOIP_PROVIDER_URLS=https://ipwho.is,https://ip-api.com/json
      - GEOIP_UNKNOWN_CACHE_TTL_MS=300000
      - HOST_CONTAINERNAME=traefik-log-dashboard
      - HOST_HOSTNAME=smooRAID
      - HOST_OS=Unraid
      - NODE_ENV=production
      - TZ=Europe/Berlin

    # Resource limits
    deploy:
      resources:
        limits:
          pids: 2048
    ## Start Traefik Config (only for dashboard)
    labels:
      - traefik.enable=true
      # # Internal
      - traefik.http.routers.${TRAEFIK_LOG_DASHBOARD_SERVICE}-internal.entrypoints=websecure-internal
      - traefik.http.routers.${TRAEFIK_LOG_DASHBOARD_SERVICE}-internal.middlewares=chain-internal@file
      - traefik.http.routers.${TRAEFIK_LOG_DASHBOARD_SERVICE}-internal.priority=5000
      - traefik.http.routers.${TRAEFIK_LOG_DASHBOARD_SERVICE}-internal.rule=Host(`${TRAEFIK_LOG_DASHBOARD_EXTERNAL_URL}`)
      - traefik.http.routers.${TRAEFIK_LOG_DASHBOARD_SERVICE}-internal.service=${TRAEFIK_LOG_DASHBOARD_SERVICE}
      - traefik.http.routers.${TRAEFIK_LOG_DASHBOARD_SERVICE}-internal.tls=true
      # # External
      - traefik.http.routers.${TRAEFIK_LOG_DASHBOARD_SERVICE}-external.entrypoints=websecure-external
      - traefik.http.routers.${TRAEFIK_LOG_DASHBOARD_SERVICE}-external.middlewares=chain-external@file
      - traefik.http.routers.${TRAEFIK_LOG_DASHBOARD_SERVICE}-external.priority=10
      - traefik.http.routers.${TRAEFIK_LOG_DASHBOARD_SERVICE}-external.rule=Host(`${TRAEFIK_LOG_DASHBOARD_EXTERNAL_URL}`)
      - traefik.http.routers.${TRAEFIK_LOG_DASHBOARD_SERVICE}-external.service=${TRAEFIK_LOG_DASHBOARD_SERVICE}
      - traefik.http.routers.${TRAEFIK_LOG_DASHBOARD_SERVICE}-external.tls=true
      # # HTTP-Header
      - traefik.http.routers.${TRAEFIK_LOG_DASHBOARD_SERVICE}-bypass.entrypoints=websecure-external
      - traefik.http.routers.${TRAEFIK_LOG_DASHBOARD_SERVICE}-bypass.middlewares=chain-external-bypass@file
      - traefik.http.routers.${TRAEFIK_LOG_DASHBOARD_SERVICE}-bypass.priority=2500
      - traefik.http.routers.${TRAEFIK_LOG_DASHBOARD_SERVICE}-bypass.rule=Host(`${TRAEFIK_LOG_DASHBOARD_EXTERNAL_URL}`) && Header(`${SPECIAL_HEADER_NAME}`, `${SPECIAL_HEADER_SECRET}`)
      - traefik.http.routers.${TRAEFIK_LOG_DASHBOARD_SERVICE}-bypass.service=${TRAEFIK_LOG_DASHBOARD_SERVICE}
      - traefik.http.routers.${TRAEFIK_LOG_DASHBOARD_SERVICE}-bypass.tls=true
      # Service port (dashboard runs on 3000)
      - traefik.docker.network=smoonet
      - traefik.http.services.${TRAEFIK_LOG_DASHBOARD_SERVICE}.loadbalancer.server.url=${TRAEFIK_LOG_DASHBOARD_INTERNAL_URL}
      ## End Traefik Config
      - com.smoochy.komodo.restore_stack=traefik
      - net.unraid.docker.icon=https://github.com/user-attachments/assets/e6cf097b-2232-4c2c-ba55-5de780724aed
      - net.unraid.docker.webui=${TRAEFIK_LOG_DASHBOARD_INTERNAL_URL}/dashboard
  traefik-log-dashboard-agent:
    container_name: traefik-log-dashboard-agent
    image: hhftechnology/traefik-log-dashboard-agent:3.0.0@sha256:aa75766b9235bf9d8d28f4dd3b1e0902ce589b10386221d43e7eab6f19ce7e57
    restart: unless-stopped

    # Network
    networks:
      smoonet:
    # Ports (internal API)
    ports:
      - "5100:5000/tcp"

    # Volumes
    volumes:
      - /mnt/user/appdata/traefik-dashboard/data/positions/:/data:rw
      - /mnt/user/appdata/traefik/logs/:/logs:ro

    # Environment variables
    environment:
      - HOST_CONTAINERNAME=traefik-log-dashboard-agent
      - HOST_HOSTNAME=smooRAID
      - HOST_OS=Unraid
      - TRAEFIK_LOG_DASHBOARD_ACCESS_PATH=/logs/access.log
      - TRAEFIK_LOG_DASHBOARD_AUTH_TOKEN=${TRAEFIK_LOG_AGENT_TOKEN}
      - TRAEFIK_LOG_DASHBOARD_ERROR_PATH=/logs/traefik.log
      - TRAEFIK_LOG_DASHBOARD_LOG_FORMAT=json
      - TRAEFIK_LOG_DASHBOARD_SYSTEM_MONITORING=true
      - TZ=Europe/Berlin

    # Resource limits
    deploy:
      resources:
        limits:
          pids: 2048
    labels:
      - com.smoochy.komodo.restore_stack=traefik
      - net.unraid.docker.icon=https://github.com/user-attachments/assets/e6cf097b-2232-4c2c-ba55-5de780724aed
networks:
  smoonet:
    external: true

Steps to reproduce

  1. Run Middleware Manager with standalone Traefik.
  2. Set active_data_source to traefik.
  3. Do not include Pangolin in the stack.
  4. Request GET /api/v1/traefik-config.

Actual behavior

The endpoint returns 500 Internal Server Error and tries to contact Pangolin:

{
  "error": "Failed to get Traefik configuration",
  "details": "failed to fetch Pangolin config: HTTP request failed: Get \"http://pangolin:3001/api/v1/traefik-config\": dial tcp: lookup pangolin on 127.0.0.11:53: no such host"
}

At the same time, in my setup:

  • config.json contains "active_data_source": "traefik"
  • the Traefik API is reachable
  • Traefik successfully loads the plugins Codex originally investigated
  • Traefik logs show repeated HTTP provider retries because Middleware Manager keeps returning 500

Expected behavior

When active_data_source is traefik:

  • /api/v1/traefik-config should not depend on Pangolin
  • Middleware Manager should build and serve the standalone Traefik config path without attempting to contact PANGOLIN_API_URL
  • Traefik's HTTP provider should receive 200 OK

Likely root cause

Based on source inspection, ConfigProxy.GetMergedConfig() appears to always call fetchPangolinConfig() instead of switching behavior based on the active data source.

If that reading is correct, standalone Traefik mode is configurable in the UI/config file, but the proxy endpoint still remains Pangolin-dependent.

Suggested direction

Make the config proxy data-source-aware:

  • keep the existing Pangolin fetch/merge path for pangolin
  • for traefik, generate the config from Middleware Manager's standalone Traefik path without requiring Pangolin

Transparency notice

This issue text was prepared with AI-assisted analysis based on live runtime logs and source inspection.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions