Authelia Docker Compose Guide: Secure 2-Factor Auth [2024-v2]

Don’t like to outsource your authentication to third-party services like Google OAuth? Then this Authelia Docker Compose guide for v4.38+ is for you.

Authelia is a self-contained and local authentication layer for Docker services. This Authelia Docker Compose tutorial is going to show you how to easily add a secure multi-factor authentication to your Docker stack.

Note: If you prefer the convenience of automating Authelia setup + more (e.g. Traefik, Backups, Portainer, Homepage, etc.), then check out Deployarr.

As you may know, I am a big fan of Docker and Traefik. I have covered this in detail in my Ultimate Docker Server series:

Ultimate Docker Server Series:
This post is part of the Docker Server Tutorial Series, which includes the following individual chapters/parts:
  1. Ultimate Docker Server: Getting Started with OS Preparation [VIDEO] [2024]
  2. Docker Media Server Ubuntu/Debian with 60+ Awesome Apps [VIDEO] [2024]
  3. ZeroTier VPN Ubuntu, Docker, Synology, Windows: Secure on-the-go access [coming soon]
  4. Nginx Proxy Manager Docker Compose Guide: Simplest Reverse Proxy [coming soon]
  5. Traefik Reverse Proxy
  6. Authelia Docker Compose Guide: Secure 2-Factor Authentication [VIDEO] [2024]
  7. Google OAuth Docker Compose Guide: Multi-Factor Authentication [VIDEO] [2024]
  8. Docker Security Practices for Homelab: Secrets, Firewall, and more
  9. Cloudflare Settings for Docker Traefik Stacks
  10. Implementing a Backup System for Docker Traefik Stack [coming soon]
  11. Automate Homelab Setup Deployarr: 60+ Apps in Minutes
It is best to follow the series from the beginning so you not only understand WHAT to do but also WHY we do it.

In my Traefik guide, I left you with basic HTTP authentication. But urged you to upgrade to a more secure and modern authentication layer such as Authelia (self-hosted) or Google Oauth (if you trust Google).

I covered Authelia in my previous post in 2020 and updated it again earlier in 2024. And, then Authelia 4.38 came out, which had significant changes. Therefore, it's time for an updated Docker Compose guide for Authelia.

We are going to do this in sections. First, we will meet the bare minimum requirements to get Authelia running on Docker. Then, I will leave you with a few Authelia enhancement ideas. We are going to do it all using Docker Compose because it is easier.

What is Authelia?

Authelia is an open-source authentication and authorization server providing 2-factor authentication and single sign-on (SSO) for your applications via a web portal. It acts as a companion of reverse proxies like Nginx, Traefik, or HAProxy to let them know whether queries should pass through. Unauthenticated users are redirected to the Authelia Sign-in portal instead.

The schematic below shows how Authelia fits into the grand scheme of things.

Authelia Tutorial For Docker And Traefik
Authelia Traefik Schematic

Detailed information is available on Authelia's GitHub page and its Documentation.

Authelia Features

Here are some key features of Authelia:

  • Several kinds of second factor:
    1. Security Key (U2F) with Yubikey.
    2. Time-based One-Time password with Google Authenticator.
    3. Mobile Push Notifications with Duo.
  • Password reset with identity verification using email confirmation.
  • Single-factor only authentication method available.
  • Access restriction after too many authentication attempts.
  • Fine-grained access control per subdomain, user, resource and network.
  • Support of basic authentication for endpoints protected by single factor.
  • Highly available using a remote database and Redis as a highly available KV store.

Types of Authelia Deployment

Authelia supports three scenarios:

  1. Local: Meant to be used for scenarios where the server is not exposed to the internet. Domains will be defined in the local hosts file and self-signed certificates will be utilized. This is useful for testing.
  2. Lite: Authelia Lite is for scenarios where the server will be exposed to the internet with proper domains, DNS, and LetsEncrypt certificates. The Lite element refers to minimal external dependencies; File based user storage; SQLite based configuration storage. In this configuration, the service will not scale well.
  3. Full: Authelia full, is similar to Lite but with scalable setup which includes external dependencies; LDAP based user storage, Database based configuration storage (MariaDB, MySQL or Postgres).

In this Authelia Docker-Compose guide, we are going to setup the Lite scenario, which is sufficient for a typical homelab user. However, we are going to also make it slightly scalable with Redis and MySQL configuration. Only LDAP user storage is not covered here.

Authelia Alternatives

Are there alternatives to Authelia? Sure, there are many replacements for Authelia: Google OAuth, Keycloak, and Authentik.

Authelia vs Google Oauth

We already discussed Google OAuth. I liked Google OAuth 2.0 and I rarely had to login because I am usually logged into my google account on the browser.

I never really had any issues using Google OAuth. But if the thought of using my private authentication layer that is open-source fascinates you, then Authelia is a strong candidate to consider.

Authelia vs Keycloak

I have personally not administered Keycloak but have used it and spoken to others that administer it. In my limited knowledge, my opinion is that Authelia is a lot simpler to administer and use than Keycloak for protecting Docker services. Authelia has also met all my needs so far.

