#!/usr/bin/env bash # # Beliebiger self-hosted Dienst aus einem Git-Repo mit docker-compose, als # eigener LXC für Proxmox VE. Folgt demselben Muster wie OPENBUREAU — passend # für eigene Werkzeuge wie RAPPORT oder DOSSIER. # # AUF DEM PROXMOX-HOST, als root: # bash <(curl -fsSL https://git.kgva.ch/karim/OPENBUREAU/raw/branch/main/proxmox/git-compose-lxc.sh) [name] [disk_gb] [ram_mb] # # Beispiel: … git-compose-lxc.sh git.kgva.ch/karim/RAPPORT-SERVER.git rapport # set -euo pipefail ############################# gemeinsamer Kopf ############################# SSH_PUBKEY_FILE="${SSH_PUBKEY_FILE:-$HOME/.ssh/id_ed25519.pub}" ROOTFS_STORAGE="${ROOTFS_STORAGE:-local-lvm}" TEMPLATE_STORAGE="${TEMPLATE_STORAGE:-local}" BRIDGE="${BRIDGE:-vmbr0}" say() { echo -e "\n\033[1;36m▸ $*\033[0m"; } ok() { echo -e "\033[1;32m✓ $*\033[0m"; } warn() { echo -e "\033[1;33m! $*\033[0m" >&2; } die() { echo -e "\033[1;31m✗ $*\033[0m" >&2; exit 1; } [ "$(id -u)" -eq 0 ] || die "Bitte als root auf dem Proxmox-Host ausführen." command -v pct >/dev/null || die "pct nicht gefunden — läuft das wirklich auf Proxmox VE?" ensure_template() { [ -n "${TEMPLATE_REF:-}" ] && return 0 pveam update >/dev/null 2>&1 || true local tpl tpl="$(pveam available --section system | awk '/debian-12-standard/{print $2}' | sort -V | tail -1)" [ -n "$tpl" ] || die "Kein debian-12-Template verfügbar." pveam list "$TEMPLATE_STORAGE" | grep -q "$tpl" || { say "Lade Template $tpl…"; pveam download "$TEMPLATE_STORAGE" "$tpl" >/dev/null; } TEMPLATE_REF="${TEMPLATE_STORAGE}:vztmpl/${tpl}" } create_lxc() { local name="$1" disk="$2" ram="$3" cores="${4:-2}" ctid ensure_template ctid="$(pvesh get /cluster/nextid)" local args=( "$ctid" "$TEMPLATE_REF" --hostname "$name" --cores "$cores" --memory "$ram" --swap 1024 --rootfs "${ROOTFS_STORAGE}:${disk}" --net0 "name=eth0,bridge=${BRIDGE},ip=dhcp" --unprivileged 1 --features "nesting=1,keyctl=1" --onboot 1 ) [ -f "$SSH_PUBKEY_FILE" ] && args+=(--ssh-public-keys "$SSH_PUBKEY_FILE") say "Erstelle LXC $ctid ($name) — ${cores} Kerne, ${ram} MB RAM, ${disk} GB…" pct create "${args[@]}" >/dev/null pct start "$ctid"; sleep 5 CTID="$ctid" } install_docker() { say "Installiere Docker in $1…" pct exec "$1" -- bash -euo pipefail -c ' export DEBIAN_FRONTEND=noninteractive apt-get update -qq apt-get install -y -qq ca-certificates curl git openssl >/dev/null curl -fsSL https://get.docker.com | sh >/dev/null systemctl enable --now docker ' } ip_of() { pct exec "$1" -- hostname -I 2>/dev/null | awk '{print $1}'; } ################################# Dienst ################################# REPO="${1:-}"; NAME="${2:-}"; DISK="${3:-20}"; RAM="${4:-4096}" [ -n "$REPO" ] || die "Bitte eine Repo-URL angeben (Arg 1)." [ -n "$NAME" ] || NAME="$(basename "${REPO%.git}" | tr '[:upper:]' '[:lower:]')" case "$REPO" in http*://*) : ;; *) REPO="https://$REPO" ;; esac create_lxc "$NAME" "$DISK" "$RAM" install_docker "$CTID" say "Klone $REPO und starte den Stack…" pct exec "$CTID" -- bash -euo pipefail -c " git clone --quiet '$REPO' '/opt/$NAME' || { echo 'Clone fehlgeschlagen.'; exit 1; } cd '/opt/$NAME' CF=\$(ls docker-compose.y*ml compose.y*ml */docker-compose.y*ml */compose.y*ml 2>/dev/null | head -1) [ -n \"\$CF\" ] || { echo 'Keine docker-compose-Datei gefunden.'; exit 1; } cd \"\$(dirname \"\$CF\")\" if [ ! -f .env ] && [ -f .env.example ]; then cp .env.example .env echo 'HINWEIS: .env aus .env.example kopiert — Secrets ggf. anpassen.' fi docker compose up -d --build " ok "$NAME (LXC $CTID) läuft unter $(ip_of "$CTID")." warn "App-spezifische Secrets (.env) ggf. prüfen: pct enter $CTID"