This site is still a work in progress. For the current docs, head to dictionarry.dev.

Traefik

Traefik is a reverse proxy that reads its routes from the apps behind it. With Docker, you describe how to reach Profilarr in labels on Profilarr’s own container, and Traefik picks them up when the container starts.

A Traefik config has three parts:

  • Entrypoints: the ports Traefik listens on, like 80 for HTTP and 443 for HTTPS.
  • Routers: rules that match a request, like Host(`profilarr.example.com`), and send it to a service.
  • Services: where a matched request goes, like Profilarr on port 6868.
Info

We recommend Traefik if you run Profilarr with Docker, because it keeps everything about Profilarr in one place. The labels sit in the same compose file as Profilarr’s image, ports, and variables, so you don’t keep a separate proxy config in sync. When you remove Profilarr, its proxy config goes with it.

Before You Start

New to Traefik? Follow Traefik’s Docker setup guide first, then come back here.

The example on this page assumes your Traefik setup has:

  • Traefik v3, running in Docker.
  • A Docker network that Traefik and Profilarr both join. The example calls it proxy.
  • An entrypoint named web on port 80, and one named websecure on port 443.
  • A certificate resolver named letsencrypt.

Traefik’s defaults already cover most of what your proxy must allow in Requirements: it doesn’t buffer /jobs/events, and it doesn’t limit upload size. It does stop reading a request after 60 seconds, which can cut off a large backup upload. To allow longer uploads, raise entryPoints.websecure.transport.respondingTimeouts.readTimeout in Traefik’s static config, for example to 10m.

Example

This example builds on the compose file in Installing Profilarr. It sets ORIGIN and adds the labels Traefik reads. It doesn’t publish port 6868, so Traefik is the only way in.

compose.yml
services:
  profilarr:
    image: ghcr.io/dictionarry-hub/profilarr:latest
    container_name: profilarr
    restart: unless-stopped
    volumes:
      - ./config:/config
    environment:
      - PUID=1000
      - PGID=1000
      - TZ=Etc/UTC
      - ORIGIN=https://profilarr.example.com
      - PARSER_HOST=parser
      - PARSER_PORT=5000
    networks:
      - default # Reaches the parser.
      - proxy # Reaches Traefik.
    labels:
      - traefik.enable=true # Opt this container in to Traefik.
      - traefik.docker.network=proxy # Without this, Traefik may pick another of Profilarr's networks and 502.
      - traefik.http.routers.profilarr.rule=Host(`profilarr.example.com`) # Must match ORIGIN.
      - traefik.http.routers.profilarr.entrypoints=websecure # HTTPS only.
      - traefik.http.routers.profilarr.tls.certresolver=letsencrypt # Gets the certificate.
      - traefik.http.services.profilarr.loadbalancer.server.port=6868 # Profilarr's port.
    depends_on:
      parser:
        condition: service_healthy

  # Not proxied: only Profilarr talks to the parser, and it has no login.
  parser:
    image: ghcr.io/dictionarry-hub/profilarr-parser:latest
    container_name: profilarr-parser
    restart: unless-stopped
    expose:
      - '5000'

networks:
  proxy:
    external: true

Redirecting HTTP to HTTPS

The router above only listens on websecure, so a visit to http://profilarr.example.com finds nothing and gets a 404. A redirect on the web entrypoint sends every HTTP request to HTTPS instead, for Profilarr and every other app behind Traefik. Add it to Traefik’s static config:

traefik.yml
entryPoints:
  web:
    address: ':80'
    http:
      redirections:
        entryPoint:
          to: websecure
          scheme: https
  websecure:
    address: ':443'

Forward Auth

With forward auth, Traefik sends every request to a sign-in service like Authelia or Authentik first, to check whether you’re signed in. If you are, Traefik passes the request on to Profilarr. If you aren’t, Traefik redirects you to the sign-in service’s login page. To create the middleware, follow your sign-in service’s guide, like Authelia’s Traefik guide. Then add it to Profilarr’s router:

compose.yml
labels:
      # ...the labels from the example, plus:
      - traefik.http.routers.profilarr.middlewares=authelia@docker

Use the middleware’s name from your setup. @docker means you defined it in labels, and @file means you defined it in Traefik’s file provider.

Scripts and apps that call Profilarr’s API with an API key can’t sign in to your sign-in service, so the middleware blocks them too. To let them through, add a second router for /api/v1 without the middleware. Traefik picks the router with the longer rule, so API requests use this one:

compose.yml
labels:
      # ...the labels above, plus a second router without the middleware:
      - traefik.http.routers.profilarr-api.rule=Host(`profilarr.example.com`) && PathPrefix(`/api/v1`)
      - traefik.http.routers.profilarr-api.entrypoints=websecure
      - traefik.http.routers.profilarr-api.tls.certresolver=letsencrypt
      - traefik.http.routers.profilarr-api.service=profilarr
Danger

Only add the API router while Profilarr’s own login is on. With AUTH=off, Profilarr accepts API requests without a key, so this router would open the API to anyone who can reach Traefik.

Once forward auth works, Profilarr’s own login is a second sign-in. See Turning Login Off before you turn it off.

Without Docker

If Profilarr doesn’t run in Docker, Traefik can’t read labels from it. Describe the router and service in a file instead, and point the service at Profilarr’s address. Traefik’s file provider reads it from the folder set in providers.file.directory, and picks up changes without a restart.

profilarr.yml
http:
  routers:
    profilarr:
      rule: Host(`profilarr.example.com`)
      entryPoints:
        - websecure
      tls:
        certResolver: letsencrypt
      service: profilarr
  services:
    profilarr:
      loadBalancer:
        servers:
          - url: http://192.168.1.10:6868
Info

We recommend Traefik because it follows locality of behaviour: the config for something lives next to that thing. For Profilarr, that means:

  • You can see how Profilarr is served by reading its compose file alone.
  • Changing Profilarr’s routing can’t break another app’s.
  • Removing Profilarr removes its routing too, so nothing stale is left behind.
  • Copying Profilarr’s compose file to another machine brings its routing with it.