Combined with Cloudflare settings for Docker and Docker Security best practices, Authelia has significantly enhanced the security of my setup.

Authelia vs Authentik

Authentik has been gaining a lot of traction as a replacement for Authelia. But unlike Authelia, Authentik appears to be geared towards enterprise environments. Consequently, it offers more features and integrations but is also more complex to setup. For example, Authelia requires just one docker container whereas Authentik requires multiple.

Automated Authelia Setup

If you have not heard of Deployarr (formerly Auto-Traefik), then you should consider checking out this playlist.

Auto-Traefik makes it very easy to setup and activate Authelia in just under 2 minutes. Check it out:

Deployarr 4: Docker Homelab in Minutes🚀 (75+ Apps)

Of course, Deployarr can do a lot more than just installing Authelia.

Deployarr was launched as a perk to my supporters and to find a way to financially support what I do with this site.

Everything that the Deployarr Script does should be possible by following this series without paying for Deployarr. But my hope is that you continue to support my work by becoming a member.

Be the 1 in 200,000. Help us sustain what we do.
114 / 150 by Dec 31, 2024
You will gain benefits such as discord roles, exclusive content, ad-free browsing, raffles, and more.
Become a Sponsor (starting from just $1.67/month)

Authelia Docker Compose Requirements

Before we get started with Authelia docker configuration, ensure that you have read and followed my previous Docker Traefik guide. You should have a working Traefik Docker stack with the Docker root folder defined using the environmental variable $DOCKERDIR.

Authelia Configuration

If you prefer to follow a video guide instead, check out my YouTube video:

Ultimate Security with Authelia and Docker Compose

That's right. We are going to first configure Authelia before setting it up. Authelia needs some basic configuration to be done before the Authelia docker service can start properly.

Prepare Authelia Folder

In the appdata folder (or a known location), create a folder called authelia. If you have been following my 2024 Ultimate Docker Server series or used Deployarr, this would be in the path /home/anand/docker/appdata.

Then, set the right permissions for the folder using the following commands (replace anand with your username):

sudo chown -R anand:anand /home/anand/docker/appdata/authelia
sudo find /home/anand/docker/appdata/authelia/ -type d -exec chmod 750 {} \;
sudo find /home/anand/docker/appdata/authelia/ -type f -exec chmod 640 {} \;

With that done, let us begin configuring Authelia.

1. Authelia "Required" Configuration

Authelia configurations are defined in configuration.yml. Some are required and some are optional.

Begin by creating an empty configuration.yml file in the authelia folder we created above and add content to it as defined below (Pay attention to indentation and spaces. YAML will throw errors if proper indentation/spacing are not followed.).

Tip: You may use the example configuration.yml from Deployarr's GitHub Repo as a starting point.
###############################################################
#                   Authelia configuration                    #
###############################################################

server:
  address: tcp://0.0.0.0:9091/
  buffers:
    read: 4096
    write: 4096
  endpoints:
    enable_pprof: false
    enable_expvars: false
  disable_healthcheck: false
  tls:
    key: ""
    certificate: ""

# https://www.authelia.com/configuration/miscellaneous/logging/
log:
  level: info
  format: text
  file_path: /config/authelia.log
  keep_stdout: true

# https://www.authelia.com/configuration/second-factor/time-based-one-time-password/
totp:
  issuer: example.com
  period: 30
  skew: 1

# AUTHELIA_DUO_PLACEHOLDER

# https://www.authelia.com/reference/guides/passwords/
authentication_backend:
  password_reset:
    disable: false
  refresh_interval: 5m
  file:
    path: /config/users.yml
    password:
      algorithm: argon2id
      iterations: 1
      salt_length: 16
      parallelism: 8
      memory: 256 # blocks this much of the RAM

# https://www.authelia.com/overview/authorization/access-control/
access_control:
  default_policy: deny
  rules:
    # - domain:
    #     - "*.example.com"
    #     - "example.com"
    #   policy: bypass
    #   networks: # bypass authentication for local networks
    #     - 10.0.0.0/8
    #     - 192.168.0.0/16
    #     - 172.16.0.0/12
    - domain:
        - "*.example.com"
        - "example.com"
      policy: two_factor

# https://www.authelia.com/configuration/session/introduction/
session:
  name: authelia_session
  same_site: lax
  expiration: 7h
  inactivity: 5m
  remember_me: 1M
  cookies:
    - domain: 'example.com'
      authelia_url: 'https://authelia.example.com'
      default_redirection_url: 'https://example.com'
  # AUTHELIA_REDIS_PLACEHOLDER

# https://www.authelia.com/configuration/security/regulation/
regulation:
  max_retries: 3
  find_time: 10m
  ban_time: 12h
  
# https://www.authelia.com/configuration/storage/introduction/
storage:
  # For local storage, uncomment lines below and comment out mysql. https://docs.authelia.com/configuration/storage/sqlite.html
  # This is good for the beginning. If you have a busy site then switch to other databases.
  local:
   path: /config/db.sqlite3

