How to add a reverse proxy to the portainer GUI that host it?

Hi,

I've a whole docker "stack" in my portainer, with traefik, and traefik works very good with it.

My docker-compose:

version: "3.9"
services:
  traefik:
    image: "traefik:latest"
    command:
      - "--log.level=DEBUG"
      - "--api.insecure=true"
      - "--providers.file.filename=/traefik-config/config.yml"
      - "--entrypoints.web.address=:80"
      - "--entrypoints.websecure.address=:443"
      - "--certificatesresolvers.myresolver.acme.dnschallenge=true"
      - "--certificatesresolvers.myresolver.acme.dnschallenge.delayBeforeCheck=30"
      - "--certificatesresolvers.myresolver.acme.dnschallenge.provider=ovh"
      - "--certificatesresolvers.myresolver.acme.email=my@email.com"
      - "--certificatesresolvers.myresolver.acme.storage=/letsencrypt/acme.json"
    ports:
      - "80:80"
      - "8080:8080"
      - "443:443"
    environment:
      - "OVH_ENDPOINT=ovh-eu"
      - "OVH_APPLICATION_KEY=AAA"
      - "OVH_APPLICATION_SECRET=BBB"
      - "OVH_CONSUMER_KEY=CCC"
    volumes:
      - config-letsencrypt:/letsencrypt
      - traefik-config:/traefik-config
      - "/var/run/docker.sock:/var/run/docker.sock:ro"      
    depends_on:
      - paperless-webserver
      - ddnsupdater
      - emby
      - transmission
      - medusa
      - grafana
      - influxdb
      


  ddnsupdater:
    image: qmcgaw/ddns-updater
    volumes:
      - config-ddns:/updater/data
    ports:
      - 8007:8000/tcp
    environment:
      - PERIOD=5m
      - CONFIG=
      - UPDATE_COOLDOWN_PERIOD=5m
      - PUBLICIP_FETCHERS=all
      - PUBLICIP_HTTP_PROVIDERS=all
      - PUBLICIPV4_HTTP_PROVIDERS=all
      - PUBLICIPV6_HTTP_PROVIDERS=all
      - PUBLICIP_DNS_PROVIDERS=all
      - PUBLICIP_DNS_TIMEOUT=3s
      - HTTP_TIMEOUT=10s

      # Web UI
      - LISTENING_PORT=8007
      - ROOT_URL=/

      # Backup
      - BACKUP_PERIOD=0 # 0 to disable
      - BACKUP_DIRECTORY=/updater/data

      # Other
      - LOG_LEVEL=info
      - LOG_CALLER=hidden
      - SHOUTRRR_ADDRESSES=
    healthcheck:
      disable: true

  emby:
    image: lscr.io/linuxserver/emby:latest
    environment:
      - PUID=1028
      - PGID=100
      - TZ=Europe/Zurich
    volumes:
      - config-emby:/config
      - media:/data/
    ports:
      - 8096:8096
  transmission:
    image: lscr.io/linuxserver/transmission:version-3.00-r8
    environment:
      - PUID=1028
      - PGID=100
      - TZ=Europe/Zurich
    volumes:
      - config-transmission:/config
      - downloads:/downloads
      - movies:/movies
      - software:/software
      - ebooks:/ebooks
    ports:
      - 9091:9091
      - 51413:51413
      - 51413:51413/udp

  medusa:
    image: lscr.io/linuxserver/medusa:latest
    environment:
      - PUID=1028
      - PGID=100
      - TZ=Europe/London
    volumes:
      - config-medusa:/config
      - downloads:/downloads
      - tvshows:/tv
    ports:
      - 8081:8081


  wireguard:
    image: linuxserver/wireguard
    cap_add:
      - NET_ADMIN
      - SYS_MODULE
    ports:
      - 51820:51820/udp
    environment:
      - PUID=1028
      - PGID=100
      - TZ=Europe/London
      - SERVERURL=vpn.mydomain.com
      - SERVERPORT=51820
      - PEERS=5
      - ALLOWEDIPS=0.0.0.0/0
    volumes:
      - config-wireguard:/config	  
    sysctls:
      - net.ipv4.conf.all.src_valid_mark=1

  paperless-broker:
    image: docker.io/library/redis:7
    volumes:
      - paperless-redis-data:/data
  paperless-db:
    image: docker.io/library/postgres:15
    volumes:
      - paperless-pgdata:/var/lib/postgresql/data
    environment:
      POSTGRES_DB: paperless
      POSTGRES_USER: paperless
      POSTGRES_PASSWORD: paperless
  paperless-webserver:
    image: ghcr.io/paperless-ngx/paperless-ngx:latest
    depends_on:
      - paperless-db
      - paperless-broker
    ports:
      - "8010:8000"
    volumes:
      - paperless-data:/usr/src/paperless/data
      - paperless-media:/usr/src/paperless/media
      - paperless-export:/usr/src/paperless/export
      - paperless-consume:/usr/src/paperless/consume
    environment:
      PAPERLESS_REDIS: redis://paperless-broker:6379
      PAPERLESS_DBHOST: paperless-db
      USERMAP_UID: 1028
      USERMAP_GID: 100
      PAPERLESS_OCR_LANGUAGE: fra
      PAPERLESS_CONSUMER_POLLING: 30
      PAPERLESS_URL: https://paperless.mydomain.com

  grafana:
    image: grafana/grafana-enterprise
    ports:
      - '3000:3000'
    volumes:
      - grafana-data:/var/lib/grafana
    user: "1028:100"
    environment:
      GF_SERVER_ROOT_URL: https://grafana.mydomain.com
      
  influxdb:
    image: influxdb:latest
    ports:
      - 8086:8086
    volumes:
      - ha-influxDb:/var/lib/influxdb2
      
  evcc:
    command: ["evcc", "-c", "/root/.evcc/evcc.yaml"]
    image: evcc/evcc:latest
    ports:
      - 7070:7070/tcp
      - 8887:8887/tcp
      - 7090:7090/udp
      - 9522:9522/udp
    volumes:
      - evcc-config:/root/.evcc

