Skip to main content

Basic Auth

Updated Feb 05, 2023 ·

Overview

Basic authentication middleware protects services by requiring a username and password before granting access.

  • Connects to the router
  • Checks username and password
  • Allows or blocks requests based on credentials

This ensures that only authorized users can access the service.

How It Works

When a request reaches the router, the basic authentication middleware intercepts it.

  • If the credentials match, the request continues to the service
  • If they are incorrect, the middleware responds with a 401 Unauthorized

This adds a security layer for services without built-in authentication.

Configuring Basic Authentication

Basic authentication in Traefik is set up using labels.

  • Define middleware name
  • Use basicAuth with hashed passwords
  • Attach middleware to a router

Example:

labels:
- "traefik.http.middlewares.test-auth.basicauth.users=traefik:$$apr1$$xyz123$$abc456, user2:$$apr1$$def789$$ghi012"
- "traefik.http.routers.cat-app.middlewares=test-auth"

Here:

  • test-auth is the middleware name
  • traefik and user2 are usernames
  • Passwords are stored as hashes

Creating Password Hashes

Passwords must be hashed before adding them to the middleware.

  • Use the htpasswd command in Linux
  • Escape dollar signs by doubling them ($ becomes $$)

Example:

htpasswd -nb traefik mypassword | sed 's/\$/\$\$/g'

Expected output:

traefik:$$apr1$$xyz123$$abc456

This output can be placed directly into the middleware label.

Lab: Using Basic Auth

This lab shows how to secure an application by adding a username and password directly through Traefik middleware. With this setup, the application will require credentials before granting access.

Clone the Repository

To try out the lab, clone the project repository from GitHub.

Clone and move into the project directory:

git clone https://github.com/joseeden/labs-traefik.git 
cd labs-traefik/05-middleware/01-basic-auth

Project structure:

05-middleware
├── 01-basic-auth
│ ├── .gitignore
│ ├── basicauth_users
│ ├── docker-compose.auth.yml
│ ├── docker-compose.secrets.yml
│ ├── docker-compose.usersfile.yml
│ ├── traefik.yml
│ └── usersfile

Creating the Passwords

Passwords must be hashed before being added to the configuration.

  • Use the htpasswd command to generate credentials
  • Escape dollar signs by replacing $ with $$
  • Optionally use an online tool for Windows

To use htbpassword, you need to install it first:

sudo apt install -y apache2-utils

Below are the credentials that we want to use:

UsernamePassword
johnsmithThr3@tl3u3lw!dN!QHt
janedoe@Ll!$szM3lLiND@h0oD

Generate the hashes using the command:

htpasswd -nb johnsmith 'Thr3@tl3u3lw!dN!QHt' | sed 's/\$/\$\$/g'

Expected output:

johnsmith:$$apr1$$cipim6NJ$$LK11Xtf0t92UvxjKCV8ii0

Repeat for other users as needed.

htpasswd -nb janedoe '@Ll!$szM3lLiND@h0oD' | sed 's/\$/\$\$/g'

Expected output:

janedoe:$$apr1$$t65c7tuF$$Qscp40RYl.Tq02pUnSv5r1

Updating Configuration

The hashed passwords are added to the middleware definition.

docker-compose.auth.yml
version: "3"

services:
traefik:
image: traefik:v2.3
ports:
- "80:80"
- "443:443"
- "8080:8080"
volumes:
- /var/run/docker.sock:/var/run/docker.sock
- ./traefik.yml:/etc/traefik/traefik.yml

# Add the catapp service
catapp:
image: mikesir87/cats:1.0
labels:
- "traefik.enable=true"
# Routers
- "traefik.http.routers.catapp.rule=Host(`catapp.localhost`)"
- "traefik.http.routers.catapp.service=catapp"
- "traefik.http.routers.catapp.entrypoints=web"
- "traefik.http.routers.catapp.middlewares=test-auth"
# Services
- "traefik.http.services.catapp.loadbalancer.server.port=5000"
# Middleware BasicAuth
- "traefik.http.middlewares.test-auth.basicauth.users=johnsmith:$$apr1$$cipim6NJ$$LK11Xtf0t92UvxjKCV8ii0,janedoe:$$apr1$$t65c7tuF$$Qscp40RYl.Tq02pUnSv5r1"

Where:

  • test-auth is the middleware name
  • Router references the middleware by its exact name

Deploying and Testing

Once configured, deploy and test the authentication.

docker stack deploy -c docker-compose.auth.yml traefik

Output:

Creating network traefik_default
Creating service traefik_traefik
Creating service traefik_catapp

Open the Traefik dashboard:

http://localhost:8080/ 

Go to Routers > HTTP Routers > Click catapp@docker. Confirm the middleware is linked to the router.

Access the application in a browser. When prompted, enter the configured username and password.

If credentials are correct, the request is allowed.

Now try entering incorrect credentials. For now, access will be blocked, but we’ll add a custom error page in later labs.