# https://www.authelia.com/configuration/notifications/introduction/
notifier:
  disable_startup_check: false
  # For testing purposes, notifications can be sent in a file. Be sure to map the volume in docker-compose.
  filesystem:
    filename: /config/notifications.txt

Customizing Authelia Configuration

At any point, you may refer to Authelia Documentation to further customize your setup.

The defaults above should work for most Docker Authelia setups. But here are some notes:

Server

This is quite straightforward. With the server directive, we are asking authelia to listen on all network interface (0.0.0.0) on port 9091.

server:
  address: tcp://0.0.0.0:9091/

There are a few other settings under server but they rarely require any tweaking.

Log

Default is set to info. But when creating bypass rules or troubleshooting, you may change the level to debug or trace.

# https://www.authelia.com/configuration/miscellaneous/logging/
log:
  level: info
  format: text
  file_path: /config/authelia.log
  keep_stdout: true

The logs will be stored in /config/authelia.log file inside the container. Since we will be mapping the /config folder to /home/anand/docker/appdata/authelia on the Docker host, you will find authelia.log inside this folder.

totp

Authelia uses time-based one-time-passwords (TOTP). By default, it is set to rotate every 30 seconds. The details for above settings are here. However, it is highly recommended not to mess with these.

# https://www.authelia.com/configuration/second-factor/time-based-one-time-password/
totp:
  issuer: simplehomelab.com
  period: 30
  skew: 1

Replace simplehomelab.com with your domain name.

authentication_backend

We are going to use file-based authentication (users.yml) with one of the strongest hashing algorithms for passwords (argon2id). We will create the users file in the later steps.

For passwords, argon2id is the recommended hashing algorithm. You may choose to use sha512 (recommended for low power devices). The defaults shown above for iterations, salt_length, parallelism, and memory should work for most instances. You may customize them based on this documentation.

Note, that customizing the values will have a huge impact on resource usage.
# https://www.authelia.com/reference/guides/passwords/
authentication_backend:
  password_reset:
    disable: false
  refresh_interval: 5m
  file:
    path: /config/users.yml
    password:
      algorithm: argon2id
      iterations: 1
      salt_length: 16
      parallelism: 8
      memory: 256 # blocks this much of the RAM

We are also disabling the ability to reset passwords. You may or may not want to turn this on in a multi-user environment.

access_control

For access control, we are denying access by default. Everything will require two-factor authentication.

You have the flexibility to bypass authentication for certain situations (e.g. requests from LAN IPs). This will be discussed in the enhancements section below. Meanwhile, feel free to check Authelia documentation for other ways to customize access.

# https://www.authelia.com/overview/authorization/access-control/
access_control:
  default_policy: deny
  rules:
    - domain:
        - "*.simplehomelab.com"
        - "simplehomelab.com"
      policy: two_factor
session

Customizing the session will determine how long authentication will be valid. Shorter intervals will result in more frequent multi-factor authentication. You can further enhance the performance of session storage by using a database backend and Redis as described later.

But this is optional and improvements are marginal in a single-user environment.

# https://www.authelia.com/configuration/session/introduction/
session:
  name: authelia_session
  same_site: lax
  expiration: 7h
  inactivity: 5m
  remember_me: 1M
  cookies:
    - domain: 'example.com'
      authelia_url: 'https://authelia.simplehomelab.com'
      default_redirection_url: 'https://simplehomelab.com'
  # AUTHELIA_REDIS_PLACEHOLDER

We are redirecting "unknown" target URLs to https://simplehomelab.com (simplehomelab.com is the test domain I use in my guides). You may change this to another page if you would like.

regulation

Regulation provides a layer of security by banning brute-force attempts. We are banning any user that has three incorrect attempts in 5 minutes (300 seconds).

# https://www.authelia.com/configuration/security/regulation/
regulation:
  max_retries: 3
  find_time: 10m
  ban_time: 12h

Note that the user account will be banned, not the IP. While this can slow down brute-force attack, an intrusion prevention system such as CrowdSec is strongly recommended.

How-To Series: Crowd Security Intrusion Prevention System
  1. Crowdsec Docker Compose Guide Part 1: Powerful IPS with Firewall Bouncer
  2. CrowdSec Docker Part 2: Improved IPS with Cloudflare Bouncer
  3. CrowdSec Docker Part 3: Traefik Bouncer for Additional Security
  4. CrowdSec Multiserver Docker (Part 4): For Ultimate Protection

storage

Authelia has built-in session storage using SQLite. This is sufficient for a single-user environment.

# https://www.authelia.com/configuration/storage/introduction/
storage:
  # For local storage, uncomment lines below and comment out mysql. https://docs.authelia.com/configuration/storage/sqlite.html
  # This is good for the beginning. If you have a busy site then switch to other databases.
  local:
   path: /config/db.sqlite3

Replacing SQLite with a database such as MySQL (described later) offers performance, scalability, and the ability to run multiple authelia instances.

notifier

