Authelia Identity Provider
Created: 6 Jul 2025.
Why I need an Identity Provider
After I started hosting this public website on my home server, I realised how useful all the documentation was – not just for me, but for others to refer to, especially when I met someone who wanted to know how something was done.
Being a amatuer photography enthusiast, it wasn’t long before I was longing to share my photos on my site as well. But it had to be behind an authenticated site. So I started thinking about how to go about achieving this. The more I searched, the more I realised it wasn’t going to easy.
What led me to Authelia
The initial approach
I started out dreaming of the ideal solution, one that would be tailored to what I wanted:
cater for multiple realms / domains
enforce two factor authentication
single ID sign on for the multiple realms / web services I intended to host
This resulted in designing a non-trivial complex relational database design to cater to the above requirements.
I did dwell into doing a POC with some components of this database design using JPA and Hibernate persistence, but soon realised it would take quite some effort to do the development work.
Then I got a Yubikey
I decided to buy a Yubikey out of curiosity more than anything else. I just had an inkling that it would be quite useful. And then I realised why it was so secure; namely that, the private key of a certificate key pair would never leave the Yubikey device. The public key of that pair would be what was kept by the portal you wanted to register this with.
I also spent some time looking at Java code, to understand how I could implement it into a simple authentication portal.
Which meant that I needed a full stack solution with Angular or React on the front end.
While taking a step back and trying to see if there was a simpler solution, it led me to look for ready made identity provider solutions.
The path I settled on
Having given up on a custom developed software solution, I eventually narrowed my short listed candidates to Keycloak, Authentik, Authelia and Pocket ID:
Keycloak was an enterprise grade solution which was too complex and an overkill.
Authelia seemed okay, but initially, it still seemed a little too complex for me.
Pocket ID was too simple and didn’t have good documentation or the ability to tweak it.
Authentik required you to use docker, which was not in my plan, as I had the option of deploying my chosen solutions on FreeBSD Bastilles or Proxmox containers / VMs.
But, I eventually decided to give Authelia a go as it had enough features, maturity and reliability for what I wanted to do, and I could host it in a Proxmox container.
I took me a while to understand the configuration options available and how to get it up and working, and integrate it with my NGINX reverse proxy. And the initial POC worked with just single factor authentication with integration to MySQL and OpenLDAP.
So, without further ado, let me provide details on how I have setup Authelia and my working configuration file. Of course, I’ve cleared out the sensitive secret entries, but the rest is exactly as I have configured it on my Authelia container.
Authentication Flow
The diagram below shows the typical flow for an incoming web request coming from the internet.

