From 102f4a97d9cdc6f733998e90f842f0bd4bbb17dd Mon Sep 17 00:00:00 2001 From: Roland Strunze <1+xosna@noreply.localhost> Date: Sun, 24 May 2026 08:25:42 +0200 Subject: [PATCH] =?UTF-8?q?docker-lxc.sh=20hinzugef=C3=BCgt?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docker-lxc.sh | 251 ++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 251 insertions(+) create mode 100644 docker-lxc.sh diff --git a/docker-lxc.sh b/docker-lxc.sh new file mode 100644 index 0000000..ea49673 --- /dev/null +++ b/docker-lxc.sh @@ -0,0 +1,251 @@ +#!/usr/bin/env bash +# ============================================================================== +# Proxmox LXC: Debian + Docker + Portainer (optional) +# Aufruf auf dem PVE-Host: +# bash <(curl -fsSL https://your-host/debian-docker-portainer-lxc.sh) +# ============================================================================== + +set -euo pipefail + +# ── Farben ───────────────────────────────────────────────────────────────────── +RED='\033[0;31m'; GREEN='\033[0;32m'; YELLOW='\033[1;33m' +CYAN='\033[0;36m'; BOLD='\033[1m'; NC='\033[0m' + +info() { echo -e "${CYAN}[INFO]${NC} $*"; } +success() { echo -e "${GREEN}[OK]${NC} $*"; } +warn() { echo -e "${YELLOW}[WARN]${NC} $*"; } +error() { echo -e "${RED}[ERROR]${NC} $*" >&2; exit 1; } + +# ── Voraussetzungen prüfen ───────────────────────────────────────────────────── +[[ $EUID -ne 0 ]] && error "Dieses Skript muss als root auf dem Proxmox-Host ausgeführt werden." +command -v pct &>/dev/null || error "'pct' nicht gefunden – läuft das Skript auf einem PVE-Host?" +command -v pvesh &>/dev/null || error "'pvesh' nicht gefunden – läuft das Skript auf einem PVE-Host?" + +# ══════════════════════════════════════════════════════════════════════════════ +echo -e "\n${BOLD}╔══════════════════════════════════════════════════════════╗${NC}" +echo -e "${BOLD}║ Proxmox LXC – Debian + Docker + Portainer Installer ║${NC}" +echo -e "${BOLD}╚══════════════════════════════════════════════════════════╝${NC}\n" + +# ── Standardwerte ────────────────────────────────────────────────────────────── +DEFAULT_CTID=$(pvesh get /cluster/nextid) +DEFAULT_HOSTNAME="debian-docker" +DEFAULT_PASSWORD="ChangeMe123!" +DEFAULT_STORAGE="local-lvm" +DEFAULT_DISK=8 # GB +DEFAULT_RAM=2048 # MB +DEFAULT_SWAP=512 # MB +DEFAULT_CORES=2 +DEFAULT_BRIDGE="vmbr0" +DEFAULT_IP="dhcp" # oder z.B. 192.168.1.100/24 +DEFAULT_GW="" # Gateway (nur bei statischer IP) + +# ── Interaktive Eingabe ──────────────────────────────────────────────────────── +ask() { + local prompt="$1" default="$2" var_name="$3" + echo -ne "${BOLD}${prompt}${NC} [${YELLOW}${default}${NC}]: " + read -r input + printf -v "$var_name" '%s' "${input:-$default}" +} + +ask_yn() { + local prompt="$1" default="${2:-y}" + echo -ne "${BOLD}${prompt}${NC} [${YELLOW}${default}${NC}]: " + read -r yn + [[ "${yn:-$default}" =~ ^[Jj1Yy] ]] +} + +echo -e "${CYAN}── Container-Grundkonfiguration ────────────────────────────${NC}" +ask "Container-ID" "$DEFAULT_CTID" CTID +ask "Hostname" "$DEFAULT_HOSTNAME" HOSTNAME +ask "Root-Passwort" "$DEFAULT_PASSWORD" PASSWORD +ask "Storage" "$DEFAULT_STORAGE" STORAGE +ask "Disk-Größe (GB)" "$DEFAULT_DISK" DISK +ask "RAM (MB)" "$DEFAULT_RAM" RAM +ask "Swap (MB)" "$DEFAULT_SWAP" SWAP +ask "CPU-Kerne" "$DEFAULT_CORES" CORES +ask "Netzwerk-Bridge" "$DEFAULT_BRIDGE" BRIDGE + +echo "" +echo -e "${CYAN}── Netzwerk ────────────────────────────────────────────────${NC}" +echo -e " Für DHCP einfach '${YELLOW}dhcp${NC}' eingeben." +echo -e " Für statische IP z.B. '${YELLOW}192.168.1.100/24${NC}'" +ask "IP-Adresse" "$DEFAULT_IP" IP_ADDR +if [[ "$IP_ADDR" != "dhcp" ]]; then + ask "Gateway" "$DEFAULT_GW" GATEWAY +fi + +echo "" +echo -e "${CYAN}── Optionale Komponenten ───────────────────────────────────${NC}" +if ask_yn "Portainer CE installieren? (Web-UI für Docker)" "j"; then + INSTALL_PORTAINER=true + ask "Portainer HTTPS-Port" "9443" PORTAINER_PORT +else + INSTALL_PORTAINER=false +fi + +if ask_yn "SSH-Zugriff für root aktivieren?" "j"; then + ENABLE_ROOT_SSH=true +else + ENABLE_ROOT_SSH=false +fi + +if ask_yn "Unprivilegierten Container erstellen? (empfohlen)" "j"; then + UNPRIVILEGED=1 +else + UNPRIVILEGED=0 +fi + +# ── Zusammenfassung ──────────────────────────────────────────────────────────── +echo "" +echo -e "${BOLD}╔══════════════ Zusammenfassung ════════════════╗${NC}" +printf "${BOLD}║${NC} %-22s %-20s ${BOLD}║${NC}\n" "Container-ID:" "$CTID" +printf "${BOLD}║${NC} %-22s %-20s ${BOLD}║${NC}\n" "Hostname:" "$HOSTNAME" +printf "${BOLD}║${NC} %-22s %-20s ${BOLD}║${NC}\n" "Storage:" "$STORAGE" +printf "${BOLD}║${NC} %-22s %-20s ${BOLD}║${NC}\n" "Disk:" "${DISK} GB" +printf "${BOLD}║${NC} %-22s %-20s ${BOLD}║${NC}\n" "RAM / Swap:" "${RAM} MB / ${SWAP} MB" +printf "${BOLD}║${NC} %-22s %-20s ${BOLD}║${NC}\n" "CPU-Kerne:" "$CORES" +printf "${BOLD}║${NC} %-22s %-20s ${BOLD}║${NC}\n" "Netzwerk:" "$IP_ADDR" +printf "${BOLD}║${NC} %-22s %-20s ${BOLD}║${NC}\n" "Portainer:" "$( $INSTALL_PORTAINER && echo "Ja (:${PORTAINER_PORT})" || echo "Nein" )" +printf "${BOLD}║${NC} %-22s %-20s ${BOLD}║${NC}\n" "Root-SSH:" "$( $ENABLE_ROOT_SSH && echo "Ja" || echo "Nein" )" +printf "${BOLD}║${NC} %-22s %-20s ${BOLD}║${NC}\n" "Unprivilegiert:" "$( [[ $UNPRIVILEGED -eq 1 ]] && echo "Ja" || echo "Nein" )" +echo -e "${BOLD}╚══════════════════════════════════════════════╝${NC}" +echo "" +ask_yn "Jetzt installieren?" "j" || { echo "Abgebrochen."; exit 0; } + +# ── Debian-Template herunterladen ────────────────────────────────────────────── +info "Suche aktuelles Debian-LXC-Template …" +TEMPLATE_STORAGE="local" +TEMPLATE=$(pveam available --section system | awk '/debian-1[2-9]/ {print $2}' | sort -V | tail -1) +[[ -z "$TEMPLATE" ]] && error "Kein Debian-Template in der PVE-Datenbank gefunden. 'pveam update' ausführen!" + +DOWNLOADED=$(pveam list "$TEMPLATE_STORAGE" 2>/dev/null | awk '{print $1}' | grep -F "$TEMPLATE" || true) +if [[ -z "$DOWNLOADED" ]]; then + info "Lade Template herunter: $TEMPLATE" + pveam download "$TEMPLATE_STORAGE" "$TEMPLATE" + success "Template geladen." +else + success "Template bereits vorhanden: $TEMPLATE" +fi + +TEMPLATE_PATH="${TEMPLATE_STORAGE}:vztmpl/${TEMPLATE}" + +# ── LXC-Container erstellen ──────────────────────────────────────────────────── +info "Erstelle LXC-Container $CTID …" + +NET_CONFIG="name=eth0,bridge=${BRIDGE}" +if [[ "$IP_ADDR" == "dhcp" ]]; then + NET_CONFIG+=",ip=dhcp" +else + NET_CONFIG+=",ip=${IP_ADDR}" + [[ -n "${GATEWAY:-}" ]] && NET_CONFIG+=",gw=${GATEWAY}" +fi + +pct create "$CTID" "$TEMPLATE_PATH" \ + --hostname "$HOSTNAME" \ + --password "$PASSWORD" \ + --storage "$STORAGE" \ + --rootfs "${STORAGE}:${DISK}" \ + --memory "$RAM" \ + --swap "$SWAP" \ + --cores "$CORES" \ + --net0 "$NET_CONFIG" \ + --unprivileged "$UNPRIVILEGED" \ + --features "keyctl=1,nesting=1" \ + --onboot 1 \ + --start 0 + +success "Container $CTID erstellt." + +# ── Container starten ────────────────────────────────────────────────────────── +info "Starte Container …" +pct start "$CTID" +sleep 5 + +# ── Hilfsfunktion: Befehl im Container ausführen ────────────────────────────── +lxc_exec() { pct exec "$CTID" -- bash -c "$*"; } + +# ── System aktualisieren ─────────────────────────────────────────────────────── +info "System aktualisieren (apt update & upgrade) …" +lxc_exec "apt-get update -qq && apt-get upgrade -y -qq" +lxc_exec "apt-get install -y -qq ca-certificates curl gnupg lsb-release wget" +success "System aktuell." + +# ── Docker installieren (offizieller Weg) ───────────────────────────────────── +info "Docker Engine installieren …" +lxc_exec " +install -m 0755 -d /etc/apt/keyrings +curl -fsSL https://download.docker.com/linux/debian/gpg \ + | gpg --dearmor -o /etc/apt/keyrings/docker.gpg --yes +chmod a+r /etc/apt/keyrings/docker.gpg + +echo \"deb [arch=\$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.gpg] \ + https://download.docker.com/linux/debian \ + \$(. /etc/os-release && echo \"\$VERSION_CODENAME\") stable\" \ + > /etc/apt/sources.list.d/docker.list + +apt-get update -qq +apt-get install -y -qq \ + docker-ce docker-ce-cli containerd.io \ + docker-buildx-plugin docker-compose-plugin + +systemctl enable docker --now +" +success "Docker installiert." + +# ── Docker testen ────────────────────────────────────────────────────────────── +info "Docker-Funktionstest …" +if lxc_exec "docker run --rm hello-world" &>/dev/null; then + success "Docker läuft korrekt." +else + warn "Docker-Test fehlgeschlagen – bitte manuell prüfen." +fi + +# ── Portainer installieren ───────────────────────────────────────────────────── +if $INSTALL_PORTAINER; then + info "Portainer CE installieren (Port ${PORTAINER_PORT}) …" + lxc_exec " +docker volume create portainer_data +docker run -d \ + --name portainer \ + --restart always \ + -p 8000:8000 \ + -p ${PORTAINER_PORT}:9443 \ + -v /var/run/docker.sock:/var/run/docker.sock \ + -v portainer_data:/data \ + portainer/portainer-ce:latest +" + success "Portainer CE gestartet." +fi + +# ── SSH konfigurieren ────────────────────────────────────────────────────────── +if $ENABLE_ROOT_SSH; then + info "Aktiviere Root-SSH-Login …" + lxc_exec " +sed -i 's/^#*PermitRootLogin.*/PermitRootLogin yes/' /etc/ssh/sshd_config +sed -i 's/^#*PasswordAuthentication.*/PasswordAuthentication yes/' /etc/ssh/sshd_config +systemctl restart ssh +" + success "Root-SSH aktiviert." +fi + +# ── Abschluss ────────────────────────────────────────────────────────────────── +CONTAINER_IP=$(pct exec "$CTID" -- hostname -I 2>/dev/null | awk '{print $1}' || echo "unbekannt") + +echo "" +echo -e "${BOLD}${GREEN}╔═══════════════════════ Fertig! ═══════════════════════╗${NC}" +echo -e "${GREEN}║${NC}" +echo -e "${GREEN}║${NC} Container-ID : ${BOLD}${CTID}${NC}" +echo -e "${GREEN}║${NC} Hostname : ${BOLD}${HOSTNAME}${NC}" +echo -e "${GREEN}║${NC} IP-Adresse : ${BOLD}${CONTAINER_IP}${NC}" +echo -e "${GREEN}║${NC}" +echo -e "${GREEN}║${NC} Docker : ${BOLD}installiert & aktiv${NC}" +if $INSTALL_PORTAINER; then +echo -e "${GREEN}║${NC} Portainer : ${BOLD}https://${CONTAINER_IP}:${PORTAINER_PORT}${NC}" +fi +if $ENABLE_ROOT_SSH; then +echo -e "${GREEN}║${NC} SSH : ${BOLD}ssh root@${CONTAINER_IP}${NC}" +fi +echo -e "${GREEN}║${NC}" +echo -e "${GREEN}║${NC} ${YELLOW}Bitte das Root-Passwort nach dem ersten Login ändern!${NC}" +echo -e "${GREEN}║${NC}" +echo -e "${BOLD}${GREEN}╚═══════════════════════════════════════════════════════╝${NC}\n" \ No newline at end of file