Finally, notifications can be done in two ways: file or via email. Email requires a valid SMTP server, which may or may not be available in your case.

I use the free SMTP relay service from Brevo (previously SendInBlue). There are a few more free services out there.

For now, we will send all notifications to a file called notifications.txt inside the authelia config folder.

# https://www.authelia.com/configuration/notifications/introduction/
notifier:
  disable_startup_check: false
  # For testing purposes, notifications can be sent in a file. Be sure to map the volume in docker-compose.
  filesystem:
    filename: /config/notifications.txt

2. Authelia Secrets

In my 2020 version of this guide, I did not use Docker secrets. I used environment variables. With revision and as with my Ultimate Docker Guide 2024, I am taking secure approach from the beginning. So, let's pass sensitive information as Docker Secrets.

At the minimum, 3 secret tokens are needed for Authelia: identity_validation.reset_password.jwt_secret, storage.encryption_key, and session_secret. All the secrets supported by Authelia are listed here.

Let's create the 3 for now. Adding secrets to Docker is essentially a multi-step process, as explained in part 2 of this Docker series.

Create Secrets Folder

If you haven't already done so, create a folder called secrets in a known location. If you have been following my guides, this would be /home/anand/docker/secrets. The folder must be owned by root:root and have 600 permission as shown below.

Docker Secrets Folder Permissions
Docker Secrets Folder Permissions

Note that you will have to gain root privileges to navigate or see contents of the secrets folder.
Create the Secret Files

Next, use the following commands to automatically create a random string for each secret and save them in the secrets folder (/home/anand/docker/secrets/).

tr -cd '[:alnum:]' </dev/urandom | fold -w "64" | head -n 1 | tr -d '\n' | sudo tee /home/anand/docker/secrets/authelia_jwt_secret
tr -cd '[:alnum:]' </dev/urandom | fold -w "64" | head -n 1 | tr -d '\n' | sudo tee /home/anand/docker/secrets/authelia_storage_encryption_key
tr -cd '[:alnum:]' </dev/urandom | fold -w "64" | head -n 1 | tr -d '\n' | sudo tee /home/anand/docker/secrets/authelia_session_secret
Secret Permissions

Next, let's ensure proper permissions for those using the following command:

sudo chown root:root /home/anand/docker/secrets/authelia*
sudo chmod 600 /home/anand/docker/secrets/authelia*

Notice that they all have the same permissions (owner root, group root, and 600 permissions) as the secrets folder.

Secrets For Authelia
Secrets For Authelia

Don't worry about any missing or additional ones. We will add a few more later. The above is just an example to show the permissions.

Add Authelia Secrets to Master Docker Compose

Open your master docker compose file for editing. If you have been following the Ultimate docker server series, this might be docker-compose-udms.yml (or whatever you named it to be).

Under secrets section, ensure you define the three secrets we created above:

########################### SECRETS
secrets:
...
  authelia_jwt_secret:
    file: $DOCKERDIR/secrets/authelia_jwt_secret
  authelia_session_secret:
    file: $DOCKERDIR/secrets/authelia_session_secret
  authelia_storage_encryption_key:
    file: $DOCKERDIR/secrets/authelia_storage_encryption_key
...
Note that the ... refer to previous lines that may already exist after having followed the previous parts of this Ultimate Docker Server series.

Note that, $DOCKERDIR is the environment variable defined in .env file to represent /home/anand/docker.

If you have any questions on where exactly this is added, check out the compose files in my GitHub Repo.

We have now completed 2 of the 4 steps in adding secrets. We will perform the remaining 2 steps when we create the Authelia Docker Compose file.

3. Authelia Users

Next, let's create a user. In our configuration.yml file we said users are in the users.yml file, which is described here.

Create a file called users.yml inside authelia configuration folder in appdata, and add the following contents to it:

###############################################################
#                         Users Database                      #
###############################################################

# This file can be used if you do not have an LDAP set up.

# List of users
users:
  AUTHELIA_USERNAME:
    disabled: false
    displayname: "AUTHELIA_USER_DISPLAY_NAME"
    email: AUTHELIA_USER_EMAIL
    password: AUTHELIA_HASHED_PASSWORD
    groups:
      - admins

Replace AUTHELIA_USERNAME with a username for the user.

Change AUTHELIA_USER_DISPLAY_NAME to a name for the user. AUTHELIA_USER_EMAIL can be a valid email or a dummy email. Remember that we do not have an SMTP server and no emails will be sent. Instead, all notifications will be stored in the notifications.txt file. Therefore, the validity of the email does not matter.

AUTHELIA_HASHED_PASSWORD is the hashed password. NOT the plain text password. To hash the password, use the following command:

sudo docker run -v /home/anand/docker/appdata/authelia/configuration.yml:/configuration.yml -it authelia/authelia:4.38.8 authelia crypto hash generate --config /configuration.yml --password MYSTRONGPASSWORD

Replace MYSTRONGPASSWORD with your strong password. Your password will be hashed using the argon2id algorithm and displayed as shown below.