Start (01): Any incoming web request comes through TCP port 80 (HTTP) and TCP port 443. The pfSense router uses Network Address Translation (NAT) to send this request to the NGINX reverse web proxy (192.168.1.10). As a side note, Let’s Encrypt is used to provide the HTTPS certificate for the web proxy, and it requires that both these ports be open for certificate renewal.
02, 03 & 04: The reverse proxy checks if the requested internal web site requires authentication or not and forwards the request on as needed.
If the site is meant to be public without any authentication (No), the reverse proxy forwards the request to the destination container **(04a). In the example above, if the request is for the public website, the request is forwarded to 192.168.1.6 on the top left.
Otherwise (Yes), the request is forwarded to Authelia (to the right) for authentication checks.
04b: For all sites requiring authentication, Authelia checks if the user session has a valid user authenticated session cookie. If it is still valid, Authelia forwards the request on to the destination site, as shown in this example 05b.
05b: If there is no existing session (new request) cookie, or the session has expired (configurable duration in Authelia), the request is forwarded to the Authelia login page.
06: Once the user enters his credentials, Authelia checks these against the OpenLDAP and MySQL database servers before allowing the user session to proceed to its final destination 07.
Authelia Configuration
1##############################################################################
2# Authelia configuration thehomelab.wiki #
3##############################################################################
4
5# Reference URL: https://thehomelab.wiki/books/dns-reverse-proxy/page/setup-authelia-to-work-with-nginx-proxy-manager
6log:
7 level: 'info'
8 format: 'text'
9 file_path: '/var/log/authelia/authelia.log'
10
11# To generate 32 bit lenght key: $ authelia crypto rand --length 32 --charset alphanumeric
12# See https://www.authelia.com/reference/guides/generating-secure-values/
13identity_validation:
14 reset_password:
15 jwt_secret: 'BuOBAq--some hex secret code generated with authelia--xX24S07dcD'
16 jwt_lifespan: '5 minutes'
17 jwt_algorithm: 'HS256'
18
19totp:
20 disable: true
21 issuer: thomas-pk.com
22 algorithm: 'sha1'
23 digits: 6
24 period: 30
25 skew: 1
26 secret_size: 32
27
28server:
29 address: 'tcp://:9091'
30 endpoints:
31 authz:
32 auth-request:
33 implementation: 'AuthRequest'
34
35# Passkeys see https://www.authelia.com/reference/guides/webauthn/
36authentication_backend:
37 password_reset:
38 disable: true
39 custom_url: ''
40 password_change:
41 disable: true
42 ldap:
43 address: 'ldap://192.168.1.12'
44 implementation: 'custom'
45 timeout: '5s'
46 start_tls: false
47# tls:
48# server_name: '192.168.1.12'
49# skip_verify: true
50# minimum version: 'TLS1.2'
51 pooling:
52 enable: false
53 count: 5
54 retries: 2
55 timeout: '10 seconds'
56 base_dn: 'DC=thomas-pk,DC=com'
57 additional_users_dn: 'OU=Users'
58 users_filter: '(&({username_attribute}={input})(objectClass=inetOrgPerson))'
59 additional_groups_dn: 'OU=Groups'
60 groups_filter: '(&(member={dn})(objectClass=posixGroup))'
61 group_search_mode: 'filter'
62 permit_referrals: false
63 permit_unauthenticated_bind: false
64 permit_feature_detection_failure: false
65 user: 'CN=admin,DC=thomas-pk,DC=com'
66 password: 'LDAP password'
67 attributes:
68 distinguished_name: 'distinguishedName'
69 username: 'uid'
70 display_name: 'displayName'
71 family_name: 'sn'
72 given_name: 'givenName'
73 middle_name: 'middleName'
74 nickname: ''
75 gender: ''
76 birthdate: ''
77 website: 'wWWHomePage'
78 profile: ''
79 picture: ''
80 zoneinfo: ''
81 locale: ''
82 phone_number: 'telephoneNumber'
83 phone_extension: ''
84 street_address: 'streetAddress'
85 locality: 'l'
86 region: 'st'
87 postal_code: 'postalCode'
88 country: 'c'
89 mail: 'mail'
90 member_of: 'memberOf'
91 group_name: 'cn'
92 extra:
93 extra_example:
94 name: ''
95 multi_valued: false
96 value_type: 'string'
97
98access_control:
99 default_policy: deny
100 rules:
101 # Rules applied to everyone
102 - domain:
103 - "www.thomas-pk.com"
104 policy: bypass
105 - domain: # Proxies only requiring username and password
106 - "history.thomas-pk.com"
107 policy: two_factor
108
109session:
110 name: authelia_session
111 # This secret can also be set using the env variables AUTHELIA_SESSION_SECRET_FILE
112 secret: BEc-- some hex code --VE
113 expiration: 3600 # 1 hour
114 inactivity: 180 # 3 minutes for testing
115 cookies:
116 - domain: thomas-pk.com # Needs to be your root domain
117 authelia_url: 'https://login.thomas-pk.com'
118 default_redirection_url: 'https://www.thomas-pk.com'
119
120regulation:
121 max_retries: 0
122 find_time: 2m
123 ban_time: 10m
124
125theme: dark # options: dark, light
126
127storage:
128 encryption_key: 'cOzD5-- some hex encryption key generated by Authelia --GYxKQcO9'
129 mysql:
130 address: 'tcp://192.168.1.11:3306'
131 database: 'authelia'
132 username: 'authelia'
133 password: 'MySQL password'
134 timeout: '5s'
135
136notifier:
137 smtp:
138 address: 'submission://smtp.gmail.com:587'
139 username: 'your_gmail_user_id@gmail.com'
140 password: 'Your gmail app password'
141 sender: "Authelia <admin@thomas-pk.com>"
142# timeout: '10s'
143# identifier: 'localhost'
144# subject: "[Authelia] {title}"
145# startup_check_address: 'thomas.pk@gmail.com'
146# disable_require_tls: false # set to true if your domain uses no tls or ssl only
147# disable_html_emails: false # set to true if you don't want html in your emails
148# tls:
149# server_name: smtp.gmail.com
150# skip_verify: false
151# minimum_version: TLS1.2
152
153webauthn:
154 disable: false
155 enable_passkey_login: true
156 display_name: 'thomas-pk.com'
157 attestation_conveyance_preference: 'indirect'
158 timeout: '60 seconds'
159 filtering:
160 permitted_aaguids: []
161 prohibited_aaguids: []
162 prohibit_backup_eligibility: false
163 selection_criteria:
164 attachment: ''
165 discoverability: 'preferred'
166 user_verification: 'preferred'
167 metadata:
168 enabled: false
169 validate_trust_anchor: true
170 validate_entry: true
171 validate_entry_permit_zero_aaguid: false
172 validate_status: true
173 validate_status_permitted: []
174 validate_status_prohibited:
175 - 'REVOKED'
176 - 'USER_KEY_PHYSICAL_COMPROMISE'
177 - 'USER_KEY_REMOTE_COMPROMISE'
178 - 'USER_VERIFICATION_BYPASS'
179 - 'ATTESTATION_KEY_COMPROMISE'
The Authelia configuration.yml file for my domain.
What’s next
Enabling TLS connection to OpenLDAP
Getting my head around how to organise user entries in LDAP. This is new technology for me and its only after working with Authelia on this project I understood the importance of LDAP.