brain/03 Bereiche/Heimnetz/Zugriff aus dem Web/Home Assistant über HAProxy.md

250 lines
12 KiB
Markdown
Raw Permalink Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

---
tags:
- upnote-import
---
# Home-Assistent über HAProxy
## FAQs
### Cert abgelaufen trotz erfolgreichem ACME-Renewal
**Symptom:** Browser meldet abgelaufenes Zertifikat (z.B. `https://kbha.straso.com`), obwohl ACME-Plugin Status `200 OK` und Renewal-Datum aktuell zeigt.
**Diagnose von extern:**
```bash
openssl s_client -connect kbha.straso.com:443 -servername kbha.straso.com </dev/null 2>/dev/null \
| openssl x509 -noout -dates -issuer
```
Zeigt altes `notAfter` → HAProxy liefert noch das alte Cert.
**Ursache:** ACME-Plugin hat zwar das neue Cert in `/conf/config.xml` und unter `/var/etc/acme-client/certs/<refid>/` gespeichert, aber HAProxy hat seine SSL-Dateien in `/tmp/haproxy/ssl/` nicht regeneriert. Grund: Im ACME-Cert war `<restartActions/>` leer → kein Reload-Trigger nach Renewal.
**Verifikation per SSH auf OPNsense:**
```bash
# Cert in config.xml prüfen (sollte aktuell sein)
awk '/<cert /{inc=1} inc{print} /<\/cert>/{if(inc){print "==="; inc=0}}' /conf/config.xml \
| awk '/<refid>RRREEEFFFID/{f=1} f{print} /<\/cert>/{if(f){exit}}' \
| sed -n 's|.*<crt>\(.*\)</crt>.*|\1|p' \
| openssl base64 -d -A | openssl x509 -noout -dates -subject
# Cert in HAProxy SSL store prüfen (zeigt alten Stand bei nicht-getriggertem Reload)
openssl x509 -in /tmp/haproxy/ssl/RRREEEFFFID.pem -noout -dates -subject
```
`RRREEEFFFID` = `certRefId` aus dem ACME-Cert-Eintrag (z.B. `68fb9ea001876`).
**Sofortfix:**
```bash
configctl haproxy restart
```
Regeneriert `/tmp/haproxy/ssl/` aus `config.xml`.
**Dauerhafte Lösung — Restart-Action im ACME-Cert verdrahten:**
1. `Services > ACME Client > Settings > Actions` → Add (oder existierende prüfen) → Name `Restart HAProxy`, Type `Configd`, Command `HAProxy: restart`
2. `Services > ACME Client > Certificates > straso.com` editieren → Feld **Automations / Restart Actions**`Restart HAProxy` auswählen → Save
3. Verifikation in `/conf/config.xml`: im `<certificate>`-Block mit `<name>straso.com</name>` muss `<restartActions>` die UUID der Action enthalten (statt `<restartActions/>` leer).
Danach reloaded HAProxy nach jedem Renewal automatisch.
**Status (2026-05-25):** Aktion `Restart HAProxy` (UUID `92528912-3c23-4ede-8b75-72c50bb106c0`) ist sowohl `*.kbu.home64.de`- als auch `straso.com`-Cert zugewiesen. Nächstes Renewal in ~60 Tagen sollte automatisch greifen.
### NPM auf dem Pi — DNS-Challenge statt HTTP
**Kontext:** Auf dem HA-Pi läuft parallel ein Nginx Proxy Manager (Add-on `a0d7b954_nginxproxymanager`). Der wird zwar im aktuellen Setup nicht extern angesprochen (Port 443 endet auf der OPNsense-HAProxy), aber er hält ein eigenes Let's-Encrypt-Cert für `kbha.straso.com`. Wenn dort die HTTP-01-Challenge konfiguriert ist, scheitert das Renewal in ~60 Tagen, weil Port 80 nicht zum Pi durchgereicht wird.
**Lösung:** Cert in NPM neu anlegen mit **DNS-Challenge IONOS**:
- DNS Provider: `IONOS`
- API Token: aus IONOS Developer Portal
- Propagation Seconds: `60`
**Renewal-Config-Pfad im Add-on:**
```
/addon_configs/a0d7b954_nginxproxymanager/letsencrypt/renewal/npm-<N>.conf
```
Inhalt muss enthalten:
```ini
authenticator = dns-ionos
dns_ionos_propagation_seconds = 60
dns_ionos_credentials = /etc/letsencrypt/credentials/credentials-<N>
```
**SSH-Zugang zum Pi:** Frenck's "Advanced SSH & Web Terminal" Add-on, Public Key in den Add-on-Settings hinterlegen, dann `ssh -p 22222 root@<pi-ip>`.
**Aufräumen:** Alte HTTP-Challenge-Certs (z.B. Cert #7) in NPM löschen, sobald das DNS-Cert (Cert #8) aktiv ist und alle Proxy Hosts darauf zeigen.
**Lessons learned:**
- HAProxy-SSL-Files liegen in `/tmp/` (flüchtig) und werden aus `config.xml` regeneriert
- `configctl haproxy restart` ist destruktiv-frei und lädt nur Config + SSL neu
- NPM auf Pi parallel zu HAProxy bringt nichts, wenn Port 443 per NAT/HAProxy-Bind abgefangen wird — Reverse-Proxy-Stack einheitlich halten
- Externes Cert prüfen mit `openssl s_client` zeigt sofort, ob Browser-Cache oder Server-Side-Problem
### Seite zeigt Fehler Invalid method encountered
```
haproxy Invalid method encountered: b'' ^
```
Grund war, dass die bind-option „accept-proxy“ und ein Proxy-Protocol zugewiesen waren. Der HA ist aber dafür gemacht, hinter einem Proxy zu lafen. In dem Fall muss beides entfernt werden.
### Google AI Analyse
The error "Received something which does not look like a PROXY protocol header" in [OPNsense](https://www.google.com/search?q=OPNsense&newwindow=1&sca_esv=69afb27cda6b1637&sxsrf=AE3TifNGCTUN_X9hUalFtKqVKJ9xTQtN-A%3A1760112723749&ei=UzDpaKqwLciE9u8PyY3QkQw&ved=2ahUKEwit9YfiiJqQAxVIh_0HHSUIPdwQgK4QegQIARAB&uact=5&oq=opnsense+Received+something+which+does+not+look+like+a+PROXY+protocol+header&gs_lp=Egxnd3Mtd2l6LXNlcnAiTG9wbnNlbnNlIFJlY2VpdmVkIHNvbWV0aGluZyB3aGljaCBkb2VzIG5vdCBsb29rIGxpa2UgYSBQUk9YWSBwcm90b2NvbCBoZWFkZXJIjhhQAFibF3AAeAGQAQCYAaMBoAHuCKoBAzEuOLgBA8gBAPgBAZgCAaACfMICBhAAGAcYHpgDAJIHAzAuMaAHuRCyBwMwLjG4B3zCBwMwLjHIBwE&sclient=gws-wiz-serp&mstk=AUtExfAj2bFRYreBlPXhaXdkbD_Z26rDtwz-nmb-hYGj9CEoaSACui3YP6f78Egef9J1ucLy4x6mmPTa9XrDpoWrbG_x4QMgYSScPEz9sacNQ2cpPBrwu8bFdNeXaCPPcLPescVBkp0wuzOtU-YbupXon2r51dCLNa10FiWSss8dcFjvxOU&csui=3), likely when using HAProxy, means that a client connected to the proxy but sent data that doesn't conform to the PROXY protocol format. To fix this, you should check your HAProxy configuration to ensure the `accept-proxy` argument is present on the `bind` line of your frontend, or if you are sending the header, verify that the backend is configured correctly to receive it. 
**Understanding the Error**
- **What is PROXY Protocol?** It's a standard text-based or binary-based protocol that proxies use to pass connection information (like the client's IP address) to the next proxy or the backend server.
- **What it Means:** The error indicates that OPNsense's HAProxy expected to see a PROXY protocol header from the client, but the client sent something else (likely just regular HTTP or another protocol) instead. 
**How to Fix It**
1. **Check Your HAProxy Frontend Configuration:**
- Navigate to `Services` > `HAProxy` > `Settings`.
- Edit the frontend section that is receiving the connection.
- Ensure that the `accept-proxy` argument is added to the `bind` line for that frontend. This allows HAProxy to recognize both version 1 (text) and version 2 (binary) PROXY protocol headers.
2. **Verify Backend Configuration:**
- If your setup involves multiple HAProxy instances or a different type of backend server, check the configuration on that backend as well.
- If the backend is not expecting the PROXY protocol, it might not understand the data it's receiving, leading to errors.
3. **Consider the Client's Request:**
- Is the client _supposed_ to be sending a PROXY protocol header? If the client is just a regular HTTP client, it won't send this header, and the `accept-proxy` directive is what's needed on the HAProxy frontend to _receive_ it.
- If your client application _is_ designed to send the PROXY protocol, then the error means its implementation is sending the header in an unexpected format. 
**Example HAProxy Configuration Snippet (for reference):**
```
frontend my_frontend
bind *:80 accept-proxy # This is the key line
# Other frontend settings
```
- `bind *:80` : This tells HAProxy to listen on port 80.
- `accept-proxy`: This tells HAProxy to accept and process the PROXY protocol from the client. 
#### Lösung: 
attribut „accept-proxy“ wieder entfernt und Proxy Protocol auf „none“ geändert.
Im Frontend:
![](..\..\files\91ded0d3-2662-4758-944d-6aafc9c9ab3a.png)<br>
Im Backend:
![](..\..\files\b2f34d78-d178-48c5-80d6-7a3e2ea3b89b.png)<br>
## <br>
## weitere Einstellungen:
### DNS-Override
![](..\..\files\e595984e-53d9-4b9e-9be2-8ba4cde1cf34.png)<br>
## <br>
### FW-Regel
![](..\..\files\4134c53e-af3e-4bd0-a251-ec507f0aee2f.png)<br>
## Files
running config file:
```
#
# Automatically generated configuration.
# Do not edit this file manually.
#
global
uid 80
gid 80
chroot /var/haproxy
daemon
stats socket /var/run/haproxy.socket group proxy mode 775 level admin
nbthread 1
hard-stop-after 60s
no strict-limits
httpclient.resolvers.prefer ipv4
tune.ssl.default-dh-param 4096
spread-checks 2
tune.bufsize 16384
tune.lua.maxmem 0
log /var/run/log local0 info
lua-prepend-path /tmp/haproxy/lua/?.lua
defaults
log global
option redispatch -1
maxconn 100
timeout client 30s
timeout connect 30s
timeout server 30s
retries 3
default-server init-addr last,libc
default-server maxconn 100
# autogenerated entries for ACLs
# autogenerated entries for config in backends/frontends
# autogenerated entries for stats
# Frontend (DISABLED): 0_SNI_frontend (Listening on 0.0.0.0:80, 0.0.0.0:443)
# Frontend (DISABLED): 1_HTTP_frontend (Listening on 127.4.4.3:80)
# Frontend (DISABLED): 1_HTTPS_frontend (Listening on 127.4.4.3:443)
# Frontend: kbha_frontend ()
frontend kbha_frontend
http-response set-header Strict-Transport-Security "max-age=63072000; includeSubDomains; preload"
bind 0.0.0.0:443 name 0.0.0.0:443 ssl curves secp384r1 no-sslv3 no-tlsv10 no-tlsv11 no-tls-tickets ciphers ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:DHE-RSA-AES256-GCM-SHA384 ciphersuites TLS_AES_256_GCM_SHA384:TLS_CHACHA20_POLY1305_SHA256 alpn h2,http/1.1 crt-list /tmp/haproxy/ssl/68e90ee37e8f60.01330497.certlist
bind 0.0.0.0:80 name 0.0.0.0:80 ssl curves secp384r1 no-sslv3 no-tlsv10 no-tlsv11 no-tls-tickets ciphers ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:DHE-RSA-AES256-GCM-SHA384 ciphersuites TLS_AES_256_GCM_SHA384:TLS_CHACHA20_POLY1305_SHA256 alpn h2,http/1.1 crt-list /tmp/haproxy/ssl/68e90ee37e8f60.01330497.certlist
bind 192.168.178.106:443 name 192.168.178.106:443 ssl curves secp384r1 no-sslv3 no-tlsv10 no-tlsv11 no-tls-tickets ciphers ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:DHE-RSA-AES256-GCM-SHA384 ciphersuites TLS_AES_256_GCM_SHA384:TLS_CHACHA20_POLY1305_SHA256 alpn h2,http/1.1 crt-list /tmp/haproxy/ssl/68e90ee37e8f60.01330497.certlist
bind 192.168.178.106:80 name 192.168.178.106:80 ssl curves secp384r1 no-sslv3 no-tlsv10 no-tlsv11 no-tls-tickets ciphers ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:DHE-RSA-AES256-GCM-SHA384 ciphersuites TLS_AES_256_GCM_SHA384:TLS_CHACHA20_POLY1305_SHA256 alpn h2,http/1.1 crt-list /tmp/haproxy/ssl/68e90ee37e8f60.01330497.certlist
mode http
option http-keep-alive
default_backend kbha_backend
option forwardfor
# logging options
# ACL: kbha
acl acl_68e90f4b9c2340.62230672 hdr(host) -i kbha.straso.com
# ACTION: kbha
use_backend kbha_backend if acl_68e90f4b9c2340.62230672
# Backend (DISABLED): portainer_backend ()
# Backend: kbha_backend (Backend for HomeAssistant)
backend kbha_backend
# health checking is DISABLED
mode http
balance source
# stickiness
stick-table type ip size 50k expire 30m
stick on src
http-reuse safe
server kbha_server 192.168.178.4:8123
# statistics are DISABLED
```
## <br>
## <br>
## <br>
## Links
### gutes Tutorial:
[Setup OPNsense with HAProxy and Let's Encrypt | Marcus Holtz](https://blog.holtzweb.com/posts/opnsense-with-haproxy-and-lets-encrypt/)
passend zum Thread im Forum [Tutorial 2024/06: HAProxy + Let's Encrypt Wildcard Certificates + 100% A+ Rating](https://forum.opnsense.org/index.php?topic=23339.0)
### noch ein Tutorial, DE mit Zusatztipps
[HAProxy auf OPNsense - Schritt für Schritt - blog.admin-intelligence.de](https://blog.admin-intelligence.de/haproxy-auf-opnsense-schritt-fuer-schritt/)