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>
180 lines
6.2 KiB
Bash
Executable File
180 lines
6.2 KiB
Bash
Executable File
#!/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 "=================================================================="
|