Home Assistant schön(er) gemacht

Bei mir läuft Home Assistant in einem Docker-Container auf einem Raspberry Pi 4, schon sehr lange. Anfangs als native Installation, da wurde dann aber die Updaterei bald nervig, deshalb Docker, da geht das Updaten (und Downgraden) deutlich schmerzfreier — mittlerweile kümmert sich watchtower darum, das geht alles vollautomatisch, sehr schick.
Dann kam irgendwann der Wunsch auf, die Installation auch aus dem Internet zugänglich zu machen. Der nächstliegende Gedanke war, auf dem Router einfach ein Portforwarding zu schalten: Router:TCP/443 -> Pi:TCP/443. Das hat aber mindestens zwei Probleme:

  • DNS-Name. Ich habe zwar die Domain sokoll.com, aber die IP des Routers ändert sich zwar selten, aber eben doch ab und an. Dann müßte das DNS nachgezogen werden. Unter der Voraussetzung, daß man den Wechsel der IP überhaupt bemerkt hat.
  • TLS-Zertifikat für den Webserver. Natürlich will ich nichts selbstsigniertes, Let’s Encrypt soll es schon sein. Dann geht aber die HTTP challenge nicht. DNS challenge ginge, mache ich ohnehin, aber dann müßte ich wild mit cronjobs hampeln und das Zertifikat von meinem Netcup-Server holen.

Alles nicht so fein. Also mußte eine andere Lösung her: der DNS-Name zeigt auf meinen Server bei Netcup, dort läuft ein Apache als reverse proxy:

<VirtualHost 185.207.105.125:443 [2a03:4000:1e:181::1]:443>
Protocols h2 http/1.1
ServerName hass.sokoll.com
ServerAlias home.sokoll.com
ServerAdmin webmaster@sokoll.com
ErrorLog ${APACHE_LOG_DIR}/hass.sokoll.com-error.log
CustomLog ${APACHE_LOG_DIR}/hass.sokoll.com-access.log combined
SSLCertificateFile /etc/dehydrated/certs/wildcard_sokoll.com/fullchain.pem
SSLCertificateKeyFile /etc/dehydrated/certs/wildcard_sokoll.com/privkey.pem
ProxyRequests off
ProxyPreserveHost On
ProxyPass /api/websocket wss://91.66.45.77/api/websocket
ProxyPassReverse /api/websocket wss://91.66.45.77/api/websocket
ProxyPass / https://91.66.45.77/
ProxyPassReverse / https://91.66.45.77/
SSLProxyEngine on
SSLProxyCheckPeerCN off
SSLProxyCheckPeerExpire off
SSLProxyCheckPeerName off
</VirtualHost>

(die IP ist schon lange nicht mehr gültig)
Das heißt: Der Request kommt bei Netcup an, und der Apache dort schubst ihn dann weiter zu meinem Router, dort gibt es ein Portforwarding auf den Pi. Nicht sonderlich elegant, funktioniert aber.

Nun änderte sich kürzlich die IP wieder, und ich mußte die Webserver-Konfiguration ändern, hatte mich vertippt, ging nicht, Fehler suchen und finden und beheben, bis zum nächsten IP-Wechsel, das ist doch alles Mist.
Auf dem Server läuft ein #Wireguard, das versorgt ein Telefon und einen Laptop mit #Pihole, das könnte doch auch den Pi bedienen? Wenn dann der Pi den Tunnel aufbaut, hätte ich immer dieselben IPs und könnte mir das ganze Gehampel mit Portforwarding auf dem Router sparen.
Wireguard ist simpel. Auf dem Server:
```
~$ ssh -l root big wg
interface: wg0
public key: RzZAu5Js3c8/5yQBPlhKg2b0jkOlxHT6vLreiC1BCgo=
private key: (hidden)
listening port: 51820

peer: yS2cSLvEovdsLLT8ne/lixoiU87o821TgBkzrVHRFS4=
endpoint: 91.66.61.253:35710
allowed ips: 192.168.3.6/32
latest handshake: 1 minute, 21 seconds ago
transfer: 16.10 MiB received, 1.83 MiB sent

peer: RF22N9Kb6AO0N+jqZvSIdPxtZj3CxgasdgwuW6ktGys=
endpoint: 91.66.61.253:58623
allowed ips: 192.168.3.5/32
latest handshake: 1 minute, 45 seconds ago
transfer: 50.42 MiB received, 715.71 MiB sent

peer: OAbhrovugDdR8he1UIzy67Szh798C4lxWelSwrd3Z3o=
endpoint: 91.66.61.253:1024
allowed ips: 192.168.3.4/32
latest handshake: 1 minute, 49 seconds ago
transfer: 19.73 MiB received, 77.50 MiB sent
~$

Auf dem Pi:

~$ ssh -l root r4 wg
interface: wg0
public key: yS2cSLvEovdsLLT8ne/lixoiU87o821TgBkzrVHRFS4=
private key: (hidden)
listening port: 35710

peer: RzZAu5Js3c8/5yQBPlhKg2b0jkOlxHT6vLreiC1BCgo=
endpoint: 185.207.105.125:51820
allowed ips: 192.168.3.1/32
latest handshake: 15 seconds ago
transfer: 1.03 MiB received, 8.97 MiB sent
persistent keepalive: every 25 seconds
~$
``
In der Apache-Konfiguration oben noch die VPN-Adresse des Pi eintragen und Apache reloaden.
Fertsch. Funktioniert traumhaft.
Gut. Ein Problem hatte ich: Der Tunnel wird von innen aufgebaut, solange da keine Pakete laufen, ist der Tunnel unten, und das ganze schöne Konstrukt funktioniert nicht. Man könnte einen Dauer-ping im Hintergrund laufen lassen, aber das wäre nun wirklich uncool. Und dann entdeckte ich eben
persistent keepalive`, was das Problem elegant löst.

Wireguard rockt da house!