Setting up Authelia to work with Nginx Proxy Manager

Setting up Authelia to work with Nginx Proxy Manager

Introduction

Every once in a while you'll have service that has does not have a user/password login. And though it doesn't perform anything critical or show anything crucial you would still like to put it behind something for your eyes only.

This is were Authelia comes in, it would sit between the user, usually you, and the service your trying to reach. Because we are also using a reverse proxy, in this case Nginx Proxy Manager by JC21 we have to make sure that all the DNS and subdomains get passed correctly.

I have previously went over deployment and configuration of NginxPM in this post: Docker Stack with Nginx and MariaDB.

Requirements

  • Docker installed: [Post] or [Official]
  • Nginx Proxy Manager installed: [Post] or [Official]
  • Preferably have a domain and sub domains ready: auth.domain.com

Docker Compose file

Below is the contents of the docker compose file, docker-compose.yml, for Authelia.

version: '3.3'

networks:
  frontend:
    external: true
  backend:

services:
  authelia:
    container_name: authelia-app
    image: authelia/authelia:latest
    volumes:
      - ./config:/config
    ports:
     - 9091:9091
    restart: unless-stopped
    healthcheck:
      disable: false
    environment:
      - TZ=America/Edmonton # Change to your timezone
    depends_on:
      - redis
    networks:
      - frontend
      - backend

  redis:
    container_name: authelia-redis
    image: redis:alpine
    volumes:
      - ./redis:/data
    ports:
      - 6378:6379
    restart: unless-stopped
    environment:
      - TZ=America/Edmonton # Change to your timezone
    networks:
      - backend

The docker-compose.yml file assumes a few things. first is that the external network frontend exist and the second is that all container volumes are stored in a persistent volume. For organization its important to nest the docker-compose.yml inside a folder usually named authelia.

Before we can docker compose up -d the file we need to do some prerequisite work first.

Configuration File

You're going to have to make and edit this configuration for your setup. This file also must be named: configuration and be nested into the Authelia folder correctly.
To make a directory there and the file do the following:

mkdir docker/authelia/config;
nano docker/authelia/configuration.yml

The nesting should be like the following: home/user/docker/authelia/config/configuration.yml.

##############################################################################
#                          Authelia configuration                            #
##############################################################################
server:
  host: 0.0.0.0
  port: 9091 # if you need this changed make sure it reflects also in the docker-compose.yml

log:
  level: debug

jwt_secret: # Change me
default_redirection_url: https://auth.domain.com # Change me
totp:
  issuer: domain.com # Change me
  period: 30
  skew: 1

#duo_api:     ## If you want push notifictions of login attempts you can pay for this feature
#  hostname: api-123456789.example.com
#  integration_key: ABCDEF
#  secret_key: yet-another-long-string-of-characters-and-numbers-and-symbols

authentication_backend:
  disable_reset_password: false
  file:
    path: /config/users_database.yml # Make sure this file exists
    password:
      algorithm: argon2id
      iterations: 1
      salt_length: 16
      parallelism: 8
      memory: 64

access_control:
  default_policy: deny
  rules:
    # Rules applied to everyone
    - domain:
        - "auth.domain.ca"
#        - "some-app-with-api.yourdomain.com"
      policy: bypass
    - domain: # Proxies only requiring username and password
        - "homepage.domain.com"
      policy: one_factor
#      networks:
#        - 192.168.1.0/24
    - domain: # Proxies needing 2 factor below
        - "glances.domain.com"
#        - "proxmox.yourdomain.com"
      policy: two_factor
#      networks:
#         - 192.168.1.0/24
         
session:
  name: authelia_session
  # This secret can also be set using the env variables AUTHELIA_SESSION_SECRET_FILE
  secret: #change me
  expiration: 3600 # 1 hour
  inactivity: 7200 # 2 hours
  domain: domain.com # Needs to be your root domain

  redis:
    host: authelia-redis
    port: 6379
    # This secret can also be set using the env variables AUTHELIA_SESSION_REDIS_PASSWORD_FILE
    password: authelia

regulation:
  max_retries: 5
  find_time: 2m
  ban_time: 10m

theme: dark   # options: dark, light

storage:
  encryption_key: # change me
# The minimum length of this key is 20 characters.  
  local:
    path: /config/db.sqlite3
    
notifier:
  filesystem:
    filename: /config/notification.txt
