Next.js bis 16.4.0 hat zwei kritische Lücken (RCE in der Bildoptimierung mit SVG und in use cache) und eine hohe (DoS über Server Actions). Prisma 7.10.1 hebt mysql2 und deepmerge-ts über bekannte Lücken. Volle Prüfung grün; dazu der Vorlagen-Ablauf mit mehr Zeit, weil sein Dry-Run wirklich gegen den Testhost plant. Refs #020 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
244 lines
12 KiB
Markdown
244 lines
12 KiB
Markdown
<p align="center"><img src="public/brand/banner.svg" alt="ProxDeploy – VMs und LXC-Container auf Proxmox VE ausrollen, per Web oder CLI." width="100%"></p>
|
||
|
||
**ProxDeploy** ist eine selbst gehostete Webanwendung mit einer CLI (`proxdeploy`). Damit wählt man
|
||
einen von mehreren Proxmox-VE-Servern (8.x/9.x, Einzelhost oder Cluster) und rollt darauf vollständig
|
||
unattended eine VM oder einen LXC-Container mit Debian oder Ubuntu aus – mit Profilen wie `base`,
|
||
`docker` oder `zabbix-agent`. Distributionen und Profile sind YAML-Dateien im Katalog, kein Code.
|
||
|
||
> ProxDeploy ist ein unabhängiges Werkzeug und stammt nicht von der Proxmox Server Solutions GmbH.
|
||
> „Proxmox“ ist eine Marke der Proxmox Server Solutions GmbH.
|
||
|
||
<p align="center"><img src="docs/bilder/live-ansicht.png" alt="Live-Ansicht eines Deployments: Phasen mit Status, Abschlussbox mit IP und SSH-Befehl" width="100%"></p>
|
||
|
||
## Was es kann
|
||
|
||
- **Assistent in neun Schritten** – Server, Typ, Distribution, Name, Ressourcen, Netzwerk (DHCP/statisch,
|
||
VLAN), Zugang (SSH-Schlüssel), Profile mit Variablen – und am Ende ein **Dry-Run** mit allen geplanten
|
||
Proxmox-Aufrufen und dem passenden CLI-Befehl.
|
||
- **Live-Fortschritt** je Phase (Server-Sent Events), in Web und CLI mit denselben Texten; bei Fehlern
|
||
Ursache und Lösungshinweis, danach auf Wunsch **Aufräumen** des halb angelegten Gasts.
|
||
- **Templates** aus offiziellen Cloud-Images (Prüfsumme geprüft, UEFI, Guest-Agent eingebaut), auf
|
||
Wunsch mit eingebackenen Profilen – ein Docker-Host ist dann in Sekunden statt Minuten fertig.
|
||
- **Ohne SSH zum Node** per API und Guest-Agent; mit SSH zusätzlich LXC-Provisionierung und
|
||
cloud-init-Snippets. Was ein Server kann, zeigt der Verbindungstest.
|
||
- **Verlauf** mit Filtern und Wiederholen, **Vorlagen** („Docker-Host klein“), hinterlegte
|
||
**SSH-Schlüssel**, **Rollen** Admin/Operator, **Audit-Log**, Anmeldung lokal oder per **OIDC**.
|
||
- **CLI** als einzelnes Binary für Linux, macOS und Windows – mit Batch-Dateien für viele Gäste.
|
||
|
||
| Übersicht | Assistent mit Dry-Run | Am Handy |
|
||
|---|---|---|
|
||
|  |  |  |
|
||
|
||
Weitere Ansichten: [Verlauf](docs/bilder/verlauf.png) · [Server mit Verbindungstest](docs/bilder/server.png) · [Katalog](docs/bilder/katalog.png).
|
||
Erzeugt mit `scripts/screenshots.ts` aus dem gebauten Stand.
|
||
|
||
## Installation
|
||
|
||
ProxDeploy braucht PostgreSQL und läuft als zwei Prozesse (app und worker). Es gehört hinter einen
|
||
Reverse-Proxy mit TLS; dann `TRUST_PROXY=true` und `APP_URL` auf die öffentliche Adresse setzen.
|
||
|
||
### Docker Compose
|
||
|
||
```bash
|
||
git clone https://git.wilde-server.de/florian.wilde/proxdeploy.git && cd proxdeploy
|
||
cp .env.example .env
|
||
# POSTGRES_PASSWORT=$(openssl rand -hex 24)
|
||
# PROXDEPLOY_SCHLUESSEL=$(openssl rand -base64 32) ← sichern! ohne ihn sind Tokens und Schlüssel verloren
|
||
# SITZUNG_GEHEIMNIS=$(openssl rand -base64 48)
|
||
# APP_URL=https://proxdeploy.example
|
||
# ADMIN_PASSWORT=… ← erster Admin, nur beim allerersten Start
|
||
docker compose up -d --build
|
||
```
|
||
|
||
Compose startet `postgres`, spielt mit `migrate` die Datenbank ein und startet dann `app` (Port 3000 auf
|
||
127.0.0.1) und `worker`. Aktualisieren: `git pull && docker compose up -d --build`.
|
||
|
||
### In einem Debian-LXC auf dem Proxmox-Host
|
||
|
||
Auf dem Proxmox-Host als root – Paket und Skripte kommen aus dem
|
||
[Release](https://git.wilde-server.de/florian.wilde/proxdeploy/releases):
|
||
|
||
```bash
|
||
v=1.0.0; basis=https://git.wilde-server.de/florian.wilde/proxdeploy/releases/download/v$v
|
||
for f in install-lxc.sh im-container.sh proxdeploy-$v.tar.gz SHA256SUMS; do curl -fsSLO "$basis/$f"; done
|
||
sha256sum -c --ignore-missing SHA256SUMS && chmod +x install-lxc.sh
|
||
./install-lxc.sh --paket proxdeploy-$v.tar.gz --url https://proxdeploy.example
|
||
```
|
||
|
||
Der Installer legt einen unprivilegierten Debian-13-Container an (DHCP auf `vmbr0`; `--ip`, `--gw`,
|
||
`--vlan`, `--storage`, `--ctid` u. a. siehe `--help`), installiert Node.js 24 (Prüfsumme geprüft) und
|
||
PostgreSQL, richtet systemd-Dienste ein und zeigt am Ende Adresse und das Passwort des ersten Admins.
|
||
Aktualisieren mit `./install-lxc.sh --aktualisieren <ctid> --paket proxdeploy-<neu>.tar.gz` – die
|
||
letzten drei Fassungen bleiben unter `/opt/proxdeploy/versionen/`. Ein eigenes Paket aus dem
|
||
Repository baut `scripts/paket-bauen.sh <version> --tar`.
|
||
|
||
## Erste Schritte
|
||
|
||
1. **Token in Proxmox:** eigenen Benutzer und die Rolle `ProxDeploy` anlegen, Token ohne
|
||
Privilege Separation – die Befehle für 8.x und 9.x stehen in [docs/proxmox-rechte.md](docs/proxmox-rechte.md).
|
||
2. **Server anlegen:** URL, Token, Zertifikat bestätigen (Fingerprint-Pinning für selbst signierte
|
||
Zertifikate), „Verbindung testen“. Optional SSH-Zugang zum Node hinterlegen.
|
||
3. **SSH-Schlüssel** unter Einstellungen hinterlegen – sie kommen automatisch in jeden Gast.
|
||
4. **Ausrollen:** fehlt das Template, baut ProxDeploy es vorher (oder unter „Templates“).
|
||
|
||
## Was ProxDeploy auf einem Server kann
|
||
|
||
Der Verbindungstest prüft jeden Server und zeigt, welcher Vorgang per API, per SSH oder gar nicht geht.
|
||
Maßgeblich ist die Proxmox-API (geprüft gegen PVE 8.x und 9.2):
|
||
|
||
- **Template bauen:** per API ab PVE 8.4 (`download-url` + `import-from`), davor per SSH
|
||
- **VM provisionieren:** über den Guest-Agent, ohne SSH
|
||
- **LXC provisionieren:** braucht SSH (Proxmox hat keine Exec-API für Container)
|
||
- **cloud-init-Snippets:** nur per SSH (keine API)
|
||
|
||
Das API-Token braucht eine eigene Rolle; die Befehle stehen in
|
||
[docs/proxmox-rechte.md](docs/proxmox-rechte.md).
|
||
|
||
## CLI
|
||
|
||
`proxdeploy` ist ein einzelnes Binary (Linux, macOS, Windows; amd64 und arm64) und spricht nur die
|
||
REST-API – dieselbe wie die Web-GUI, mit denselben Phasentexten.
|
||
|
||
```bash
|
||
# Linux amd64 – andere Plattformen: siehe Release (darwin, windows, arm64)
|
||
curl -fsSL -o /usr/local/bin/proxdeploy \
|
||
https://git.wilde-server.de/florian.wilde/proxdeploy/releases/download/v1.0.0/proxdeploy-1.0.0-linux-amd64
|
||
chmod +x /usr/local/bin/proxdeploy
|
||
```
|
||
|
||
```bash
|
||
proxdeploy login https://proxdeploy.example # fragt Benutzer und Passwort, speichert ein Token
|
||
proxdeploy servers
|
||
proxdeploy distros --type lxc
|
||
proxdeploy profiles
|
||
proxdeploy vm web01 --server rz1 --distro debian-13 --profile base,docker --ip 10.0.20.15/24 --gw 10.0.20.1 --vlan 20
|
||
proxdeploy lxc dns01 --server rz1 --distro ubuntu-24.04 --dry-run
|
||
proxdeploy template build --server rz1 --distro debian-13 --profile base,docker
|
||
proxdeploy batch gaeste.yaml
|
||
proxdeploy status a-7f3k
|
||
proxdeploy logs a-7f3k --follow
|
||
proxdeploy history --type lxc --status fehlgeschlagen
|
||
proxdeploy cleanup a-7f3k # halb angelegten Gast nach Fehlschlag löschen (mit Rückfrage)
|
||
```
|
||
|
||
```
|
||
⬡ ProxDeploy v0.4 · Server rz1 · Node pve01 · Debian 13 (Template 9013)
|
||
|
||
✓ Prüfungen VMID 120 frei · local-zfs · vmbr0 VLAN 20
|
||
✓ Klonen full clone 9013 → 120 · Disk auf 40G
|
||
✓ cloud-init user florian · SSH-Key · Profile base, docker
|
||
✓ Start VM 120 läuft
|
||
✓ Guest-Agent antwortet nach 18s
|
||
◐ Provisionierung cloud-init läuft … 1m 12s
|
||
```
|
||
|
||
- Was nicht angegeben ist, füllt der Server: Storage, Bridge und Node aus den Server-Einstellungen
|
||
bzw. dem Verbindungstest, Benutzer = eigener Benutzername, SSH-Schlüssel = die in den Einstellungen
|
||
hinterlegten. `--preset` belegt aus einer Vorlage vor; Flags gehen vor.
|
||
- Konfiguration in `~/.config/proxdeploy/config.toml` (Rechte 0600): `url`, `token`, optional
|
||
`server` als Standard für `--server` und `[instances.<name>]` für weitere Instanzen
|
||
(`--instance`). `PROXDEPLOY_URL`, `PROXDEPLOY_TOKEN`, `PROXDEPLOY_INSTANCE` gehen vor.
|
||
- Tokens für Skripte und CI: Web-GUI → Einstellungen → API-Tokens, dann `proxdeploy login <url> --token pd_…`.
|
||
- Ausgabe: Farben (24-bit, sonst 256) nur im Terminal und ohne `NO_COLOR`/`--no-color`; `--ascii`
|
||
ersetzt Symbole durch `[OK]`, `[..]`, `[!!]`; `--quiet` zeigt nur die Abschlussbox; `--json` ist
|
||
maschinenlesbar. Ohne Terminal (Pipe, CI) erscheint jede Phase als eine Zeile, sobald sie fertig ist.
|
||
- Exit-Codes: `0` Erfolg, `1` Auftrag fehlgeschlagen, `2` Bedienfehler, `3` Verbindung/Anmeldung.
|
||
- `Strg+C` hängt nur ab – der Auftrag läuft weiter (`proxdeploy status <id>`); abbrechen mit
|
||
`proxdeploy cancel <id>`.
|
||
|
||
`batch` rollt mehrere Gäste aus; die Schlüssel heißen wie die Flags. Die Datei wird vollständig
|
||
geprüft, bevor der erste Auftrag startet:
|
||
|
||
```yaml
|
||
defaults:
|
||
server: rz1
|
||
distro: debian-13
|
||
profile: [base]
|
||
guests:
|
||
- name: web01
|
||
type: vm
|
||
profile: [base, docker]
|
||
ip: 10.0.20.15/24
|
||
gw: 10.0.20.1
|
||
memory: 4096
|
||
- name: mon01
|
||
type: lxc
|
||
profile: [base, zabbix-agent]
|
||
vars: { zabbix-agent: { server: zbx.example } }
|
||
```
|
||
|
||
Bauen: `cli/bauen.sh 0.4.0` legt die sechs Binaries und `SHA256SUMS` unter `cli/bin/` ab (Go 1.27).
|
||
|
||
## Anmeldung per OIDC (z. B. authentik)
|
||
|
||
Optional zusätzlich zu lokalen Konten. Beim Identity Provider einen vertraulichen Client anlegen,
|
||
Redirect-URI `<APP_URL>/api/v1/auth/oidc/rueckruf`, Scopes `openid profile email`, den
|
||
Gruppen-Claim ins ID-Token geben. Dann in der `.env`:
|
||
|
||
```bash
|
||
OIDC_AKTIV=true
|
||
OIDC_ISSUER=https://auth.example/application/o/proxdeploy/
|
||
OIDC_CLIENT_ID=…
|
||
OIDC_CLIENT_SECRET=…
|
||
OIDC_ANZEIGENAME=authentik
|
||
OIDC_GRUPPEN_CLAIM=groups
|
||
OIDC_GRUPPE_ADMIN=proxdeploy-admins
|
||
OIDC_GRUPPE_OPERATOR=proxdeploy-operators
|
||
```
|
||
|
||
- Ablauf: Authorization Code mit PKCE, State und Nonce; das ID-Token wird gegen die Schlüssel des IdP geprüft.
|
||
- Die Rolle kommt bei **jeder** Anmeldung aus den Gruppen; wer in keiner der beiden Gruppen ist, kommt nicht hinein.
|
||
- Neue SSO-Benutzer werden beim ersten Anmelden angelegt. Ein vorhandenes lokales Konto wird **nie**
|
||
über den Namen übernommen; verknüpfen geht angemeldet unter Einstellungen → „Mit … verknüpfen“.
|
||
- Gesperrte Konten bleiben gesperrt, auch per SSO. Getestet gegen einen Mock-IdP (`tests/oidc.test.ts`);
|
||
ein echter IdP folgt beim Feldtest.
|
||
|
||
## Katalog erweitern
|
||
|
||
- **Neue Distribution:** eine YAML-Datei unter `catalog/distros/` – Image-URL, Prüfsummen-Quelle,
|
||
Standardbenutzer, LXC-Template-Muster. Für eine neue Familie (z. B. `rhel` mit dnf) kommt ein
|
||
Adapter unter `src/engine/adapter/` dazu. → [docs/katalog.md](docs/katalog.md#neue-distribution-hinzufügen)
|
||
- **Eigenes Profil:** in der Web-GUI unter Katalog → „Profil anlegen“ (YAML mit Live-Prüfung und
|
||
Skriptvorschau) oder als Datei unter `catalog/profiles/`. → [docs/katalog.md](docs/katalog.md#eigenes-profil-anlegen)
|
||
|
||
## Stand
|
||
|
||
**1.0.0** – alle Etappen der Vorgabe umgesetzt. Änderungen stehen im [CHANGELOG](CHANGELOG.md), der
|
||
Plan in [docs/architektur.md](docs/architektur.md), die Aufgaben in [docs/issues/](docs/issues/README.md).
|
||
|
||
| Geprüft | |
|
||
|---|---|
|
||
| Proxmox VE 9.x | **Feldtest auf PVE 9.2**: VMs und LXC mit Debian 12/13 und Ubuntu 22.04/24.04/26.04, mit und ohne SSH zum Node ([#020](docs/issues/020-feldtest.md)) |
|
||
| Proxmox VE 8.x | im Code unterstützt (Rechte, API-Wege je Version gegen nachgebaute Server getestet), **nicht im Feldtest** |
|
||
| Anmeldung | lokale Benutzer im Betrieb geprüft; OIDC gegen einen nachgebauten Identity Provider getestet, noch nicht gegen einen echten |
|
||
| Betrieb | Docker Compose lokal, LXC-Installer samt Update auf PVE 9.2 |
|
||
|
||
## Entwicklung
|
||
|
||
Voraussetzungen: Node 24 (z. B. über nvm), pnpm 12 (corepack), Docker für PostgreSQL.
|
||
|
||
```bash
|
||
pnpm install
|
||
cp .env.example .env # Schlüssel erzeugen: openssl rand -base64 32 / 48, ADMIN_PASSWORT setzen
|
||
pnpm db:up # PostgreSQL 17 auf 127.0.0.1:5437 (inkl. Testdatenbank)
|
||
pnpm db:migrate
|
||
pnpm build && PORT=3310 APP_URL=http://127.0.0.1:3310 pnpm start
|
||
```
|
||
|
||
Prüfen vor jedem Commit:
|
||
|
||
```bash
|
||
pnpm lint && pnpm typecheck && pnpm format:pruefen && pnpm test
|
||
pnpm test:e2e # Browser-Abläufe gegen den gebauten Stand (Desktop und 390 px)
|
||
pnpm cli:pruefen # openapi.json und Go-Typen aktuell, go vet, go test (Golden-Files)
|
||
```
|
||
|
||
Ändert sich ein Schema der API, erst `pnpm openapi`, dann in `cli/` `go generate ./...` – der
|
||
Go-Client nutzt die aus `cli/api/openapi.json` erzeugten Typen.
|
||
|
||
Konventionen (deutsche Bezeichner, Schichtung, Versionen) stehen in [CLAUDE.md](CLAUDE.md).
|
||
|
||
## Lizenz
|
||
|
||
Noch nicht festgelegt.
|