How to deploy Authelia - an open-source authentication and authorization server using docker-compose behind Caddy v2.9.1

How to deploy Authelia - an open-source authentication and authorization server using docker-compose behind Caddy v2.9.1

Authelia is an open-source authentication and authorization server providing two-factor authentication and single sign-on (SSO) for your applications via a web portal. It acts as a companion for reverse proxies by allowing, denying, or redirecting requests.

Happy New Year 2025 to All Viewers. Wishing you a year of health, wealth, and endless opportunities.

I am bit busy with someother work. So I didn’t get time to write articles. From now onwards, I will try to write the articles regularly.

Let’s get started…

Today I am going to show you how to deploy Authelia using docker compose behind Caddy proxy.

Lets start with the actual deployment…

Prerequisite

Please make sure you should fulfill the below requirements before proceeding to the actual deployment.

  1. Ubuntu latest server (any Linux flavor works but I am using Ubuntu here).
  2. Docker and Docker Compose installed on the Ubuntu Server.

Introduction to Authelia

Authelia is an open-source authentication and authorization server and portal fulfilling the identity and access management (IAM) role of information security in providing multi-factor authentication and single sign-on (SSO) for your applications via a web portal. It acts as a companion for common reverse proxies like Caddy, Traefi, NGINX, etc…

Here I am going to integrate Authelia with Caddy Reverse Proxy. Authelia can handle requests to the authz endpoints with specific headers and return standardized responses based on the headers and policies.

Caddy utilizes the ForwardAuth authz implementation to forward the requests to Authelia based on prosy authorization end point, response header and session cookie.

The Single Sign-On Multi-Factor Portal for Web Apps.

Authelia Server Core Features

Core features of Authelia Server.

  • Compressed container image is smaller than 20 MB.
  • Memeory usage normally under 30 MB.
  • Authorization policies and other backend tasks are completed in mere milliseconds.
  • Login portal loads in 100 milliseconds.
  • Prevent brute force login attempts by only allowing a certain number of logins before the user is locked for a period.
  • Users can reset their LDAP or internal passwords through the web interface with email validation.
  • Allows users to login once to a wide range of web applications via session cookie, Open ID and trusted headers.
  • Control which users and groups have access to which specific resources or domains with granular policy definitions.
  • Authelia supports multiple second-factor methods including TOTP, Mobile Push (DUO) and WebAuthn.
  • The login portal is straight forward and the workflow is completely transparent to the users.

Prepare Authelia Server Environment

Let’s create a local folder authelia to store Authelia configuration data (/config) in docker container, /opt/authelia for disaster recovery purpose.

Create folder in /opt directory to persistent Stalwart data folder, /config

cd /opt
sudo mkdir -p authelia

Authelia Configuration

Thare are 2 ways to inetgrate Authelia with an authentication backend.

Users are stored in remote servers like OpenLDAP, LLDAP, FreeIPA or Microsoft Active Directory.

Here I used LLDAP backend to store the users information. I will write an article on it.

LLDAP
theme: auto
default_2fa_method: 'totp'
server:
  address: 'tcp://0.0.0.0:9091/'
  endpoints:
    authz:
      forward-auth:
        implementation: 'ForwardAuth'

log:
  level: debug

totp:
  disable: false
  issuer: 'authelia.example.com'
  algorithm: 'sha1'
  digits: 6
  period: 30
  skew: 1
  secret_size: 32
  allowed_algorithms:
    - 'SHA1'
  allowed_digits:
    - 6
  allowed_periods:
    - 30
  disable_reuse_security_policy: false

webauthn:
  disable: true

authentication_backend:
  password_reset:
    disable: false
  refresh_interval: 15m
  ldap:
    implementation: custom
    address: ldap://lldap:3890
    timeout: 5s
    start_tls: false
    base_dn: dc=example,dc=com
    users_filter: (&(|({username_attribute}={input})({mail_attribute}={input}))(objectClass=person))
    additional_groups_dn: ou=groups
    additional_users_dn: ou=people
    groups_filter: (member={dn})
    user: uid=admin,ou=people,dc=example,dc=com
    attributes:
      display_name: displayName
      distinguished_name: distinguishedName
      username: uid
      mail: mail
      member_of: memberOf
      group_name: cn

password_policy:
  standard:
    enabled: false
    min_length: 8
    max_length: 0
    require_uppercase: true
    require_lowercase: true
    require_number: true
    require_special: false

access_control:
  default_policy: deny
  rules:
    - domain: public.example.com
      policy: bypass
    - domain: secure.example.com
      policy: two_factor

session:
  name: authelia_session
  secret: some-secret
  same_site: 'lax'
  inactivity: '5m'
  expiration: '1h'
  remember_me: '1M'
  cookies:
    - domain: example.com
      authelia_url: https://authelia.example.com

regulation:
  max_retries: 3
  find_time: 120
  ban_time: 300

storage:
  encryption_key: secure-encryption-key
  local:
    path: /config/db.sqlite3

