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:
13
README.md
13
README.md
@@ -61,6 +61,19 @@ app/
|
||||
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
|
||||
|
||||
- Einen zufälligen `SECRET_KEY` in `.env` setzen.
|
||||
|
||||
164
scripts/proxmox/install-linkvault.sh
Executable file
164
scripts/proxmox/install-linkvault.sh
Executable 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 "=================================================================="
|
||||
Reference in New Issue
Block a user