Letsencrypt & haproxy - no down time
Post date: Jan 11, 2016 2:59:12 PM
So letsencrypt requires port 80 and 443 access in order to generate or renew certs. This can be an issue if your server already uses port 80, 443, if you need a cert for a appliance can can't run letsencrypt on that device, or you just can't afford the down time. All the above is a BS attempt at stopping non-admins from generating certs (this is a BS as you can still "get" letsencrypt to give you a cert using the webroot feature and a non-root user, but that's a topic for another time).
My solution is simple, let a "proxy" look at the inbound url and forward *all* letsencrypt connections to the letsencrypt standalone service. This way matter what sub(s) or domain(s) needed or used one copy of letsencrypt can answer ALL the requests. This means you only ever need 1 copy of letsencrypt for all the servers BEHIND the load balancer and you never need to take down or in anyway modify your existing server or website.
What you need to for all this
letsencrypt
apache (if on the same machine) configured to only listen on any ip other than the one web traffic is being sent to from the wan (internet). In my example (127.0.0.1)
letsencrypt set to listen on 8080 (or any other none 80 (**IF** it's on the same server/ip as haproxy).
If letsencrypt ever decide to make it so you can't change the listening/bind port just setup a virtual nic and have it only bind to that ip.
Heres my haproxy config
Haproxy config
global
log /dev/log local0
log /dev/log local1 notice
chroot /var/lib/haproxy
stats socket /run/haproxy/admin.sock mode 660 level admin
stats timeout 30s
user haproxy
group haproxy
daemon
# Default SSL material locations
ca-base /etc/ssl/certs
crt-base /etc/ssl/private
# Default ciphers to use on SSL-enabled listening sockets.
# For more information, see ciphers(1SSL). This list is from:
# https://hynek.me/articles/hardening-your-web-servers-ssl-ciphers/
ssl-default-bind-ciphers ECDH+AESGCM:DH+AESGCM:ECDH+AES256:DH+AES256:ECDH+AES128:DH+AES:ECDH+3DES:DH+3DES:RSA+AESGCM:RSA+AES:RSA+3DES:!aNULL:!MD5:!DSS
ssl-default-bind-options no-sslv3
defaults
log global
mode tcp
option tcplog
#mode http
#option httplog
option dontlognull
timeout connect 500
timeout client 100
timeout server 500
errorfile 400 /etc/haproxy/errors/400.http
errorfile 403 /etc/haproxy/errors/403.http
errorfile 408 /etc/haproxy/errors/408.http
errorfile 500 /etc/haproxy/errors/500.http
errorfile 502 /etc/haproxy/errors/502.http
errorfile 503 /etc/haproxy/errors/503.http
errorfile 504 /etc/haproxy/errors/504.http
listen stats
bind 0.0.0.0:9000 #Listen on all IP's on port 9000
mode http
balance
timeout client 5000
timeout connect 4000
timeout server 30000
#This is the virtual URL to access the stats page
stats uri /haproxy_stats
#Authentication realm. This can be set to anything. Escape space characters with a backslash.
stats realm HAProxy\ Statistics
#The user/pass you want to use. Change this password!
stats auth ******:*****
#This allows you to take down and bring up back end servers.
#This will produce an error on older versions of HAProxy.
stats admin if TRUE
#Application Setup
frontend ContentSwitching
bind 10.1.97.2:80
bind 10.1.97.2:443 ssl crt /etc/haproxy/ssl/
mode http
option httplog
acl letsencrypt_remote_host path_beg /.well-known/acme-challenge/
use_backend letsencrypt_nodes if letsencrypt_remote_host
default_backend linux_www_node
backend letsencrypt_nodes
mode http
server letsencrypt 127.0.0.1:8080
backend linux_www_node
mode http
compression algo gzip
compression type text/html text/plain text/css text/js
balance roundrobin
stick-table type ip size 200k expire 30m
stick on src
server node1 127.0.0.1:80 check
And now and example of the letsencrypt cli
letsencrypt cli
/usr/bin/letsencrypt --agree-tos --renew-by-default --standalone --standalone-supported-challenges http-01 --http-01-port 8080 certonly -d sub1.nomadcf.com -d sub2.nomadcf.com -d sub3.nomadcf.com