volumes:
  traefik-config:
    driver_opts:
      type: "nfs"
      o: "addr=192.168.0.60,nolock,rw,soft"
      device: ":/volume2/apps/config/traefik"
  tvshows:
    driver_opts:
      type: "nfs"
      o: "addr=192.168.0.60,nolock,rw,soft"
      device: ":/volume2/apps/media/tvshows"
  movies:
    driver_opts:
      type: "nfs"
      o: "addr=192.168.0.60,nolock,rw,soft"
      device: ":/volume2/apps/media/movies"
  ebooks:
    driver_opts:
      type: "nfs"
      o: "addr=192.168.0.60,nolock,rw,soft"
      device: ":/volume2/apps/media/ebooks"
  media:
    driver_opts:
      type: "nfs"
      o: "addr=192.168.0.60,nolock,rw,soft"
      device: ":/volume2/apps/media"
  software:
    driver_opts:
      type: "nfs"
      o: "addr=192.168.0.60,nolock,rw,soft"
      device: ":/volume2/apps/media/software"
  config-emby:
    driver_opts:
      type: "nfs"
      o: "addr=192.168.0.60,nolock,rw,soft"
      device: ":/volume2/apps/config/emby"
  config-ddns:
    driver_opts:
      type: "nfs"
      o: "addr=192.168.0.60,nolock,rw,soft"
      device: ":/volume2/apps/config/ddns"
  downloads:
    driver_opts:
      type: "nfs"
      o: "addr=192.168.0.60,nolock,rw,soft"
      device: ":/volume2/apps/work/torrent/downloads"
  config-transmission:
    driver_opts:
      type: "nfs"
      o: "addr=192.168.0.60,nolock,rw,soft"
      device: ":/volume2/apps/config/transmission"
  config-medusa:
    driver_opts:
      type: "nfs"
      o: "addr=192.168.0.60,nolock,rw,soft"
      device: ":/volume2/apps/config/medusa"
  config-letsencrypt:
    driver_opts:
      type: "nfs"
      o: "addr=192.168.0.60,nolock,rw,soft"
      device: ":/volume2/apps/config/letsencrypt"
  config-heimdall:
    driver_opts:
      type: "nfs"
      o: "addr=192.168.0.60,nolock,rw,soft"
      device: ":/volume2/apps/config/heimdall"
  config-wireguard:
    driver_opts:
      type: "nfs"
      o: "addr=192.168.0.60,nolock,rw,soft"
      device: ":/volume2/apps/config/wireguard"
  paperless-redis-data:
    driver_opts:
      type: "nfs"
      o: "addr=192.168.0.60,nolock,rw,soft"
      device: ":/volume2/apps/media/scanner/paperless-redis-data"
  paperless-pgdata:
    driver_opts:
      type: "nfs"
      o: "addr=192.168.0.60,nolock,rw,soft"
      device: ":/volume2/apps/media/scanner/paperless-pgdata"
  paperless-data:
    driver_opts:
      type: "nfs"
      o: "addr=192.168.0.60,nolock,rw,soft"
      device: ":/volume2/apps/media/scanner/paperless-data"
  paperless-media:
    driver_opts:
      type: "nfs"
      o: "addr=192.168.0.60,nolock,rw,soft"
      device: ":/volume2/apps/media/scanner/paperless-media"
  paperless-export:
    driver_opts:
      type: "nfs"
      o: "addr=192.168.0.60,nolock,rw,soft"
      device: ":/volume2/apps/media/scanner/paperless-export"
  paperless-consume:
    driver_opts:
      type: "nfs"
      o: "addr=192.168.0.60,nolock,rw,soft"
      device: ":/volume2/public/Scans"
  grafana-data:
    driver_opts:
      type: "nfs"
      o: "addr=192.168.0.60,nolock,rw,soft"
      device: ":/volume2/apps/work/grafana/data"
  ha-influxDb:
    driver_opts:
      type: "nfs"
      o: "addr=192.168.0.60,nolock,rw,soft"
      device: ":/volume2/apps/work/grafana/ha-influxDb"
  n8n-data:
    driver_opts:
      type: "nfs"
      o: "addr=192.168.0.60,nolock,rw,soft"
      device: ":/volume2/apps/work/n8n"
  evcc-config:
    driver_opts:
      type: "nfs"
      o: "addr=192.168.0.60,nolock,rw,soft"
      device: ":/volume2/apps/config/evcc"

