Keycloak + HAProxy

I would have though this to be a common deployment but I had quite a significant challenge in getting this setup to run

 

Here is my working config for Keycloak behind a reverse proxy

Traffic flow

Client keycloak.hawkless.id.au—>HTTPS—>HAProxy—>HTTPS—>Keycloak Container

 

haproxy.cfg

global
maxconn 4000
tune.ssl.default-dh-param 2048

listen stats
bind 0.0.0.0:9010
mode http
stats enable
stats uri /stats
stats realm HAProxy Statistics
stats auth statsadmin:passwd


frontend http
bind *:80
mode http

acl letsencrypt-acl path_beg -i /.well-known/acme-challenge/
http-request redirect scheme https if !letsencrypt-acl
use_backend letsencrypt if letsencrypt-acl

timeout client 1h


backend letsencrypt
mode http
server letsencrypt 127.0.0.1:8888
timeout connect 1h
timeout server 1h

backend kc
mode http
server cps01 127.0.0.1:8443 check ssl verify none
timeout connect 1h
timeout server 1h


frontend https
bind *:443 ssl crt /certs/dev-server4.pem
mode http
use_backend kc if { ssl_fc_sni -i kc.hawkless.id.au }
default_backend kc
timeout client 1h



 

PROXY_ADDRESS_FORWARDING = true seems to conflict with using “http-request add-header X-Forwarded-Proto: https” in HAProxy which is required for some services(OpenStack Horizon)
So use PROXY_ADDRESS_FORWARDING = false and have HAProxy pass the traffic to the SSL port on the Keycloak container instead of the HTTPS port

Docker commands for Keycloak and HAProxy

docker run -d -p 8080:8080 -p 8443:8443  -e DB_VENDOR=MYSQL -e DB_ADDR=192.168.2.1 -e DB_DATABASE=keycloak -e DB_USER=keycloak -e DB_PASSWORD=dbpass -e KEYCLOAK_USER=admin -e KEYCLOAK_PASSWORD=kcpass -e PROXY_ADDRESS_FORWARDING=false --name keycloak jboss/keycloak
docker run -d -p 9010:9010 -p 80:80 -p 443:443 --net host --name haproxy -v /home/ubuntu/proxy/config:/usr/local/etc/haproxy:ro -v /home/ubuntu/proxy/certs:/certs:ro haproxy haproxy -f /usr/local/etc/haproxy/haproxy.cfg