notifier:
  disable_startup_check: false
  smtp:
    address: 'smtp://smtp.example.com:587'
    username: 'yourname@example.com'
    password: 'secure-password'
    sender: 'Authelia <authelia@authelia.example.com>'
    identifier: 'authelia.example.com'
    subject: '[Authelia] {title}'
    startup_check_address: 'mailtest@example.com'
    tls:
      server_name: 'smtp.example.com'

Caddyfile – Authelia

The Caddyfile is a convenient Caddy configuration format for humans.

Caddyfile is easy to write, easy to understand, and expressive enough for most use cases.

Production-ready Caddyfile for Jekyll as Static File Server. You can use it for other static site generators as well, like Hugo.

Learn more about Caddyfile here to get familiar with it.

Use the below commands to create the Caddy configuration file,

cd /opt
sudo touch Caddyfile

Open Caddyfile with nano editor using sudo nano Caddyfile

Copy and paste the below code in the Caddyfile configuration file.

{
    email you@example.com
    default_sni stalwart
    cert_issuer acme
    # Production acme directory
    acme_ca https://acme-v02.api.letsencrypt.org/directory
    # Staging acme directory
    #acme_ca https://acme-staging-v02.api.letsencrypt.org/directory
    servers {
        metrics
        protocol h1 h2c h3
        strict_sni_host on
        trusted_proxies cloudflare {
            interval 12h
            timeout 15s  
        }
    }
    admin 0.0.0.0:2019
}

mail.example.com {
    log {
        output file /var/log/caddy/authelia.log {
            roll_size 20mb
            roll_keep 2
            roll_keep_for 6h
        }
        format console
        level error
    }

    reverse_proxy authelia:9091 {
        transport http {
            keepalive 300s
        }
    }
}

Please go to Caddy Post to get more insight to deploy it in the docker swarm cluster.

Prepare Docker Compose File

Now it’s time to create a docker compose file that contains the Caddy Reverse Proxy service and Authelia service in /opt directory. docker compose is the configuration file in .yml (Yet Another Markup Language).

Create a docker network caddy, we will use it to expose application containers or internal services to outside world.

docker network create caddy

Use the below commands to create the configuration file,

cd /opt
sudo touch docker-compose.yml

Open docker-compose.yml with nano editor using sudo nano docker-compose.yml

Copy and paste the below code in the docker-compose.yml configuration file.

Here is the full docker-compose file.

secrets:
  jwt_secret:
    file: ./jwt_secret.txt
  backend_password:
    file: ./backend_password.txt
  smtp_password:
    file: ./smtp_password.txt
volumes:
  caddydata:
  caddyconfig:
  caddylogs:
  authelia:
networks:
  caddy:
    external: true
services:
  caddy:
    image: rajaseg/caddy
    restart: unless-stopped
    container_name: caddy
    ports:
      - "80:80"
      - "443:443"
      - "2019:2019"
    networks:
      - caddy
    volumes:
      - ./Caddyfile:/etc/caddy/Caddyfile
      - ./caddydata:/data
      - ./caddyconfig:/config
      - ./caddylogs:/var/log/caddy
  authelia:
    image: authelia/authelia:latest
    container_name: authelia
    restart: unless-stopped
    depends_on:
      caddy:
        condition: service_started
    volumes:
      - ./authelia:/config
    secrets:
      - jwt_secret
      - backend_password
      - smtp_password
    networks:
      - caddy
    environment:
      - AUTHELIA_IDENTITY_VALIDATION_RESET_PASSWORD_JWT_SECRET_FILE=/run/secrets/jwt_secret
      - AUTHELIA_AUTHENTICATION_BACKEND_LDAP_PASSWORD_FILE=/run/secrets/backend_password
      - AUTHELIA_NOTIFIER_SMTP_PASSWORD_FILE=/run/secrets/smtp_password

Lets discuss about some of the configuration options above.

depends_on

depends_on expresses startup and shutdown dependencies between services.

short syntax

The short syntax variant only specifies service names of the dependencies. Service dependencies cause the following behaviors:

  • Compose creates services in dependency order. In the above scenario, caddy is created before stalwart.
  • Compose removes services in dependency order. In the above scenario, authelia is removed before caddy.
  • restart_policy is to configure whether and how to restart containers when they exit. condition: One of none, on-failure or any. Default is any*.*

Compose guarantees dependency services have been started before starting a dependent service. Compose waits for dependency services to be ready before starting a dependent service.

Deploy the Docker Compose

Now it’s time to deploy our docker-compose file above using the below command

docker compose up -d

Authelia relies on session cookies to authorize user access to various protected websites.

There are currently two providers for session storage:

Memory (default, stateful, no additional configuration) Redis (stateless).

Here I am just utilizing Authelia memory for session storage.

You can use redis for the purpose if you are deploying it in the production environment.

Now access the web interface of Authelia using what ever the name mentioned in the Caddyfile.

Warning

Make sure that you have DNS entry for your application (authelia.example.com) in your DNS Management Application.

Please find below images for your reference.

Below screen shots are for reference purpose.

Authelia Web Interface

I hope you enjoyed this post. Please share your thoughts or feedback on it by commenting.

Stay tuned for other deployments 🙂