Episode ini mengintegrasikan Authelia dengan HAProxy: memahami kebutuhan modul Lua haproxy-auth-request, membangun backend Authelia, memanggil endpoint verifikasi dengan acl, menangani status 401, dan menyusun haproxy.cfg yang melindungi beberapa layanan sekaligus.

NGINX punya auth_request, Traefik punya middleware forwardAuth, Caddy punya direktif forward_auth. HAProxy — jujur saja — tidak punya fitur asli yang setara. Namun jangan salah: HAProxy adalah reverse proxy dan load balancer yang sangat mumpuni, dan dengan sedikit bantuan modul Lua, ia bisa menjalankan pola forward authentication yang sama dengan sempurna.
Episode ini tentang jembatan itu: haproxy-auth-request, sebuah modul Lua karya Tim Wolla yang memberikan HAProxy kemampuan sub-request verifikasi seperti auth_request NGINX. Analoginya: HAProxy adalah satpam lama yang sangat berpengalaman, tapi tidak pernah dilatih menelepon resepsionis. Modul Lua adalah pelatih yang mengajarinya.
Karena fitur ini bukan bawaan, kalian perlu menyediakan tiga hal untuk HAProxy:
USE_LUA=1).json sebagai dependensinya.Semuanya dimuat lewat konfigurasi global:
global
lua-prepend-path /usr/local/etc/haproxy/?/http.lua
lua-load /usr/local/etc/haproxy/auth-request.lua
defaults
mode http
log global
option httplog
timeout connect 5s
timeout client 30s
timeout server 30slua-load memuat skrip auth-request, dan lua-prepend-path memberitahu HAProxy di mana menemukan dependensi haproxy-lua-http. Dua baris inilah yang membuka kemampuan forward auth di HAProxy.
Selanjutnya, definisikan Authelia sebagai backend biasa dengan health check:
backend be_authelia
server authelia authelia:9091 checkIni tidak beda dengan backend aplikasi lain. Yang membedakan adalah bagaimana frontend memanfaatkannya untuk sub-request verifikasi.
Sebelum sub-request dikirim, frontend harus melengkapi header X-Forwarded-*. Authelia membaca header ini untuk mengetahui skema, host, dan URI asli permintaan — bahan evaluasi access control rules. Tanpa header ini, semua permintaan tampak datang dari alamat HAProxy itu sendiri.
frontend fe_http
bind *:443 ssl crt /etc/haproxy/example.com.pem
option forwardfor
http-request set-var(req.scheme) str(https) if { ssl_fc }
http-request set-var(req.scheme) str(http) if !{ ssl_fc }
http-request set-header X-Forwarded-Method %[method]
http-request set-header X-Forwarded-Proto %[var(req.scheme)]
http-request set-header X-Forwarded-Host %[req.hdr(Host)]
http-request set-header X-Forwarded-URI %[path]%[query]
acl host-auth hdr(Host) -i auth.example.com
acl host-nextcloud hdr(Host) -i nextcloud.example.com
acl protected hdr(Host) -m reg -i ^(nextcloud|gitea|grafana)\.example\.comoption forwardfor menambahkan X-Forwarded-For dengan IP sumber, dan baris http-request set-header melengkapi sisanya. ACL protected mendefinisikan host mana yang harus melewati verifikasi Authelia — ini pengganti dari "layanan mana yang dipasangi middleware".
Inti integrasi ada di baris berikut — di dalam frontend, sebelum routing:
http-request lua.auth-intercept be_authelia /api/authz/forward-auth HEAD * remote-user,remote-groups,remote-name,remote-email - if protected
http-request deny if protected !{ var(txn.auth_response_successful) -m bool } { var(txn.auth_response_code) -m int 403 }
http-request redirect location %[var(txn.auth_response_location)] if protected !{ var(txn.auth_response_successful) -m bool }Mari bedah ketiga baris ini — ini jantung episode ini:
http-request lua.auth-intercept be_authelia /api/authz/forward-auth HEAD * ... — mengirim sub-request HEAD ke backend be_authelia pada endpoint /api/authz/forward-auth, meminta header remote-user, remote-groups, remote-name, dan remote-email dalam respons. Hasilnya disimpan dalam variabel txn.auth_response_*.
http-request deny — jika verifikasi gagal dan kode respons 403 (kebijakan deny di access control rules), blokir permintaan langsung. Ini menangani kasus user yang terautentikasi tapi tidak berhak.
http-request redirect — jika verifikasi tidak sukses (belum login), arahkan ke portal Authelia menggunakan URL yang dikirim Authelia pada header Location respons — lengkap dengan parameter rd untuk kembali ke halaman semula.
Important
Urutan ketiga baris ini tidak boleh dipertukarkan. deny untuk kasus 403 harus dievaluasi sebelum redirect untuk kasus belum login — jika dibalik, user yang tidak berhak justru diarahkan ke portal dan berpotensi masuk ke putaran redirect yang membingungkan.
Terakhir, rute permintaan: portal Authelia ke backend Authelia, aplikasi yang dilindungi ke backend-nya sendiri. Header identitas yang dikumpulkan sub-request otomatis disuntikkan ke permintaan asli oleh modul auth-request ketika verifikasi sukses — inilah yang membuat aplikasi mengenali Remote-User tanpa login kedua.
use_backend be_authelia if host-auth
use_backend be_nextcloud if host-nextcloud
backend be_nextcloud
server nextcloud nextcloud:80Modul haproxy-auth-request juga menangani cookie sesi: cookie yang dikirim Authelia pada respons verifikasi diteruskan ke browser, sehingga sesi Authelia tetap hidup di seluruh subdomain — prasyarat SSO yang kita bangun dari episode 7.
Keseluruhan konfigurasi dalam satu file:
global
lua-prepend-path /usr/local/etc/haproxy/?/http.lua
lua-load /usr/local/etc/haproxy/auth-request.lua
defaults
mode http
log global
option httplog
timeout connect 5s
timeout client 30s
timeout server 30s
backend be_authelia
server authelia authelia:9091 check
backend be_nextcloud
server nextcloud nextcloud:80
frontend fe_http
bind *:443 ssl crt /etc/haproxy/example.com.pem
option forwardfor
http-request set-var(req.scheme) str(https) if { ssl_fc }
http-request set-var(req.scheme) str(http) if !{ ssl_fc }
http-request set-header X-Forwarded-Method %[method]
http-request set-header X-Forwarded-Proto %[var(req.scheme)]
http-request set-header X-Forwarded-Host %[req.hdr(Host)]
http-request set-header X-Forwarded-URI %[path]%[query]
acl host-auth hdr(Host) -i auth.example.com
acl host-nextcloud hdr(Host) -i nextcloud.example.com
acl protected hdr(Host) -m reg -i ^(nextcloud)\.example\.com
http-request lua.auth-intercept be_authelia /api/authz/forward-auth HEAD * remote-user,remote-groups,remote-name,remote-email - if protected
http-request deny if protected !{ var(txn.auth_response_successful) -m bool } { var(txn.auth_response_code) -m int 403 }
http-request redirect location %[var(txn.auth_response_location)] if protected !{ var(txn.auth_response_successful) -m bool }
use_backend be_authelia if host-auth
use_backend be_nextcloud if host-nextcloudSebelum memuatnya, validasi sintaks dengan haproxy -c -f /etc/haproxy/haproxy.cfg — HAProxy akan memeriksa seluruh file tanpa mengeksekusinya.
nextcloud.example.com — harus diarahkan ke portal auth.example.com.Remote-User tersedia bagi aplikasi.deny: user yang diblok access control rules harus menerima 403 langsung, bukan redirect.Tip
HAProxy menawarkan stick tables yang bisa dipakai untuk rate limiting dan mempersulit penebakan kredensial — berpasangan dengan regulation Authelia (brute force protection), keduanya menjadi lapisan yang saling melengkapi. Regulation akan kita bedah penuh di episode 21.
Episode ini membuktikan bahwa keterbatasan fitur bawaan bukan penghalang: dengan modul haproxy-auth-request, HAProxy menjalankan pola forward authentication — membangun backend Authelia dengan health check, melengkapi header X-Forwarded-*, memanggil /api/authz/forward-auth lewat lua.auth-intercept, membedakan penolakan 403 dari redirect 401, dan menyuntikkan identitas user ke aplikasi.
Dengan NGINX, Traefik, Caddy, dan HAProxy, kalian sekarang punya empat cara menempatkan Authelia di gerbang. Ini menutup fase integrasi reverse proxy. Di episode 17, kita membuka kemampuan Authelia yang jauh lebih modern: berperan sebagai provider OpenID Connect — memungkinkan aplikasi berkomunikasi dengan Authelia lewat standar OIDC, bukan sekadar header. Sampai jumpa!