Authelia

Setupguide for Authelia Multi Factor Authentication Middleware

Overview


Overview

What is Authelia?

Authelia.pngGitHub-logo.pnglogo (1).png

 

 

 

Introduction

Authelia is a two-factor authentication (2FA) and single sign-on (SSO) server focused on enhancing the security of applications and users. Acting as an extension of reverse proxies, it provides various authentication-related features, such as:

Features Summary

This is a list of the key features of Authelia:

Architecture

Authelia integrates seamlessly with reverse proxies like Traefik (see the full list of supported proxies). It enhances these proxies by adding authentication and authorization features alongside a login portal.

Authelia is connected to the reverse proxy but does not directly interact with the backend applications. Payloads sent by clients to the protected applications never reach Authelia; only authentication-related information, such as the Authorization header, is processed. This allows Authelia to protect any HTTP-based APIs, including REST and GraphQL APIs, without interfering with application data.

architecture-diagram_hu16792232065769869876.webp

Workflow

Reverse proxies configured with Authelia send all incoming requests to Authelia for authentication verification. Authelia instructs the reverse proxy to either:

Step-by-Step Workflow

  1. ❔ Unauthenticated User Request:

    When an unauthenticated user sends their first request to the reverse proxy, Authelia determines the user is not authenticated (no session cookie provided). The user is redirected to the Authelia login portal.

  2. 🔐 Authentication Portal:

    The user completes the authentication workflow via Authelia's portal. Upon successful authentication, a session cookie is issued, valid for all subdomains of the protected domain.

  3. ✔️ Authenticated User Request:

    The user revisits the initial website, now including the session cookie in their requests. Authelia verifies the session and instructs the reverse proxy to allow the request to pass through.

sequence-diagram_hu7576888935821004374.webp

Getting Started

Getting Started

Step by Step Setup Guide for Authelia (+Traefik)

Authelia.pngGitHub-logo.pnglogo (1).png

This article provides detailed instructions on integrating Authelia as a middleware with Traefik. Using Docker labels for configuration, this setup allows Traefik to query Authelia for authorization on every web request. Authelia validates session cookies and access permissions for secure resource control. The information is partially sourced from Brynn Crowley, referencing his setup guide.

Prerequisites

Important Notes

Configuration uses Docker labels directly in docker-compose.yaml to configure the Traefik Middleware.
Examples use a whoami application for demonstration.
Advanced configurations (e.g., SMTP) are available in Authelia documentation.


Step-by-Step Guide

Step 1: Create Folders in the GlusterFS

mkdir -p /mnt/glustermount/data/authelia_data/
mkdir -p /mnt/glustermount/data/authelia_data/logs
mkdir -p /mnt/glustermount/data/authelia_data/config
mkdir -p /mnt/glustermount/data/authelia_data/secrets

Step 2: Create External Network for Traefik Proxy (if not already done)

Create the management_net network:

docker network create -d overlay management_net

Step 3: Configure User Database

Create a basic user database:

nano mkdir -p /mnt/glustermount/data/authelia_data/config/users.yml

Paste this Content:

users:
  authelia: ## Username
    displayname: 'Authelia User'
    ## WARNING: This is a default password for testing only!
    ## IMPORTANT: Change this password before deploying to production!
    ## Generate a new hash using the instructions at:
    ## https://www.authelia.com/reference/guides/passwords/#passwords
    ## Password is 'authelia'
    password: '$6$rounds=50000$BpLnfgDsc2WD8F2q$Zis.ixdg9s/UOJYrs56b5QEZFiZECu0qZVNsIYxBaNJ7ucIL.nlxVCT5tqh8KHG8X4tlwCFm5r6NTOZZ5qRFN/'
    email: 'authelia@authelia.com'
    groups:
      - 'admin'
      - 'dev'

The current password listed is authelia. It is important you Generate a new password hash.

Step 3.1: Generate Password Hash (Optional)

docker run --rm -it authelia/authelia:latest authelia crypto hash generate argon2

Step 4: Create Secrets

First provide needed Rights:

chown 8000:8000 /mnt/glustermount/data/authelia_data/secrets/ && chmod 0700 /mnt/glustermount/data/authelia_data/secrets/

