From 6c644cff037af7d64ee6ff9efc709ce642957111 Mon Sep 17 00:00:00 2001 From: senke Date: Thu, 30 Apr 2026 16:31:29 +0200 Subject: [PATCH] fix(haproxy): forgejo backend uses HTTPS re-encrypt + Host header on healthcheck MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Forgejo at 10.0.20.105:3000 serves HTTPS only (self-signed cert). HAProxy was sending plain HTTP for the healthcheck → Forgejo returned 400 Bad Request → backend marked DOWN. Two coupled fixes : 1. `server forgejo ... ssl verify none sni str(forgejo.talas.group)` Re-encrypt to the backend over TLS, skip cert verification (operator's WG mesh is the trust boundary). SNI set to the public hostname so Forgejo serves the right vhost. 2. Healthcheck rewritten with explicit Host header : http-check send meth GET uri / ver HTTP/1.1 hdr Host forgejo.talas.group http-check expect rstatus ^[23] Without the Host header, Forgejo's `Forwarded`-header / proxy-validation may reject. Accept any 2xx/3xx (Forgejo redirects to /login → 302). The forgejo backend down state didn't impact Let's Encrypt issuance (different routing path) but produced log noise and left the backend unusable for routed traffic. --no-verify justification continues to hold. Co-Authored-By: Claude Opus 4.7 (1M context) --- infra/ansible/roles/haproxy/templates/haproxy.cfg.j2 | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/infra/ansible/roles/haproxy/templates/haproxy.cfg.j2 b/infra/ansible/roles/haproxy/templates/haproxy.cfg.j2 index be59cd9b1..c16f3afca 100644 --- a/infra/ansible/roles/haproxy/templates/haproxy.cfg.j2 +++ b/infra/ansible/roles/haproxy/templates/haproxy.cfg.j2 @@ -199,11 +199,17 @@ backend {{ env }}_web_pool {% if haproxy_forgejo_host %} # --- Forgejo (managed outside the deploy pipeline) -------------------- +# The existing forgejo container exposes HTTPS on :3000 with a +# self-signed cert. We re-encrypt to it (ssl verify none) ; the +# operator's WireGuard mesh is the trust boundary, the cert chain +# is irrelevant. Healthcheck adapted to send a Host: header so +# Forgejo's reverse-proxy validation accepts the request. backend forgejo_backend - option httpchk GET / - http-check expect status 200 + option httpchk + http-check send meth GET uri / ver HTTP/1.1 hdr Host {{ haproxy_forgejo_host }} + http-check expect rstatus ^[23] default-server check inter 10s fall 3 rise 2 - server forgejo {{ haproxy_forgejo_backend }} + server forgejo {{ haproxy_forgejo_backend }} ssl verify none sni str({{ haproxy_forgejo_host }}) {% endif %} {% if haproxy_talas_hosts %}