Files
lernbar/docs/BETRIEB-PROXMOX.md
Florian WildeandClaude Opus 5.5 76836197b5 Anleitung fuer den Betrieb auf Proxmox
Von der leeren VM ueber Docker, Caddy mit HTTPS, Deploy-Schluessel,
erstes Konto und zweistufige Sicherung bis zur Abnahme vor dem
Echtbetrieb. Die Caddy-Konfiguration ist mit caddy validate geprueft.

Die README weist jetzt darauf hin, dass HTTPS Pflicht ist: Das
Anmeldecookie ist im Betrieb Secure, ueber http:// scheitert die
Anmeldung ohne Fehlermeldung.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-05 06:33:31 +02:00

261 lines
10 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# Lern-Bar auf Proxmox betreiben
Diese Anleitung führt von einer leeren Proxmox-Umgebung zur laufenden Lern-Bar im
Betriebsnetz: eine virtuelle Maschine mit Debian, darin Docker mit der Lern-Bar und Caddy
als Reverse Proxy mit HTTPS. Rechne mit etwa zwei Stunden.
> **HTTPS ist Pflicht, nicht Kür.** Die Lern-Bar setzt das Anmeldecookie im Betrieb mit dem
> Merkmal `Secure`. Über `http://` nimmt der Browser es nicht an – die Anmeldung scheitert
> dann ohne Fehlermeldung, man landet einfach wieder auf der Anmeldeseite.
---
## Inhalt
1. [VM oder LXC?](#1-vm-oder-lxc)
2. [Die VM anlegen](#2-die-vm-anlegen)
3. [Grundeinrichtung](#3-grundeinrichtung)
4. [Docker installieren](#4-docker-installieren)
5. [Die Lern-Bar holen und starten](#5-die-lern-bar-holen-und-starten)
6. [HTTPS mit Caddy](#6-https-mit-caddy)
7. [Das erste Konto](#7-das-erste-konto)
8. [Sicherung](#8-sicherung)
9. [Aktualisieren](#9-aktualisieren)
10. [Abnahme vor dem Echtbetrieb](#10-abnahme-vor-dem-echtbetrieb)
---
## 1. VM oder LXC?
**Eine VM.** Docker läuft auch in einem LXC-Container, braucht dort aber `nesting` und
`keyctl`, und in unprivilegierten Containern gibt es immer wieder Ärger mit dem
Speichertreiber und den Rechten auf Volumes. Eine VM ist sauber vom Host getrennt, wird von
Proxmox Backup als Ganzes gesichert und verhält sich wie jeder andere Server. Der zusätzliche
Arbeitsspeicher von ein paar hundert Megabyte fällt nicht ins Gewicht.
## 2. Die VM anlegen
| Einstellung | Wert |
|---|---|
| Betriebssystem | Debian 13 („trixie"), Netinstall-Abbild |
| Prozessor | 2 Kerne, Typ `host` |
| Arbeitsspeicher | 2 GB (der Bau des Abbilds braucht kurzzeitig mehr als der Betrieb) |
| Festplatte | 32 GB, VirtIO SCSI, auf einem Speicher, der in die Proxmox-Sicherung fällt |
| Netz | VirtIO, im **Server-VLAN** |
| Optionen | QEMU Guest Agent aktivieren |
Bei der Installation nur **SSH-Server** und **Standard-Systemwerkzeuge** auswählen, keine
grafische Oberfläche.
Danach:
- feste IP-Adresse vergeben oder im DHCP reservieren
- DNS-Eintrag anlegen, etwa `lernbar.betrieb.local` – diesen Namen nutzen die Azubis
- in der VM `sudo apt install qemu-guest-agent && sudo systemctl enable --now qemu-guest-agent`
## 3. Grundeinrichtung
Die Lern-Bar bringt dafür ihre eigene Checkliste mit: **Checklisten → Linux-Server
grundlegend einrichten** (Woche 13). Kurzfassung:
```bash
# Persönlicher Benutzer mit sudo, SSH nur mit Schlüssel (Schritte siehe Handout S8)
sudo apt update && sudo apt upgrade -y
sudo apt install -y unattended-upgrades ufw git
sudo dpkg-reconfigure -plow unattended-upgrades
# Firewall: SSH nur aus dem Verwaltungsnetz, Web für alle im LAN
sudo ufw default deny incoming
sudo ufw allow from 10.10.99.0/24 to any port 22 proto tcp # Verwaltungsnetz anpassen
sudo ufw allow 80/tcp
sudo ufw allow 443/tcp
sudo ufw enable
```
> **Docker und ufw:** Ports, die Docker veröffentlicht, laufen an ufw vorbei. Bei der
> Lern-Bar ist das unkritisch, weil `docker-compose.yml` Port 3000 nur auf `127.0.0.1`
> veröffentlicht – von außen ist er nicht erreichbar. Wer das ändert, öffnet den Port für
> alle, egal was ufw sagt.
## 4. Docker installieren
Aus dem Paketarchiv von Docker, nicht aus Debian – dort fehlt die Compose-Erweiterung in
aktueller Fassung.
```bash
sudo apt install -y ca-certificates curl
sudo install -m 0755 -d /etc/apt/keyrings
sudo curl -fsSL https://download.docker.com/linux/debian/gpg -o /etc/apt/keyrings/docker.asc
sudo chmod a+r /etc/apt/keyrings/docker.asc
echo "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.asc] \
https://download.docker.com/linux/debian $(. /etc/os-release && echo "$VERSION_CODENAME") stable" \
| sudo tee /etc/apt/sources.list.d/docker.list > /dev/null
sudo apt update
sudo apt install -y docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin
# Den eigenen Benutzer berechtigen – danach einmal ab- und wieder anmelden
sudo usermod -aG docker "$USER"
```
Prüfen: `docker compose version` zeigt eine Fassung 2.x.
## 5. Die Lern-Bar holen und starten
Für den Server einen **eigenen Lesezugang** zum Git-Repository anlegen, nicht die eigenen
Zugangsdaten hinterlegen. In Gitea: Repository → Einstellungen → **Deploy-Schlüssel**, einen
SSH-Schlüssel der VM ohne Schreibrecht eintragen.
```bash
ssh-keygen -t ed25519 -f ~/.ssh/lernbar_deploy -N ""
cat ~/.ssh/lernbar_deploy.pub # als Deploy-Schlüssel in Gitea eintragen
cat >> ~/.ssh/config <<'EOF'
Host git.wilde-server.de
IdentityFile ~/.ssh/lernbar_deploy
EOF
sudo mkdir -p /opt/lernbar && sudo chown "$USER": /opt/lernbar
git clone --branch feat/lernbar-erstfassung \
git@git.wilde-server.de:florian.wilde/lernbar.git /opt/lernbar
```
> Solange `main` noch nicht freigegeben ist, läuft der Betrieb vom Zweig
> `feat/lernbar-erstfassung`. Nach der Freigabe einmal `git -C /opt/lernbar checkout main`,
> danach holt `update.sh` von dort.
Bauen und starten:
```bash
cd /opt/lernbar
docker compose up -d --build # der erste Bau dauert einige Minuten
curl -s http://127.0.0.1:3000/api/gesundheit
# {"zustand":"in Ordnung"}
```
Die Daten liegen im Docker-Volume `lernbar_lernbar-daten`, auf dem Host unter
`/var/lib/docker/volumes/lernbar_lernbar-daten/_data`.
## 6. HTTPS mit Caddy
Caddy läuft direkt auf der VM, nimmt die Verbindungen auf 443 an und reicht sie an
`127.0.0.1:3000` weiter.
```bash
sudo apt install -y caddy
```
`/etc/caddy/Caddyfile`:
```caddyfile
lernbar.betrieb.local {
# Variante A: Zertifikat der eigenen Zertifizierungsstelle (empfohlen)
tls /etc/caddy/lernbar.crt /etc/caddy/lernbar.key
# Variante B: Caddys eigene Zertifizierungsstelle – siehe unten
# tls internal
request_body {
max_size 30MB # Fotos als Anhang, die Anwendung selbst begrenzt auf 25 MB
}
reverse_proxy 127.0.0.1:3000
}
```
```bash
sudo systemctl reload caddy
```
**Welches Zertifikat?**
- **Variante A – eigene Zertifizierungsstelle:** Gibt es im Betrieb eine Zertifizierungsstelle
(etwa die Active-Directory-Zertifikatsdienste), ein Serverzertifikat für
`lernbar.betrieb.local` ausstellen. Die Rechner in der Domäne vertrauen ihr bereits.
Datei und Schlüssel nach `/etc/caddy/` legen, Rechte `640`, Gruppe `caddy`.
- **Variante B – `tls internal`:** Caddy stellt das Zertifikat selbst aus. Damit Browser es
annehmen, muss das Wurzelzertifikat
`/var/lib/caddy/.local/share/caddy/pki/authorities/local/root.crt` auf allen Geräten als
vertrauenswürdig hinterlegt werden – an Domänenrechnern per Gruppenrichtlinie, an Handys von
Hand.
- **Ist die Lern-Bar aus dem Internet erreichbar** (öffentlicher DNS-Name, Port 443 offen),
holt Caddy ohne `tls`-Zeile selbst ein Zertifikat von Let's Encrypt.
> Für die **Installation auf dem Handy** (Startbildschirm, Offline-Lernen) verlangen die
> Browser ein Zertifikat, dem das Gerät vertraut. Mit Variante B heißt das: Wurzelzertifikat
> auch auf den Diensthandys installieren.
## 7. Das erste Konto
```bash
cd /opt/lernbar
docker compose exec lernbar node werkzeuge/konto.js \
--name "Vorname Nachname" --email ausbilder@betrieb.de --rolle ausbilder
```
Das ausgegebene Passwort notieren, unter `https://lernbar.betrieb.local` anmelden und es unter
**Verwaltung → Eigenes Passwort** ändern. Danach unter **Verwaltung** die Azubikonten anlegen
und im **Wochenplan** die Wochen einplanen.
Hat das einzige Ausbilderkonto sein Passwort vergessen, setzt derselbe Befehl es neu.
## 8. Sicherung
Zwei Ebenen, die sich ergänzen:
1. **Proxmox sichert die ganze VM**, etwa nächtlich auf Proxmox Backup Server. Damit lässt sich
der ganze Server zurückholen.
2. **Die Lern-Bar sichert ihre Daten selbst** – Datenbank und Anhänge in einem Archiv, das sich
auch auf einem neuen Server einspielen lässt.
`/etc/cron.d/lernbar-sicherung`:
```cron
SHELL=/bin/sh
PATH=/usr/local/bin:/usr/bin:/bin
# 02:30 sichern, 02:45 Archive älter als 30 Tage aufräumen
30 2 * * * root cd /opt/lernbar && docker compose exec -T lernbar /app/werkzeuge/sicherung.sh /daten/sicherungen >> /var/log/lernbar-sicherung.log 2>&1
45 2 * * * root cd /opt/lernbar && docker compose exec -T lernbar find /daten/sicherungen -name 'lernbar-*.tar.gz' -mtime +30 -delete
# 03:00 eine Kopie vom Server wegschaffen – Ziel und Zugang anpassen
0 3 * * * root rsync -a /var/lib/docker/volumes/lernbar_lernbar-daten/_data/sicherungen/ sicherung@nas.betrieb.local:/lernbar/ >> /var/log/lernbar-sicherung.log 2>&1
```
Die Uhrzeiten liegen vor der Proxmox-Sicherung, damit das frische Archiv mit in die
VM-Sicherung fällt.
**Zurückspielen** steht in der [README](../README.md#zurückspielen). Und: Eine Sicherung, die
nie zurückgespielt wurde, ist keine Sicherung. Einmal im Quartal nach der Checkliste
**Wiederherstellung testen** (Woche 8) auf eine Test-VM zurückspielen.
## 9. Aktualisieren
```bash
cd /opt/lernbar
./update.sh
```
Das Skript sichert, holt den neuen Stand, baut, schaltet um und wartet auf das Lebenszeichen.
Meldet sich die neue Fassung nicht gesund, schaltet es von selbst auf die vorherige zurück.
Neue Inhalte – etwa weitere Wochen – kommen auf demselben Weg, weil sie Teil des Repositorys
sind. Neue Wochen erscheinen danach im Wochenplan unter „noch nicht eingeplant".
Updates des Systems selbst spielt `unattended-upgrades` ein. Docker und Caddy kommen dabei mit,
weil sie aus Paketquellen installiert sind.
## 10. Abnahme vor dem Echtbetrieb
Bevor die Azubis die Adresse bekommen:
- [ ] Anmeldung über `https://lernbar.betrieb.local` von einem Arbeitsplatz – ohne
Zertifikatswarnung
- [ ] Anmeldung vom Handy, Installation auf dem Startbildschirm
- [ ] Ein Anhang mit 20 MB lässt sich hochladen
- [ ] Ein Berichtsheft-PDF lässt sich herunterladen
- [ ] `http://lernbar.betrieb.local` leitet auf HTTPS um
- [ ] `http://<IP>:3000` ist von einem anderen Rechner aus **nicht** erreichbar
- [ ] Sicherung von Hand ausgelöst, Archiv liegt auf dem NAS
- [ ] Die Sicherung auf eine Test-VM zurückgespielt, Konten und Daten sind da
- [ ] `./update.sh` einmal durchgelaufen
- [ ] Die VM erscheint in der Proxmox-Sicherung und in der Überwachung