Files
linkvault/scripts/proxmox/install-linkvault.sh
Erik Thiele fc9033d89a 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>
2026-07-19 19:11:47 +02:00

165 lines
5.3 KiB
Bash
Executable File
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
#!/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 "=================================================================="