Kapitel 02 beginnt mit einem Server, auf dem Apache, Docker und certbot schon laufen. Dieses Kapitel schließt die Lücke davor: der komplette Weg von der Entscheidung "wir bestellen einen Server" bis zu genau diesem Zustand. Es gehört chronologisch VOR Kapitel 02, steht aber als 08 am Ende der Reihe, weil es nachträglich ergänzt wurde und die Kapitelnummern stabile Referenzen sind.
Ein ehrlicher Hinweis vorweg: Die Referenz-Installation von WJ Konstanz-Hegau (Server "hafen") läuft auf Ubuntu 24.04 LTS und wurde historisch von Hand aufgebaut. Dieses Kapitel beschreibt den Standard für NEUE Server, und der heißt Ubuntu 26.04 LTS. Die Schrittfolge ist auf 26.04 recherchiert und im Script scripts/01-provision-server.sh ausführbar hinterlegt; die Faktengrundlage mit Quellen-URLs und Verifikations-Stand liegt in meta/recherche-ubuntu-2604.md (Stand 2026-08-14). Wo eine Aussage dort nur als Richtwert geführt ist, sagen wir das auch hier dazu.
Der rote Faden des ganzen Kapitels ist Lockout-Vermeidung: Jeder Schritt, der einen Zugang schließen kann (SSH-Härtung, Firewall), wird erst ausgeführt, nachdem der neue Zugang nachweislich funktioniert. Das ist keine Erfindung von uns, sondern der gemeinsame Kern der Initial-Server-Setup-Guides von DigitalOcean und Hetzner (Quellen im Recherche-Dossier, Abschnitt 3).
1. Vorarbeit: Alles Entscheidbare passiert VOR dem Server
Drei Entscheidungen und eine Datei könnt ihr komplett ohne Server treffen. Wer sie vorzieht, provisioniert später in einem Rutsch durch, statt zwischen Bestellformular, DNS-Panel und Terminal zu springen.
1.1 Domain und Subdomain-Plan
Ihr braucht Zugriff auf die DNS-Verwaltung EINER Zone. Das ist die einzige harte Voraussetzung. Zwei Fälle:
- Der Kreis verfügt über seine Domain (Provider-Login vorhanden, Records selbst setzbar): Nehmt die Bestandsdomain als
BASIS_DOMAIN. - Die Bestandsdomain ist unbeweglich (liegt beim Verband, beim alten Vorstand, bei einer Agentur): Registriert eine günstige, kurze Zweitdomain im eigenen Hetzner-Account des Kreises. Das ist das Referenz-Muster: Konstanz-Hegau betreibt die Infra-Dienste unter
wjknh.de(Records perhcloudscriptbar), während die lange Vereinsdomainwj-konstanz-hegau.debeim ursprünglichen Provider bleibt. Ihr müsst die alte Domain nicht umziehen; es reicht, in einer Zone selbst schalten zu können.
Der Subdomain-Plan des Standards, parametrisiert auf BASIS_DOMAIN:
| Subdomain | Dienst | Pflicht |
|---|---|---|
cloud.<BASIS_DOMAIN> | Nextcloud | ja |
office.<BASIS_DOMAIN> | Collabora | ja |
flow.<BASIS_DOMAIN> | n8n | nur bei FLOW_ENABLED="ja" (Kapitel 04/05) |
analytics.<BASIS_DOMAIN> | Umami | optional |
pm.<BASIS_DOMAIN> | OpenProject | optional |
Die Labels cloud, office, flow sind die Defaults der kreis.conf und unsere Empfehlung: selbsterklärend für Mitglieder, die eine Adresse eintippen. Die Referenz nennt ihre Nextcloud "hafen", der Name ist frei; wer keinen eigenen Servernamen pflegen will, fährt mit cloud am klarsten. Wichtig ist nur eines (Lehre aus der Hochrhein-Demo): Wählt ab Tag 1 die Domain, die ihr dauerhaft behaltet. Mit finaler Domain ist ein späterer Serverwechsel nur Daten-Sync plus DNS-Flip; mit Übergangs-Domain baut ihr euch einen Umzug ein.
Talk-TURN/STUN braucht keine eigene Subdomain, es läuft über den Cloud-Hostnamen (Kapitel 03).
1.2 DNS-Records setzen
Pro Dienst genau ein A-Record auf die Server-IP, optional ein AAAA-Record auf die IPv6-Adresse. TTL: der Standardwert eures Providers reicht. Mehr ist es nicht; kein Wildcard-Zertifikat, keine CNAME-Ketten. Die Referenz holt bewusst ein Einzel-Zertifikat je Subdomain per HTTP-01-Challenge (certbot --apache -d <name>): Das funktioniert provider-unabhängig, während ein Wildcard die DNS-01-Challenge und damit API-Zugriff auf die Zone bräuchte. Für eine Handvoll Subdomains lohnt das nicht.
Die Server-IP kennt ihr erst nach der Bestellung (Abschnitt 2). Praktikable Reihenfolge: Server bestellen, IP notieren, Records setzen, und während das DNS propagiert die restliche Vorarbeit erledigen. Vor dem ersten certbot-Lauf (in Kapitel 02) muss mindestens der Record der Nextcloud-Domain propagiert sein, sonst scheitert die Zertifikats-Ausstellung; ein erneuter Lauf nach dem DNS-Fix reicht dann.
1.3 Mail-Versand entscheiden: Relay, nie eigener Mailserver
Die Nextcloud braucht einen SMTP-Ausgang für System-Mails (Einladungen, Passwort-Reset, Benachrichtigungen, Formulare). Was sie NICHT braucht und was der Standard ausdrücklich ausschließt: einen eigenen Mailserver auf dem Kreis-Server. Hetzner Cloud sperrt die Mail-Ports 25 und 465 ausgehend standardmäßig (Freigabe per Limit-Antrag frühestens nach dem ersten bezahlten Monat; Port 587 bleibt offen. Quelle: Hetzner-Cloud-FAQ, docs.hetzner.com/cloud/servers/faq/, Abruf 2026-08-14), und Reputations-Pflege, Blacklists, DKIM/DMARC und Spam-Abwehr stehen in keinem Verhältnis zum Nutzen. Der Server versendet ausschließlich als SMTP-Client über ein fremdes Relay. So macht es auch die Referenz: Absender hafen@wj-konstanz-hegau.de, versendet über den VereinOnline-Mailserver per SMTPS (Port 465, implizites TLS).
Praktische Folge der Port-Sperre für einen frisch angelegten Hetzner-Account: Ein Relay über Port 465 funktioniert erst nach der Freigabe. Bis dahin nutzt ihr 587/tls (in der conf: SMTP_PORT="587", SMTP_SECURE="tls") oder stellt den Limit-Antrag und testet den Versand danach.
Eure Optionen, in Reihenfolge der Empfehlung (Details und SPF-Lage: meta/inventar-dns-mail.md):
- VO-Mailserver als Relay (Referenz-Muster): Wenn euer Kreis VereinOnline mit eigener Domain nutzt, existiert dort schon ein Mailkonto-System samt passendem SPF-Record. Ein Postfach bzw. SMTP-Zugang anlegen (z. B.
cloud@<vereinsdomain>), fertig. Kein DNS-Eingriff nötig. - Bestehendes Kreis-Postfach beim Mail-Provider: Jeder Kreis hat irgendwo Mail (Verbands-Hosting, IONOS, Hetzner-Webhosting, Google/Microsoft). Ein dediziertes Postfach für die Cloud anlegen und dessen SMTP-Zugang nutzen. Bei Google/Microsoft auf App-Passwort- bzw. SMTP-Auth-Politik achten. Für die VO-freie Variante ist das der Default.
- Transaktions-Relay (SMTP2GO, Brevo o. ä.): nur wenn 1 und 2 nicht gehen. Kostenlose Kontingente reichen für System-Mails eines Kreises, aber ihr holt euch SPF- und meist DKIM-Pflege in der Absenderdomain und einen weiteren Vertragspartner ins Haus (AVV prüfen).
SPF-Hinweis für alle Optionen: Die Absenderdomain muss den tatsächlich versendenden Server per SPF autorisieren, sonst landen System-Mails im Spam oder werden abgewiesen. Bei Option 1 und 2 ist das in der Regel schon der Fall, weil der Provider im bestehenden SPF-Record der Domain steht; bei Option 3 muss der Relay-Anbieter per include: ergänzt werden. Faustregel: Wählt die Absenderadresse so, dass sie als echtes Postfach oder Alias existiert, dann funktionieren auch Bounces und Antworten.
Das Ergebnis dieser Entscheidung sind vier Werte für die kreis.conf (SMTP_HOST, SMTP_PORT, SMTP_SECURE, SMTP_USER) plus die Absenderadresse SMTP_FROM. Das SMTP-Passwort gehört NIE in die conf: In der conf steht nur der Key-Name (SMTP_PASSWORD_KEY), der Wert liegt in eurer Secret-Ablage und wird beim Setup ohne Ausgabe übernommen (Kapitel 06, Secrets-Register).
1.4 kreis.conf ausfüllen: alle Variablen am Anfang, genau einmal
Der ganze Standard liest seine kreisspezifischen Werte aus einer einzigen Datei, der kreis.conf. Jede Variable wird genau einmal gesetzt, am Anfang, und danach von allen Scripts nur noch gelesen. Es gibt keinen zweiten Ort, an dem ihr eure Domain oder euer Kürzel eintragt.
Der bequemste Weg ist der Konfigurator: Öffnet konfigurator.html lokal im Browser, füllt das Formular aus und ladet die erzeugte kreis.conf herunter. Das Formular läuft komplett im Browser, es werden keine Daten übertragen, und es fragt bewusst keine Passwörter und keine Tokens ab; die erzeugte Datei enthält entsprechend keine. Abgeleitete Werte (volle Domains, Instanz-Slug) zeigt es live an, Pflichtfelder sind markiert, alles andere hat einen übernehmbaren Default. Wer lieber im Editor arbeitet: Kopiert die Datei scripts/kreis.conf.example zu kreis.conf (im Explorer oder Finder duplizieren und umbenennen reicht, ein Terminal braucht es dafür nicht) und die Kommentare in der Datei führen euch durch; das Schema mit allen Validierungsregeln steht in meta/variablen-schema.md.
Was ihr an dieser Stelle schon beantworten könnt, weil es reine Vorarbeit ist: Block 1 (Kreisname, Kürzel, Servername), Block 2 (Domains, aus 1.1), Block 4 (initiale Admin-Konten und Gruppen-Leads, rollenbasiert und mit euren echten Usernamen, nie mit Werten des Referenz-Kreises), Block 5 (Mail, aus 1.3) und Block 6 (Betrieb). Offen bleibt nur SERVER_IP aus Block 3, die tragt ihr nach der Bestellung nach.
Auf dem Server gilt dann: chmod 600 kreis.conf. Jedes Script bricht mit klarer Fehlermeldung ab, wenn Pflichtvariablen fehlen oder noch Platzhalter in <Spitzen-Klammern> enthalten sind.
2. Ubuntu 26.04 LTS installieren
Der Standard für neue Server ist Ubuntu 26.04 LTS "Resolute Raccoon", veröffentlicht am 2026-04-23, mit 5 Jahren Standard-Support (Security- und Bugfix-Updates). Quellen: Release-Ankündigung und Release Notes, verlinkt in meta/recherche-ubuntu-2604.md Abschnitt 1. Noch einmal zur Einordnung: Die Referenz-Installation läuft auf 24.04 und bleibt dort, bis ein Upgrade ansteht; für einen NEUEN Server gibt es keinen Grund, mit der älteren LTS zu starten.
Bestellung bei Hetzner Cloud (Referenz-Kontext; jeder andere Anbieter mit Ubuntu-Cloud-Images funktioniert genauso):
- Eigenes Hetzner-Cloud-Projekt im Account des Kreises (Server-Ownership-Entscheidung aus Kapitel 02, Abschnitt 1: eigener Account, nicht Co-Tenant eines anderen Kreises).
- SSH-Key VOR der Server-Erstellung im Projekt hinterlegen und bei der Bestellung auswählen. Das Cloud-Image legt den Key dann bei root ab, und ihr loggt euch von der ersten Sekunde an per Key ein; ein Root-Passwort per Mail entfällt. Für neue Schlüssel ist Ed25519 die Empfehlung (Richtwert, verbreiteter Konsens):
ssh-keygen -t ed25519 -C "<KREIS_KUERZEL>-admin".Windows-Hinweis: Der Befehl gilt wortgleich auch unter Windows. Windows 10 und 11 bringen den OpenSSH-Client mit,
ssh-keygen,sshundscplaufen direkt in der PowerShell. Nur die Pfade sehen anders aus: Der Schlüssel landet unterC:\Users\<name>\.ssh\id_ed25519.pubstatt~/.ssh/; den öffentlichen Schlüssel für die Hetzner-Console zeigt ihr mittype $env:USERPROFILE\.ssh\id_ed25519.puban. Wer PuTTY nutzt: Mit PuTTYgen erzeugte Schlüssel vor dem Hinterlegen ins OpenSSH-Format exportieren (Conversions-Menü), sonst lehnt der Server sie ab. Alle späteren Befehle dieses Kapitels laufen ohnehin AUF dem Server (per SSH-Sitzung) und sind damit betriebssystem-unabhängig; „zweites Terminal" heißt unter Windows einfach: zweites PowerShell-Fenster. - Als Image Ubuntu 26.04 wählen. Prüft im Image-Angebot der Cloud Console, dass 26.04 dort bereits als Standard-Image gelistet ist; das Recherche-Dossier hat diesen Punkt nicht verifiziert (offener Punkt 4 im Dossier). Falls (noch) nicht verfügbar: 24.04 LTS ist der belegte Fallback, auf dem die gesamte Referenz läuft; die Schrittfolge dieses Kapitels ist auf beiden identisch.
- Größe: Für Nextcloud + Talk-HPB + Collabora reicht die Klasse der Referenz-Maschine (Erfahrungswerte in Kapitel 02, Abschnitt 1: ca. 5 bis 10 Euro pro Monat, eine Instanz komfortabel).
Ein interaktiver Installer kommt bei Cloud-Servern nicht vor: Hetzner provisioniert ein fertiges Image, die Netzwerkkonfiguration liefert Cloud-Init aus (Netplan-YAML unter /etc/netplan/; Richtwert, auf der Referenz beobachtet). Die 26.04-Installer-Neuerungen wie TPM-gestützte Full-Disk-Encryption betreffen euch deshalb nicht.
Was sich gegenüber 24.04 serverseitig ändert (Quelle: Release-Notes-Summary für LTS-Umsteiger, Verifikations-Stand je Zeile im Dossier, Abschnitt 2):
| Komponente | 24.04 | 26.04 | Praktische Folge |
|---|---|---|---|
| Kernel | 6.8 | 7.0 | keine für dieses Setup |
| OpenSSH | 9.6 | 10.2 | DSA entfernt (keine DSA-Hostkeys mehr); neuer Post-Quantum-Schlüsselaustausch mlkem768x25519-sha256; neue Option PerSourcePenalties (Straf-Drosselung nach Fehl-Logins; ob per Default aktiv, prüft ihr mit sshd -T | grep persourcepenalties) |
| Netplan | 1.0 | 1.2 | eigene wait-online-Logik; für dieses Setup keine Handgriffe |
| PHP | 8.2/8.3 | 8.5 | irrelevant, Nextcloud läuft im Container mit eigenem PHP |
Zwei Dauerläufer, die schon auf 24.04 galten und die ihr kennen solltet: unattended-upgrades ist auf Ubuntu Server per Default installiert und aktiv (täglich, automatisch nur Security-Updates; Konfiguration in /etc/apt/apt.conf.d/20auto-upgrades und 50unattended-upgrades). Und sshd startet seit Ubuntu 22.10 per systemd-Socket-Aktivierung: ssh.socket lauscht, ssh.service startet bei Verbindung. Praktische Folge: Nach einer Port-Änderung reicht ein Restart von ssh.service nicht, ihr müsst ssh.socket neu starten (für 26.04 als Fortbestand Richtwert; auf dem Zielsystem mit systemctl status ssh.socket prüfbar). Der Standard ändert den SSH-Port nicht, deshalb bleibt das für euch ein Hintergrund-Fakt.
Erster Login und Server-IP nachtragen:
ssh root@<SERVER_IP>
Jetzt SERVER_IP in der kreis.conf ergänzen und die DNS-Records aus 1.2 setzen, falls noch nicht geschehen.
3. Grundhärtung: Admin-User, SSH-Key-only, ufw
Ab hier gibt es zwei gleichwertige Wege: bash 01-provision-server.sh erledigt alles Folgende (und Abschnitt 4) in einem idempotenten Lauf, die manuellen Befehle darunter zeigen, was dabei passiert. Beide führen zum selben Zustand; der Automatik-Weg steht gesammelt in Abschnitt 5. Wer den Standard zum ersten Mal aufsetzt, sollte die manuelle Fassung einmal gelesen haben, um im Fehlerfall zu wissen, wo er steht.
System aktualisieren:
apt update && apt upgrade -y
Non-Root-Admin-User anlegen (tägliche Administration nie als root; der Username ist euer SSH_USER aus der conf):
adduser --disabled-password --gecos "" <SSH_USER>
usermod -aG sudo <SSH_USER>
--disabled-password heißt: kein Passwort-Login, der User kommt nur per SSH-Key hinein. Den Key übernehmt ihr von root (das Hetzner-Image hat ihn dort abgelegt):
mkdir -p /home/<SSH_USER>/.ssh
cp /root/.ssh/authorized_keys /home/<SSH_USER>/.ssh/authorized_keys
chown -R <SSH_USER>:<SSH_USER> /home/<SSH_USER>/.ssh
chmod 700 /home/<SSH_USER>/.ssh
chmod 600 /home/<SSH_USER>/.ssh/authorized_keys
Neuen Login testen, BEVOR irgendetwas geschlossen wird. In einem ZWEITEN Terminal, die Root-Session bleibt offen:
ssh <SSH_USER>@<SERVER_IP>
sudo -v
Erst wenn beides klappt, geht es weiter. Das ist der wichtigste Einzelschritt des Kapitels.
SSH härten (Key-only, kein Root-Login). Als Drop-in, nicht durch Editieren der Hauptdatei; das übersteht Paket-Updates konfliktfrei (Richtwert):
cat > /etc/ssh/sshd_config.d/60-wjd-haerten.conf <<'EOF'
PasswordAuthentication no
PermitRootLogin no
EOF
sshd -t
systemctl restart ssh
Im Script liegt genau dieser Schritt bewusst hinter dem Flag --ssh-haerten und verweigert sich, wenn der Admin-User keine authorized_keys hat. Der Default PermitRootLogin prohibit-password (Root nur per Key) ist als 26.04-Default nicht gegengeprüft (Richtwert); mit dem Drop-in ist Root-Login ohnehin komplett aus und die Frage erledigt.
Firewall ufw. Die Reihenfolge ist die halbe Sicherheit: SSH ZUERST erlauben, dann aktivieren, sonst sperrt euch das enable aus:
ufw allow OpenSSH
ufw enable
ufw allow 80/tcp
ufw allow 443/tcp
ufw status
Mehr Ports braucht die Grundprovisionierung nicht. Talk-TURN/STUN (3478 tcp/udp) kommt erst in Kapitel 03 dazu.
Die eine Docker-Falle, die ihr jetzt schon kennen müsst: Docker publiziert Container-Ports per iptables AN ufw VORBEI. Ein ports: "8080:80" in einer Compose-Datei ist öffentlich erreichbar, egal was ufw status behauptet. Deshalb binden alle Compose-Dateien des Standards ihre Ports ausschließlich an localhost (127.0.0.1:8085:80), und der einzige öffentliche Zugang ist der Apache-Reverse-Proxy. Das ist als dokumentiertes Docker-Verhalten im Dossier als Richtwert geführt (Gegencheck-Quelle dort verlinkt); die Gegenmaßnahme lokal-binden-plus-Proxy ist unabhängig davon richtig und der gebaute Zustand der Referenz.
unattended-upgrades prüfen (ist per Default aktiv, ihr verifiziert nur):
dpkg -s unattended-upgrades | grep Status
cat /etc/apt/apt.conf.d/20auto-upgrades
4. Basisdienste: Apache, Docker, certbot
Apache mit Reverse-Proxy-Modulen. Apache ist im Standard der einzige Dienst, der auf 80/443 lauscht, und reicht alles per vHost an localhost-Backends weiter (ProxyPass/ProxyPassReverse, für Anwendungen wie Nextcloud und n8n mit ProxyPreserveHost On; Richtwert-Details im Dossier, Abschnitt 4.5):
apt install -y apache2
a2enmod proxy proxy_http proxy_wstunnel headers ssl rewrite
apache2ctl configtest
systemctl reload apache2
proxy/proxy_http für die HTTP-Backends, proxy_wstunnel für WebSockets (n8n, Talk-HPB), headers für X-Forwarded-Header, ssl und rewrite für die TLS-vHosts und Redirects, die certbot anlegt.
Docker aus dem offiziellen apt-Repo. Nicht das Ubuntu-Paket docker.io, nicht das Convenience-Script; das offizielle Repo ist der von Docker empfohlene Weg und unterstützt Ubuntu 26.04 explizit (Quelle: Docker-Installationsdoku, im Dossier verifiziert). GPG-Key ablegen, Repo im deb822-Format eintragen, Pakete installieren:
install -m 0755 -d /etc/apt/keyrings
curl -fsSL https://download.docker.com/linux/ubuntu/gpg -o /etc/apt/keyrings/docker.asc
chmod a+r /etc/apt/keyrings/docker.asc
cat > /etc/apt/sources.list.d/docker.sources <<'EOF'
Types: deb
URIs: https://download.docker.com/linux/ubuntu
Suites: resolute
Components: stable
Signed-By: /etc/apt/keyrings/docker.asc
EOF
apt update
apt install -y docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin
usermod -aG docker <SSH_USER>
(Suites ist der Ubuntu-Codename; das Script liest ihn aus /etc/os-release, auf 24.04 wäre es noble.) Sicherheitshinweis: Mitgliedschaft in der Gruppe docker ist root-äquivalent. Nur der Admin-User kommt hinein, niemand sonst; die Gruppenmitgliedschaft greift erst nach neuem Login.
certbot als Snap. Das Certbot-Projekt empfiehlt für die meisten Nutzer ausdrücklich die Snap-Installation (Quelle im Dossier verifiziert); eine eventuell vorhandene apt-Version fliegt vorher raus, um Konflikte zu vermeiden:
apt remove -y certbot
snap install --classic certbot
ln -sf /snap/bin/certbot /usr/local/bin/certbot
certbot renew --dry-run
Der Snap bringt das Auto-Renewal selbst mit (systemd-Timer). Der dry-run meldet zu diesem Zeitpunkt noch "keine Zertifikate", das ist in Ordnung; nach dem ersten Zertifikat in Kapitel 02 prüft ihr ihn erneut.
5. Übergabepunkt: bereit für Kapitel 02
Der Automatik-Weg fasst die Abschnitte 3 und 4 zusammen. Von eurem Rechner aus:
scp kreis.conf scripts/0*.sh root@<SERVER_IP>:/root/setup/
ssh root@<SERVER_IP>
cd /root/setup
bash 01-provision-server.sh
# zweites Terminal: ssh <SSH_USER>@<SERVER_IP> testen, sudo -v, dann:
bash 01-provision-server.sh --ssh-haerten
Das Script ist idempotent (mehrfaches Ausführen legt nichts doppelt an), bricht bei fehlenden oder Platzhalter-Werten in der kreis.conf mit klarer Meldung ab und führt die SSH-Härtung nur mit dem Flag und nur bei vorhandenen Keys aus. Rollback-Hinweise je Schritt: scripts/README-scripts.md.
"Bereit für Kapitel 02" heißt konkret, dass diese Prüfungen alle durchgehen:
ssh <SSH_USER>@<SERVER_IP> # Key-Login klappt
sudo -v # sudo klappt
ssh root@<SERVER_IP> # wird nach Härtung ABGELEHNT
ufw status # active; OpenSSH, 80/tcp, 443/tcp
systemctl is-active apache2 # active
apache2ctl -M | grep -E "proxy|ssl|headers" # Module geladen
docker --version && docker compose version # Docker + Compose-Plugin da
certbot --version # certbot antwortet
dig +short <CLOUD_SUBDOMAIN>.<BASIS_DOMAIN> # liefert eure SERVER_IP
Ab hier übernimmt Kapitel 02 (per Script: 02-nextcloud-docker.sh): Nextcloud-Compose-Stack, Apache-vHost, Let's-Encrypt-Zertifikat, dann Struktur und Betrieb. Die kreis.conf bleibt liegen und wird von allen Folge-Scripts weiterverwendet; kein Wert wird ein zweites Mal eingegeben.
Checkliste
Vorarbeit (ohne Server):
- DNS-Verwaltung einer Zone in eurer Hand (Bestandsdomain oder kurze Zweitdomain im Kreis-Account)?
- Subdomain-Plan festgelegt (cloud/office, plus flow nur bei Flow-Scope), finale Domain ab Tag 1?
- Mail-Entscheidung getroffen (Relay-Option 1, 2 oder 3), kein eigener Mailserver geplant?
- SPF der Absenderdomain autorisiert den versendenden Provider (bei Option 3:
include:ergänzt)? kreis.confper Konfigurator oder aus der Example-Datei ausgefüllt, keine Platzhalter<...>mehr, keine Secrets darin?
Bestellung und Installation:
- Eigenes Hetzner-Projekt des Kreises, SSH-Key (Ed25519) vor der Bestellung hinterlegt und ausgewählt?
- Ubuntu 26.04 LTS als Image (Verfügbarkeit in der Cloud Console geprüft; Fallback 24.04 dokumentiert)?
SERVER_IPin derkreis.confnachgetragen, A-Records (optional AAAA) gesetzt?
Grundhärtung:
- System aktualisiert, Admin-User mit sudo-Gruppe und
authorized_keysangelegt? - Neuer Login im ZWEITEN Terminal getestet (ssh +
sudo -v), Root-Session dabei offen gehalten? - SSH-Härtung als Drop-in aktiv (
PasswordAuthentication no,PermitRootLogin no), Root-Login scheitert nachweislich? - ufw: SSH VOR dem
enableerlaubt, danach nur 80/443 ergänzt? - Docker/ufw-Falle verstanden: Container-Ports nur an 127.0.0.1, öffentlich ist allein der Apache?
- unattended-upgrades verifiziert (per Default aktiv)?
Basisdienste:
- Apache läuft, Module proxy/proxy_http/proxy_wstunnel/headers/ssl/rewrite aktiv,
configtestohne Fehler? - Docker aus dem offiziellen Repo (deb822), NICHT docker.io; nur der Admin-User in der Gruppe
docker? - certbot als Snap installiert, apt-Version entfernt,
renew --dry-runbekannt? - Alle Übergabepunkt-Prüfungen aus Abschnitt 5 grün?
Referenz KNH
So sieht der Ist-Zustand bei Konstanz-Hegau aus (Inventare 2026-08-14), inklusive der Abweichungen vom hier beschriebenen Neu-Server-Weg:
- OS: hafen läuft auf Ubuntu 24.04 LTS, nicht 26.04. Der Server wurde vor dem 26.04-Release aufgebaut und historisch von Hand provisioniert; dieses Kapitel und
01-provision-server.shsind die generalisierte, auf 26.04 gehobene Fassung dieses Wegs für neue Kreise. - Domains: Zwei Zonen. Die Bestandsdomain
wj-konstanz-hegau.deliegt beim ursprünglichen Provider (GoDaddy-Nameserver) und trägt Nextcloud (hafen.), Collabora (office.), OpenProject (pm.) und den Kompetenz-Hub. Die kurze Zweitdomainwjknh.deliegt im WJ-eigenen Hetzner-Account (Records perhcloud --context wj zone rrset) und trägt n8n (flow.), Umami (analytics.) und die Demo-Replika. Alle A-Records zeigen auf dieselbe Server-IP. - Zertifikate: je vHost ein eigenes Let's-Encrypt-Zertifikat via
certbot --apache, Auto-Renewal aktiv, kein Wildcard. - Mail: kein eigener Mailserver. Nextcloud versendet als
hafen@wj-konstanz-hegau.deüber den VereinOnline-Mailserver (smtp/465/ssl); MX und SPF der Vereinsdomain zeigen auf VereinOnline, deshalb kommt der Versand sauber durch. Das ist Mail-Option 1 in Reinform. - Härtungs-Muster: Alle Dienste außer Apache (und TURN/STUN für Talk) binden auf 127.0.0.1 hinter Apache-vHosts; genau das Muster, das die Docker/ufw-Falle entschärft.
- Naming: Die Referenz nennt ihre Cloud "hafen" statt "cloud" und beweist damit, dass das Label frei ist; die Empfehlung
cloudgilt für Kreise ohne eigene Namens-Idee. - Zweiter Beleg: Die Hochrhein-Demo (
wjhcloud.wjknh.de) wurde auf demselben Server komplett nach dem Script-Weg aufgebaut (Compose an 127.0.0.1:8085, vHost, Einzel-Zertifikat) und ist damit der Nachweis, dass die Schrittfolge ab dem Übergabepunkt reproduzierbar durchläuft.