Intro
Some of my hosted services do not have OIDC support or any sort of authentication out of the box. Since I am already running an instance of Authelia, I decided to use it to secure those services. It was not as straight forward as I thought, specially using HAProxy on pfSense. There are a few outdated guides that accomplish this but they still missed a step or two to get it working right.
Pre-requisites
- pfSense with haproxy-devel package installed
- A working Authelia instance already configured and accessible
- Basic understanding of HAProxy ACLs and actions
- Services you want to protect must be accessible through HAProxy
Setting up the Lua Scripts
You need to download 3 scripts into /usr/local/share/lua/5.3
on your pfsense host.
First, you need to add the auth-request.lua
file via the HAProxy -> Files section, setting the type to Lua Script and the content to the one on the link above. It should look the following screenshot.

Then, download the 3 files, including the auth-request.lua
by issuing the following commands.
curl https://raw.githubusercontent.com/rxi/json.lua/refs/heads/master/json.lua > /usr/local/share/lua/5.3/json.lua
curl https://raw.githubusercontent.com/haproxytech/haproxy-lua-http/refs/heads/master/http.lua > /usr/local/share/lua/5.3/haproxy-lua-http.lua
curl https://raw.githubusercontent.com/TimWolla/haproxy-auth-request/refs/heads/main/auth-request.lua > /usr/local/share/lua/5.3/auth-request.lua
After downloading these files, navigate to HAProxy -> Settings -> Global Advance Passthrough and under custom options paste lua-prepend-path /usr/local/share/lua/5.3/haproxy-lua-http.lua
. Click on save.
Configuring the Backend
On the backend you want to protect, configure the following Access Control Lists.
Name | Expression | Value |
---|---|---|
remote_user_exist | Custom acl: | var(req.auth_response_header.remote_user) -m found |
remote_groups_exist | Custom acl: | var(req.auth_response_header.remote_groups) -m found |
remote_name_exist | Custom acl: | var(req.auth_response_header.remote_name) -m found |
remote_email_exist | Custom acl: | var(req.auth_response_header.remote_email) -m found |
As well as the following Actions.
Action | Name | fmt | Condition acl names |
---|---|---|---|
http-request set-header | Remote-User | %[ var(req.auth_response_header.remote_user) ] | remote_user_exist |
http-request set-header | Remote-Groups | %[ var(req.auth_response_header.remote_groups) ] | remote_groups_exist |
http-request set-header | Remote-Name | %[ var(req.auth_response_header.remote_name) ] | remote_name_exist |
http-request set-header | Remote-Email | %[ var(req.auth_response_header.remote_email) ] | remote_email_exist |
It should look something like the following image.

Configuring the Frontend
Configure your frontend like you usually would, adding the appropriate ACLs and actions. Then, add one more ACL as follows.
Name | Expression | Value |
---|---|---|
protected-frontends | Host matches | host |
If you have more than one host, replace the expression with Host regex using a value like ^(app1|app2|app3)\.mydomain\.com$
In the Actions section, add the following.
Action | customaction | Condition acl names |
---|---|---|
Custom | http-request set-var(req.scheme) str(https) | { ssl_fc } |
Custom | http-request set-var(req.scheme) str(http) | !{ ssl_fc } |
Custom | http-request set-var(req.questionmark) str(?) | { query -m found } |
Custom | http-request lua.auth-intercept | protected-frontends |
Remember to change
Action | Name | fmt | Condition acl names |
---|---|---|---|
http-request header set | X-Real-IP | %[ src ] | protected-frontends |
http-request header set | X-Forwarded-Method | %[ var(req.method) ] | protected-frontends |
http-request header set | X-Forwarded-Proto | %[ var(req.scheme) ] | protected-frontends |
http-request header set | X-Forwarded-Host | %[ req.hdr(Host) ] | protected-frontends |
http-request header set | X-Forwarded-Uri | %[ path ]%[ var(req.questionmark) ]%[ query ] | protected-frontends |
Action | Rule | Condition acl names |
---|---|---|
http-request redirect | location %[var(txn.auth_response_location)] | protected-frontends !{ var(txn.auth_response_successful) -m bool } |
Action | Condition acl names |
---|---|
http-request deny | protected-frontends !{ var(txn.auth_response_successful) -m bool } { var(txn.auth_response_code) -m int 403 } |
The order of rules and actions does not really matter, as they will be re-arranged when the configuration file is auto-generated. It should look something like the following images.


Done!
After applying these settings, saving and restarting the HAProxy service, your applications should be protected by Authelia.
Resources
Thanks to these resources for useful information.