Configure HAProxy with Authelia on pfSense

Kovasky Buezo | Aug 18, 2025 min read

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.

HAProxy files section in pfSense

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.

NameExpressionValue
remote_user_existCustom acl:var(req.auth_response_header.remote_user) -m found
remote_groups_existCustom acl:var(req.auth_response_header.remote_groups) -m found
remote_name_existCustom acl:var(req.auth_response_header.remote_name) -m found
remote_email_existCustom acl:var(req.auth_response_header.remote_email) -m found

As well as the following Actions.

ActionNamefmtCondition acl names
http-request set-headerRemote-User%[ var(req.auth_response_header.remote_user) ]remote_user_exist
http-request set-headerRemote-Groups%[ var(req.auth_response_header.remote_groups) ]remote_groups_exist
http-request set-headerRemote-Name%[ var(req.auth_response_header.remote_name) ]remote_name_exist
http-request set-headerRemote-Email%[ var(req.auth_response_header.remote_email) ]remote_email_exist

It should look something like the following image.

HAProxy backend with Authelia ACL and Actions on pfSense

Configuring the Frontend

Configure your frontend like you usually would, adding the appropriate ACLs and actions. Then, add one more ACL as follows.

NameExpressionValue
protected-frontendsHost matcheshost

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.

ActioncustomactionCondition acl names
Customhttp-request set-var(req.scheme) str(https){ ssl_fc }
Customhttp-request set-var(req.scheme) str(http)!{ ssl_fc }
Customhttp-request set-var(req.questionmark) str(?){ query -m found }
Customhttp-request lua.auth-intercept _ipvANY /api/authz/forward-auth HEAD * remote-user,remote-groups,remote-name,remote-email -protected-frontends

Remember to change with your Authelia backend name. The suffix ipvANY is necessary as HAProxy in pfSense adds the _ipvANY bit to the name when generating the configuration file. For example, if your Authelia backend is named “authelia”, use: authelia_ipvANY

ActionNamefmtCondition acl names
http-request header setX-Real-IP%[ src ]protected-frontends
http-request header setX-Forwarded-Method%[ var(req.method) ]protected-frontends
http-request header setX-Forwarded-Proto%[ var(req.scheme) ]protected-frontends
http-request header setX-Forwarded-Host%[ req.hdr(Host) ]protected-frontends
http-request header setX-Forwarded-Uri%[ path ]%[ var(req.questionmark) ]%[ query ]protected-frontends
ActionRuleCondition acl names
http-request redirectlocation %[var(txn.auth_response_location)]protected-frontends !{ var(txn.auth_response_successful) -m bool }
ActionCondition acl names
http-request denyprotected-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.

HAProxy frontend1 with Authelia ACL and Actions on pfSense HAProxy frontend2 with Authelia ACL and Actions on pfSense

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.