# Traefik

> Serving Profilarr through Traefik with Docker labels.

A page from the Profilarr documentation by https://github.com/santiagosayshey, last updated 2026-09-29 (commit: https://github.com/Dictionarry-Hub/profilarr.com/commit/8b95fac60cf982478f81d77b43c956ea6df9dd49). Web version: https://profilarr.com/docs/traefik. Edit on GitHub: https://github.com/Dictionarry-Hub/profilarr.com/edit/develop/src/routes/docs/traefik/+page.svx

[Traefik](https://traefik.io/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](https://doc.traefik.io/traefik/setup/docker/) 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](https://profilarr.com/docs/reverse-proxy#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](https://profilarr.com/docs/docker#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`

```yaml
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`

```yaml
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](https://www.authelia.com/) or [Authentik](https://goauthentik.io/) 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](https://www.authelia.com/integration/proxies/traefik/). Then add it to Profilarr's router:

`compose.yml`

```yaml
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](https://profilarr.com/api/v1) 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`

```yaml
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`](https://profilarr.com/docs/authentication#turning-login-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](https://profilarr.com/docs/authentication#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](https://doc.traefik.io/traefik/reference/install-configuration/providers/others/file/) reads it from the folder set in `providers.file.directory`, and picks up changes without a restart.

`profilarr.yml`

```yaml
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](https://htmx.org/essays/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.

---

Index of this site's Markdown pages: https://profilarr.com/llms.txt
