debian_install.sh aktualisiert

This commit is contained in:
2026-05-24 11:36:04 +02:00
parent f834fb09b0
commit 587b1a11ee
+543
View File
@@ -0,0 +1,543 @@
#!/usr/bin/env bash
# ==============================================================================
# Proxmox LXC: Debian (minimal, sauber, produktionsbereit)
# Aufruf auf dem PVE-Host:
# bash <(curl -fsSL https://your-host/debian-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 Installer ║${NC}"
echo -e "${BOLD}╚══════════════════════════════════════════════════╝${NC}\n"
# ── Standardwerte ──────────────────────────────────────────────────────────────
DEFAULT_CTID=$(pvesh get /cluster/nextid)
DEFAULT_HOSTNAME="debian"
DEFAULT_PASSWORD="ChangeMe123!"
DEFAULT_DISK=4 # GB
DEFAULT_RAM=512 # MB (Debian braucht wenig)
DEFAULT_SWAP=512 # MB
DEFAULT_CORES=1
DEFAULT_BRIDGE="vmbr0"
DEFAULT_IP="dhcp"
DEFAULT_GW=""
# ── Hilfsfunktionen ────────────────────────────────────────────────────────────
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:-j}"
echo -ne "${BOLD}${prompt}${NC} [${YELLOW}${default}${NC}]: "
read -r yn
[[ "${yn:-$default}" =~ ^[Jj1Yy] ]]
}
# ── Storage-Auswahl (dynamisch) ────────────────────────────────────────────────
select_storage() {
echo -e "${CYAN}── Storage-Auswahl ──────────────────────────────────────────${NC}"
echo -e " Verfügbare Storages auf diesem Host:\n"
mapfile -t STORAGE_LINES < <(
pvesm status --content rootdir 2>/dev/null \
| awk 'NR>1 && $3=="active" {print $1, $2, $5, $4}' | sort
)
if [[ ${#STORAGE_LINES[@]} -eq 0 ]]; then
mapfile -t STORAGE_LINES < <(
pvesm status 2>/dev/null \
| awk 'NR>1 && $3=="active" {print $1, $2, $5, $4}' | sort
)
fi
if [[ ${#STORAGE_LINES[@]} -eq 0 ]]; then
warn "Keine aktiven Storages gefunden bitte manuell eingeben."
ask "Storage-Name" "local-lvm" STORAGE
return
fi
local i=1
local -a STORAGE_NAMES=()
printf " ${BOLD}%-4s %-20s %-14s %-12s %-12s${NC}\n" "Nr." "Name" "Typ" "Frei" "Gesamt"
echo -e " ──────────────────────────────────────────────────────────"
for line in "${STORAGE_LINES[@]}"; do
read -r sname stype sused stotal <<< "$line"
local sfree=0
if [[ "$stotal" =~ ^[0-9]+$ ]] && [[ "$sused" =~ ^[0-9]+$ ]]; then
sfree=$(( stotal - sused ))
fi
human_size() {
local kb=$1
if (( kb >= 1073741824 )); then printf "%.1f TiB" "$(echo "scale=1; $kb/1073741824" | bc)"
elif (( kb >= 1048576 )); then printf "%.1f GiB" "$(echo "scale=1; $kb/1048576" | bc)"
elif (( kb >= 1024 )); then printf "%.1f MiB" "$(echo "scale=1; $kb/1024" | bc)"
else printf "%d KiB" "$kb"; fi
}
local free_str total_str
if [[ "$stotal" =~ ^[0-9]+$ ]] && (( stotal > 0 )); then
free_str=$(human_size "$sfree")
total_str=$(human_size "$stotal")
else
free_str="n/a"; total_str="n/a"
fi
local color="$GREEN"
if [[ "$stotal" =~ ^[0-9]+$ ]] && (( stotal > 0 )); then
local pct=$(( sfree * 100 / stotal ))
(( pct < 15 )) && color="$RED"
(( pct >= 15 && pct < 30 )) && color="$YELLOW"
fi
printf " ${BOLD}%-4s${NC} ${color}%-20s${NC} %-14s %-12s %-12s\n" \
"[$i]" "$sname" "$stype" "$free_str" "$total_str"
STORAGE_NAMES+=("$sname")
(( i++ ))
done
echo ""
local DEFAULT_NUM=1
while true; do
echo -ne "${BOLD}Auswahl (Nummer eingeben)${NC} [${YELLOW}${DEFAULT_NUM}${NC}]: "
read -r sel
sel="${sel:-$DEFAULT_NUM}"
if [[ "$sel" =~ ^[0-9]+$ ]] && (( sel >= 1 && sel <= ${#STORAGE_NAMES[@]} )); then
STORAGE="${STORAGE_NAMES[$((sel-1))]}"
success "Storage gewählt: ${BOLD}${STORAGE}${NC}"
break
else
warn "Ungültige Eingabe. Bitte eine Zahl zwischen 1 und ${#STORAGE_NAMES[@]} eingeben."
fi
done
echo ""
}
# ══════════════════════════════════════════════════════════════════════════════
# KONFIGURATION
# ══════════════════════════════════════════════════════════════════════════════
echo -e "${CYAN}── Container-Grundkonfiguration ─────────────────────────────${NC}"
ask "Container-ID" "$DEFAULT_CTID" CTID
ask "Hostname" "$DEFAULT_HOSTNAME" HOSTNAME
ask "Root-Passwort" "$DEFAULT_PASSWORD" PASSWORD
echo ""
select_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.50/24${NC}'"
ask "IP-Adresse" "$DEFAULT_IP" IP_ADDR
if [[ "$IP_ADDR" != "dhcp" ]]; then
ask "Gateway" "$DEFAULT_GW" GATEWAY
fi
echo ""
echo -e "${CYAN}── Container-Typ ─────────────────────────────────────────────${NC}"
if ask_yn "Unprivilegierten Container erstellen? (empfohlen)" "j"; then
UNPRIVILEGED=1
else
UNPRIVILEGED=0
fi
echo ""
echo -e "${CYAN}── Optionale Pakete ──────────────────────────────────────────${NC}"
echo -e " Wähle zusätzliche Pakete die installiert werden sollen:\n"
if ask_yn "curl, wget, git (Basis-Tools)" "j"; then
INSTALL_BASETOOLS=true
else
INSTALL_BASETOOLS=false
fi
if ask_yn "htop, ncdu, tree, net-tools (System-Monitoring)" "j"; then
INSTALL_MONITORING=true
else
INSTALL_MONITORING=false
fi
if ask_yn "vim + nano (Editoren)" "j"; then
INSTALL_EDITORS=true
else
INSTALL_EDITORS=false
fi
if ask_yn "ufw (Firewall, deaktiviert)" "n"; then
INSTALL_UFW=true
else
INSTALL_UFW=false
fi
if ask_yn "cron + logrotate (Automatisierung)" "j"; then
INSTALL_CRON=true
else
INSTALL_CRON=false
fi
if ask_yn "fail2ban (Schutz gegen Brute-Force)" "n"; then
INSTALL_FAIL2BAN=true
else
INSTALL_FAIL2BAN=false
fi
echo ""
echo -e "${CYAN}── Zeitzone ──────────────────────────────────────────────────${NC}"
ask "Zeitzone" "Europe/Berlin" TIMEZONE
echo ""
echo -e "${CYAN}── SSH-Zugriff ───────────────────────────────────────────────${NC}"
if ask_yn "SSH-Root-Login von externen Terminals aktivieren?" "j"; then
ENABLE_ROOT_SSH=true
ask "SSH-Port" "22" SSH_PORT
echo ""
echo -e " ${BOLD}Authentifizierungsmethode:${NC}"
echo -e " ${YELLOW}[1]${NC} Nur Passwort"
echo -e " ${YELLOW}[2]${NC} Nur SSH-Key (du gibst deinen Public Key ein)"
echo -e " ${YELLOW}[3]${NC} Passwort ${BOLD}und${NC} SSH-Key (beide erlaubt)"
echo -ne "${BOLD}Auswahl${NC} [${YELLOW}1${NC}]: "
read -r ssh_auth_sel
case "${ssh_auth_sel:-1}" in
2) SSH_AUTH="key" ;;
3) SSH_AUTH="both" ;;
*) SSH_AUTH="password" ;;
esac
SSH_PUBKEY=""
if [[ "$SSH_AUTH" == "key" || "$SSH_AUTH" == "both" ]]; then
echo ""
echo -e " Gib deinen SSH-Public-Key ein (Inhalt von ${YELLOW}~/.ssh/id_rsa.pub${NC} o.ä.):"
echo -ne " ${BOLD}Public Key:${NC} "
read -r SSH_PUBKEY
if [[ -z "$SSH_PUBKEY" ]]; then
warn "Kein Public Key eingegeben falle auf Passwort-Auth zurück."
SSH_AUTH="password"
fi
fi
else
ENABLE_ROOT_SSH=false
SSH_PORT="22"
SSH_AUTH="password"
fi
# ── Zusammenfassung ────────────────────────────────────────────────────────────
echo ""
echo -e "${BOLD}╔══════════════════ Zusammenfassung ════════════════════╗${NC}"
printf "${BOLD}${NC} %-22s %-26s ${BOLD}${NC}\n" "Container-ID:" "$CTID"
printf "${BOLD}${NC} %-22s %-26s ${BOLD}${NC}\n" "Hostname:" "$HOSTNAME"
printf "${BOLD}${NC} %-22s %-26s ${BOLD}${NC}\n" "Storage:" "$STORAGE"
printf "${BOLD}${NC} %-22s %-26s ${BOLD}${NC}\n" "Disk / RAM / Swap:" "${DISK} GB / ${RAM} MB / ${SWAP} MB"
printf "${BOLD}${NC} %-22s %-26s ${BOLD}${NC}\n" "CPU-Kerne:" "$CORES"
printf "${BOLD}${NC} %-22s %-26s ${BOLD}${NC}\n" "Netzwerk:" "$IP_ADDR"
printf "${BOLD}${NC} %-22s %-26s ${BOLD}${NC}\n" "Zeitzone:" "$TIMEZONE"
printf "${BOLD}${NC} %-22s %-26s ${BOLD}${NC}\n" "Unprivilegiert:" "$( [[ $UNPRIVILEGED -eq 1 ]] && echo "Ja" || echo "Nein" )"
printf "${BOLD}${NC} %-22s %-26s ${BOLD}${NC}\n" "Basis-Tools:" "$( $INSTALL_BASETOOLS && echo "Ja" || echo "Nein" )"
printf "${BOLD}${NC} %-22s %-26s ${BOLD}${NC}\n" "Monitoring-Tools:" "$( $INSTALL_MONITORING && echo "Ja" || echo "Nein" )"
printf "${BOLD}${NC} %-22s %-26s ${BOLD}${NC}\n" "Editoren:" "$( $INSTALL_EDITORS && echo "Ja" || echo "Nein" )"
printf "${BOLD}${NC} %-22s %-26s ${BOLD}${NC}\n" "UFW Firewall:" "$( $INSTALL_UFW && echo "Ja" || echo "Nein" )"
printf "${BOLD}${NC} %-22s %-26s ${BOLD}${NC}\n" "Cron/Logrotate:" "$( $INSTALL_CRON && echo "Ja" || echo "Nein" )"
printf "${BOLD}${NC} %-22s %-26s ${BOLD}${NC}\n" "fail2ban:" "$( $INSTALL_FAIL2BAN && echo "Ja" || echo "Nein" )"
printf "${BOLD}${NC} %-22s %-26s ${BOLD}${NC}\n" "Root-SSH:" "$( $ENABLE_ROOT_SSH && echo "Ja (Port ${SSH_PORT}, ${SSH_AUTH})" || echo "Nein" )"
echo -e "${BOLD}╚═══════════════════════════════════════════════════════╝${NC}"
echo ""
ask_yn "Jetzt installieren?" "j" || { echo "Abgebrochen."; exit 0; }
# ══════════════════════════════════════════════════════════════════════════════
# INSTALLATION
# ══════════════════════════════════════════════════════════════════════════════
# ── 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 gefunden. Bitte '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 ──────────────────────────────────────────────────────────────
lxc_exec() { pct exec "$CTID" -- bash -c "$*"; }
# ── System aktualisieren ───────────────────────────────────────────────────────
info "System aktualisieren …"
lxc_exec "apt-get update -qq && apt-get upgrade -y -qq"
lxc_exec "apt-get install -y -qq ca-certificates locales"
success "System aktuell."
# ── Zeitzone setzen ────────────────────────────────────────────────────────────
info "Zeitzone setzen: ${TIMEZONE}"
lxc_exec "
ln -sf /usr/share/zoneinfo/${TIMEZONE} /etc/localtime
echo '${TIMEZONE}' > /etc/timezone
dpkg-reconfigure -f noninteractive tzdata 2>/dev/null || true
"
success "Zeitzone gesetzt."
# ── Locale konfigurieren ───────────────────────────────────────────────────────
info "Locale konfigurieren (de_DE.UTF-8 + en_US.UTF-8) …"
lxc_exec "
sed -i 's/^# *de_DE.UTF-8/de_DE.UTF-8/' /etc/locale.gen
sed -i 's/^# *en_US.UTF-8/en_US.UTF-8/' /etc/locale.gen
locale-gen 2>/dev/null
update-locale LANG=de_DE.UTF-8 LC_MESSAGES=en_US.UTF-8
" 2>/dev/null || warn "Locale-Konfiguration übersprungen."
success "Locale konfiguriert."
# ── Optionale Pakete installieren ──────────────────────────────────────────────
PKGS=()
if $INSTALL_BASETOOLS; then
PKGS+=(curl wget git)
fi
if $INSTALL_MONITORING; then
PKGS+=(htop ncdu tree net-tools iputils-ping)
fi
if $INSTALL_EDITORS; then
PKGS+=(vim nano)
fi
if $INSTALL_CRON; then
PKGS+=(cron logrotate)
fi
if $INSTALL_FAIL2BAN; then
PKGS+=(fail2ban)
fi
if $INSTALL_UFW; then
PKGS+=(ufw)
fi
if [[ ${#PKGS[@]} -gt 0 ]]; then
info "Installiere optionale Pakete: ${PKGS[*]}"
lxc_exec "apt-get install -y -qq ${PKGS[*]}"
success "Pakete installiert."
fi
# ── fail2ban konfigurieren (falls installiert) ─────────────────────────────────
if $INSTALL_FAIL2BAN; then
info "fail2ban konfigurieren …"
lxc_exec "
cat > /etc/fail2ban/jail.local << 'F2B'
[DEFAULT]
bantime = 1h
findtime = 10m
maxretry = 5
backend = systemd
[sshd]
enabled = true
F2B
systemctl enable fail2ban --now
"
success "fail2ban aktiv (SSH-Schutz: 5 Versuche / 10 Min → 1h Ban)."
fi
# ── UFW konfigurieren (falls installiert) ──────────────────────────────────────
if $INSTALL_UFW; then
info "UFW vorbereiten (deaktiviert, SSH freigegeben) …"
lxc_exec "
ufw default deny incoming
ufw default allow outgoing
ufw allow ${SSH_PORT}/tcp comment 'SSH'
# ufw enable ← bewusst nicht aktiviert; bitte manuell nach Prüfung aktivieren
"
success "UFW konfiguriert (noch deaktiviert mit 'ufw enable' aktivieren)."
fi
# ── SSH vollständig konfigurieren ─────────────────────────────────────────────
if $ENABLE_ROOT_SSH; then
info "Installiere und konfiguriere SSH-Server …"
lxc_exec "apt-get install -y -qq openssh-server"
lxc_exec "
sed -i 's/^#*PermitRootLogin.*/PermitRootLogin yes/' /etc/ssh/sshd_config
grep -q '^PermitRootLogin' /etc/ssh/sshd_config || echo 'PermitRootLogin yes' >> /etc/ssh/sshd_config
sed -i 's/^#*Port .*/Port ${SSH_PORT}/' /etc/ssh/sshd_config
grep -q '^Port ' /etc/ssh/sshd_config || echo 'Port ${SSH_PORT}' >> /etc/ssh/sshd_config
"
if [[ "$SSH_AUTH" == "password" ]]; then
lxc_exec "
sed -i 's/^#*PasswordAuthentication.*/PasswordAuthentication yes/' /etc/ssh/sshd_config
grep -q '^PasswordAuthentication' /etc/ssh/sshd_config || echo 'PasswordAuthentication yes' >> /etc/ssh/sshd_config
sed -i 's/^#*PubkeyAuthentication.*/PubkeyAuthentication no/' /etc/ssh/sshd_config
"
elif [[ "$SSH_AUTH" == "key" ]]; then
lxc_exec "
sed -i 's/^#*PasswordAuthentication.*/PasswordAuthentication no/' /etc/ssh/sshd_config
sed -i 's/^#*PubkeyAuthentication.*/PubkeyAuthentication yes/' /etc/ssh/sshd_config
grep -q '^PubkeyAuthentication' /etc/ssh/sshd_config || echo 'PubkeyAuthentication yes' >> /etc/ssh/sshd_config
mkdir -p /root/.ssh && chmod 700 /root/.ssh
echo '${SSH_PUBKEY}' >> /root/.ssh/authorized_keys
chmod 600 /root/.ssh/authorized_keys
"
else
lxc_exec "
sed -i 's/^#*PasswordAuthentication.*/PasswordAuthentication yes/' /etc/ssh/sshd_config
grep -q '^PasswordAuthentication' /etc/ssh/sshd_config || echo 'PasswordAuthentication yes' >> /etc/ssh/sshd_config
sed -i 's/^#*PubkeyAuthentication.*/PubkeyAuthentication yes/' /etc/ssh/sshd_config
grep -q '^PubkeyAuthentication' /etc/ssh/sshd_config || echo 'PubkeyAuthentication yes' >> /etc/ssh/sshd_config
mkdir -p /root/.ssh && chmod 700 /root/.ssh
echo '${SSH_PUBKEY}' >> /root/.ssh/authorized_keys
chmod 600 /root/.ssh/authorized_keys
"
fi
lxc_exec "systemctl enable ssh --now && systemctl restart ssh"
info "Prüfe SSH-Erreichbarkeit auf Port ${SSH_PORT}"
sleep 3
CT_TEST_IP=$(pct exec "$CTID" -- hostname -I 2>/dev/null | awk '{print $1}' || true)
if [[ -n "$CT_TEST_IP" ]] && nc -z -w5 "$CT_TEST_IP" "$SSH_PORT" 2>/dev/null; then
success "SSH erreichbar → ssh root@${CT_TEST_IP} -p ${SSH_PORT}"
else
warn "SSH-Port noch nicht erreichbar evtl. kurz warten und erneut testen."
fi
fi
# ── Proxmox Hinweise-Panel setzen (Markdown) ──────────────────────────────────
info "Setze Proxmox-Hinweise (Notes) für Container $CTID"
sleep 2
NOTES_IP=$(pct exec "$CTID" -- hostname -I 2>/dev/null | awk '{print $1}' || echo "")
[[ -z "$NOTES_IP" ]] && NOTES_IP="n/a (DHCP bitte in Konsole prüfen)"
# Debian-Version ermitteln
DEBIAN_VER=$(pct exec "$CTID" -- bash -c ". /etc/os-release && echo \$VERSION" 2>/dev/null || echo "Debian")
# SSH-Befehl
SSH_LINE=""
if $ENABLE_ROOT_SSH; then
if [[ "$SSH_PORT" == "22" ]]; then
SSH_LINE="ssh root@${NOTES_IP}"
else
SSH_LINE="ssh root@${NOTES_IP} -p ${SSH_PORT}"
fi
fi
# Badges + Info als Markdown
NOTE="[![Debian](https://img.shields.io/badge/${DEBIAN_VER// /%20}-A81D33?style=for-the-badge&logo=debian&logoColor=white)](https://www.debian.org)"
NOTE+=$'\n\n'
NOTE+="---"$'\n\n'
NOTE+="**🌐 IP-Adresse:** \`${NOTES_IP}\`"$'\n\n'
if $ENABLE_ROOT_SSH; then
NOTE+="**🔑 SSH:** \`${SSH_LINE}\`"$'\n\n'
fi
# Installierte optionale Pakete auflisten
INSTALLED_LIST=""
$INSTALL_BASETOOLS && INSTALLED_LIST+="curl wget git "
$INSTALL_MONITORING && INSTALLED_LIST+="htop ncdu net-tools "
$INSTALL_EDITORS && INSTALLED_LIST+="vim nano "
$INSTALL_CRON && INSTALLED_LIST+="cron logrotate "
$INSTALL_FAIL2BAN && INSTALLED_LIST+="fail2ban "
$INSTALL_UFW && INSTALLED_LIST+="ufw "
if [[ -n "$INSTALLED_LIST" ]]; then
NOTE+="**📦 Pakete:** \`${INSTALLED_LIST% }\`"$'\n\n'
fi
NOTE+="**🕐 Zeitzone:** ${TIMEZONE}"$'\n\n'
NOTE+="---"$'\n\n'
NOTE+="Installiert mit [gitea.vourx.com](https://gitea.vourx.com)"
NOTE+=" | [Debian Docs](https://www.debian.org/releases/)"
NOTE+=" | [Debian Packages](https://packages.debian.org)"
pvesh set /nodes/$(hostname)/lxc/${CTID}/config --description "${NOTE}" 2>/dev/null \
&& success "Proxmox-Hinweise gesetzt." \
|| warn "Hinweise konnten nicht gesetzt werden bitte manuell eintragen."
# ── System aufräumen ───────────────────────────────────────────────────────────
info "System aufräumen …"
lxc_exec "apt-get autoremove -y -qq && apt-get autoclean -qq"
success "Fertig aufgeräumt."
# ── Abschluss ──────────────────────────────────────────────────────────────────
CONTAINER_IP=$(pct exec "$CTID" -- hostname -I 2>/dev/null | awk '{print $1}' || echo "unbekannt")
echo ""
echo -e "${BOLD}${GREEN}╔══════════════════════════════════════════════════════╗${NC}"
echo -e "${GREEN}${NC} ${BOLD}Installation abgeschlossen!${NC}"
echo -e "${BOLD}${GREEN}╠══════════════════════════════════════════════════════╣${NC}"
echo -e "${GREEN}${NC}"
printf "${GREEN}${NC} %-20s ${BOLD}%s${NC}\n" "Container-ID:" "$CTID"
printf "${GREEN}${NC} %-20s ${BOLD}%s${NC}\n" "Hostname:" "$HOSTNAME"
printf "${GREEN}${NC} %-20s ${BOLD}%s${NC}\n" "IP-Adresse:" "$CONTAINER_IP"
printf "${GREEN}${NC} %-20s ${BOLD}%s${NC}\n" "Zeitzone:" "$TIMEZONE"
echo -e "${GREEN}${NC}"
if $ENABLE_ROOT_SSH; then
echo -e "${GREEN}${NC} ${CYAN}── SSH-Verbindung ────────────────────────────────${NC}"
if [[ "$SSH_PORT" == "22" ]]; then
printf "${GREEN}${NC} ${BOLD}ssh root@%s${NC}\n" "$CONTAINER_IP"
else
printf "${GREEN}${NC} ${BOLD}ssh root@%s -p %s${NC}\n" "$CONTAINER_IP" "$SSH_PORT"
fi
printf "${GREEN}${NC} %-20s ${BOLD}%s${NC}\n" "Auth-Methode:" "$SSH_AUTH"
echo -e "${GREEN}${NC}"
fi
if $INSTALL_UFW; then
echo -e "${GREEN}${NC} ${YELLOW}🔒 UFW installiert aber noch nicht aktiv.${NC}"
echo -e "${GREEN}${NC} ${YELLOW} Im Container mit 'ufw enable' aktivieren.${NC}"
echo -e "${GREEN}${NC}"
fi
echo -e "${GREEN}${NC} ${YELLOW}⚠ Root-Passwort nach erstem Login bitte ändern!${NC}"
echo -e "${GREEN}${NC}"
echo -e "${BOLD}${GREEN}╚══════════════════════════════════════════════════════╝${NC}"
echo ""