Then Create Secret Files:

docker run --rm -u 8000:8000 -v /mnt/glustermount/data/authelia_data/secrets/:/secrets docker.io/authelia/authelia sh -c "cd /secrets && authelia crypto rand --length 64 session_secret.txt storage_encryption_key.txt jwt_secret.txt"

Step 5: Create Basic Authelia Configuration

Create a File called "configuration.yaml" in your Config Folder (In this Example /mnt/glustermount/data/authelia_data/config)

nano /mnt/glustermount/data/authelia_data/config/configuration.yaml

Make sure to Change the Tags "YOURDOMAIN" to your actual Domainname.

server:
  address: 'tcp4://:9091'

log:
  level: debug
  file_path: '/var/log/authelia/authelia.log'
  keep_stdout: true

identity_validation:
  elevated_session:
    require_second_factor: true
  reset_password:
    jwt_lifespan: '5 minutes'
    jwt_secret: {{ secret "/secrets/jwt_secret.txt" | mindent 0 "|" | msquote }}

totp:
  disable: false
  issuer: 'YOURDOMAIN.com'
  period: 30
  skew: 1

password_policy:
  zxcvbn:
    enabled: true
    min_score: 4

authentication_backend:
  file:
    path: '/config/users.yml'
    password:
      algorithm: 'argon2'
      argon2:
        variant: 'argon2id'
        iterations: 3
        memory: 65535
        parallelism: 4
        key_length: 32
        salt_length: 16

access_control:
  default_policy: 'deny'
  rules:
    - domain: 'traefik.YOURDOMAIN.com'
      policy: 'one_factor'
    - domain: 'whoami-secure.YOURDOMAIN.com'
      policy: 'two_factor'

session:
  name: 'authelia_session'
  secret: {{ secret "/secrets/session_secret.txt" | mindent 0 "|" | msquote }}
  cookies:
    - domain: 'YOURDOMAIN.com'
      authelia_url: 'https://auth.YOURDOMAIN.com'

regulation:
  max_retries: 4
  find_time: 120
  ban_time: 300

storage:
  encryption_key: {{ secret "/secrets/storage_encryption_key.txt" | mindent 0 "|" | msquote }}
  local:
    path: '/config/db.sqlite3'

notifier:
  disable_startup_check: false
  filesystem:
    filename: '/config/notification.txt'

Step 6: Create Docker Compose

It is important to know that Traefik needs to wait for Authelia to startup. Thats what the depends Function is for.
Otherwise Traefik will not notice the Authelia Middleware and maybe provide an Error.

Make sure to Change the Tags "YOURDOMAIN" to your actual Domainname.

version: '3.3'