Storing Credentials Safely

Keep sensitive login details out of your codebase.

  • Do not place credentials directly in docker-compose.yml
  • Save them in a separate file excluded from Git
  • Use environment variables loaded from a .env file (also excluded from Git)
  • For production, store them in a secrets manager like Vault, AWS Secrets Manager, or Docker secrets

This way, passwords stay secure and never end up in the repository.

Using a separate file

This method uses a separate file to store credentials, keeping them out of the main configuration.

  1. Create a usersfile file in the same directory as your Docker compose file. This file will contain the hashed credentials, one per line.

    Run the command once again, but without sed:

    htpasswd -nb johnsmith 'Thr3@tl3u3lw!dN!QHt'
    htpasswd -nb janedoe '@Ll!$szM3lLiND@h0oD'

    Then create the .env file and add the credentials:

    johnsmith:$apr1$cipim6NJ$LK11Xtf0t92UvxjKCV8ii0
    janedoe:$apr1$t65c7tuF$Qscp40RYl.Tq02pUnSv5r1
    info

    NOTE:

  2. Add usersfile to .gitignore:

    usersfile
  3. Delete the existing service first:

    docker stack rm traefik
  4. We'll use the docker-compose.usersfile.yml for this example:

    version: "3"

    services:
    traefik:
    image: traefik:v2.3
    ports:
    - "80:80"
    - "443:443"
    - "8080:8080"
    volumes:
    - /var/run/docker.sock:/var/run/docker.sock
    - ./traefik.yml:/etc/traefik/traefik.yml
    - ./usersfile:/usersfile:ro # <-- mount your users file here

    catapp:
    image: mikesir87/cats:1.0
    labels:
    - "traefik.enable=true"
    # Routers
    - "traefik.http.routers.catapp.rule=Host(`catapp.localhost`)"
    - "traefik.http.routers.catapp.service=catapp"
    - "traefik.http.routers.catapp.entrypoints=web"
    - "traefik.http.routers.catapp.middlewares=test-auth"
    # Services
    - "traefik.http.services.catapp.loadbalancer.server.port=5000"
    # Middleware BasicAuth using usersfile
    - "traefik.http.middlewares.test-auth.basicauth.usersfile=/usersfile"
  5. Deploy the stack:

    docker stack deploy -c docker-compose.usersfile.yml traefik

The credentials will be pulled from usersfile at runtime, never stored in Git. To verify if it works, access the catapp.localhost in your browser, and try the other credential.

Using Docker Secrets

Using Docker secrets is a safe way to manage your Basic Auth credentials without exposing them in your images or compose files.

  1. Create the secret file (basicauth_users) locally:

    htpasswd -nb johnsmith 'Thr3@tl3u3lw!dN!QHt' > basicauth_users
    htpasswd -nb janedoe '@Ll!$szM3lLiND@h0oD' >> basicauth_users
    htpasswd -nb michaelscarn 'n0g0DNN0!h@t3t08y' >> basicauth_users
    echo "basicauth_users" >> .gitignore
  2. Create the Docker secret:

    docker secret create basicauth_users ./basicauth_users
  3. Use the docker-compose.secrets.yml that references the file inside the container:

    Important notes:

    • Secrets appear inside containers at /run/secrets/<secret_name> by default
    • Use the secret file path like usersfile=/run/secrets/basicauth_users
    • Your Docker setup must support secrets (Compose file version 3.1 or higher)
    • Mark secrets as external if created outside Compose with docker secret create

    Example docker-compose.secrets.yml:

    version: "3"

    services:
    traefik:
    image: traefik:v2.3
    ports:
    - "80:80"
    - "443:443"
    - "8080:8080"
    volumes:
    - /var/run/docker.sock:/var/run/docker.sock
    - ./traefik.yml:/etc/traefik/traefik.yml
    secrets:
    - basicauth_users

    catapp:
    image: mikesir87/cats:1.0
    labels:
    - "traefik.enable=true"
    # Routers
    - "traefik.http.routers.catapp.rule=Host(`catapp.localhost`)"
    - "traefik.http.routers.catapp.service=catapp"
    - "traefik.http.routers.catapp.entrypoints=web"
    - "traefik.http.routers.catapp.middlewares=test-auth"
    # Services
    - "traefik.http.services.catapp.loadbalancer.server.port=5000"
    # Middleware BasicAuth using usersfile
    - "traefik.http.middlewares.test-auth.basicauth.usersfile=/run/secrets/basicauth_users"

    secrets:
    basicauth_users:
    external: true
  4. Deploy the stack:

    docker stack deploy -c docker-compose.secrets.yml traefik

Note that in step 1, a third user was added. Use this user to test access and verify your setup.

Cleanup

Delete the deployed stack:

docker stack rm traefik 

You can also delete the usersfile and basicauth_users :

rm -f usersfile
rm -f basicauth_users