#  smtp:
#    username: <your-user@your-email-domain.org>
#    password: <your-user-email-password-for-smtp>
#    host: <your-email-host-url-or-ip>
#    port: <your-email-port-for-smtp>  # 25 non-ssl, 443 ssl, 587 tls
#    sender: <sender@your-email-domain.org>
#    subject: "[Authelia] {title}"
#    disable_require_tls: false # set to true if your domain uses no tls or ssl only
#    disable_html_emails: false # set to true if you don't want html in your emails
#    tls:
#      server_name: <your-email-host-url-or-ip>
#      skip_verify: false
#      minimum_version: TLS1.2

You will want to change the following lines to your own configuration:
Line 11 jwt_secret: use openssl rand -hex 32 in a terminal to generate a 64 character random alphanumeric string.
Line 12 default_redirection_url:, change this to your subdomain or domain that will be directed to Authelia. In this case it will be the subdomain https://auth.domain.com.
Line 14 issuer:, change this to your top level domain, in this case domain.com
Line 39 - "auth.domain.ca", change this to your auth URL. Leave the quotation marks.
Line 56 secret:, change this to an alphanumeric string of at least 64 characters. You can use the previous command openssl rand -hex 32 to generate a different secret.
Line 66 password:, generate a 64 character password.
Line 76 encryption_key:, generate a key of at least 20 characters.
access_control: - You will enter the domain of services you want to put behind Authelia. Depending on where you place them, they will have different levels of authentication. For further granular control head to the official documentation on access_control.

Users Database file

You will also need to make a users_database.yml that is nested in the config folder you've previously made. You can use the following command to create a users_database.yml inside of the config folder.

nano docker/authelia/configuration.yml

Here's the layout of the users_database.yml

###############################################################
#                        Users Database                       #
###############################################################
 
# This file can be used if you do not have an LDAP set up.
 
# List of users
users:
  JohnDoe:
    displayname: "John Doe"
    email: youremail@domain.com
# hash using docker run authelia/authelia:latest authelia hash-password SOMEPASSWORD
    password: "$argon2id$v=19$m=65536,t=3,p=4$2fa01408014891e1020dc040e4839ed85706913abdabe13c95584003f4c9e88bfc"
    groups:
      - admins
      - dev

JohnDoe is the username during Authelia login.
displayname is how Authelia will display the user's name.
email for SMTP transactional emails
password:, you'll use docker run authelia/authelia:latest authelia hash-password SOMEPASSWORD to generate a hashed password. SOMEPASSWORD is the password you're going to use to login. I don't think it needs to be said but SOMEPASSWORD should be change to a secure password then hashed.
groups is how you will give special access to users, remove groups if the user doesn't require them.

Nginx Proxy Manager Configuration (Authelia)

The nginx proxy syntax below will go in the advanced tab on the proxy host. To get there, do the following:

  • Login to Nginx Proxy Manager
  • Select Proxy Host
  • Add Proxy Host
  • Domain Names field example: auth.domain.com
  • scheme is http
  • Forward Hostname/IP would be the container name or IP of the container. In our docker compose case: authelia-app
  • Forward Port is 9091 or whatever you mapped
  • Enable Block Common Exploits and Websockets Support
  • SSL tab, get or assign the SSL certificate.
  • Enable Froce SSL, HTTP/2 Support, HSTS Enabled and HSTS subdomains.
  • Advanced Tab and paste the following:
 location / {
        set $upstream_authelia http://IP.0.0.1:9091; 
        proxy_pass $upstream_authelia;
        client_body_buffer_size 128k;
 
        #Timeout if the real server is dead
        proxy_next_upstream error timeout invalid_header http_500 http_502 http_503;
 
        # Advanced Proxy Config
        send_timeout 5m;
        proxy_read_timeout 360;
        proxy_send_timeout 360;
        proxy_connect_timeout 360;
 
        # Basic Proxy Config
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;
        proxy_set_header X-Forwarded-Host $http_host;
        proxy_set_header X-Forwarded-Uri $request_uri;
        proxy_set_header X-Forwarded-Ssl on;
        proxy_redirect  http://  $scheme://;
        proxy_http_version 1.1;
        proxy_set_header Connection "";
        proxy_cache_bypass $cookie_session;
        proxy_no_cache $cookie_session;
        proxy_buffers 64 256k;
 
        # If behind reverse proxy, forwards the correct IP
        set_real_ip_from 10.0.0.0/8;
        set_real_ip_from 172.0.0.0/8;
        set_real_ip_from 192.168.0.0/16;
        set_real_ip_from fc00::/7;
        real_ip_header X-Forwarded-For;
        real_ip_recursive on;
    }

Change Line 2: set $upstream_authelia http://IP.0.0.1:9091; to your machine's LAN IP address or the container name, in this case authelia-app.
Save the Proxy Host.