services:
  traefik:
    user: 0:0 #Container being started with Root rights
    image: 'traefik:latest'
    security_opt:
      - 'no-new-privileges=true'
    restart: 'unless-stopped'
    depends_on:
      - authelia
    ports:
      # The Web UI (enabled by --api.insecure=true in traefik.toml)
      - '8080:8080'
      # The Available Ports (forward your router's incoming ports to the ports on the host)
      - '80:80'
      - '443:443'
    networks:
      management_net:
        aliases:
          - 'auth.domain.com'
      authelia: {}
    volumes:
      # So that Traefik can listen to the Docker events (read-only)
      - '/var/run/docker.sock:/var/run/docker.sock:ro'
      # LetsEncrypt ACME Configuration
      - '/mnt/glustermount/data/traefik_data/acme.json:/le/acme.json'
      # Mount for Traefik AccessLog
      - '/mnt/glustermount/data/traefik_data/access.log:/access.log'
      # (STATIC CONFIG)
      - './traefik/config/traefik.yml:/traefik.yml:ro'
      # (DYNAMIC CONFIG)
      - './traefik/config/dynamic.yml:/dynamic.yml:ro'

    environment:
      - TZ=Europe/Zurich
    deploy:
      mode: replicated
      replicas: 1
      labels:
        - 'traefik.enable=true'
        - 'traefik.http.routers.traefik.rule=Host(`traefik.YOURDOMAIN.com`)'
        - 'traefik.http.routers.traefik.service=api@internal'
        - 'traefik.http.services.traefik.loadbalancer.server.port=8080'
        - 'traefik.http.routers.traefik.tls.certresolver=leresolver'
        - 'traefik.http.routers.traefik.entrypoints=websecure'
        - 'traefik.http.routers.http-catchall.rule=hostregexp(`{host:.+}`)'
        - 'traefik.http.routers.http-catchall.entrypoints=web'
        - 'traefik.http.routers.http-catchall.middlewares=redirect-to-https'
        - 'traefik.http.middlewares.redirect-to-https.redirectscheme.scheme=https'
        #Authelia Integration
        - 'traefik.http.routers.dashboard.middlewares=authelia@docker'

  authelia:
    image: 'authelia/authelia:4.38'
    container_name: 'authelia'
    volumes:
      - '/mnt/glustermount/data/authelia_data/secrets:/secrets:ro'
      - '/mnt/glustermount/data/authelia_data/config:/config'
      - '/mnt/glustermount/data/authelia_data/logs:/var/log/authelia/'
    networks:
      authelia: {}
      management_net: {}
    labels:
      ## Expose Authelia through Traefik
      traefik.enable: 'true'
      traefik.docker.network: 'authelia'
      traefik.http.routers.authelia.rule: 'Host(`auth.YOURDOMAIN.com`)'
      traefik.http.routers.authelia.entrypoints: 'websecure'
      traefik.http.routers.authelia.tls.certresolver: 'leresolver'
      traefik.http.services.authelia.loadbalancer.server.port: '9091'
      ## Setup Authelia ForwardAuth Middlewares
      traefik.http.middlewares.authelia.forwardAuth.address: 'http://traefik_authelia:9091/api/authz/forward-auth'
      traefik.http.middlewares.authelia.forwardAuth.trustForwardHeader: 'true'
      traefik.http.middlewares.authelia.forwardAuth.authResponseHeaders: 'Remote-User,Remote-Groups,Remote-Name,Remote-Email'
    environment:
      TZ: 'Europe/Zurich'
      X_AUTHELIA_CONFIG_FILTERS: 'template'

  whoami-secure:
    image: 'traefik/whoami'
    restart: 'unless-stopped'
    container_name: 'whoami-secure'
    depends_on:
      - authelia
    labels:
      traefik.enable: 'true'
      traefik.http.routers.whoami-secure.rule: 'Host(`whoami-secure.YOURDOMAIN.com`)'
      traefik.http.routers.whoami-secure.entrypoints: 'websecure'
      traefik.http.routers.whoami-secure.middlewares: 'authelia@docker'
      traefik.http.services.whoami-secure.loadbalancer.server.port: '80'
      traefik.http.routers.whoami-secure.tls.certresolver: 'leresolver'
    networks:
      management_net: {}
networks:
  management_net:
    external: true  # Primary network for management
  authelia:

Step 7: Start the Stack

You can either do that with the provided Command or start the Stack with Portainer.

docker compose up -d

Step 8: Verify Setup

Now you are ready to Setup with further Configuration.

It is possible to add Authelia Middleware to your Custom Applications by adding a Traefiklabel to your Composefiles:

traefik.http.routers.YOUR-APPLICATION.middlewares: 'authelia@docker'

Troubleshooting


Further Configuration

Check out other Posts in my Wiki about setting up SMTP for example. https://wiki.aeoneros.com/books/authelia/chapter/configuration

Add OIDC

To be able to use Authelia for OIDC in 3rd Party Software make sure to Check out my OIDC Guide https://wiki.aeoneros.com/books/authelia/chapter/openid-connect-10

 

Configuration (Notifications)


Configuration (Notifications)

Setup SMTP

Authelia.png

GitHub-logo.pnglogo (1).png

 

 

 

 

How to Set Up SMTP Notifications for Authelia

Authelia supports sending email notifications via an SMTP server, which is essential for account management and security events like password recovery and login alerts. This guide will walk you through configuring SMTP notifications for Authelia.

Prerequisites

Configuration File Example

Below is a basic example of the notifier section in the configuration.yml file:

notifier:
  disable_startup_check: false
  smtp:
    address: 'smtp://127.0.0.1:25'
    timeout: '5s'
    username: 'test'
    password: 'password'
    sender: "Authelia "
    identifier: 'localhost'
    subject: "[Authelia] {title}"
    startup_check_address: 'test@aeoneros.com'
    disable_require_tls: false
    disable_starttls: false
    disable_html_emails: false
    tls:
      server_name: 'smtp.aeoneros.com'
      skip_verify: false
      minimum_version: 'TLS1.2'
      maximum_version: 'TLS1.3'
      certificate_chain: |
        -----BEGIN CERTIFICATE-----
        ...
        -----END CERTIFICATE-----
        -----BEGIN CERTIFICATE-----
        ...
        -----END CERTIFICATE-----        
      private_key: |
        -----BEGIN RSA PRIVATE KEY-----
        ...
        -----END RSA PRIVATE KEY-----

Key Configuration Options

Using Gmail

If you are using Gmail as your SMTP server, you must generate an App Password. Configure the notifier section as follows:

notifier:
  smtp:
    address: 'submission://smtp.gmail.com:587'
    username: 'your-email@gmail.com'
    password: 'your-app-password'
    sender: "Admin "

Follow Google's documentation to generate an app password: Generate App Password.

Testing the Configuration

To test your configuration, restart Authelia and check the logs:

docker logs authelia

Ensure no errors related to the SMTP connection appear. Use the startup_check_address to validate the SMTP setup without sending actual emails.

Troubleshooting

With the correct configuration, SMTP notifications enhance user experience and provide critical security alerts seamlessly.

OpenID Connect 1.0

OpenID Connect 1.0

What is OIDC?

Authelia.png GitHub-logo.png logo (1).png

 

 

 

Overview

This page shows one example use case of OpenID Connect (OIDC), using Traefik as a reverse proxy, Authelia as an identity provider (OIDC Provider), and Linkwarden (the “Relying Party”). Please note that OIDC supports many different use cases and flow types—this walkthrough is just to demonstrate one approach.


How_OIDC_works.webp

Example OIDC Flow

  1. User goes to the Relying Party (Linkwarden).
    The user attempts to access Linkwarden, which is behind Traefik. Because Linkwarden requires authentication, the user must log in.
  2. User chooses to log in with the OIDC Provider (Authelia).
    When the user selects a “Login with Authelia” option, Linkwarden (through Traefik) redirects the user to Authelia.
  3. User gets redirected to the OIDC Provider (Authelia).
    The browser is sent to Authelia’s login page.
  4. User logs in with the OIDC Provider (Authelia).
    Authelia verifies the user’s credentials (for example, via LDAP, a local user database, or some other method).
  5. OIDC Provider (Authelia) generates an ID Token (JWT).
    • This ID Token contains “claims” (such as username, groups, and email) based on the scopes defined in Authelia’s configuration.
    • Authelia signs the ID Token (it is a JWT) before sending it back to Linkwarden (the Relying Party).

    Here’s a simple table of possible scopes and example claim data:

    Scope Claim
    Profile Name
    Groups Groupa, Groupb, Groupc
    Email test @gmail.com
  6. Relying Party (Linkwarden) reads the ID Token to grant access.
    Linkwarden looks at the returned claims within the token (only what was allowed by the configured OIDC scopes) and decides whether to allow the user in. It then notifies the user’s browser that login was successful.
  7. User is logged in.
    The user is now recognized as authenticated in Linkwarden.

What Are OIDC Scopes?

OIDC scopes determine what information the Relying Party can request (and potentially receive) about the user. Typical scopes include:

- openid
- groups
- email
- profile

it may receive your group memberships, email address, and display name in the returned ID Token.


What Is a JWT?

A JWT (JSON Web Token) is the format often used to transmit information securely between parties as a JSON object:


Conclusion

Using OIDC with Traefik, Authelia, and Linkwarden is just one practical illustration of OpenID Connect flows. Authelia serves as the OIDC Provider, creating JWT-based ID Tokens. Linkwarden (the Relying Party) receives these signed tokens, reads the claims (like email or group memberships), and grants access. You can tailor the scopes and claims for your setup, making this flow flexible and secure for various applications.

OpenID Connect 1.0

