Running multiple SSL web service containers on the same host using HAProxy

October 10th, 2019

Scenario:

  • Multiple containers running a web service over SSL (with their own certificates)
  • Different web domains for each service
  • Single machine and single public IP
  • How to make both services work on the same machine?

I couldn’t find easy instructions on how to get this done, but a bit of research and trial and error led me to HAProxy. The setup is pretty simple:

  • Setup DNS A records to point to the machine for both domains
  • Start the containers using different ports (for example, 8443 and 8444). Port mapping with docker is really useful here, just use the -p 8443:443 and -p 8444:443 options when launching the containers. Verify the services work on the two ports
  • Install haproxy
  • Set the configuration as follows (yours might need to be tweaked, but it’s a start):
frontend plain-http-in
	bind	*:80
	acl host_a hdr(host) -i a.com
	acl host_b hdr(host) -i b.com
	use_backend a_plain if host_a
	use_backend b_plain if host_b


frontend ssl-http-in
	bind	*:443
	option tcplog
	mode tcp
	tcp-request inspect-delay 5s
	tcp-request content accept if { req_ssl_hello_type 1 }
	acl host_a req_ssl_sni -i a.com
	acl host_b req_ssl_sni -i b.com
	use_backend a_ssl if host_a
	use_backend b_ssl if host_b

backend a_plain
	balance source
	server node1 localhost:8080

backend b_plain
	balance source
	server node1 localhost:8081

backend a_ssl
	balance source
	mode tcp
	option ssl-hello-chk
	server node1 localhost:8443 check

backend b_ssl
	balance source
	mode tcp
	option ssl-hello-chk
	server node1 localhost:8444 check
  • Restart haproxy.
  • Done!

This will also forward connections from port 80 to 8080 and 8081 respectively for a.com and b.com.

It’s worth to note that ancient browsers might have issues with this setup, but for the rest of the world this will do just fine.