Add Proxmox LXC helper-script for automated installation

Creates a Debian 12 LXC container and sets up LinkVault as a systemd
service inside it, following the tteck/community-scripts pattern.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
Erik Thiele
2026-07-19 19:11:47 +02:00
parent 47685f0d34
commit fc9033d89a
2 changed files with 177 additions and 0 deletions

View File

@@ -61,6 +61,19 @@ app/
templates/ Jinja2 + HTMX Oberfläche templates/ Jinja2 + HTMX Oberfläche
``` ```
## Proxmox
Für den Betrieb in einem Proxmox-VE-LXC-Container gibt es ein Helper-Script,
das einen Debian-12-Container anlegt und LinkVault darin als systemd-Service
einrichtet. Auf dem Proxmox-Host ausführen:
```bash
bash scripts/proxmox/install-linkvault.sh
```
Konfiguration (Container-ID, IP, Ressourcen, ...) über Umgebungsvariablen,
siehe Kommentare im Script.
## Hinweise für den Produktivbetrieb ## Hinweise für den Produktivbetrieb
- Einen zufälligen `SECRET_KEY` in `.env` setzen. - Einen zufälligen `SECRET_KEY` in `.env` setzen.

View File

@@ -0,0 +1,164 @@
#!/usr/bin/env bash
#
# LinkVault Proxmox VE Helper-Script
#
# Muss als root auf dem Proxmox-VE-Host ausgeführt werden. Legt einen neuen
# Debian-12-LXC-Container an und installiert darin LinkVault (FastAPI-App)
# als systemd-Service.
#
# Verwendung (auf dem Proxmox-Host):
# bash install-linkvault.sh
#
# Konfiguration über Umgebungsvariablen (optional, siehe Defaults unten), z.B.:
# CTID=150 CT_HOSTNAME=linkvault CT_IP=192.168.1.50/24 CT_GW=192.168.1.1 \
# bash install-linkvault.sh
#
set -euo pipefail
# ---------------------------------------------------------------------------
# Konfiguration (per ENV überschreibbar)
# ---------------------------------------------------------------------------
CTID="${CTID:-$(pvesh get /cluster/nextid)}"
CT_HOSTNAME="${CT_HOSTNAME:-linkvault}"
CT_DISK_GB="${CT_DISK_GB:-8}"
CT_MEMORY_MB="${CT_MEMORY_MB:-1024}"
CT_SWAP_MB="${CT_SWAP_MB:-512}"
CT_CORES="${CT_CORES:-2}"
CT_BRIDGE="${CT_BRIDGE:-vmbr0}"
CT_IP="${CT_IP:-dhcp}" # z.B. 192.168.1.50/24, sonst "dhcp"
CT_GW="${CT_GW:-}" # nur nötig bei statischer IP
CT_STORAGE="${CT_STORAGE:-local-lvm}"
TEMPLATE_STORAGE="${TEMPLATE_STORAGE:-local}"
CT_PASSWORD="${CT_PASSWORD:-}" # leer = zufällig generiert
REPO_URL="${REPO_URL:-https://gitea.teamthiele.de/ethiele/linkvault.git}"
APP_PORT="${APP_PORT:-8000}"
# ---------------------------------------------------------------------------
# Vorbedingungen
# ---------------------------------------------------------------------------
if ! command -v pct &>/dev/null; then
echo "Fehler: 'pct' nicht gefunden dieses Script muss auf einem Proxmox-VE-Host laufen." >&2
exit 1
fi
if [ -z "$CT_PASSWORD" ]; then
CT_PASSWORD="$(openssl rand -base64 18)"
fi
echo "==> Container-ID: $CTID"
echo "==> Hostname: $CT_HOSTNAME"
echo "==> Storage (RootFS): $CT_STORAGE"
echo "==> Netzwerk: $CT_BRIDGE / $CT_IP"
# ---------------------------------------------------------------------------
# Debian-12-Template sicherstellen
# ---------------------------------------------------------------------------
TEMPLATE="debian-12-standard_12.7-1_amd64.tar.zst"
if ! pveam list "$TEMPLATE_STORAGE" | grep -q "$TEMPLATE"; then
echo "==> Lade Debian-12-Template herunter..."
pveam update
pveam download "$TEMPLATE_STORAGE" "$TEMPLATE"
fi
# ---------------------------------------------------------------------------
# LXC-Container anlegen
# ---------------------------------------------------------------------------
if [ "$CT_IP" = "dhcp" ]; then
NET_CONF="name=eth0,bridge=${CT_BRIDGE},ip=dhcp"
else
if [ -z "$CT_GW" ]; then
echo "Fehler: CT_GW (Gateway) muss bei statischer IP gesetzt sein." >&2
exit 1
fi
NET_CONF="name=eth0,bridge=${CT_BRIDGE},ip=${CT_IP},gw=${CT_GW}"
fi
echo "==> Erstelle LXC-Container $CTID..."
pct create "$CTID" "${TEMPLATE_STORAGE}:vztmpl/${TEMPLATE}" \
--hostname "$CT_HOSTNAME" \
--cores "$CT_CORES" \
--memory "$CT_MEMORY_MB" \
--swap "$CT_SWAP_MB" \
--rootfs "${CT_STORAGE}:${CT_DISK_GB}" \
--net0 "$NET_CONF" \
--password "$CT_PASSWORD" \
--unprivileged 1 \
--features nesting=1 \
--onboot 1
echo "==> Starte Container..."
pct start "$CTID"
echo "==> Warte auf Netzwerk..."
for i in $(seq 1 30); do
if pct exec "$CTID" -- ping -c1 -W2 deb.debian.org &>/dev/null; then
break
fi
sleep 2
done
# ---------------------------------------------------------------------------
# Installation innerhalb des Containers
# ---------------------------------------------------------------------------
echo "==> Installiere Abhängigkeiten und LinkVault im Container..."
pct exec "$CTID" -- bash -c "
set -euo pipefail
export DEBIAN_FRONTEND=noninteractive
apt-get update -qq
apt-get install -y -qq git python3 python3-venv python3-pip build-essential curl >/dev/null
if [ ! -d /opt/linkvault ]; then
git clone --quiet '${REPO_URL}' /opt/linkvault
fi
cd /opt/linkvault
python3 -m venv .venv
.venv/bin/pip install -q --upgrade pip
.venv/bin/pip install -q -r requirements.txt
if [ ! -f .env ]; then
cp .env.example .env
SECRET=\$(.venv/bin/python3 -c 'import secrets; print(secrets.token_hex(32))')
sed -i \"s#^SECRET_KEY=.*#SECRET_KEY=\$SECRET#\" .env
fi
useradd --system --home /opt/linkvault --shell /usr/sbin/nologin linkvault 2>/dev/null || true
chown -R linkvault:linkvault /opt/linkvault
cat > /etc/systemd/system/linkvault.service <<EOF
[Unit]
Description=LinkVault
After=network.target
[Service]
Type=simple
User=linkvault
Group=linkvault
WorkingDirectory=/opt/linkvault
EnvironmentFile=/opt/linkvault/.env
ExecStart=/opt/linkvault/.venv/bin/uvicorn app.main:app --host 0.0.0.0 --port ${APP_PORT}
Restart=on-failure
RestartSec=5
[Install]
WantedBy=multi-user.target
EOF
systemctl daemon-reload
systemctl enable --quiet linkvault
systemctl restart linkvault
"
CT_ACTUAL_IP="$(pct exec "$CTID" -- hostname -I | awk '{print $1}')"
echo ""
echo "=================================================================="
echo " LinkVault wurde installiert (Container $CTID / $CT_HOSTNAME)"
echo ""
echo " URL: http://${CT_ACTUAL_IP}:${APP_PORT}"
echo " Container-Login: root / ${CT_PASSWORD}"
echo ""
echo " Wichtig: In /opt/linkvault/.env innerhalb des Containers noch den"
echo " OPENAI_API_KEY eintragen, danach:"
echo " pct exec ${CTID} -- systemctl restart linkvault"
echo "=================================================================="