#!/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}" GIT_TOKEN="${GIT_TOKEN:-}" # Gitea Access Token, falls Repo privat ist # --------------------------------------------------------------------------- # 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="$(pveam list "$TEMPLATE_STORAGE" | awk '{print $1}' | grep -o 'debian-12-standard_[^ ]*\.tar\.zst' | sort -V | tail -n1)" if [ -z "$TEMPLATE" ]; then echo "==> Lade Debian-12-Template herunter..." pveam update TEMPLATE="$(pveam available --section system | awk '{print $2}' | grep '^debian-12-standard_.*\.tar\.zst$' | sort -V | tail -n1)" if [ -z "$TEMPLATE" ]; then echo "Fehler: Kein debian-12-standard-Template in 'pveam available' gefunden." >&2 exit 1 fi pveam download "$TEMPLATE_STORAGE" "$TEMPLATE" fi echo "==> Verwende Template: $TEMPLATE" # --------------------------------------------------------------------------- # 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 if [ -n '${GIT_TOKEN}' ]; then git -c http.extraHeader=\"Authorization: token ${GIT_TOKEN}\" clone --quiet '${REPO_URL}' /opt/linkvault else git clone --quiet '${REPO_URL}' /opt/linkvault fi 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 <