my config file:

http:
  routers:
    traefik:
      rule: Host(`traefik.mydomain.com`)
      entrypoints: websecure
      service: traefik
      middlewares:
      - force-secure
      tls:
        certresolver: myresolver
    ddnsupdater:
      rule: Host(`ddns.mydomain.com`)
      entrypoints: websecure
      service: ddnsupdater
      tls:
        certresolver: myresolver
    emby:
      rule: Host(`emby.mydomain.com`)
      entrypoints: websecure
      service: emby
      tls:
        certresolver: myresolver
    transmission:
      rule: Host(`transmission.mydomain.com`)
      entrypoints: websecure
      service: transmission
      tls:
        certresolver: myresolver
    medusa:
      rule: Host(`medusa.mydomain.com`)
      entrypoints: websecure
      service: medusa
      tls:
        certresolver: myresolver
    paperless:
      rule: Host(`paperless.mydomain.com`)
      entrypoints: websecure
      service: paperless
      tls:
        certresolver: myresolver
    grafana:
      rule: Host(`grafana.mydomain.com`)
      entrypoints: websecure
      service: grafana
      tls:
        certresolver: myresolver
    influxdb:
      rule: Host(`influxdb.mydomain.com`)
      entrypoints: websecure
      service: influxdb
      tls:
        certresolver: myresolver
    evcc:
      rule: Host(`evcc.mydomain.com`)
      entrypoints: websecure
      service: evcc
      tls:
        certresolver: myresolver
    portainer:
      rule: Host(`portainer.mydomain.com`)
      entrypoints: websecure
      service: portainer
      tls:
        certresolver: myresolver

  services:
    traefik:
      loadbalancer:
        servers:
          - url: http://192.168.0.30:8080
    ddnsupdater:
      loadbalancer:
        servers:
          - url: http://192.168.0.30:8007
    emby:
      loadbalancer:
        servers:
          - url: http://192.168.0.30:8096
    transmission:
      loadbalancer:
        servers:
          - url: http://192.168.0.30:9091
    medusa:
      loadbalancer:
        servers:
          - url: http://192.168.0.30:8081
    paperless:
      loadbalancer:
        servers:
          - url: http://192.168.0.30:8010
    grafana:
      loadbalancer:
        servers:
          - url: http://192.168.0.30:3000
    influxdb:
      loadbalancer:
        servers:
          - url: http://192.168.0.30:8086
    evcc:
      loadbalancer:
        servers:
          - url: http://192.168.0.30:7070
    portainer:
      loadbalancer:
        servers:
          - url: https://192.168.0.30:9443
 
  middlewares:
    force-secure:
      redirectscheme:
        scheme: https
        permanent: true