Nginx Proxy Manager Configuration (Services)

With Authelia's proxy host setup we can now place Authelia between the web and services. To do so you would setup a proxy host as normal for your services or if you already have them running then it's just 1 more step.

In the Advanced tab of the proxy host window you'll add the following after making changes to fit your services:

location /authelia {
    internal;
    set $upstream_authelia http://authelia-app:9091/api/verify; #ADD YOUR IP AND PORT OF AUTHELIA
    proxy_pass_request_body off;
    proxy_pass $upstream_authelia;    
    proxy_set_header Content-Length "";
 
    # Timeout if the real server is dead
    proxy_next_upstream error timeout invalid_header http_500 http_502 http_503;
    client_body_buffer_size 128k;
    proxy_set_header Host $host;
    proxy_set_header X-Original-URL $scheme://$http_host$request_uri;
    proxy_set_header X-Real-IP $remote_addr;
    proxy_set_header X-Forwarded-For $remote_addr; 
    proxy_set_header X-Forwarded-Proto $scheme;
    proxy_set_header X-Forwarded-Host $http_host;
    proxy_set_header X-Forwarded-Uri $request_uri;
    proxy_set_header X-Forwarded-Ssl on;
    proxy_redirect  http://  $scheme://;
    proxy_http_version 1.1;
    proxy_set_header Connection "";
    proxy_cache_bypass $cookie_session;
    proxy_no_cache $cookie_session;
    proxy_buffers 4 32k;
 
    send_timeout 5m;
    proxy_read_timeout 240;
    proxy_send_timeout 240;
    proxy_connect_timeout 240;
}
 
    location / {
        set $upstream_dockerapp http://docker-app:61208;  #CHANGE NAME AND IP AND PORT
        proxy_pass $upstream_dockerapp;  #change name of the service
 
		auth_request /authelia;
		auth_request_set $target_url $scheme://$http_host$request_uri;
		auth_request_set $user $upstream_http_remote_user;
		auth_request_set $groups $upstream_http_remote_groups;
		proxy_set_header Remote-User $user;
		proxy_set_header Remote-Groups $groups;
		error_page 401 =302 http://auth.domain.com/?rd=$target_url; #change YOURDOMAIN.COM to your domain
 
		client_body_buffer_size 128k;
 
		proxy_next_upstream error timeout invalid_header http_500 http_502 http_503;
 
		send_timeout 5m;
		proxy_read_timeout 360;
		proxy_send_timeout 360;
		proxy_connect_timeout 360;
 
		proxy_set_header Host $host;
		proxy_set_header X-Real-IP $remote_addr;
		proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
		proxy_set_header X-Forwarded-Proto $scheme;
		proxy_set_header X-Forwarded-Host $http_host;
		proxy_set_header X-Forwarded-Uri $request_uri;
		proxy_set_header X-Forwarded-Ssl on;
		proxy_redirect  http://  $scheme://;
		proxy_http_version 1.1;
		proxy_set_header Connection "";
		proxy_cache_bypass $cookie_session;
		proxy_no_cache $cookie_session;
		proxy_buffers 64 256k;
 
		set_real_ip_from 192.168.1.0/16;
		real_ip_header X-Forwarded-For;
		real_ip_recursive on;
 
    }

Your going to have to change a few things in the Nginx syntax for services.
Line 3: set $upstream_authelia http://authelia-app:9091/api/verify; Change the url to the IP of your server or the container name.
Line 33: set $upstream_glances http://docker-app:61208; Change the value after the $upstream_ to a simple name of your service, example:docker, homepage, ghostblog. Change the URL to the IP of your service or the container name.
Line 34: proxy_pass $upstream_docker; Change the value after the $upstream_ to match Line 33.
Line 42: error_page 401 =302 http://auth.domain.com/?rd=$target_url; Change the domain to your auth domain or subdomain.
Save the proxy host and visit the service.

Congrats You're Now Done and Ready for deployment.

For more documentation and help visit these resources:

GitHub - authelia/authelia: The Single Sign-On Multi-Factor portal for web apps
The Single Sign-On Multi-Factor portal for web apps - GitHub - authelia/authelia: The Single Sign-On Multi-Factor portal for web apps
GitHub - NginxProxyManager/nginx-proxy-manager: Docker container for managing Nginx proxy hosts with a simple, powerful interface
Docker container for managing Nginx proxy hosts with a simple, powerful interface - GitHub - NginxProxyManager/nginx-proxy-manager: Docker container for managing Nginx proxy hosts with a simple, po…

Have fun and take care.