Setup OIDC Guide for Beginners

Authelia.png GitHub-logo.png logo (1).png

 

 

 

Overview

Please take a look at how OIDC works here if you haven’t already: What is OIDC?
This little Wiki Article will guide you through how to get OIDC running. In this example, we will set up OIDC with the service Linkwarden.


Requirements

Make sure you have the following set up:


Step 1

Open your Authelia configuration file and edit it (in this example, we store it on a GlusterFS mount at /mnt/glustermount/data/authelia_data/config/configuration.yml):

nano /mnt/glustermount/data/authelia_data/config/configuration.yml

Step 2

Scroll to the bottom of your config file and add the following code:

identity_providers:
  oidc:
    hmac_secret: 'this_is_a_secret_abc123abc123abc'
    jwks:
     -  key_id: 'F2H5xqbYsa3AssEZTU'
        algorithm: 'RS256'
        use: 'sig'
        key: {{ secret "/secrets/rsa_2048_private.txt" | mindent 10 "|" | msquote }}
    lifespans:
      access_token: '1 hour'
      authorize_code: '1 minute'
      id_token: '1 hour'
      refresh_token: '90 minutes'
    enable_client_debug_messages: false

Step 3

By adding the identity_providers section, you enable OIDC in Authelia. All settings in that block belong to OIDC. Please note this is only the minimum required configuration for our setup. You can find more details here: Authelia OIDC Introduction.

HMAC_Secret

The HMAC Secret is a random string known only to Authelia. Do not make this public.

The HMAC secret is used to sign the JWT. This string is hashed to a SHA256 (RFC6234) byte string.

It’s strongly recommended you use a random alphanumeric string with 64 or more characters.

Generate a key in Docker CLI:

docker run --rm authelia/authelia:latest authelia crypto rand --length 64 --charset alphanumeric

For example: "rzUPr41040tMvw4tg95Ud2HdcvdDMVZPQQPpHAist386QajGftF4IlFSw0yi2gtD"
Copy it to: hmac_secret: 'this_is_a_secret_abc123abc123abc'

JWKs

The list of issuer JSON Web Keys. At least one of these must be an RSA Private key configured with the RS256 algorithm. You can configure multiple keys or algorithms. The first key for each algorithm is the default if a client isn’t configured to use a specific key_id.

Below is a contextual example:

identity_providers:
  oidc:
    jwks:
      - key_id: 'example'
        algorithm: 'RS256'
        use: 'sig'
        key: |
          -----BEGIN RSA PRIVATE KEY-----
          ...
          -----END RSA PRIVATE KEY-----
        certificate_chain: |
          -----BEGIN CERTIFICATE-----
          ...
          -----END CERTIFICATE-----
          -----BEGIN CERTIFICATE-----
          ...
          -----END CERTIFICATE-----

RFC Internet Standard:
RFC (Request for Comments) documents define internet standards, protocols, and best practices. For example, RFC7519 outlines how JSON Web Tokens should be structured and validated, ensuring a standard approach to token-based authentication.

KeyID

This is completely optional unless there’s a collision between automatically generated key IDs. If provided, it must be a unique string with fewer than 100 characters, matching the regular expression ^[a-zA-Z0-9](([a-zA-Z0-9._~-]*)([a-zA-Z0-9]))?$.

The default if this value is omitted is the first 7 characters of the public key SHA256 thumbprint in hex, followed by a hyphen, then the lowercase algorithm value.

docker run --rm authelia/authelia:latest authelia crypto rand --length 15 --charset alphanumeric

For example: "F2H5xqbYsa3AssEZTU"


Use

The key usage. Defaults to sig, which is currently the only available option.


Algorithm

The algorithm for this key. Typically optional, as it can be automatically detected based on the type of key. At least one RS256 key must be provided.


Key

You can generate an RSA keypair using the Authelia Docker container:

docker run --rm -u "$(id -u):$(id -g)" -v "$(pwd)":/keys authelia/authelia:latest authelia crypto pair rsa generate --directory /keys

Assuming your working directory is /mnt/glustermount/data/authelia_data/, you’ll end up with private.pem and public.pem.

