From 4eb2948a3785852f42b7e20299991c96f4883fb2 Mon Sep 17 00:00:00 2001 From: arnol Date: Wed, 22 Jul 2026 21:14:28 +0200 Subject: [PATCH] Re-add 01 PVE Host --- 01-PVE-Host.md | 176 +++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 176 insertions(+) create mode 100644 01-PVE-Host.md diff --git a/01-PVE-Host.md b/01-PVE-Host.md new file mode 100644 index 0000000..948b1df --- /dev/null +++ b/01-PVE-Host.md @@ -0,0 +1,176 @@ +# PVE-Host (``) — Rebuild-Runbook + +Basis: Proxmox VE, frisch installiert (Fujitsu Esprimo, i3, 32GB RAM). Alles ab hier ist tatsächlich ausgeführt. + +## 1. Grundpakete + +```bash +apt-get install -y git tree +``` + +## 2. Tailscale (Subnet-Router) + +```bash +curl -fsSL https://tailscale.com/install.sh | sh + +cat > /etc/sysctl.d/99-tailscale.conf <<'EOF' +net.ipv4.ip_forward=1 +net.ipv6.conf.all.forwarding=1 +EOF +sysctl -p /etc/sysctl.d/99-tailscale.conf + +tailscale up --authkey= --advertise-routes= --accept-risk=lose-ssh +``` + +**Danach zwingend in der Tailscale-Admin-Konsole (login.tailscale.com/admin/machines):** +- Bei `` → „Edit route settings" → Route `` genehmigen (Subnet-Routes werden nie automatisch aktiviert) +- Unter Settings → DNS → Nameserver `` (AdGuard) hinzufügen + „Override local DNS" aktivieren → macht Ad-Blocking im ganzen Tailnet aktiv, auch mobil +- Unter Settings → DNS → „HTTPS Certificates" aktivieren (wird für `tailscale cert`/`tailscale serve` auf allen Tailnet-Mitgliedern gebraucht, z.B. Vaultwarden) +- Auth-Key erzeugen unter Settings → Keys → „Generate auth key" (reusable, ~90 Tage), wird für alle weiteren Instanzen gebraucht + +⚠️ **NICHT TUN:** `--advertise-exit-node` setzen. Bewusste Entscheidung: kein Exit-Node, sonst würde jeglicher mobiler Internet-Traffic über die Heimleitung (DS-Lite) zurückgeroutet — nur die Subnet-Route wird gebraucht. + +## 3. NAS: ZFS-Mirror + +Vorher: Laufwerke identifizieren, SMART-Check, Datenprüfung auf vorhandenen Inhalt (**vor** dem Löschen — hier nur der Soll-Zustand, nicht das chronologische Nachschauen-was-noch-drauf-war im Detail, das nicht Teil dieser Freigabe ist). + +```bash +# Stabile Device-Namen ermitteln +ls -la /dev/disk/by-id/ | grep -E "ata-SAMSUNG|ata-ST1000" + +# Beide Platten komplett löschen (IRREVERSIBEL — vorher SMART + Dateninhalt prüfen!) +wipefs -a /dev/sda /dev/sdb +sgdisk --zap-all /dev/sda +sgdisk --zap-all /dev/sdb + +# Mirror anlegen +zpool create -o ashift=12 nas mirror \ + /dev/disk/by-id/ata-SAMSUNG_HD103SJ_S246J9AZ807325 \ + /dev/disk/by-id/ata-ST1000DM003-1CH162_Z1D7GZ5Q + +zfs create -o compression=lz4 -o atime=off nas/freigabe +``` + +## 4. HDD-Spindown (Stromsparen) + +```bash +hdparm -S 241 /dev/disk/by-id/ata-SAMSUNG_HD103SJ_S246J9AZ807325 /dev/disk/by-id/ata-ST1000DM003-1CH162_Z1D7GZ5Q + +cat >> /etc/hdparm.conf <<'EOF' + +# NAS-HDDs: Standby nach 30 Minuten Inaktivität (Stromsparen, ZFS-Mirror "nas") +/dev/disk/by-id/ata-SAMSUNG_HD103SJ_S246J9AZ807325 { + spindown_time = 241 +} +/dev/disk/by-id/ata-ST1000DM003-1CH162_Z1D7GZ5Q { + spindown_time = 241 +} +EOF +``` + +`smartd` (Debian-Default-Config, `-n standby`) weckt schlafende Platten nicht — nichts weiter zu tun. Der ZFS-Pool ist bewusst **nicht** als PVE-Storage registriert, damit `pvestatd` ihn nicht permanent pollt. + +## 5. Git-Repo (dieses Repo) + +```bash +mkdir -p /root/projects/homelab-config +# Eigenen Projekt-Kontext + chronologisches Log anlegen (Format/Inspiration: +# ENTSCHEIDUNGEN.md und der Aufbau dieses Portfolios selbst) +cd /root/projects/homelab-config +git init +git add . +git commit -m "Initial project setup" +``` + +Später auf die NAS-Freigabe verlagert (nachdem CT 101 steht): + +```bash +mv /root/projects/homelab-config /nas/freigabe/homelab-config +chown -R 101000:101000 /nas/freigabe/homelab-config +git config --global --add safe.directory /nas/freigabe/homelab-config +``` + +⚠️ **Warum `chown 101000:101000` und `safe.directory`:** Der Ordner liegt physisch im ZFS-Dataset, das per Bind-Mount in CT 101 (unprivileged, UID-Offset 100000) eingebunden ist. Ohne `safe.directory`-Eintrag verweigert Git auf dem PVE-Host die Arbeit ("dubious ownership"), weil der Owner (101000) nicht root ist. + +## 6. Wake-on-LAN-Trigger (für PC1, ausgelöst von Guacamole/VPS) + +```bash +apt-get install -y wakeonlan +useradd -m -s /bin/bash wolonly +mkdir -p /home/wolonly/.ssh +ssh-keygen -t ed25519 -f /root/.ssh/wol_vps_key -N "" -C "vps-wol-trigger" + +cat > /usr/local/bin/wake-pc1.sh <<'EOF' +#!/usr/bin/env bash +wakeonlan -i +echo "Magic packet an gesendet." +EOF +chmod +x /usr/local/bin/wake-pc1.sh + +KEY=$(cat /root/.ssh/wol_vps_key.pub) +echo "no-port-forwarding,no-x11-forwarding,no-agent-forwarding,command=\"/usr/local/bin/wake-pc1.sh\" $KEY" > /home/wolonly/.ssh/authorized_keys +chown -R wolonly:wolonly /home/wolonly/.ssh +chmod 700 /home/wolonly/.ssh +chmod 600 /home/wolonly/.ssh/authorized_keys +``` + +Der private Key (`/root/.ssh/wol_vps_key`) wird in die Guacamole-Verbindung "Wake PC1" eingebettet (siehe `06-vps-strato.md`). + +⚠️ **NICHT TUN:** `restrict,command="..."` als Kurzform in `authorized_keys` verwenden. `restrict` schließt `no-pty` mit ein — Guacamoles SSH-Client fordert aber immer ein Pseudo-Terminal an, auch für einen reinen Einzelbefehl. Mit `no-pty` schlägt die Verbindung mit „Unable to allocate PTY" fehl. Stattdessen die Einzel-Restriktionen explizit auflisten (siehe oben), `no-pty` weglassen. + +⚠️ **NICHT TUN:** MAC-Adresse mit Bindestrichen (`D8-BB-C1-90-66-3F`, Windows-`ipconfig`-Format) an `wakeonlan` übergeben. Erwartet Doppelpunkte (``), sonst Fehler "not a hardware address". + +## 7. DNS-Falle bei neuen Containern (wichtig für alle folgenden `pct create`-Schritte) + +Seit der PVE-Host selbst Tailscale-Mitglied ist, zeigt sein `/etc/resolv.conf` auf `100.100.100.100` (Tailscales interner Stub-Resolver). Neue Container erben das automatisch (kein `--nameserver` bei `pct create` angegeben) — sind selbst aber noch keine Tailscale-Mitglieder und können diese Adresse nicht erreichen. Resultat: `apt-get update` hängt endlos, ohne Fehlermeldung. + +**Immer bei `pct create` mitgeben:** +```bash +--nameserver +``` + +**Für bereits existierende Container dauerhaft fixen** (übersteht Neustarts, im Gegensatz zum manuellen Editieren von `/etc/resolv.conf`, das bei jedem Containerstart überschrieben wird): +```bash +pct set --nameserver +``` +Angewendet auf CT 100, 101, 102, 103. + +## 8. TUN-Device für Tailscale-in-LXC (für CT 102, CT 103) + +Unprivileged Container haben standardmäßig kein `/dev/net/tun` — ohne das startet `tailscaled` nicht. + +```bash +pct stop +cat >> /etc/pve/lxc/.conf <<'EOF' +lxc.cgroup2.devices.allow: c 10:200 rwm +lxc.mount.entry: /dev/net/tun dev/net/tun none bind,create=file 0 0 +EOF +pct start +``` + +Danach sollte `ls -la /dev/net/tun` im Container ein Character-Device zeigen (nicht "No such file or directory"). + +## 9. Tailscale-Route-Konflikt bei LAN-eigenen Containern + +⚠️ **NICHT TUN:** `--accept-routes` bei einem Container setzen, der selbst schon direkt im ``-LAN hängt (z.B. CT 102). Der PVE-Host advertised dieses Subnetz als Tailscale-Route — akzeptiert der Container das, landet in Tailscales eigener Policy-Routing-Tabelle (`ip route show table 52`) ein Eintrag ` dev tailscale0`, der Rückverkehr zur eigenen LAN-IP fälschlich über Tailscale statt direkt über `eth0` schickt. Symptom: Dienste auf dem Container sind über die LAN-IP nicht mehr erreichbar (Timeout, nicht Refused), obwohl sie laufen. + +Für Container, die bereits nativ im LAN sitzen: `tailscale up ... --accept-routes=false`. Peer-zu-Peer-Erreichbarkeit zu anderen Tailnet-Mitgliedern funktioniert davon unabhängig. + +## 10. PVE-Weboberfläche mit echtem Zertifikat (via `tailscale serve`) + +Proxmox' Standard-Webinterface (`:8006`) nutzt ein selbstsigniertes Zertifikat → Browser-Warnung bei jedem Zugriff. Gleicher Trick wie bei Vaultwarden: **nicht** Proxmox' eigene Zertifikatsdateien anfassen (die sind für die interne Cluster-Kommunikation kritisch), sondern per `tailscale serve` reverse-proxyen. + +```bash +tailscale serve --bg https+insecure://localhost:8006 +``` + +`https+insecure://` ist hier bewusst nötig — das Backend (`pveproxy` auf `:8006`) hat selbst ein selbstsigniertes Zertifikat, das `tailscale serve` beim lokalen Proxy-Hop akzeptieren muss, ohne es zu verifizieren (nur der äußere, dem Nutzer sichtbare Hop bekommt das echte Tailscale-Zertifikat). + +Erreichbar unter `https://.` (kein `:8006` mehr nötig, Port 443 Standard), automatisch gültiges Let's-Encrypt-Zertifikat, automatische Erneuerung. Voraussetzung: „HTTPS Certificates" in der Tailscale-Admin-Konsole aktiviert (siehe Abschnitt 2). + +## Referenz: aktuelle LXC-Übersicht + +```bash +pct list +for id in 100 101 102 103; do echo "CT $id:"; pct config $id | grep -E "memory|cores|net0"; done +```