Authelia 4.38 Hashed Password
Authelia 4.38 Hashed Password

If Authelia Docker image does not already exist on your system, it will be downloaded during the process, as shown above.

Copy hashed password in its entirety (highlighted by red box) and replace AUTHELIA_HASHED_PASSWORD in the users.yml.

Save the file and exit.

Adding Additional Users

Membership Required

You must be a member to access this content.

View Membership Levels

Already a member? Log in here

Just because a user belongs to the group admins, does not mean that the user is admin. Group name is just a name. Access is controlled using access control policies.

4. Authelia Traefik Configuration

Now that Authelia configuration is done. Let us configure Traefik to use Authelia.

Building on the same framework we built using the Docker-Traefik guide, we need to add two sections to Traefik configuration: a middleware for authelia and a middleware chain for authelia.

Authelia Traefik Middleware

First, let us create a Authelia Traefik middleware that will forward authentication to the Authelia container. Create a file called middlewares-authelia.yml in your Traefik rules folder and add the following contents to it:

If you have followed my Traefik guide, the rules folder will be appdata/traefik3/rules/udms, where udms is the hostname. In my GitHub repo, you will find files from 5 of my docker hosts, identified by hostnames: hs, mds, ws, ds918, and dns.
http:
  middlewares:
    middlewares-authelia:
      forwardAuth:
        address: "http://authelia:9091/api/verify?rd=https://authelia.{{env "DOMAINNAME_HS"}}"
        trustForwardHeader: true
        authResponseHeaders:
          - "Remote-User"
          - "Remote-Groups"

Remember the DOMAINNAME_HS environmental variable we passed into Traefik container? This is where it comes in handy. {{env "DOMAINNAME_HS"}} will refer to the domain name set for this variable. You may replace it and hardcode your domain name.

We are basically specifying the URL to which authentication requests must be forwarded.

Since this is a dynamic configuration using a file provider, traefik will pick it up automatically.

Authelia Middleware Chain

Again, building on my Traefik guide, let's build the middleware chain for Authelia.

We will reuse a few of the middlewares from the Traefik guide: middlewares-rate-limit and middlewares-secure-headers.

Create a file called chain-authelia.yml in your Traefik rules folder and add the following contents to it:

http:
  middlewares:
    chain-authelia:
      chain:
        middlewares:
          - middlewares-rate-limit
          - middlewares-secure-headers
          - middlewares-authelia

If you do not understand what this does, then I suggest reading my Traefik guide.

In short, we are rate limit and specifying security headers, which are both security measures. Then we are including Authelia authentication in the chain (the middleware we created in the previous step).

In my GitHub Repo you may find more middlewares than what is described above. For Authelia purposes, the above middlewares are sufficient. As you follow more of my guides you may add additional middlewares.

That's it. We are now ready to create Authelia docker-compose file.

Be the 1 in 200,000. Help us sustain what we do.
114 / 150 by Dec 31, 2024
Join Us (starting from just $1.67/month)

5. Authelia Docker Compose (v4.38 and Above)

Now that all the configuration part is done. Let us add the Authelia docker compose service.

Just a reminder that Traefik should be up and running at this point.
Create Authelia Docker Compose File

Let's create the Authelia Docker compose file. Head over to the compose folder in my Github Repository, and then into any of the host folders. Find the compose file for Authelia and copy the contents.

Create a file called authelia.yml inside /home/anand/docker/compose/udms. Copy-paste the contents into authelia.yml compose file (pay attention to blank spaces at the beginning of each line).

services:
  # Authelia (Lite) - Self-Hosted Single Sign-On and Two-Factor Authentication
  authelia:
    container_name: authelia
    image: authelia/authelia:4.38.8
    security_opt:
      - no-new-privileges:true
    restart: unless-stopped
    # profiles: ["core", "all"]
    networks:
      - t3_proxy
      - default
    # ports:
    #   - "9091:9091"
    volumes:
      - $DOCKERDIR/appdata/authelia:/config
    environment:
      - TZ=$TZ
      - PUID=$PUID
      - PGID=$PGID
      - AUTHELIA_IDENTITY_VALIDATION_RESET_PASSWORD_JWT_SECRET_FILE=/run/secrets/authelia_jwt_secret
      - AUTHELIA_SESSION_SECRET_FILE=/run/secrets/authelia_session_secret
      - AUTHELIA_STORAGE_ENCRYPTION_KEY_FILE=/run/secrets/authelia_storage_encryption_key
      # - AUTHELIA_STORAGE_MYSQL_PASSWORD_FILE=/run/secrets/authelia_storage_mysql_password
      # - AUTHELIA_SESSION_REDIS_PASSWORD_FILE=/run/secrets/authelia_session_redis_password
      # - AUTHELIA_DUO_API_INTEGRATION_KEY_FILE=/run/secrets/authelia_duo_api_integration_key
      # - AUTHELIA_DUO_API_SECRET_KEY_FILE=/run/secrets/authelia_duo_api_secret_key
    secrets:
      - authelia_jwt_secret
      - authelia_storage_encryption_key
      - authelia_session_secret
    labels:
      - "traefik.enable=true"
      ## HTTP Routers
      - "traefik.http.routers.authelia-rtr.entrypoints=websecure"
      - "traefik.http.routers.authelia-rtr.rule=Host(`authelia.$DOMAINNAME_HS`)"
      ## Middlewares
      - "traefik.http.routers.authelia-rtr.middlewares=chain-no-auth@file" # Should be chain-no-auth and not chain-authelia
      ## HTTP Services
      - "traefik.http.routers.authelia-rtr.service=authelia-svc"
      - "traefik.http.services.authelia-svc.loadbalancer.server.port=9091"

