Compare commits
4
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
3c77d34b7e | ||
|
|
8c83fb372b | ||
|
|
553b923445 | ||
|
|
09ac4d2507 |
@@ -13,7 +13,7 @@ Inspired by [community-scripts/ProxmoxVE](https://github.com/community-scripts/P
|
||||
| [nexus](ct/nexus.sh) | App LXC for [nexus](https://gitea.luki-net.org/l.kirchner/nexus-hub) (Family Knowledge Hub): host-mode runner (label `nexus`, CI + deploy), service skeleton, `/opt/nexus` layout. Runtime is provisioned/extended via [`install/nexus-runtime.sh`](install/nexus-runtime.sh) (idempotent, re-runnable) | ✅ in production |
|
||||
| [nexus-db](ct/nexus-db.sh) | PostgreSQL 16 + pgvector for nexus — least-privilege role, pg_hba allowlist (only the nexus LXC), DSN handed over via credentials file | ✅ in production |
|
||||
| [authentik](ct/authentik.sh) | Central homelab IdP (official Docker Compose via LXC nesting) — headless bootstrap admin **and** API token for agent-driven blueprint configuration, blueprints mount, permanent auth domain (WebAuthn RP-ID) | ✅ in production |
|
||||
| [runner](ct/runner.sh) | General **instance-wide** Gitea Actions runner (label `homelab`) — Docker for throwaway CI test containers, deliberately **no** sudoers/deploy rights | 🔄 in review ([PR #6](https://gitea.luki-net.org/luki-net/proxmox-scripts/pulls/6)) |
|
||||
| [runner](ct/runner.sh) | General **instance-wide** Gitea Actions runner (label `homelab`) — Docker for throwaway CI test containers, deliberately **no** sudoers/deploy rights | ✅ in production |
|
||||
|
||||
Run any one-liner on a Proxmox VE host as root:
|
||||
|
||||
@@ -32,12 +32,14 @@ CTID=200 HOSTNAME=devpi DISK_SIZE=30 RAM=4096 CORES=4 IPCFG=dhcp \
|
||||
|
||||
All defaults (`DEFAULT_HOSTNAME`, `DEFAULT_DISK`, …) and app config values are settable per call via env vars.
|
||||
|
||||
Every input is validated (digits-only for CTID/disk/cores/RAM/VLAN, IP/CIDR/gateway format, hostname/storage charsets). Invalid interactive input re-prompts — including pasted values with invisible control/non-ASCII bytes, which are rejected rather than silently stripped. Env-provided values are validated too and abort the run when malformed (no re-prompt loop in non-interactive use).
|
||||
|
||||
## The pattern
|
||||
|
||||
Two files per app, both sourcing the shared libs via `curl`:
|
||||
|
||||
- **`ct/<app>.sh`** runs on the PVE host: prompts → unprivileged LXC → pushes a config env file into the container → bootstraps the installer. Apps that need Docker (authentik, runner) enable `nesting+keyctl` automatically.
|
||||
- **`install/<app>-install.sh`** runs inside the LXC: packages, unprivileged app user, secrets generated on-host (never printed), systemd units, a `/root/<app>.credentials` notes file — then shreds the bootstrap env. Idempotent where it matters: re-runs skip what exists.
|
||||
- **`ct/<app>.sh`** runs on the PVE host: prompts → unprivileged LXC → pushes a config env file into the container → bootstraps the installer. Apps that need Docker (authentik, runner) enable `nesting+keyctl` automatically. The standard prompts include an **SSH root login choice** (`SSH_ROOT_LOGIN`, default yes for homelab convenience; `no` keeps the Debian key-only default) — applied inside the container as an sshd drop-in by `configure_ssh_root_login`.
|
||||
- **`install/<app>-install.sh`** runs inside the LXC: packages, unprivileged app user, secrets generated on-host (never printed), systemd units, a `/root/<app>.credentials` notes file — then shreds the bootstrap env. Idempotent where it matters: re-runs skip what exists. `setup_base_apt` also fixes the bare-template **locale situation**: `C.UTF-8` is exported up front (glibc built-in, covers the first apt run without perl warnings), then `en_US.UTF-8` is generated and set as the system default.
|
||||
|
||||
Shared libs: [`lib/build.func`](lib/build.func) (host-side: prompts, LXC create, bootstrap) and [`lib/install.func`](lib/install.func) (in-container: apt, users, systemd, http-wait).
|
||||
|
||||
@@ -50,15 +52,11 @@ Shared libs: [`lib/build.func`](lib/build.func) (host-side: prompts, LXC create,
|
||||
|
||||
## Contributing
|
||||
|
||||
**All changes go through a pull request with cross-review** (Claude Code ↔ Codex, or a human) — no direct pushes to `main`. This rule exists because of two real incidents where an un-reviewed script shipped a missing `source build.func` (see wiki → Lessons). CI (`bash -n`, source-check, validation suite) is being introduced with [PR #5](https://gitea.luki-net.org/luki-net/proxmox-scripts/pulls/5) and runs on the `homelab` runner.
|
||||
**All changes go through a pull request with cross-review** (Claude Code ↔ Codex, or a human) — no direct pushes to `main`. This rule exists because of two real incidents: a pasted VLAN tag carrying an invisible non-UTF-8 byte broke `pct create` mid-run, and the "missing `source build.func`" bug shipped twice — caught in review on the nexus-db PR, but reaching production via an un-reviewed authentik commit (see wiki → Lessons).
|
||||
|
||||
How to add a script: [docs/adding-a-script.md](docs/adding-a-script.md).
|
||||
CI (`.gitea/workflows/ci.yml`, instance-wide `homelab` runner from [ct/runner.sh](ct/runner.sh)) enforces on every PR: `bash -n` over all scripts, the "every `ct/*.sh` sources `build.func`" check ([tests/check_ct_source.sh](tests/check_ct_source.sh)) and the validation unit tests ([tests/test_validation.sh](tests/test_validation.sh)); shellcheck runs when available on the runner.
|
||||
|
||||
## Contributing (verbindlich seit K-114)
|
||||
|
||||
**Alle Änderungen laufen als PR mit Cross-Review** — keine Direkt-Commits auf `main`. Hintergrund: Der „`build.func` nicht gesourct"-Bug hat es einmal bis in die Produktion geschafft (authentik-Anlage), während dieselbe Fehlerklasse im nexus-db-PR vom Review gefangen wurde. Die CI (`.gitea/workflows/ci.yml`, Runner-Label `homelab` — instanzweiter Runner aus `ct/runner.sh`) erzwingt zusätzlich: `bash -n` über alle Scripts, „jedes `ct/*.sh` sourct `build.func`" (`tests/check_ct_source.sh`) und die Validierungs-Unit-Tests (`tests/test_validation.sh`).
|
||||
|
||||
Eingaben in `prompt_lxc_config` sind validiert (Ziffern-Checks, IP/CIDR/Gateway-Format, Re-Prompt bei unsichtbaren Steuer-/Non-ASCII-Zeichen — Lesson vom 2026-06-11). Neue App-Prompts bitte über `prompt_validated`/`require_valid` aus `lib/build.func` bauen statt nacktem `read`.
|
||||
Build new app prompts on `prompt_validated`/`require_valid` from `lib/build.func` instead of bare `read`. How to add a script: [docs/adding-a-script.md](docs/adding-a-script.md).
|
||||
|
||||
## Repo layout
|
||||
|
||||
@@ -69,6 +67,9 @@ Eingaben in `prompt_lxc_config` sind validiert (Ziffern-Checks, IP/CIDR/Gateway-
|
||||
├── lib/
|
||||
│ ├── build.func # Shared host-side helpers (prompts, LXC create, bootstrap)
|
||||
│ └── install.func # Shared in-container helpers (apt, systemd, users, http-wait)
|
||||
├── tests/
|
||||
│ ├── test_validation.sh # Unit tests for the input validation helpers
|
||||
│ └── check_ct_source.sh # Every ct/*.sh must source build.func
|
||||
├── docs/
|
||||
│ └── adding-a-script.md
|
||||
├── README.md
|
||||
|
||||
@@ -63,8 +63,34 @@ valid_token_word "$RUNNER_LABELS" || { msg_err "RUNNER_LABELS enthält unzuläss
|
||||
# der unprivilegierte User darf dort nicht schreiben.
|
||||
run_user() { runuser -u "$APP_USER" -- env -C "$RUNNER_DIR" HOME="$APP_HOME" "$@"; }
|
||||
|
||||
# ── Pakete: git/rsync, Node (checkout-Action), Docker (Test-Container) ────────
|
||||
setup_base_apt git rsync ca-certificates curl
|
||||
# ── Pakete: git/rsync, Node (checkout-Action), Docker (Test-Container),
|
||||
# Build-Werkzeuge (Compiler-Sprachen in CI) ─────────────────────────────────
|
||||
#
|
||||
# make/gcc/protobuf: Der Runner faehrt Host-Mode, also gibt es kein Image, das
|
||||
# Werkzeuge mitbringt — was hier nicht liegt, hat kein Job. Konkret gemessen an
|
||||
# l.kirchner/patchmgr (Go):
|
||||
# make "make: command not found" in jedem Gate-Job
|
||||
# gcc ohne gefundenen C-Compiler bleibt cgo aus (go env
|
||||
# meldet dann CGO_ENABLED=0), und "go test -race" ist
|
||||
# nicht baubar
|
||||
# protobuf-compiler protoc fuer die Codegenerierung
|
||||
# libprotobuf-dev liefert /usr/include/google/protobuf/*.proto; ohne die
|
||||
# Includes scheitert protoc trotz vorhandenem Binary
|
||||
#
|
||||
# ACHTUNG protoc: Das bindet jedes Repo der Instanz an die protoc-Fassung der
|
||||
# Distribution (Debian 12: 3.21.x). Anders als make/gcc ist protoc ein
|
||||
# Codegenerator — ein Distro-Upgrade aendert erzeugten Code fuer alle Nutzer
|
||||
# gleichzeitig. Wer eine eigene Fassung braucht, pinnt sie im Projekt
|
||||
# (Release-Tarball, buf, oder Docker — der Runner hat Docker) statt sie hier
|
||||
# zu heben.
|
||||
#
|
||||
# Bewusst NICHT installiert: sudo. Ein Workflow soll auf diesem Runner nichts
|
||||
# nachinstallieren koennen — was gebraucht wird, steht hier.
|
||||
#
|
||||
# Go selbst gehoert nicht hierher: Projekte holen es ueber actions/setup-go,
|
||||
# weil CI-Matrizen mehrere Fassungen fahren.
|
||||
setup_base_apt git rsync ca-certificates curl \
|
||||
make gcc protobuf-compiler libprotobuf-dev
|
||||
|
||||
NODE_HAVE="$(command -v node >/dev/null 2>&1 && node -v | sed -E 's/^v([0-9]+).*/\1/' || echo 0)"
|
||||
if [[ "$NODE_HAVE" != "$NODE_MAJOR" ]]; then
|
||||
|
||||
Reference in New Issue
Block a user