Securing Docker Containers with Authentik Forward Auth: Add SSO and MFA in 10 Minutes

Docker tutorial - IT technology blog
Docker tutorial - IT technology blog

The Problem: When an App is Great but Lacks Security

You’ve just found a cool self-hosted tool on GitHub, like the Glances system monitoring dashboard or a file manager. You deploy it to your VPS using Docker in no time. However, you suddenly realize a major flaw: The application has no login page.

Anyone with your IP can view and delete data. Exposing these apps to the Internet without protection is like leaving your front door wide open, which is why maintaining Docker socket security is so vital. Previously, I used Nginx’s Basic Auth as a temporary fix, or would set up Nginx Proxy Manager to manage access. However, this method is inconvenient. The login interface looks like it’s from the 90s, there’s no MFA, and every time you add a new user, you have to manually edit config files and reload the server.

Why Authentik is the Top Choice Today?

To protect “no-login” apps, we usually consider a few options:

  • Basic Auth: Easy to implement but outdated and insecure.
  • Authelia: Lightweight but the YAML configuration can be a headache for beginners.
  • OAuth2 Proxy: Powerful but setting it up for each individual app is time-consuming.
  • Authentik: This is my go-to all-in-one solution. It acts as both an Identity Provider (like Google/Okta) and supports Forward Auth with a very modern management interface.

Since switching to Authentik, I only need to remember a single password (SSO) for over 20 internal applications. More importantly, I can enforce OTP codes from a phone for every access, reducing the risk of account hacking to nearly zero.

How Does Forward Auth Work?

Imagine Authentik as a bouncer standing in front of a bar (your application). The Reverse Proxy (Traefik) acts as the ticket inspector.

  1. When a guest arrives, Traefik asks Authentik: “Does this person have a membership card?”.
  2. If not: Authentik invites the guest to the registration desk (Login Page).
  3. If yes: Authentik nods, and Traefik opens the door for the guest to enter the application.

This entire process happens outside the original application. You don’t need to touch a single line of the app’s code to achieve enterprise-grade security.

Detailed Deployment Guide

In this article, I’m using Traefik because of its smart ability to automatically discover containers via labels. Make sure you have Docker Compose v2 installed on your machine, which is necessary for modern workflows like the Docker Compose include strategy.

Step 1: Initialize Authentik

Create a dedicated directory for management. I recommend using Docker Compose v2 for more stable container connectivity.

mkdir authentik && cd authentik
wget https://goauthentik.io/docker-compose.yml -O docker-compose.yml

# Automatically generate random passwords for the database
echo "PG_PASS=$(openssl rand -base64 36)" >> .env
echo "AUTHENTIK_SECRET_KEY=$(openssl rand -base64 36)" >> .env

docker compose up -d

After about a minute, access http://<Your-IP>:9000/if/flow/initial-setup/ to set up the admin account.

Step 2: Configure Provider and Application

To protect a specific app, you need to perform two steps in the Admin interface:

  1. Go to Resources -> Providers -> Create. Select Proxy Provider.
  2. Select Forward auth (single application) mode. Enter the application domain, for example: https://uptime.example.com.
  3. Go to Resources -> Applications -> Create. Name the app and attach the newly created Provider.

Step 3: Attach “Protection” to the Docker Container

This is where the magic happens. Below is an example configuration for the whoami app. You just need to add these labels to the docker-compose.yml file of any application you want to secure.

services:
  whoami:
    image: traefik/whoami
    networks:
      - proxy
    labels:
      - "traefik.enable=true"
      - "traefik.http.routers.whoami.rule=Host(`uptime.example.com`)"
      - "traefik.http.routers.whoami.entrypoints=websecure"
      - "traefik.http.routers.whoami.tls=true"
      
      # Enable Authentik Middleware
      - "traefik.http.routers.whoami.middlewares=authentik@docker"
      
      # Configure Middleware to connect to the Authentik server
      - "traefik.http.middlewares.authentik.forwardauth.address=http://authentik-server:9000/outpost.goauthentik.io/auth/traefik"
      - "traefik.http.middlewares.authentik.forwardauth.trustForwardHeader=true"
      - "traefik.http.middlewares.authentik.forwardauth.authResponseHeaders=X-authentik-username,X-authentik-groups,X-authentik-email"

Pro tip: Place Authentik and Traefik on the same Docker network. This allows data to travel internally, speeding up response times by about 20-30ms compared to calling via a public IP.

The Result After Setup

Now, when you access the application, you’ll see a professional login screen, and you can even implement HTTPS for local Docker for your development environments. You can enable MFA (TOTP) in Authentik’s User settings. Only those with the 6-digit code on their phone can enter the system. Additionally, you can view detailed logs of who logged in, when, and from which IP, which is a key part of your security posture alongside using Docker Bench for Security.

Troubleshooting Common Errors

If you encounter a “Too many redirects” error, double-check the External Host field in the Provider. It must match the domain declared in Traefik 100%, including https://. If the authResponseHeaders line is missing, the backend application won’t know who is accessing it, leading to frustrating permission errors.

Implementing Authentik might seem a bit complex at first. However, the security benefits and convenience it provides are well worth it. You’ll no longer have to worry every time you expose a new application to the Internet.

Share: