doc: konsolidierte Homelab-Dokumentation + Original-Plan

This commit is contained in:
2026-06-04 02:15:42 +02:00
parent 1ceaa8e103
commit daf5ffc8d0
13 changed files with 1372 additions and 1 deletions
+261
View File
@@ -0,0 +1,261 @@
# homelab — aufbau-anleitung
Schritt-für-Schritt nach dem Manifest. Reihenfolge ist bewusst: erst Fundament (Pools, Datasets), dann Netzgerüst (Caddy/WireGuard/DNS), dann Apps. Domains und IPs hier als Platzhalter (`deinedomain.ch`, `10.0.0.x`) — anpassen.
---
## 1 — proxmox & rpool
Proxmox-Installer von USB. Bei der Disk-Auswahl die NVMe nehmen, Filesystem **zfs (RAID0)** (= Single-Disk ZFS), `ashift=12`, compression `lz4`. Das wird dein `rpool`.
Nach dem ersten Boot: Enterprise-Repo raus, No-Subscription-Repo rein, updaten.
```bash
zpool status # rpool sollte ONLINE sein
zfs set atime=off rpool
```
---
## 2 — tank (mirror) anlegen
Disk-IDs holen (nie /dev/sdX verwenden — die wandern):
```bash
ls -l /dev/disk/by-id/ | grep -i ata # die zwei 4TB-Platten identifizieren
zpool create -o ashift=12 \
-O compression=lz4 -O atime=off -O xattr=sa \
tank mirror /dev/disk/by-id/PLATTE1 /dev/disk/by-id/PLATTE2
zpool status tank # mirror, beide ONLINE
```
Monatlichen Scrub einrichten:
```bash
echo '0 3 1 * * root /sbin/zpool scrub tank' > /etc/cron.d/zfs-scrub
```
---
## 3 — datasets & quotas
```bash
zfs create -o quota=1300G tank/business
zfs create -o quota=300G tank/private
zfs create -o quota=600G -o recordsize=1M tank/immich
zfs create -o quota=150G tank/paperless
zfs create -o quota=150G tank/nextcloud
zfs create -o quota=150G tank/dump
zfs create -o quota=50G tank/gitea
zfs list -o name,quota,used tank # kontrollieren
```
`tank/dump` als Proxmox-Backup-Storage eintragen: Datacenter → Storage → Add → Directory, Pfad `/tank/dump`, Inhalt "VZDump backup file".
---
## 4 — LXC-muster & mountpoints
Pro Container: rootfs auf `rpool`, Bulk-Daten auf `tank`. Beispiel Nextcloud (CTID 110), exklusives Dataset → verwalteter Mountpoint:
```bash
pct set 110 -mp0 tank/nextcloud,mp=/data,backup=0
```
Fileserver (102) braucht die **geteilten** Datasets als Bind-Mount (mehrere Dienste im selben LXC):
```bash
pct set 102 -mp0 /tank/business,mp=/srv/business
pct set 102 -mp1 /tank/private,mp=/srv/private
```
**Hinweis unprivilegierte LXC:** in-container UID wird um 100000 verschoben. Damit Schreiben klappt, dem Dataset die verschobene UID/GID geben, z.B. für in-container `1000`:
```bash
chown -R 101000:101000 /tank/business /tank/private
```
Tipp: alle drei Zugriffsdienste (Samba/Filebrowser/Syncthing) **im selben LXC 102** halten — dann gibt es keine container-übergreifenden UID-Probleme.
---
## 5 — fileserver: samba + filebrowser + syncthing (LXC 102)
Debian-LXC, dann:
**Samba** (zwei Shares):
```bash
apt install -y samba
groupadd buro; useradd -M -G buro karim; smbpasswd -a karim
```
`/etc/samba/smb.conf` (Auszug):
```ini
[business]
path = /srv/business
valid users = @buro
read only = no
force group = buro
create mask = 0660
directory mask = 0770
[private]
path = /srv/private
valid users = karim
read only = no
create mask = 0600
directory mask = 0700
```
```bash
systemctl restart smbd
```
Mounten am Mac: Finder → ⌘K → `smb://10.0.0.102/business`. Linux: `mount -t cifs //10.0.0.102/business /mnt/business -o user=karim`.
**Filebrowser** (Web + Share-Links), rooted über beide Shares:
```bash
curl -fsSL https://raw.githubusercontent.com/filebrowser/get/master/get.sh | bash
filebrowser config init
filebrowser config set --root /srv --address 0.0.0.0 --port 8080
filebrowser users add karim DEINPASSWORT --perm.admin
```
Als systemd-Service einrichten (Unit anlegen, enable). Caddy proxyt später `files.deinedomain.ch``10.0.0.102:8080`.
**Syncthing** (das "Drive"): `apt install syncthing`, als User-Service starten, Web-UI auf `:8384`, Ordner `/srv/business` (oder gezielte Unterordner) freigeben und auf dem Laptop verbinden. Da Syncthing plain files schreibt, bleibt SMB parallel nutzbar.
---
## 6 — ordnerstruktur anlegen
```bash
# business
mkdir -p /srv/business/{_vorlagen,_buro,_bibliothek/{details,cad-blocks,materialien,referenzen},projekte}
mkdir -p /srv/business/projekte/2026-001_beispiel/{00_admin,01_grundlagen,02_vorstudien,03_vorprojekt,04_bauprojekt,05_bewilligung,06_ausschreibung,07_ausfuhrung,08_abschluss,cad,plaene,visualisierung,fotos}
# private
mkdir -p /srv/private/{dokumente/2026,finanzen,studium,projekte,scans,archiv}
chown -R 101000:101000 /srv/business /srv/private
```
Für neue Projekte das `2026-001_beispiel`-Gerüst als Vorlage kopieren (oder ein kleines Skript in `_vorlagen/` ablegen).
---
## 7 — caddy (LXC 100)
`apt install caddy`, dann `/etc/caddy/Caddyfile`:
```
files.deinedomain.ch { reverse_proxy 10.0.0.102:8080 }
cloud.deinedomain.ch { reverse_proxy 10.0.0.110:80 }
fotos.deinedomain.ch { reverse_proxy 10.0.0.111:2283 }
www.deinedomain.ch { root * /srv/www; file_server }
```
```bash
systemctl reload caddy
```
Caddy holt TLS automatisch. Am Router nur 80/443 auf Caddy forwarden.
---
## 8 — wireguard (LXC 101, wg-easy)
Docker im LXC, wg-easy gibt dir eine GUI für Peers:
```bash
docker run -d --name wg-easy --cap-add NET_ADMIN --cap-add SYS_MODULE \
-e WG_HOST=vpn.deinedomain.ch -e PASSWORD_HASH='...' \
-p 51820:51820/udp -p 51821:51821/tcp \
-v ~/.wg-easy:/etc/wireguard --restart unless-stopped \
ghcr.io/wg-easy/wg-easy
```
Am Router **nur** UDP 51820 forwarden. Peers in der UI anlegen, QR scannen. Im Tunnel erreichst du das interne Subnetz → alle privaten Dienste, ohne sie je öffentlich zu machen.
---
## 9 — adguard home (LXC 103)
Installieren, als DNS im Router (oder im WireGuard-Profil) setzen. Interne A-Records anlegen, damit `cloud.deinedomain.ch` etc. intern auf die LXC-IPs zeigen → gleiche Hostnamen drinnen wie draussen.
---
## 10 — app-stacks (NC, immich, paperless)
Pro Stack ein Docker-LXC, compose-File ins Gitea. Muster für **Nextcloud** (110):
- compose mit `app`, `db` (Postgres), `redis`. Volumes für App/DB auf rootfs (NVMe).
- Daten-Volume auf das gemountete `/data` (= `tank/nextcloud`).
- Caddy proxyt `cloud.deinedomain.ch`.
**Immich** (111) und **Paperless-ngx** (113) analog — offizielle compose-Files nehmen (ändern sich regelmässig, drum upstream statt hier einfrieren) und nur den Daten-Pfad auf das jeweilige `tank/...`-Mount zeigen. Paperless' Consume-Ordner auf `/srv/private/scans` zeigen lassen → Scans landen automatisch im Archiv.
---
## 11 — monitoring
- **Uptime Kuma** (140): jeden Dienst als HTTP-Check anlegen, Push aufs Handy (ntfy/Telegram).
- **Beszel** (141): Agent auf dem Proxmox-Host, Pool-Auslastung im Blick.
- **Pool-Alert <85%** als simpler Cron:
```bash
cat > /etc/cron.hourly/zfs-capacity << 'EOF'
#!/bin/bash
cap=$(zpool list -H -o capacity tank | tr -d '%')
[ "$cap" -ge 85 ] && echo "tank $cap%" | ntfy publish homelab
EOF
chmod +x /etc/cron.hourly/zfs-capacity
```
---
## 12 — backup (sanoid + restic)
**Snapshots** (sanoid) — `/etc/sanoid/sanoid.conf`:
```ini
[tank/business]
use_template = prod
[tank/private]
use_template = prod
[tank/immich]
use_template = prod
[template_prod]
hourly = 24
daily = 30
monthly = 6
autosnap = yes
autoprune = yes
```
**Offsite** zur Hetzner Storage Box (Restic über SFTP):
```bash
export RESTIC_REPOSITORY="sftp:uXXXXX@uXXXXX.your-storagebox.de:/backup"
export RESTIC_PASSWORD_FILE=/root/.restic-pw
restic init
restic backup /tank/business /tank/private /tank/nextcloud /tank/immich /tank/paperless /tank/gitea
restic forget --keep-daily 14 --keep-weekly 8 --keep-monthly 12 --prune
```
In einen täglichen Cron packen.
**Restore-Test (Pflicht):** einmal `restic restore latest --target /tmp/restoretest --include /tank/private/dokumente` und prüfen ob die Files stimmen. Ein ungetestetes Backup ist kein Backup.
---
## reihenfolge auf einen blick
1. Proxmox + rpool → 2. tank Mirror + Scrub → 3. Datasets + Quotas → 4. Fileserver (Samba/Filebrowser/Syncthing) + Ordner → 5. Caddy + WireGuard + AdGuard → 6. Kern-Apps → 7. Monitoring → 8. Backup + Restore-Test → 9. Erweiterungen nach Lust.