Then, place private.pem somewhere like: /mnt/glustermount/data/authelia_data/secrets/rsa_2048_private.txt

Create folders if necessary:

mkdir /mnt/glustermount/data/authelia_data/config/secrets

Open private.pem, copy the content:

-----BEGIN RSA PRIVATE KEY-----
...
-----END RSA PRIVATE KEY-----

And paste it into a new file:

nano /mnt/glustermount/data/authelia_data/config/secrets/rsa_2048_private.txt

Save with CTRL+O and exit with CTRL+X.

If you use different Paths like mentioned in Step 2, please adjust the Configs.


Step 4

Add Clients/Services to OIDC. Here is an example on how to add Linkwarden: Setup OIDC for Linkwarden.


Conclusion

With the above configuration, Authelia can function as an OIDC provider, signing JWT tokens for your clients or services (like Linkwarden). Make sure to correctly configure your OIDC clients with the same settings (client IDs, secrets, scopes) to ensure smooth authentication. Once you’ve confirmed it’s working with a test service, you can reuse these steps for additional applications that support OIDC.

OpenID Connect 1.0

Add OIDC-Integration for Linkwarden

Authelia.png GitHub-logo.png logo (1).png

 

 

 

Overview

This page will show you how to add Linkwarden as a client (integration) for Authelia using OpenID Connect (OIDC). We’ll walk through configuring the clients section in Authelia’s configuration.yml, updating your access control rules, and finally setting up Linkwarden with the correct environment variables.


Step 1: 
Authelia Configuration for the New Client

In the OIDC setup guide, you’ve already configured the basic OIDC parameters (hmac_secret, jwks, etc.). Now, we need to add the clients block to your OIDC configuration to allow Linkwarden to authenticate via Authelia.

Open your Authelia configuration file:

nano /mnt/glustermount/data/authelia_data/config/configuration.yml

Within the identity_providers > oidc section, add or edit the clients block as follows:

identity_providers:
  oidc:
    hmac_secret: 'this_is_a_secret_abc123abc123abc'
    jwks:
     -  key_id: 'F2H5xqbYsa3AssEZTU'
        algorithm: 'RS256'
        use: 'sig'
        key: {{ secret "/secrets/rsa_2048_private.txt" | mindent 10 "|" | msquote }}
    lifespans:
      access_token: '1 hour'
      authorize_code: '1 minute'
      id_token: '1 hour'
      refresh_token: '90 minutes'
    enable_client_debug_messages: false
    clients:
      - client_id: 'linkwarden'
        client_name: 'Linkwarden'
        client_secret: '$pbkdf2-sha512$310000$c8p78n7pUMln0jzvd4aK4Q$JNRBzwAo0ek5qKn50cFzzvE9RXV88h1wJn5KGiHrD0YKtZaR/nCb2CJPOsKaPK0hjf.9yHxzQGZziziccp6Yng' #insecure_secret
        public: false
        authorization_policy: 'two_factor'
        redirect_uris:
          - 'https://linkwarden.YOURDOMAIN.com/api/v1/auth/callback/authelia'
        scopes:
          - 'openid'
          - 'groups'
          - 'email'
          - 'profile'
        userinfo_signed_response_alg: 'none'
        token_endpoint_auth_method: 'client_secret_basic'

Step 1.1: client_id

This references the unique identifier for the client (RFC: RFC3986, Section 2.3). In this example, it’s set to linkwarden. You could instead use a random string to avoid collisions or for security best practices. Tools like it-tools token generator can be used to generate a random client ID.

Step 1.2: client_name

This is a human-readable name for your application. Here, we’re calling it Linkwarden. You can name it anything that will help you identify this application in the future.

Step 1.3: client_secret

This is the secret used by the client to authenticate to Authelia (RFC: RFC3986, Section 2.3). In the example above, we’re using a hashed secret labeled insecure_secret for testing.

You can generate a more secure secret by running:

docker exec -it authelia authelia crypto hash generate pbkdf2 --variant sha512 --random --random.length 72 --random.charset rfc3986

When using Docker-Swarm Change the Containername by adding your Stackname infront or using the ContainerID:

