From 4887cf458ea4f60af19ef3ec33b8cc3173a3c6ec Mon Sep 17 00:00:00 2001 From: Joao Gilberto Magalhaes Date: Fri, 23 Oct 2026 09:29:01 -0400 Subject: [PATCH] fix: haproxy letsencrypt integration and upgrade EasyHAProxy to 6.5.1 The letsencrypt integration set EASYHAPROXY_LETSENCRYPT_EMAIL (with a stray quote) and a letsencrypt label, which EasyHAProxy has not read since before 4.6.0. With an email set, http redirected to https and nothing answered on 443. - Pass EASYHAPROXY_CERTBOT_EMAIL and EASYHAPROXY_CERTBOT_SERVER. - Label the app with certbot=true on its http definition: EasyHAProxy requests the certificate and serves https itself, so the separate 443 definition goes. https labels are only added when a letsencrypt email is set, as documented. - Keep the certificates in /var/lib/dokku/data/haproxy. - Turn the stats page off with HAPROXY_STATS_ENABLE=false. - Upgrade EasyHAProxy from 6.1.1 to 6.5.1. --- docs/networking/proxies/haproxy.md | 2 ++ plugins/haproxy-vhosts/Dockerfile | 2 +- .../haproxy-vhosts/docker-args-process-deploy | 19 ++++--------------- plugins/haproxy-vhosts/internal-functions | 3 ++- .../templates/compose.yml.sigil | 7 ++++--- tests/unit/haproxy.bats | 6 ++++++ 6 files changed, 19 insertions(+), 20 deletions(-) diff --git a/docs/networking/proxies/haproxy.md b/docs/networking/proxies/haproxy.md index 4f393ca18..b6534897b 100644 --- a/docs/networking/proxies/haproxy.md +++ b/docs/networking/proxies/haproxy.md @@ -185,6 +185,8 @@ dokku haproxy:set --global letsencrypt-email automated@dokku.sh After enabling, the Haproxy container will need to be restarted and apps will need to be rebuilt. All http requests will then be redirected to https. +Certificates are requested over http-01 on port 80, so each domain must resolve to the server. They are kept in `/var/lib/dokku/data/haproxy` and renewed automatically. + #### Customizing the letsencrypt server The letsencrypt integration is set to the production letsencrypt server by default. To change this, set the `letsencrypt-server` property with the `--global` flag: diff --git a/plugins/haproxy-vhosts/Dockerfile b/plugins/haproxy-vhosts/Dockerfile index 6063196ae..8496c6512 100644 --- a/plugins/haproxy-vhosts/Dockerfile +++ b/plugins/haproxy-vhosts/Dockerfile @@ -1 +1 @@ -FROM byjg/easy-haproxy:6.1.1 +FROM byjg/easy-haproxy:6.5.1 diff --git a/plugins/haproxy-vhosts/docker-args-process-deploy b/plugins/haproxy-vhosts/docker-args-process-deploy index 0c19f32c4..559027dd8 100755 --- a/plugins/haproxy-vhosts/docker-args-process-deploy +++ b/plugins/haproxy-vhosts/docker-args-process-deploy @@ -103,22 +103,11 @@ trigger-haproxy-vhosts-docker-args-process-deploy() { fi fi - if [[ -n "$proxy_container_https_port" ]] || [[ -n "$proxy_container_https_port_candidate" ]]; then - if [[ -z "$proxy_container_https_port" ]]; then - dokku_log_warn "Warning: https:443 port mapping not found" - dokku_log_warn "Utilizing first https port mapping, http:$proxy_host_https_port_candidate:$proxy_container_https_port_candidate" - proxy_container_https_port="$proxy_container_https_port_candidate" - fi - + # EasyHAProxy serves https itself: it requests the certificate (certbot), terminates + # TLS on 443 and forwards to the same container port as http + if [[ -n "$letsencrypt_email" ]] && { [[ -n "$proxy_container_https_port" ]] || [[ -n "$proxy_container_https_port_candidate" ]]; }; then output="$output --label haproxy.$APP-$PROC_TYPE.redirect_ssl=true" - output="$output --label haproxy.$APP-$PROC_TYPE-https.localport=$proxy_container_https_port" - output="$output --label haproxy.$APP-$PROC_TYPE-https.letsencrypt=true" - output="$output --label haproxy.$APP-$PROC_TYPE-https.mode=http" - output="$output --label haproxy.$APP-$PROC_TYPE-https.port=443" - - if [[ -n "$haproxy_domains" ]]; then - output="$output --label haproxy.$APP-$PROC_TYPE-https.host=$haproxy_domains" - fi + output="$output --label haproxy.$APP-$PROC_TYPE.certbot=true" else output="$output --label haproxy.$APP-$PROC_TYPE.redirect_ssl=false" fi diff --git a/plugins/haproxy-vhosts/internal-functions b/plugins/haproxy-vhosts/internal-functions index 3ee7d43a5..9f34d8975 100755 --- a/plugins/haproxy-vhosts/internal-functions +++ b/plugins/haproxy-vhosts/internal-functions @@ -39,7 +39,8 @@ fn-haproxy-template-compose-file() { HAPROXY_LOG_LEVEL="$(fn-haproxy-computed-log-level)" HAPROXY_LETSENCRYPT_EMAIL="$(fn-haproxy-computed-letsencrypt-email)" HAPROXY_LETSENCRYPT_SERVER="$(fn-haproxy-computed-letsencrypt-server)" - HAPROXY_REFRESH_CONF="$(fn-haproxy-computed-refresh-conf)") + HAPROXY_REFRESH_CONF="$(fn-haproxy-computed-refresh-conf)" + HAPROXY_DATA_DIR="${DOKKU_LIB_ROOT}/data/haproxy") sigil -f "$COMPOSE_TEMPLATE" "${SIGIL_PARAMS[@]}" | cat -s >"$OUTPUT_PATH" } diff --git a/plugins/haproxy-vhosts/templates/compose.yml.sigil b/plugins/haproxy-vhosts/templates/compose.yml.sigil index 49146677c..74e0dba00 100644 --- a/plugins/haproxy-vhosts/templates/compose.yml.sigil +++ b/plugins/haproxy-vhosts/templates/compose.yml.sigil @@ -11,10 +11,10 @@ services: - CERTBOT_LOG_LEVEL={{ $.HAPROXY_LOG_LEVEL }} - HAPROXY_LOG_LEVEL={{ $.HAPROXY_LOG_LEVEL }} {{ if $.HAPROXY_LETSENCRYPT_EMAIL }} - - EASYHAPROXY_LETSENCRYPT_EMAIL={{ $.HAPROXY_LETSENCRYPT_EMAIL }}" - - EASYHAPROXY_LETSENCRYPT_SERVER={{ $.HAPROXY_LETSENCRYPT_SERVER }} + - EASYHAPROXY_CERTBOT_EMAIL={{ $.HAPROXY_LETSENCRYPT_EMAIL }} + - EASYHAPROXY_CERTBOT_SERVER={{ $.HAPROXY_LETSENCRYPT_SERVER }} {{ end }} - - HAPROXY_STATS_PORT=false + - HAPROXY_STATS_ENABLE=false network_mode: bridge @@ -28,3 +28,4 @@ services: volumes: - "/var/run/docker.sock:/var/run/docker.sock:ro" + - "{{ $.HAPROXY_DATA_DIR }}:/etc/easyhaproxy/certs/certbot" diff --git a/tests/unit/haproxy.bats b/tests/unit/haproxy.bats index 6edc97db8..e8135f4d4 100644 --- a/tests/unit/haproxy.bats +++ b/tests/unit/haproxy.bats @@ -246,6 +246,12 @@ teardown() { assert_success assert_output "true" + run /bin/bash -c "docker inspect $TEST_APP.web.1 --format '{{ index .Config.Labels \"haproxy.$TEST_APP-web.certbot\" }}'" + echo "output: $output" + echo "status: $status" + assert_success + assert_output "true" + run /bin/bash -c "dokku ports:report $TEST_APP --ports-map" echo "output: $output" echo "status: $status"