Problem with wsgi.scheme and Gunicorn behind Traefik

Hi, I'm using Traefik as reverse-proxy / edge for services that use Gunicorn.
Traefik uses HTTPS, the Gunicorn instances behind it uses HTTP.

Gunicorn listens to any of these headers to determine if it should switch scheme - from docs:
{'X-FORWARDED-PROTOCOL': 'ssl', 'X-FORWARDED-PROTO': 'https', 'X-FORWARDED-SSL': 'on'}

(It works when I use Nginx as reverse proxy instead. with X-Forwarded-Proto)

Any takes on why this isn't working properly?

The Traefik compose file:

version: "3.3"

services:
  proxy:
    image: "traefik:v2.2"
    command:
      - "--providers.docker=true"
      - "--providers.docker.network=traefik-public"
      - "--entrypoints.web.address=:80"
      - "--entrypoints.websecure.address=:443"
      - "--log.level=INFO"
      - "--certificatesresolvers.letsencrypt.acme.httpchallenge=true"
      - "--certificatesresolvers.letsencrypt.acme.httpchallenge.entrypoint=web"
      - "--certificatesresolvers.letsencrypt.acme.email=<email>"
      - "--certificatesresolvers.letsencrypt.acme.storage=/letsencrypt/acme.json"
    ports:
      - "80:80"
      - "443:443"
      - "8080:8080"
    volumes:
      - "/var/run/docker.sock:/var/run/docker.sock:ro"
      - "./letsencrypt:/letsencrypt"
    networks:
      - traefik-public
    labels:
      # global redirect to https
      - "traefik.http.routers.http-catchall.rule=hostregexp(`{host:.+}`)"
      - "traefik.http.routers.http-catchall.entrypoints=web"
      - "traefik.http.routers.http-catchall.middlewares=redirect-to-https"
      # middleware redirect
      - "traefik.http.middlewares.redirect-to-https.redirectscheme.scheme=https"

networks:
  traefik-public:
    external: true

And one of the instances:

version: '3.6'

services:
  instance:
    image: <image>
    networks:
      - traefik-public
      - default
    labels:
      - "traefik.enable=true"
      - "traefik.http.routers.instance-${COMPOSE_PROJECT_NAME}.rule=Host(`example.se`)"
      - "traefik.http.routers.instance-${COMPOSE_PROJECT_NAME}.entrypoints=websecure"
      - "traefik.http.services.instance-${COMPOSE_PROJECT_NAME}.loadbalancer.server.port=6543"
      - "traefik.http.routers.instance-${COMPOSE_PROJECT_NAME}.tls=true"
      - "traefik.http.routers.instance-${COMPOSE_PROJECT_NAME}.tls.certresolver=letsencrypt"

I'm guessing that I should add custom request headers, but i can't get that to stick. My guess is that I simply don't configure the middleware correctly?

Does anyone have some examples of running Gunicorn with a similar setup? Or could point me in the right direction?

All the best,
Robin

Hi Robin,
In Codification, we worked out that the issue stems from Gunicorn not accepting any custom headers unless they were coming from a verified IP, in this case, your Traefik reverse proxy.
To resolve your issue, the following flag should be added to your Gunicorn web server upon startup:

--forwarded-allow-ips="<traefik_reverse_proxy_ip>"

This will cause Gunicorn to view your Traefik reverse proxy as a verified and trusted IP source. By default, Traefik adds the X-FORWARDED-PROTO header when SSL = on, removing the need for additional label configuration.

Nathan Stephenson,
Solutions Engineer at https://codification.io/

1 Like

Hi, I know it was I who emailed your consultant the solution. But yeah that solved the problem :smile:

All the best,
Robin

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