What are we doing here?
Let's set up HAProxy with some lovely free certs from Let's Encrypt via certbot for a couple of domains. Everything running in docker, and all tied together with docker-compose. We'll use docker user-defined networks, because that's the Right Thing To Do.
This should be easy. Right?
Docker: easy. HAProxy: easy. Let's Encrypt: easy. Docker and HAProxy and Let's Encrypt: minor pain in the arse.
There's a few things that make this a bit of a hassle:
- We want haproxy to be running on port 80/443, but those are the ports certbot needs to do validation
We'll have to do this in two stages. - haproxy with the default config won't start up if it can't resolve the container IPs for the backends.
Since certbot is just a command to be run in a container, it probably won't be running when haproxy starts up.
Some extra config is needed in haproxy. - certbot needs to be run once in one way to request the certs, and then every couple of days/weeks in another way to check and renew certs.
We'll need to different incantations for certbot. - When the certs are renewed, we'll need to tell haproxy to pick them up
Some docker-in-docker magic is required. - certbot doesn't know how to make haproxy-complicit cert pem files
We'll need to do a little scripting.
Stage 1 - get some certs
Since this is a greenfield setup, we can let certbot take care of the initial cert setup itself. HAProxy should be down for this. The Dockerfile for the letsencrypt image looks like:
FROM ubuntu:latest
ENV DEBIAN_FRONTEND=noninteractive
RUN apt-get update && \
apt-get install -y software-properties-common && \
add-apt-repository ppa:certbot/certbot && \
apt-get update && \
apt-get install -y certbot docker.io
COPY deploy-hook /deploy-hook
RUN chmod +x /deploy-hook
Note we're installing the docker.io package, and copying in a script. We'll need them later on. The deploy-hook script looks like:
#!/usr/bin/env bash
cat /etc/letsencrypt/live/wiki.davidstark.name/fullchain.pem \
/etc/letsencrypt/live/wiki.davidstark.name/privkey.pem \
> /etc/letsencrypt/haproxy.pem \
&& docker kill -s HUP haproxy