Here are some notes about the Authelia Docker Compose:

  • We are going to fix the Authelia docker image as 4.38.8 because, sometimes, latest tag brings in breaking changes, which can crash your setup.
  • Docker profiles is commented out as explained previously (see my Docker guide for how I use profiles).
  • networks: We added Authelia to t3_proxy and default networks. You could probably leave out the default network. I included default because my MariaDB container was on default network.
  • ports: Exposing ports is typically not needed for Authelia.
  • The environmental variable $DOCKERDIR is already defined in our .env file. All Authelia data is being stored in an authelia-specific folder within appdata.
  • In the environment and secret sections, we are specifying the 3 Authelia secrets we created previously (steps 3 and 4 in adding secrets).
  • With the labels, we are specifying that Authelia will use the websecure entrypoint and chain-no-auth file provider we created previously.
  • Authelia listens on port 9091. So, we point authelia-rtr.service to a service name authelia-svc and in the next line, we define where that service is listening at (authelia-svc.loadbalancer.server.port=9091.
Add Authelia to the Docker Stack

We created the authelia.yml file. Now we need to add it to our master docker-compose-udms.yml file. To do so, add the path to the authelia.yml (compose/udms/authelia.yml) file under the include block, as shown below:

Update (March 21, 2024): The version tag at the top of Docker compose file is now obsolete and throws a warning. This has been removed from my guides.
...
...

include:
...
  - compose/$HOSTNAME/authelia.yml
...
Note that the ... refer to previous lines that may already exist after having followed the previous parts of this Ultimate Docker Server series.

$HOSTNAME here will be replaced with udms automatically (as defined in the .env file).

Save the Master Docker Compose file.

6. Starting Authelia and Registering

Recreate the stack and follow Authelia container logs using the following commands:

sudo docker compose -f /home/anand/docker/docker-compose-udms.yml up -d
sudo docker compose -f /home/anand/docker/docker-compose-udms.yml logs -tf --tail="50" authelia

You should see confirmation that Authelia Docker container started successfully, as shown below. [Read: Dozzle Docker Compose: Simple Docker Logs Viewer]

Authelia Docker Compose - Container Started
Authelia Docker Compose - Container Started

Now that Authelia Docker container is up and running. Let us test it out.

Authelia First Time Use and Registration

Let's visit https://authelia.simplehomelab.com (obviously use your domain name). Now and while accessing a service protected by Authelia, you should see the following login form.

Authelia First Login
Authelia First Login

Log in using the username and password you defined in users.yml file.

Next, you will have to register your device. Click on Methods, choose One-time Password, and then click Not registered yet?, as shown below.

Authelia Registration
Authelia Registration

Next, pick One-Time Password as the registration method and hit ADD.

Authelia Totp Registration
Authelia Totp Registration

An OTP code will be sent to the email, which you will have to enter in the following screen to confirm registration (IMPORTANT! Keep this screen open until you complete the registration step).

Authelia Confirm Otp Registration
Authelia Confirm Otp Registration

What if you did not configure SMTP server for email notifications? Well, in that case, the code is embedded in the notification saved to notification.txt file.

Open the notifications.txt file inside Authelia config folder in appdata to find the code, as shown below:

Authelia Otp Code
Authelia Otp Code

Enter the code in the previous screen to confirm device registration. Hit next to continue to OTP registration.

Authelia Otp Registration
Authelia Otp Registration

You can use any of the authenticator apps (Duo, Authy, Google Authenticator, etc.) to scan the code. I recommend Duo because it supports push notifications, which makes authentications easier (described later).

Authelia Registration Qr Code
Authelia Registration Qr Code

After scanning, enter the OTP code from the authenticator app into Authelia.

Enter Authelia Otp Code
Enter Authelia Otp Code

This should complete your account registration for Authelia and you should see something like the screenshot below.

Account Registration Complete
Account Registration Complete

That is about it. You can now start using Authelia multi-factor authentication for your Docker apps. Authelia protects some of my key administration apps such as Guacamole.

One again, all the steps described in this guide can be completed in a matter for 2 minutes using the Deployarr script. Check it out if you are interested.

Authentication and Conditional Bypassing

Now that we have Authelia working, let's look at ways to protect apps and also some ways to conditionally bypass authentication.

Putting Docker Services behind Authelia

If you created the authelia traefik middleware and middleware chain discussed above, then putting docker services behind Authelia authentication is simple. All you need to do is add the following middleware (chain-authelia) to docker-compose labels:

      ## Middlewares
      - "traefik.http.routers.service-rtr.middlewares=chain-authelia@file"

service-rtr could be different for different services. As always, check the docker-compose files in GitHub repo for working examples.

Putting Non-Docker Services behind Authelia

Adding non-docker apps or apps from docker host or external hosts is also quite simple using file providers, as previously explained in my Traefik guide.

Auto Traefik 2 (Part 9) - Putting External Applications Behind Traefik

Let's take the same example of Adguard Home running on Raspberry Pi, as in my Traefik guide.

Previously, we had AdGuard Home with no Traefik authentication (chain-no-auth). Putting it behind Authelia is as simple as changing the middleware from chain-no-auth to chain-authelia, as shown below:

http:
  routers:
    adguard-rtr:
      rule: "Host(`ag.{{env "DOMAINNAME_HS"}}`)"
      entryPoints:
        - websecure
      middlewares:
        - chain-authelia
      service: adguard-svc
      tls:
        certResolver: dns-cloudflare
        options: tls-opts@file
  services:
    adguard-svc:
      loadBalancer:
        servers:
          - url: "http://192.168.1.225:80"

Note that AdGuard Home is listening on a non-SSL port. Some services (e.g. NextCloud, UniFi controller, Proxmox etc.) tend to be available via HTTPS protocol with a self-signed certificate. For these, be sure to refer to my guide on putting HTTPS apps behind Traefik.

Since the rules directory is dynamic, simply by adding this file to that directory we have created the route. You should be able to connect to AdGuard Home behind Authelia, without restarting Traefik!

Bypassing Authelia

This is my preferred method for bypassing.

Although you can use Authelia's built-in access control methods, I do not use it. I leverage custom headers to let Traefik handle the bypassing instead of the authentication service.

Traefik has built-in mechanisms for conditional bypassing. Depending on certain conditions, I can specify a different middleware or a middleware chain. This is explained in detail in my separate guide on Traefik Auth bypass.

Several apps in my GitHub repo have auth bypasses set based on certain conditions.

Authelia Enhancements

At this point, you should already have a fully functional Authelia Docker authentication system. But depending on your situation, you could benefit from some optional enhancements. Let's look at some of those now.

Redis

In simple terms, Redis is a key-value caching mechanism that can enhance the performance of applications that access databases frequently. If you do not have Redis, it is quite easy to have it up and running using Deployarr or with my Redis Docker guide.

If you have a Redis instance available add the following block under session: (replace # AUTHELIA_REDIS_PLACEHOLDER) in configuration.yml file to activate the usage of Redis (pay attention to indentation).

session:
  # https://www.authelia.com/configuration/session/redis/
  redis:
    host: redis
    port: 6379

Customize the host with the host running Redis. If Redis and Authelia are on the same Docker network, you can use the hostname (redis; if that is how your Redis service is called). The port is typically 6379.

We are going to use Secrets to provide Redis password.

Adding Secrets for Redis
  1. You will have to create a secret file: /home/anand/docker/secrets/authelia_session_redis_password.
  2. Define the secret globally in the master docker compose file.
    ...
      authelia_session_redis_password:
        file: $DOCKERDIR/secrets/authelia_session_redis_password
    ...
    
  3. Define the AUTHELIA_SESSION_REDIS_PASSWORD_FILE environment variable and point it to the secret file.
    ...
        environment:
          - AUTHELIA_SESSION_REDIS_PASSWORD_FILE=/run/secrets/authelia_session_redis_password
    ...
    
  4. Enable the secret in Authelia docker compose.
    ...
        secrets:
          - authelia_session_redis_password
    ...
    

Reminder that in a non-busy system, using Redis will have minimal impact. Recreate Authelia for the changes to take effect.

Implementing TLS can secure the connection between Authelia and Redis. This is not discussed in this guide, but is highly recommended for a multiuser/business environment.

MySQL Storage

Authelia offers several storage backends. In this example, let us use MySQL. Add the following block under storage: in configuration.yml file, paying attention to the indentation.

The assumption at this point is that you already have MySQL/MariaDB running and have created a database and database-specific user for Authelia.
storage:
# https://www.authelia.com/configuration/storage/mysql/
  mysql:
    host: mariadb
    port: 3306
    database: authelia
    username: DBUSERNAME
    # password: DBPASSWORD

Once again, if MariaDB and Authelia are on the same network, you can use mariadb for hostname (if that is how your MariaDB service is called). 3306 is the default MariaDB port. Customize the database name and username based on your situation.

Note that you may also define and host, port, database, username, and even password using environment variables (check for variable names to use). If you decide to do so, the only line in configuration.yml will be mysql: under storage: to enable it.

Only the password can be specified as a secret (check for supported secrets). The four steps are exactly the same as described for Redis, with minor changes. Use AUTHELIA_STORAGE_MYSQL_PASSWORD_FILE for environment variable name and authelia_storage_mysql_password for secret name.

If you use MySQL, be sure to comment out or remove the SQLite storage backend in the configuration.yml file.

Recreate Authelia for the changes to take effect.

Implementing TLS can secure the connection between Authelia and MySQL. This is not discussed in this guide, but is highly recommended for a multiuser/business environment.

Email Notifications

Storing notifications in a text file is not ideal. If you have an email server (I use and recommend Brevo (there are others too), which is free), you can enable email notification by adding the following block under notifier::

notifier:
  smtp:
    username: SMTP_USERNAME
    # password: SMTP_PASSWORD
    host: SMTP_HOST
    port: 587 # Or 465
    sender: SENDER_EMAIL

Once again, you can specify the above details in 2 ways: directly in configuration.yml and as environment variables (check for variable names to use).

If you decide to go with environment variables and secrets, then the only line in configuration.yml will be smtp: under notifier: to enable it.

Only the SMTP_PASSWORD can be specified as a secret (check for supported secrets). The four steps are exactly the same as described for Redis, with minor changes. Use AUTHELIA_NOTIFIER_SMTP_PASSWORD_FILE for environment variable name and authelia_notifier_smtp_password for secret name.

After enabling email notifications, you may choose to disable writing notifications to the notifications.txt file (comment out or remove those lines).

Recreate Authelia for the changes to take effect.

When configured correctly, here is an example of an email you may receive during account registration (of course, a valid email is now necessary).

Opening Authelia Registration Link
Opening Authelia Registration Link

Enabling Duo Push Notification for Authelia

As I hinted before, I like Duo because it supports push notifications that allow one-click easy login approvals compared to entering the OTP. Enabling this is a little bit of work and unintuitive.

But don't worry, I will walk you through it and it's FREE.

First, head over to Duo's website and register an account.

1. Create a Duo User

From the Users menu, click on Add User as shown below and create a new user.

Add Duo User For Authelia Push Authentication
Add Duo User For Authelia Push Authentication

Fill in the user details.

Note: The username must be the same as what you used for Authelia in users.yml.

Scroll down and add a phone number.

2. Activate the User

You should see a warning message (shown below) on the Duo admin page that says that the user is not activated.

Activate New Duo User
Activate New Duo User

Send the activation link to the user's/your phone and click the received link to activate the user.

3. Create an Application

Under Applications, select Protect an Application, search for Partner Auth API and click Protect, as shown below.

Add New Application For Duo Push Authentication
Add New Application For Duo Push Authentication

Once created, copy the Integration key, Secret key, and API hostname.

4. Configure Duo API in Authelia Configuration

Open up Authelia's configuration.yml and add the following code block to it (replace # AUTHELIA_DUO_PLACEHOLDER).

# https://www.authelia.com/configuration/second-factor/duo/
duo_api:
  hostname: API_HOSTNAME
  # integration_key: INTEGRATION_KEY
  # secret_key: SECRET_KEY

Once again, you can specify the above details in 2 days: directly in configuration.yml and as environment variables (check for variable names to use).

If you decide to go with environment variables and secrets, then the only line in configuration.yml will be duo_api: to enable it.

Only the INTEGRATION_KEY and SECRET_KEY can be specified as a secrets (check for supported secrets). The four steps are exactly the same as described for Redis, with minor changes. Use AUTHELIA_DUO_API_INTEGRATION_KEY_FILE and AUTHELIA_DUO_API_SECRET_KEY_FILE for environment variable names and authelia_duo_api_integration_key and authelia_duo_api_secret_key for secret names, respectively.

Recreate Authelia for the changes to take effect.

5. Test Authelia Duo Push Notification

Try to access a Docker app behind Authelia. This time from Methods, choose Push Notification as shown below.

Authelia 2-Factor Authentication
Authelia Push Authentication Registration

You should receive a push notification on your phone and all you need to do is approve with one click and your login should go through.

Final Thoughts on Authelia for Docker Traefik

It seemed like a lengthy process but in reality, implementing this Authelia Docker Compose tutorial shouldn't take more than an hour. I was very satisfied with Google OAuth. And Authelia is equally awesome or better depending on what is important to you.

I am not sure if Authelia offers more protection than Google OAuth but I feel like I have more control and obviously more privacy. And the duo push authorization made it simpler to use.

Authelia does offer support for hardware security keys. I have not explored those yet but if you do, then you are covered there as well.

If you have any piece of information that is missing in this Authelia Docker guide, please feel free to add in the comments to help others. Otherwise, I hope this Docker Compose for Authelia was useful in making your stack more secure.

Be the 1 in 200,000. Help us sustain what we do.
114 / 150 by Dec 31, 2024
Join Us (starting from just $1.67/month)

Anand

Anand is a self-learned computer enthusiast, hopeless tinkerer (if it ain't broke, fix it), a part-time blogger, and a Scientist during the day. He has been blogging since 2010 on Linux, Ubuntu, Home/Media/File Servers, Smart Home Automation, and related HOW-TOs.

Try Deployarr