Skip to content

Instantly share code, notes, and snippets.

@jbouwh
Last active December 11, 2023 15:21
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save jbouwh/3b6042ed4ca1189e1f37d0f8ff7274e5 to your computer and use it in GitHub Desktop.
Save jbouwh/3b6042ed4ca1189e1f37d0f8ff7274e5 to your computer and use it in GitHub Desktop.
Expose Home Assistant using haproxy and letsencrypt using DNS chalenge with TransIP API
#! /usr/bin/bash
sudo docker run -it --rm --name="certbot" \
--mount type=bind,source=/etc/letsencrypt,target="/etc/letsencrypt" \
--mount type=bind,source=/var/log/letsencrypt,target="/opt/certbot-dns-transip/logs" \
--mount type=bind,source=/etc/transip,target="/opt/certbot-dns-transip/config" \
rbongers/certbot-dns-transip certonly --reuse-key \
--manual --preferred-challenges=dns --manual-auth-hook /opt/certbot-dns-transip/auth-hook \
--manual-cleanup-hook /opt/certbot-dns-transip/cleanup-hook \
--cert-name certname.example.com \
-d '*.example.com' \
#! /bin/bash
#
# Syntax `certrenew`
#
# Author: J. Bouwhuis
#
# Version: 3.1
# Date: 31.03.2023
#
# renews certificates using certbot (via docker) and deploys only when a new cert was generated
basecert='certname.example.com'
ha_proxy_cert_path='/etc/haproxy/cert.pem'
logfile=/var/log/$(basename $0).log
curdir=`dirname $0`
basedir='/etc/letsencrypt'
certdir='live'
# create hash of current certs
cert=$basedir/$certdir/$basecert/cert.pem
chain=$basedir/$certdir/$basecert/chain.pem
fullchain=$basedir/$certdir/$basecert/fullchain.pem
privkey=$basedir/$certdir/$basecert/privkey.pem
# Get current certificate state (if exists)
basesum=`cat $basedir/$certdir/$basecert/cert.sha256 2> /dev/null`
# Start cert renewal check using docker
TIME="`date +%F-%H%M%S`"
logger -s -t $(basename $0) "Renewing certificates" 2> /dev/null
echo "$TIME Check for renewal certificate $basecert"
docker pull rbongers/certbot-dns-transip:latest
docker run --rm --name="certbot" \
--mount type=bind,source=/etc/letsencrypt,target="/etc/letsencrypt" \
--mount type=bind,source=/var/log/letsencrypt,target="/opt/certbot-dns-transip/logs" \
--mount type=bind,source=/var/log/letsencrypt,target="/var/log/letsencrypt/" \
--mount type=bind,source=/etc/transip,target="/opt/certbot-dns-transip/config" \
rbongers/certbot-dns-transip:latest renew > $logfile >/dev/null 2>&1
TIME="`date +%F-%H%M%S`"
# Check hash after check
postsum=`sha256sum $cert | awk '{print $1}'` 2> /dev/null
if [ "$basesum" != "$postsum" ]; then
# Update sha256 new hash and log
echo $postsum > $basedir/$certdir/$basecert/cert.sha256
TIME="`date +%F-%H%M%S`"
echo "$TIME Processing renewed certificate $basecert"
certbasepath=$basedir/$certdir/$basecert
logger -s -t $(basename $0) "Processing renewed web certificate $basecert" 2> /dev/null
cat $cert $chain $privkey > $ha_proxy_cert_path
chmod 400 $ha_proxy_cert_path
systemctl restart haproxy
logger -s -t $(basename $0) "Certificate renewed." 2> /dev/null
# Finish
TIME="`date +%F-%H%M%S`"
echo "$TIME Renewal certificate completed successfully"
logger -s -t $(basename $0) "Certificate renewal completed successfully" 2> /dev/null
else
# No renewals
logger -s -t $(basename $0) "Renewal procedure completed, no certificates updated" 2> /dev/null
TIME="`date +%F-%H%M%S`"
echo "$TIME Renewal certificate not needed"
logger -s -t $(basename $0) "No certficate updates needed" 2> /dev/null
fi
exit 0
# /etc/cron.d/certrenew: crontab entries for the certbot certificate renewal
#
# Eventually, this will be an opportunity to validate certificates
# haven't been revoked, etc. Renewal will only occur if expiration
# is within 30 days.
SHELL=/bin/sh
PATH=/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin
0 23 * * * root test -x /usr/local/sbin/certrenew && perl -e 'sleep int(rand(3600))' && /usr/local/sbin/certrenew > /dev/null
<?php
return [
'transip_login' => 'TRANSIP_USERNAME',
'transip_private_key' => '
-----BEGIN PRIVATE KEY-----
PASTE YOUR PRIVATE KEY HERE
-----END PRIVATE KEY-----',
// only allow access from whitelisted IP's. default: true
// 'transip_whitelist_only_token' => true,
'logfile' => 'logs/certbot-transip.log',
'loglevel' => 'info', // options: debug, info, error
];
?>
global
log /dev/log local0
log /dev/log local1 notice
chroot /var/lib/haproxy
stats socket /run/haproxy/admin.sock mode 660 level admin expose-fd listeners
stats timeout 30s
user haproxy
group haproxy
daemon
# Default SSL material locations
ca-base /etc/ssl/certs
crt-base /etc/ssl/private
# See: https://ssl-config.mozilla.org/#server=haproxy&server-version=2.0.3&config=intermediate
ssl-default-bind-ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384
ssl-default-bind-ciphersuites TLS_AES_128_GCM_SHA256:TLS_AES_256_GCM_SHA384:TLS_CHACHA20_POLY1305_SHA256
ssl-default-bind-options ssl-min-ver TLSv1.2 no-tls-tickets
ssl-dh-param-file /etc/haproxy/dhparam.pem
defaults
log global
mode http
option httplog
option dontlognull
timeout connect 5000
timeout client 50000
timeout server 50000
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
frontend homeassistant
http-request set-log-level silent
bind :::80 v4v6
bind :::443 v4v6 ssl crt /etc/haproxy/cert.pem
http-request redirect scheme https unless { ssl_fc }
http-response set-header Strict-Transport-Security "max-age=31536000; includeSubDomains;"
http-request add-header X-Forwarded-Proto https
acl network_allowed_src src 192.168.x.x/24
acl url_stats path_beg /stats
http-request deny if url_stats !network_allowed_src
stats uri /stats
stats admin if network_allowed_src
option forwardfor
acl acl_ha_prod hdr(host) -i ha_fqdn.example.com
use_backend homeassistant_prod if acl_ha_prod
backend homeassistant_prod # Production
no log
server homeassistant 192.168.x.x:8123 check inter 60s
# To test your config:
# haproxy -f /etc/haproxy/haproxy.cfg -c
# make sure you install dhparam.pem
# See https://github.com/internetstandards/Internet.nl/blob/main/docker/it/targetbase/dh_param_infiles/ffdhe3072.txt
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment