TLS / Zertifikat¶
Fünf Wege — der zweite ist für die meisten der richtige.
| Weg | Wann |
|---|---|
| 1 — Selbstsigniert | Standard nach der Installation, für Tests |
| 2 — Zertifikat aus Vesana | Let's Encrypt oder Firmen-CA, Vesana erneuert selbst |
| 3 — Eigenes Zertifikat hochladen | gekauftes Zertifikat, Firmen-CA ohne ACME |
| 4 — Von Hand (certbot o. ä.) | bestehende Abläufe auf dem Host |
| 5 — Reverse-Proxy davor | TLS endet schon vor Vesana |
Weg 1 — Selbstsigniert (Standard)¶
Ohne eigenes Zertifikat erzeugt der nginx-Container beim ersten Start ein selbstsigniertes Paar (10 Jahre, CN = Host aus BASE_URL) im Volume ssl. HTTPS funktioniert damit sofort, der Browser warnt aber, und Agents verbinden sich nur mit einem Zertifikats-Pin (den der Installationsbefehl mitbringt).
Weg 2 — Zertifikat direkt aus Vesana¶
Admin → System → Zertifikat. Vesana holt das Zertifikat selbst per ACME (das Protokoll von Let's Encrypt), setzt es ein und erneuert es rechtzeitig — ohne certbot, ohne Cronjob, ohne Handarbeit auf dem Host. Die Compose-Datei bleibt, wie sie ist.
1. Namen¶
Alle Namen, unter denen Vesana erreichbar ist: Browser-Adresse, die Server-URL der Agents, beim Split-Container-Modus der Admin-Host. Wildcards (*.firma.it) gehen nur mit der DNS-Prüfung; ein Wildcard deckt genau eine Ebene (a.firma.it), nicht firma.it selbst und nicht a.b.firma.it.
2. Prüfung und CA¶
| Prüfung | Voraussetzung |
|---|---|
| DNS-Anbieter (empfohlen) | Vesana legt kurz einen TXT-Eintrag _acme-challenge.<name> über die API Ihres DNS-Anbieters an. Kein Port von außen nötig, Wildcards möglich. |
| HTTP über Port 80 | Der Name muss aus dem Internet auf Port 80 bis zu diesem Server reichen. Vesana leitet dann nur /.well-known/acme-challenge/ an sich selbst weiter, alles andere bleibt die Umleitung auf HTTPS. Hat der Name einen AAAA-Eintrag, prüft Let's Encrypt zuerst über IPv6. |
CA: Let's Encrypt, Let's Encrypt (Test) (Staging — Zertifikate, denen niemand vertraut; zum Ausprobieren) oder eine eigene ACME-CA (z. B. step-ca, Smallstep, Sectigo/HARICA mit EAB). Bei einer eigenen CA tragen Sie die Verzeichnis-Adresse ein, bei Bedarf EAB-Kennung und -Schlüssel und — wenn die CA selbst ein Firmen-Zertifikat nutzt — deren Wurzel.
3. DNS-Anbieter¶
Vesana kennt alle DNS-Anbieter von lego (über 200, darunter OVH, Cloudflare, IONOS, Hetzner, Route 53, Azure DNS, Google Cloud DNS, Gandi, INWX, Netcup, Infomaniak, deSEC, PowerDNS, RFC2136 und acme-dns). Die Felder je Anbieter erscheinen von selbst; „Anleitung für …" führt zur Seite des Anbieters mit den Rechten, die das Konto braucht.
Beispiel OVH: OVH kennt drei Anmeldearten — Application-Key + Secret + Consumer-Key, OAuth2 (Client-ID + Secret) oder ein Access-Token, jeweils mit OVH_ENDPOINT (z. B. ovh-eu). Es reicht EINE davon. Für den Consumer-Key genügen die Rechte POST und DELETE auf /domain/zone/*.
Zugang prüfen legt einen Test-Eintrag an, wartet, bis er sichtbar ist, und entfernt ihn wieder — ohne die CA zu fragen. So sehen Sie sofort, ob Zugangsdaten und Rechte stimmen.
Zugangsdaten liegen verschlüsselt in der Datenbank (AES-256-GCM) und kommen in keiner Antwort, keinem Protokoll und keinem Support-Bundle im Klartext vor. Geben Sie dem Konto nur Rechte auf die eine Zone.
Windows-DNS / DNS ohne API¶
Zwei Wege:
- CNAME-Delegation: In Ihrer Zone einmalig je Name einen CNAME anlegen, der auf eine Zone mit API zeigt, und dort den Anbieter wählen: Vesana folgt dem CNAME und schreibt den TXT-Eintrag in die delegierte Zone.
- RFC2136 (Anbieter „RFC2136"/dnsupdate): dynamisches Update direkt an den DNS-Server — mit TSIG-Schlüssel oder, für Active Directory, mit Kerberos (GSS-TSIG:
DNSUPDATE_TSIG_GSS_REALM,…_USERNAME,…_PASSWORD).
Firmennetz ohne Weg nach außen¶
Ob der Prüf-Eintrag angekommen ist, fragt Vesana bei den autoritativen Nameservern der Zone nach — dort sieht auch die CA nach. Die Antworten der Resolver im eigenen Netz stehen nur zur Information daneben: ein Resolver, der zu früh gefragt wurde, merkt sich „gibt es nicht“ für die Negativ-Zwischenspeicherzeit der Zone (oft 10–60 Minuten).
Blockt das Netz DNS-Anfragen nach außen (Port 53), unter „Resolver und Propagation" eigene Resolver eintragen und „Nur über die Resolver prüfen" wählen — oder „Nur warten" mit einer festen Wartezeit. Erreicht der Server die CA gar nicht, nennt die Fehlermeldung das; dann bleiben eine eigene CA im Firmennetz oder Weg 3.
4. Ausstellen und einsetzen¶
- Nutzungsbedingungen der CA anzeigen und bestätigen (einmal je CA).
- Probelauf: stellt bei Let's Encrypt ein Test-Zertifikat in Staging aus (zählt nicht gegen die Grenzen) und setzt nichts ein.
- Ausstellen: das Zertifikat liegt danach „bereit". Lief kurz vorher ein Probelauf (oder eine andere Ausstellung) für dieselben Namen, wartet Vesana zuerst die Lebensdauer (TTL) des Prüf-Eintrags ab — meist 2 bis 5 Minuten, angezeigt mit Uhrzeit: die Resolver der CA merken sich den alten Eintrag so lange, und eine Prüfung davor würde abgelehnt.
- Vorprüfung: Vesana nennt jedes Gerät (Agent, Collector), dessen Server-URL das neue Zertifikat nicht abdeckt — z. B. weil es Vesana über eine IP-Adresse erreicht. Solche Geräte vorher über Admin → Agents & Collectors → Agent-Verbindung auf einen gedeckten Namen umziehen. Mit Befund geht Einsetzen nur mit ausdrücklicher Bestätigung.
- Einsetzen: der Updater prüft das Paar noch einmal, schreibt es atomar, testet die nginx-Konfiguration, lädt alle nginx-Rollen neu (Weboberfläche, Agent-Gateway, Admin-Port) und prüft per TLS-Verbindung, dass das neue Zertifikat ausgeliefert wird. Scheitert ein Schritt, ist sofort die vorige Fassung wieder da.
- Kontrollphase (30 Minuten): Vesana beobachtet, ob Agents/Collectors, die vorher Kontakt hatten, weiter melden, und nennt jedes, das schweigt.
Erneuern¶
Vesana erneuert von selbst: im Erneuerungsfenster, das die CA nennt (ARI), sonst wenn noch ein Drittel der Laufzeit übrig ist (90 Tage ⇒ nach 60 Tagen). Scheitert eine Erneuerung, versucht Vesana es nach 1 h, 6 h und dann täglich wieder — nie in enger Schleife. Der Grund steht auf der Seite, in der Instanz-Gesundheit und im Diagnose-Log (Kategorie „Zertifikat"); dauert es länger als 48 Stunden, warnt der Check „TLS Certificate" am Host „Vesana Server" über die normalen Alarm-Regeln — Wochen vor dem Ablauf.
Rückweg, Ausschalten¶
- Rückweg setzt die vorige Fassung wieder ein — gibt es keine, das Zertifikat, das vor dem ersten Einsetzen ausgeliefert wurde (meist das selbstsignierte).
- ⚠️ HSTS: Vesana sendet
Strict-Transport-Security. Sobald Browser Vesana einmal mit einem gültigen Zertifikat gesehen haben, blockieren sie den Namen bis zu einem Jahr, wenn wieder ein selbstsigniertes kommt — ohne „trotzdem fortfahren". Der Rückweg auf ein selbstsigniertes Zertifikat verlangt deshalb eine ausdrückliche Bestätigung. - ACME ausschalten behält das aktive Zertifikat bis zum Ablauf (mit Ablaufwarnung), erneuert aber nicht mehr.
Agents und Collectors¶
Ein öffentlich vertrautes Zertifikat (Let's Encrypt), das den Namen der Server-URL deckt, akzeptieren Agents und Collectors ohne Pin — auch solche, die bisher mit Pin auf das selbstsignierte verbunden waren. Ein ACME-Zertifikat pinnt Vesana nie (es wechselt bei jeder Erneuerung). Stammt das Zertifikat von einer Firmen-CA, muss deren Wurzel auf den Geräten im Vertrauensspeicher liegen. Der lokale Aktive Collector verbindet sich über localhost und ist nicht betroffen.
Backup und Umzug¶
Zertifikat, Schlüssel, ACME-Konto und Zugangsdaten liegen in der Datenbank. Nach einem Restore auf einer frischen Maschine setzt Vesana das Zertifikat innerhalb von 15 Minuten von selbst wieder ein.
Weg 3 — Eigenes Zertifikat hochladen¶
Admin → System → Zertifikat → Eigenes Zertifikat hochladen. Kette (Server-Zertifikat zuerst, dann die Zwischenzertifikate) und unverschlüsselten Schlüssel als PEM einfügen oder als Datei wählen. Vesana prüft, ob der Schlüssel passt, die Kette zusammenhängt und das Zertifikat gilt; eingesetzt wird über dieselbe Vorprüfung wie bei Weg 2. Die Ablaufwarnung gilt genauso.
Weg 4 — Von Hand (certbot o. ä.)¶
Der Stack-nginx liest genau EIN Paar aus dem Volume ssl: /etc/nginx/ssl/fullchain.pem + privkey.pem. Es gilt für alle Hostnamen, die dieser nginx bedient — bei aktivem Split-Container-Modus also auch für den Admin-Namen.
cd /opt/vesana # dein Vesana-Verzeichnis
docker compose -f docker-compose.prod.yml cp /etc/letsencrypt/live/vesana.example.com/fullchain.pem nginx:/etc/nginx/ssl/fullchain.pem
docker compose -f docker-compose.prod.yml cp /etc/letsencrypt/live/vesana.example.com/privkey.pem nginx:/etc/nginx/ssl/privkey.pem
docker compose -f docker-compose.prod.yml exec nginx nginx -s reload
Läuft das Agent-Gateway oder ein eigener Admin-Container, lesen diese dasselbe Paar — dort ebenfalls neu laden (… exec agent-gateway nginx -s reload bzw. … exec nginx-admin nginx -s reload).
Vesana erkennt ein so eingespieltes Zertifikat („von Hand eingespielt"), überschreibt es nie still und überwacht seinen Ablauf (Check „TLS Certificate").
Weg 5 — Reverse-Proxy davor¶
Wenn schon ein nginx / Traefik / HAProxy / Caddy vor dem Server steht und TLS dort terminiert wird.
Der Vesana-Stack spricht selbst immer HTTPS (mindestens mit dem selbstsignierten Zertifikat); sein HTTP-Port leitet nur auf HTTPS um. Der Reverse-Proxy reicht deshalb per HTTPS an den HTTPS-Port des Stacks weiter. Belegt der Proxy 80/443, bekommt Vesana in der .env andere Ports:
(Nicht 8443 — das ist der Standard-Port des Agent-Gateways.) Danach den Stack neu anlegen.
Im externen Reverse-Proxy (nginx-Beispiel):
server {
listen 443 ssl http2;
server_name vesana.example.com;
ssl_certificate /etc/letsencrypt/live/vesana.example.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/vesana.example.com/privkey.pem;
location / {
proxy_pass https://127.0.0.1:9443;
proxy_ssl_verify off; # Stack-Zertifikat ist selbstsigniert; Verbindung bleibt auf 127.0.0.1
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
# Antwort-Header der Anmeldung sind größer als der nginx-Standardpuffer
# (4 KB). Ohne diese Zeilen: „upstream sent too big header" → 502 beim Login.
proxy_buffer_size 32k;
proxy_buffers 8 32k;
proxy_busy_buffers_size 64k;
proxy_request_buffering off;
proxy_read_timeout 1800s;
client_max_body_size 20g; # Backup-Upload und Offline-Update
}
}
Danach drei Punkte:
- Echte Client-Adressen: Die Adresse bzw. das Netz des Proxys unter Admin → Anmeldung & Sicherheit → Admin-Zugriff → Erweitert als vertrauenswürdigen Proxy eintragen. Sonst sehen Sitzungsliste, Audit-Log und Admin-Allowlist alle Nutzer mit der Adresse des Proxys. Eine Umgebungsvariable dafür gibt es nicht.
- Agent-Gateway nicht entschlüsseln: Ist das Agent-Gateway aktiv, den Gateway-Port als reinen TCP-Stream durchleiten oder direkt erreichbar lassen — Agents und Collectors prüfen dort das Zertifikat des Stacks.
- Agents hinter dem Proxy: Der Installationsbefehl prüft, was unter der Agent-Server-URL wirklich antwortet: ein öffentlich vertrautes Zertifikat des Proxys braucht keinen Pin, ein anderes bekommt seinen eigenen.
Ein Zertifikat aus Vesana (Weg 2) per HTTP-Prüfung funktioniert hinter einem Proxy nur, wenn dieser /.well-known/acme-challenge/ an den HTTP-Port des Stacks weiterreicht; einfacher ist die DNS-Prüfung — oder das Zertifikat bleibt Sache des Proxys.
CSP¶
Der eingebaute nginx sendet eine strenge Content-Security-Policy und setzt sie durch: Skripte, Stile, Bilder, Verbindungen und Schriften sind nur von der Instanz selbst erlaubt (dazu die Kartenkacheln von OpenStreetMap und OpenFreeMap sowie Google Fonts). Das frame-ancestors 'none' der Richtlinie und X-Frame-Options: SAMEORIGIN verhindern das Einbetten von Vesana in fremde Seiten; nur ein Freigabe-Link eines Dashboards darf für die dort eingetragenen Ursprünge eingebettet werden. Die Browser melden Verstöße an die Instanz; sie erscheinen im Diagnose-Log (Kategorie „Sicherheit“). Ein Reverse-Proxy davor darf die Header nicht entfernen und sollte keine eigenen Skripte in die Seite einfügen, sie würden blockiert.
Header-Hygiene¶
Der eingebaute nginx setzt:
Strict-Transport-Security: max-age=31536000; includeSubDomainsX-Content-Type-Options: nosniffX-Frame-Options: SAMEORIGINX-XSS-Protection: 1; mode=blockReferrer-Policy: strict-origin-when-cross-originPermissions-Policy: geolocation=(), microphone=(), camera=()Content-Security-Policy: …
Hinter einem eigenen Reverse-Proxy kommen diese Header vom Stack bereits mit; der Proxy muss sie nur durchlassen.
TLS-Test¶
Externe Werkzeuge:
- SSL Labs Test für Cert-Chain und Cipher-Suite-Bewertung
testssl.shfür lokale Validierung