fix(haproxy): forgejo backend uses HTTPS re-encrypt + Host header on healthcheck

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) <noreply@anthropic.com>
This commit is contained in:
senke 2026-04-30 16:31:29 +02:00
parent 0bd3e563b2
commit 6c644cff03

View file

@ -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 %}