Skip to main content
  1. Posts/

Secure Access with Authelia

·5 mins· loading ·
Self-hosting Application
Timo
Author
Timo
Business Applications Architect, Network Engineer, Self-hosting Hobbyist.
Table of Contents

Sooner or later most of us at least think about opening some of our services up to the internet and there is plenty of reason that lead to this idea.
Did you spin up a shiny new file sharing service like Gokapi and want to share some snapshots from last weekend’s birthday party or is it just your neat Wiki you put hours into and can’t wait to share your knowledge with others?

💭 Keep the risk in mind …

IMHO you should always be mindful about publishing things to the internet, be aware of the risks that come with it and prefer accessing your services through a VPN like WireGuard.
Of course there are plenty of counter measures you should take - IP masking (e.g. Cloudflare Proxy), DDoS protection and access restriction to name a few - but an element of risk remains.

🔒 Make things more secure …

Wouldn’t it be great to add another layer of security to your services? That’s where Authelia comes into play.
A simple way to add an authentication and authorization portal to your applications.

Authelia

Why Authelia?
#

Security usually means things get tricky to set up and harder to use, this is not the case with Authelia. The setup process is straight forward, configuration is easy through YAML files, and it really is “blazing fast” as stated on the project website. Authelia just works and never failed me.

What is Authelia?
#

Authelia is a lightweight open-source authentication and authorization server and portal fulfilling the identity and access management (IAM) role of information security in providing multifactor authentication and single sign-on (SSO) for your applications via a web portal.
It acts as a companion for common reverse proxies.

Login Portal
Authelia login portal.

Installation
#

Installation via docker-compose is quite easy, just use the following docker-compose.yml.

version: '3.3'
services:
  authelia:
    image: authelia/authelia
    volumes:
      - ./config:/config
    ports:
      - <PORT>:9091
    restart: unless-stopped
    # healthcheck:
      # disable: true
    environment:
      - TZ=Europe/Berlin
    depends_on:
      - redis

  redis:
    image: redis:alpine
    volumes:
      - ./redis:/data
    expose:
      - 6379
    restart: unless-stopped
    environment:
      - TZ=Europe/Berlin
Change TZ, volumes and<PORT> to suit your setup.

How does it work?
#

Users and access control are configured in configuration.yml and users_database.yml, both available in ./config/.

First you need to build your users_database.yml, setting up your first user.

# Creating users_database.yml
cd /path/to/authelia/config
vim users_database.yml

# Generating password hash for first user (define a secure password for <'SOMEPASSWORD'>)
docker run --rm authelia/authelia:latest authelia hash-password 'SOMEPASSWORD'

Configure your first user in users_database.yml.

---
###############################################################
#                         Users Database                      #
###############################################################

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

users:
  test-user:
    displayname: "Tester"
    password: "$argon2id$v=19$m=65536,t=3,p=4$4oI0bY5UJg2tzvWamPcipA$hVTeFKR2hM1i103Cw2yd+AS1ethwBgCX8FqzpizAcOU"   #hash using docker run --rm authelia/authelia:latest authelia hash-password 'SOMEPASSWORD'
    email: tester@domain.tld
#    groups:
#      - admins
...

Set your services up for access control in configuration.yml.

vim /path/to/authelia/config/configuration.yml

access_control:
  default_policy: deny
  rules:
    # Rules applied to everyone
    # - domain: public.example.com
    #  policy: bypass
    - domain: service_1.domain.tld
      policy: one_factor
    - domain: service_2.domain.tld
      policy: two_factor
    - domain: service_3.domain.tld
      policy: bypass  
After configuration changes Authelia needs to be restarted with docker-compose restart.

Once configured all you have to do is edit the advanced configuration of the Proxy Host in Nginx Proxy Manager, use the following example:

Click for advanced NPM proxy host configuration ...
location /authelia {
  internal;
  set $upstream_authelia http://<IP-ADDRESS>:<PORT>/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_<service> http://<IP-ADDRESS>:<PORT>;  #CHANGE NAME OF UPSTREAM AND IP-ADDRESS AND PORT
      proxy_pass $upstream_<service>;  #CHANGE NAME OF UPSTREAM
 
  	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 https://auth.domain.tld/?rd=$target_url; #CHANGE TO AUTHELIA 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.178.0/24;
  	real_ip_header X-Forwarded-For;
  	real_ip_recursive on;
 
  }
Change <IP-ADDRESS>, <PORT>, upstream_<service> and https://auth.domain.tld to values suitable for your setup.

Access control
#

Authelia allows for a in depth access control which among other things lets you bypass certain subdirectories of your URL.
This is needed when the application you’re securing via Authelia publishes API endpoints for e.g. mobile apps.

Configure access control in the configuration.yml by adding two entries for your domain.
The first entry adds a bypass rule for subdirectories starting with /api and /login while the second entry activates 2FA for the whole domain.

vim /path/to/authelia/config/configuration.yml

access_control:
  default_policy: deny
  rules:
    - domain: example.domain.tld
      resources: 
       - '^/api/.*$'
       - '^/api$'
       - '^/api/'
       - '^/login/.*$'
       - '^/login$'
       - '^/login/'
      policy: bypass
    - domain: example.domain.tld
      policy: two_factor

Authelia’s Access Control has way more capabilities than that, check out the official documentation if you want to know more.

Final thoughts
#

Authelia is a great way to add an extra layer of security to your applications. It’s easy to set up, lightweight and fast giving you the opportunity to set up your first portal in a matter of minutes. There is no reason you should wait, go ahead and give it a try.

Please consider leaving a ⭐ on the Authelia GitHub Repository if you love it as much as I do