Files
linkvault/scripts/proxmox/install-linkvault.sh
Erik Thiele 1a1b6fd896 Set container timezone during Proxmox install
Debian LXC templates default to UTC, which made the "hinzugefügt am"
timestamps and export filenames look wrong. Add a TIMEZONE variable
(default Europe/Berlin) applied via timedatectl during install, and
document it in the README.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-07-30 15:51:45 +02:00

180 lines
6.2 KiB
Bash
Executable File
Raw Permalink 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}"
GIT_TOKEN="${GIT_TOKEN:-}" # Gitea Access Token, falls Repo privat ist
TIMEZONE="${TIMEZONE:-Europe/Berlin}" # wirkt sich auf die angezeigten Datumsangaben aus
# ---------------------------------------------------------------------------
# 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"
echo "==> Zeitzone: $TIMEZONE"
# ---------------------------------------------------------------------------
# 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
timedatectl set-timezone '${TIMEZONE}' || echo 'Warnung: Zeitzone ${TIMEZONE} konnte nicht gesetzt werden.'
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 <<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 "=================================================================="