MATRIX-01 (Mail-Absender-Frage): per Config verifiziert, dass weder Synapse noch MAS Mail versenden - kein Konfigurationsblock in den deployten Werten. MATRIX-02: Korrektur einer falschen Annahme - "k3s-Host (10.0.0.2)" und "matrix" sind dieselbe Maschine, nicht zwei getrennte. Remote-Write nutzt bereits die private IP. MATRIX-04 neu: Host-Level Pre-Update-Benachrichtigung (Issue #24). Cross-Referenzen in zone-axion1337.md (ZONE-02 entblockt) und cfgmon.md (CFGMON-03-Update, neues CFGMON-08 fuer die Gitea-Runner-Standortfrage) aktualisiert. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
12 KiB
CFGMON
Monitoring-Stack, Gitea und der Reverse Proxy für alles Öffentliche.
| Hostname | CFGMON |
| OS | Ubuntu 24.04.4 LTS |
| IPv4 | 188.245.193.243 |
| IPv6 | 2a01:4f8:c17:93eb::1 |
| Privat | 10.0.0.3 (enp7s0, Hetzner-Netz — dort liegt auch k3s auf 10.0.0.2) |
| DNS | rohana.axion1337.de → Gitea, selendis.axion1337.de → Grafana |
| Stand | 2026-07-30 |
Dienste
| Container | Image | Compose-Projekt | Definition |
|---|---|---|---|
| prometheus | prom/prometheus:v3.3.1 |
monitoring |
sorb/threadnet-operating, monitoring/ |
| loki | grafana/loki:3.7.1 |
monitoring |
dito |
| grafana | grafana/grafana:12.0.0 |
monitoring |
dito |
| alloy | grafana/alloy:v1.16.0 |
monitoring |
dito |
| node-exporter | prom/node-exporter:v1.9.1 |
monitoring |
dito |
| traefik | traefik:v3.7.9 |
thread-net-git |
nicht versioniert, Portainer-Stack in /data/compose/8 |
| gitea | gitea/gitea:latest |
thread-net-git |
dito |
| cadvisor | gcr.io/cadvisor/cadvisor:latest |
thread-net-git |
dito |
| portainer_agent | portainer/agent:2.27.5 |
— | standalone, kein Compose |
Prometheus-Jobs: operating_prometheus, operating_node-exporter,
operating_cadvisor, operating_traefik (alle lokal), k3s_host_node
(10.0.0.2:9100), pterodactyl_host_node und gameserver_cadvisor
(beide 157.90.155.206, siehe game).
CFGMON-01 — Zertifikatserneuerung braucht offene Ports (IPv4 und IPv6)
Status: offen — zeitkritisch ab 2026-09-28
Das Cert für selendis.axion1337.de wurde am 2026-07-30 ausgestellt und läuft am
2026-10-28 ab. Traefik erneuert ca. 30 Tage vorher, also ab Ende September.
Gitea (rohana.axion1337.de) hängt am selben Resolver und ist damit genauso
betroffen — inklusive der Erreichbarkeit dieses Repos per HTTPS.
Traefik nutzt TLS-ALPN-01
(--certificatesresolvers.letsencrypt.acme.tlschallenge=true). Die Challenge läuft
ausschließlich über Port 443, erreichbar aus dem offenen Internet. Bei
gesperrtem Port scheitert sie mit:
urn:ietf:params:acme:error:connection :: Timeout during connect (likely firewall problem)
Traefik liefert dann sein Default-Self-Signed-Cert aus. Das fällt niemandem auf, bis jemand die Seite aufruft — genau so ist es am 2026-07-30 passiert.
Eine IP-Allowlist ist keine Option: Let's Encrypt veröffentlicht seine Validierungs-IPs nicht und prüft seit Einführung der Multi-Perspective Validation aus mehreren Regionen gleichzeitig.
IPv6 war der vermutete Fallstrick — geprüft und in Ordnung. rohana, selendis
(und noch www.*, siehe ZONE-01) haben AAAA-Records
auf 2a01:4f8:c17:93eb::1. Damit validiert LE bevorzugt über IPv6. Die
Hetzner-Cloud-Firewall kennt kein familienübergreifendes „any": das Feld Source IPs
ist eine Liste, 0.0.0.0/0 deckt IPv6 nicht mit ab, ::/0 muss separat drinstehen.
Stand 2026-07-30 enthält die Inbound-Regel für TCP 443 beide Einträge — vom User in der Hetzner-Console nachgesehen. Damit ist der IPv6-Pfad frei.
Diese Angabe stammt nicht aus einer Messung von diesem Host aus, sondern aus der
Console. Vom Host ist es nicht verifizierbar: die Cloud-Firewall liegt außerhalb des
Systems, iptables und ufw sagen nichts darüber (und Root gibt es hier nicht), eine
Verbindung auf die eigene öffentliche Adresse läuft lokal, es gibt keinen zweiten Host
für eine Rückverbindung, und Traefik läuft ohne Access-Log — es existieren also auch
keine historischen Client-IPs. Für eine Prüfung von hier aus wäre ein
Hetzner-API-Token mit Read-Berechtigung nötig.
Auch die erfolgreiche Ausstellung vom 2026-07-30 um 12:00 UTC belegt IPv6 nicht:
zu dem Zeitpunkt existierte für selendis noch kein AAAA-Record, LE hat also über
IPv4 validiert. Die Erneuerung Ende September ist der erste Lauf, der IPv6 überhaupt
versucht.
Damit bleibt als Risiko nur, ob die Ports offen bleiben. Sie wurden am 2026-07-30 für die Ausstellung geöffnet; der Normalzustand dieser Umgebung ist, 80 und 443 aus Sicherheitsvorsicht auf die eigene IP zu beschränken. Werden sie wieder zugezogen, scheitert die Erneuerung Ende September genau wie heute Mittag — und zwar still.
Nächster Schritt: Entscheidung zwischen
- A — Ports offen lassen bzw. zur Erneuerung wieder öffnen. Nichts umzubauen, aber alle ~60 Tage daran zu denken, und ein Fehlschlag fällt erst auf, wenn jemand die Seite aufruft. Wenn A, dann mit einem Kalendereintrag auf Mitte September, nicht auf das Ablaufdatum.
- B — auf DNS-01 umstellen (empfohlen). Validierung über einen TXT-Record,
kein offener Port nötig, läuft bei dichter Firewall durch. Braucht ein
API-Token für die Zone bei IONOS, als Secret für Traefik hinterlegt. Ermöglicht
zusätzlich Wildcard-Certs (
*.axion1337.de), also künftige Subdomains ohne Portöffnung. Setzt voraus, dass der Traefik-Stack anfassbar ist — siehe CFGMON-02.
CFGMON-02 — Traefik, Gitea und cAdvisor sind nicht versioniert
Status: offen
Die drei laufen im Compose-Projekt thread-net-git aus /data/compose/8, einem
von Portainer verwalteten Stack. Es gibt kein Repo dazu. Betroffen ist damit
ausgerechnet die Infrastruktur, an der alles andere hängt:
- Traefik — die einzige Stelle, an der Entrypoints, ACME-Resolver und
Zertifikatsspeicher definiert sind. Die Resolver-Namen aus dieser Datei sind der
Grund, warum ein Label
certresolver=lemonatelang ins Leere zeigte. - Gitea — hostet die Repos, in denen die Infrastruktur beschrieben wird. Das ist ein Bootstrapping-Problem: die Definition von Gitea könnte in Gitea liegen, wäre bei einem Ausfall aber genau dann nicht erreichbar, wenn man sie braucht.
- cAdvisor — wird von Prometheus als
operating_cadvisorgescrapt, ist also eine Abhängigkeit des Monitoring-Stacks, die selbst außerhalb der IaC liegt.
Nächster Schritt: Stack-Definition aus Portainer exportieren
(/data/compose/8/docker-compose.yml plus zugehörige Files), in ein Repo überführen
und dabei die :latest-Tags pinnen — gitea/gitea:latest und
cadvisor:latest machen jeden Pull zu einem unkontrollierten Update. Beim Übertragen
denselben Projektnamen thread-net-git beibehalten, sonst legt Compose neue leere
Volumes an. Für Gitea zusätzlich klären, wo die Definition liegen soll, damit sie
bei einem Gitea-Ausfall erreichbar bleibt.
CFGMON-03 — Prometheus-Remote-Write und Loki sind öffentlich ohne Auth
Status: offen
Prometheus läuft mit --web.enable-remote-write-receiver und Port 9090 ist
veröffentlicht, weil der k3s-Cluster und der Matrix-Server dorthin pushen. Loki ist
auf 3100 ebenfalls veröffentlicht.
Ein offener Remote-Write-Receiver ohne Auth erlaubt Fremden, beliebige Metriken
einzuspeisen — damit lassen sich Dashboards und Alerts unbrauchbar machen — und
über die Query-API alle Daten auszulesen. Bei Loki auf 3100 gilt dasselbe für
Logs, die typischerweise mehr Interna enthalten als Metriken.
In monitoring/docker-compose.yml steht dazu bereits ein Warnhinweis als Kommentar,
umgesetzt ist er nicht.
Nächster Schritt: Beide Ports per Hetzner-Cloud-Firewall auf die Absender
einschränken. Sauberer wäre, sie gar nicht öffentlich zu binden: k3s liegt mit
10.0.0.2 im selben privaten Netz wie CFGMON (10.0.0.3), der Push könnte also
über das private Netz laufen.
Update 2026-07-30: der k3s/Matrix-Host (49.13.132.245, privat 10.0.0.2 — ist
derselbe Host, siehe MATRIX-02)
nutzt für seinen eigenen Remote-Write/Loki-Push bereits die private IP
(http://10.0.0.3:9090/:3100, verifiziert in apps/monitoring/alloy-config.yaml), nicht
188.245.193.243. Der öffentlich erreichbare, unauthentifizierte Port bleibt trotzdem ein
CFGMON-seitiges Risiko (jeder im Internet könnte ihn ansprechen, nicht nur der k3s-Host) -
dieser Teil des Punkts ist also weiterhin offen, nur nicht mehr durch fehlende
Netz-Erreichbarkeit des Matrix-Hosts blockiert.
CFGMON-04 — Grafana-Admin-Credentials aus .env gelten nicht für die HTTP-API
Status: offen, geringe Priorität
GF_SECURITY_ADMIN_USER und GF_SECURITY_ADMIN_PASSWORD greifen nur beim
allerersten Start mit leerem Volume. Der Live-Admin wurde offenbar später in der UI
geändert, die Werte aus der .env sind damit funktionslos. Verifikation von
Datasources und Dashboards läuft deshalb über grafana.db statt über die API.
Kein Defekt, aber eine Falle: die .env sieht aus, als wäre sie die Quelle der
Wahrheit, ist es aber nicht.
Nächster Schritt: entweder das echte Admin-Passwort in die .env nachziehen und
dokumentieren, dass es nur den Ersteinrichtungsfall abdeckt, oder einen
Service-Account mit API-Token für Verifikationszwecke anlegen. Letzteres ist
sauberer, weil dafür kein Admin-Passwort nötig ist.
CFGMON-08 — Kein Gitea-Actions-Runner registriert, Standort noch offen
Status: offen
gitea.rohana.axion1337.de (dieser Host) hostet mehrere Repos mit .gitea/workflows/
(u. a. axion1337.chat-gitops, ThreadNet-Web), aber es läuft kein Runner — Workflows
existieren, greifen aber nie. Tracking der eigentlichen Notwendigkeit (drei Baustellen
hängen daran: Web-/Desktop-Build-CI, Electron-Automatisierung, npm-Publish für
threadnet-call) läuft zentral in
gitops#33 — hier nur
die Standort-Frage, die noch nicht entschieden ist:
- Auf CFGMON (neben Gitea selbst): kürzeste Wege zu Gitea, aber dieser Host hat laut CFGMON-02 ohnehin schon unversionierte Infrastruktur - ein weiterer nicht-deklarativer Baustein wäre ungünstig, außer der Runner wird von Anfang an sauber (IaC) aufgesetzt.
- Auf dem k3s/Matrix-Cluster (siehe matrix): passt zum GitOps-Modell dort
(alles deklarativ), Runner-Pod bräuchte aber Netzzugriff zu Gitea auf CFGMON - existiert
bereits privat (
10.0.0.2↔10.0.0.3). - Secret-Handling für CI-Tokens (z. B. der npm-Publish-Token für
threadnet-call): unabhängig vom Standort über Gitea Actions' eigene Secrets-Funktion (Repo-/Org-Settings), nicht SOPS - siehe Begründung in gitops#33.
Nächster Schritt: Standort entscheiden, dann Runner registrieren, dann #33 und die verlinkten Issues (ThreadNet-Web#2, gitops#44) abarbeiten.
Erledigt
CFGMON-05 — Monitoring-Stack unter IaC bringen · erledigt 2026-07-30
Der Stack lief aus /opt/monitoring ohne Versionierung und mit :latest-Tags. Jetzt
in sorb/threadnet-operating unter monitoring/, Images gepinnt,
Grafana-Datasources und 9 Dashboards provisioniert. Projektname monitoring
beibehalten, dadurch blieben die Volumes erhalten.
CFGMON-06 — Grafana-Certresolver zeigte ins Leere · erledigt 2026-07-30
Das Label sagte certresolver=le, Traefik kennt den Resolver aber als
letsencrypt. Traefik protokollierte Router uses a nonexistent certificate resolver und lieferte für selendis.axion1337.de sein Default-Self-Signed-Cert
aus. Aus dem Altbestand in /opt/monitoring unverändert übernommen und dort
mindestens seit dem 2026-07-27 vorhanden.
Behoben in threadnet-operating, Commit a400f8a. Cert von Let's Encrypt (YR2)
ausgestellt, gültig bis 2026-10-28 — die Nachfolge davon ist
CFGMON-01.
CFGMON-07 — Alloy verlor seine Positions-Datei bei jedem Deploy · erledigt 2026-07-30
--storage.path=/var/lib/alloy/data war gesetzt, aber ohne Volume: die
Positions-Datei lag im Container-Layer. Nach jedem Recreate las Alloy alle
Docker-Logdateien von vorn, worauf Loki alles älter als 7 Tage mit HTTP 400 abwies
(timestamp too old, reject_old_samples). Betroffen waren nur Alt-Logzeilen bis
zurück zu 2025, keine aktuellen Daten.
Behoben durch ein alloy_data-Volume, Commit edac97e. Verifiziert: Positions
überleben --force-recreate, zweiter Recreate erzeugt 0 Fehler.