docker exec -it traefik_authelia authelia crypto hash generate pbkdf2 --variant sha512 --random --random.length 72 --random.charset rfc3986
docker exec -it 337adb14377e authelia crypto hash generate pbkdf2 --variant sha512 --random --random.length 72 --random.charset rfc3986

Example output:

Random Password: Xh.nVAMt3P5m~fUTBj4issbKc38Xx5E47nUN7YvTzSntJv0DK2_EKdURzZFYhhs4LE4oKf~c
Digest: $pbkdf2-sha512$310000$fK3lAD7WgJ147IBgnUdC9g$F1QMc0kpTwVIUNldTaAGG8uD0EoQRxham7nN8HUXHVhNNUh2ubPu/wgo.YxXYC5ewNL.j3WPqnFLCB/mwfWSgA

You’d then place the Digest portion into the client_secret field in Authelia and use the corresponding “Random Password” value (or the “insecure_secret” equivalent) in the Linkwarden environment variable.

Step 1.4: redirect_uris and authorization_policy

Make sure the redirect URI matches https://linkwarden.YOURDOMAIN.com/api/v1/auth/callback/authelia (or whichever endpoint Linkwarden expects). Adjust your authorization_policy (such as one_factor or two_factor) depending on your security needs.


 

Step 2: Add Domain to Authelia Access Control

Next, you’ll want to allow access for linkwarden.YOURDOMAIN.com in your Authelia rules. Typically, this is done in the access_control section:

access_control:
  default_policy: 'deny'
  rules:
    - domain: 'whoami-secure.YOURDOMAIN.com'
      policy: 'two_factor'
    - domain: 'links.YOURDOMAIN.com'
      policy: 'two_factor'

Replace links.YOURDOMAIN.com or add another rule for the domain or subdomain where Linkwarden resides (linkwarden.YOURDOMAIN.com).


Step 3: Add OIDC Settings to Linkwarden

If using a Docker Compose setup, you can add the following environment variables in your docker-compose.yaml (or the equivalent setup in Portainer):

services:
  linkwarden:
    image: ghcr.io/linkwarden/linkwarden:v2.9.3
    environment:
      # SSO - Authelia
      - NEXT_PUBLIC_AUTHELIA_ENABLED=true
      - AUTHELIA_WELLKNOWN_URL=https://auth.YOURDOMAIN.com/.well-known/openid-configuration
      - AUTHELIA_CLIENT_ID=${AUTHELIA_CLIENT_ID}
      - AUTHELIA_CLIENT_SECRET=${AUTHELIA_CLIENT_SECRET}
      # SSO - Accounts
      - DISABLE_NEW_SSO_USERS=false

Important: Make sure DISABLE_NEW_SSO_USERS is set to false or new users will be blocked from logging in via SSO.

Environment Variables Table

Environment Variable Default Description
NEXT_PUBLIC_AUTHELIA_ENABLED - If set to true, Authelia will be enabled and you'll need to define the variables below.
AUTHELIA_WELLKNOWN_URL - https://{{authelia.domain.com}}/.well-known/openid-configuration
AUTHELIA_CLIENT_ID - Client ID
AUTHELIA_CLIENT_SECRET - Client Secret. (Random Password from command below)

AUTHELIA_WELLKNOWN_URL: This is an OIDC discovery URL that describes what Authelia supports (endpoints, claims, etc.)
AUTHELIA_CLIENT_ID (RFC RFC3986, Section 2.3): Again, best practice is a random unique string.
AUTHELIA_CLIENT_SECRET (RFC RFC3986, Section 2.3): Generated secret value (either from the example above or your own generator).


After updating the environment variables in your Docker Compose or Portainer configuration, restart Linkwarden to apply the changes:

docker-compose up -d

Or the equivalent command depending on your environment. Once Linkwarden is back online, you can head to its login page and try logging in with Authelia.


Step 5: Troubleshooting

If something goes wrong:


Conclusion

By adding Linkwarden as an OIDC client in Authelia and configuring the environment variables in Linkwarden, you can centralize authentication and enable secure, convenient login. Be sure to use secure secrets, update your access control lists carefully, and confirm everything is functioning by testing the login flow. Once everything is tested and stable, you’re ready to enjoy single sign-on with Authelia for Linkwarden.