Everything works, EXCEPT, my redirection to my portainer instance. What am I missing?

When I try to access it, I get an "Internal Server Error", and in the traefik container logs, I get this:

2024-11-28T13:22:11Z DBG github.com/traefik/traefik/v3/pkg/server/service/loadbalancer/wrr/wrr.go:196 > Service selected by WRR: ddd915a8f082847a

2024-11-28T13:22:11Z DBG github.com/traefik/traefik/v3/pkg/proxy/httputil/proxy.go:113 > 500 Internal Server Error error="tls: failed to verify certificate: x509: certificate is valid for 0.0.0.0, not 192.168.0.30"

2024-11-28T13:22:11Z DBG github.com/traefik/traefik/v3/pkg/server/service/loadbalancer/wrr/wrr.go:196 > Service selected by WRR: ddd915a8f082847a

2024-11-28T13:22:11Z DBG github.com/traefik/traefik/v3/pkg/proxy/httputil/proxy.go:113 > 500 Internal Server Error error="tls: failed to verify certificate: x509: certificate is valid for 0.0.0.0, not 192.168.0.30"

(192.168.0.30 is the docker host)

You connect to Portainer via a https port, so it will respond with a custom TLS cert. Switch to http and use the unencrypted port.

1 Like

Hi @bluepuma77

Thanks for the answer.

I tried to change this to

portainer:
  loadbalancer:
    servers:
      - url: http://192.168.0.30:9000

reloaded the whole docker-stack, but I still get the exact same error, do you have an idea?

Regarding wording, it is not a "redirection", Traefik forwards or proxies requests.

Web services respond with a redirect to the browser, so it requests a different URL. See HTTP status codes 3xx.

It does not make sense that Traefik still shows the same error message regarding TLS cert, the target port should be http only.

Alternatively you can set insecureSkipVerify to disable the internal TLS check, either globally or by creating a transport and assigning it to the service.


Sidenote: I would never use depends_on for a proxy. One failing service (after an update) might disable access to all services.


Further note that you can assign the certResolver on entrypoint, saving some duplication, compare to simple Traefik example.

1 Like

Thanks for the recommandation.
I did remove the depends_on. I initially added it because some services were not yet started but traefik was already trying to communicate to exchange some services.

Back on the issue:

I'm not sure what I did differently, but even without the insecureSkipVerify, it now does work. It's a bit weird, since the error were present with the updated timestamp, but anyway, quite happy with the result, thank you very much!

This topic was automatically closed 3 days after the last reply. New replies are no longer allowed.