From d2b54cd0de978811d39c227401b6ada77f08ae41 Mon Sep 17 00:00:00 2001 From: Roland Strunze <1+xosna@noreply.localhost> Date: Sun, 24 May 2026 10:26:20 +0200 Subject: [PATCH] Dateien nach "/" hochladen --- ubuntu-lxc.sh | 543 ++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 543 insertions(+) create mode 100644 ubuntu-lxc.sh diff --git a/ubuntu-lxc.sh b/ubuntu-lxc.sh new file mode 100644 index 0000000..bd0d0e6 --- /dev/null +++ b/ubuntu-lxc.sh @@ -0,0 +1,543 @@ +#!/usr/bin/env bash +# ============================================================================== +# Proxmox LXC: Ubuntu Server LTS (minimal, sauber, produktionsbereit) +# Aufruf auf dem PVE-Host: +# bash <(curl -fsSL https://your-host/ubuntu-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 – Ubuntu LTS Installer ║${NC}" +echo -e "${BOLD}╚══════════════════════════════════════════════════╝${NC}\n" + +# ── Standardwerte ────────────────────────────────────────────────────────────── +DEFAULT_CTID=$(pvesh get /cluster/nextid) +DEFAULT_HOSTNAME="ubuntu" +DEFAULT_PASSWORD="ChangeMe123!" +DEFAULT_DISK=4 # GB +DEFAULT_RAM=1024 # MB (Ubuntu LTS empfohlen) +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 +# ══════════════════════════════════════════════════════════════════════════════ + +# ── Ubuntu-Template herunterladen ────────────────────────────────────────────── +info "Suche aktuelles Ubuntu-LXC-Template …" +TEMPLATE_STORAGE="local" +TEMPLATE=$(pveam available --section system | awk '/ubuntu-24\.04/ {print $2}' | sort -V | tail -1) +[[ -z "$TEMPLATE" ]] && error "Kein Ubuntu-LTS-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)" + +# Ubuntu-Version ermitteln +UBUNTU_VER=$(pct exec "$CTID" -- bash -c ". /etc/os-release && echo \$VERSION" 2>/dev/null || echo "Ubuntu") + +# 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="[![Ubuntu](https://img.shields.io/badge/${UBUNTU_VER// /%20}-A81D33?style=for-the-badge&logo=ubuntu&logoColor=white)](https://ubuntu.com)" +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+=" | [Ubuntu Docs](https://ubuntu.com/server/docs)" +NOTE+=" | [Ubuntu Packages](https://packages.ubuntu.com)" + +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 ""