diff --git a/ubuntu-lxc.sh b/ubuntu-lxc.sh index bd0d0e6..3094898 100644 --- a/ubuntu-lxc.sh +++ b/ubuntu-lxc.sh @@ -1,6 +1,6 @@ #!/usr/bin/env bash # ============================================================================== -# Proxmox LXC: Ubuntu Server LTS (minimal, sauber, produktionsbereit) +# Proxmox LXC: Ubuntu Server 26.04 LTS # Aufruf auf dem PVE-Host: # bash <(curl -fsSL https://your-host/ubuntu-lxc.sh) # ============================================================================== @@ -22,18 +22,17 @@ command -v pct &>/dev/null || error "'pct' nicht gefunden – läuft das Skrip 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" +echo -e "\n${BOLD}╔══════════════════════════════════════════════════════════╗${NC}" +echo -e "${BOLD}║ Proxmox LXC – Ubuntu Server 26.04 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_HOSTNAME="ubuntu-server" +DEFAULT_DISK=8 # GB (Ubuntu braucht mehr als Debian) +DEFAULT_RAM=1024 # MB DEFAULT_SWAP=512 # MB -DEFAULT_CORES=1 +DEFAULT_CORES=2 DEFAULT_BRIDGE="vmbr0" DEFAULT_IP="dhcp" DEFAULT_GW="" @@ -53,6 +52,23 @@ ask_yn() { [[ "${yn:-$default}" =~ ^[Jj1Yy] ]] } +ask_password() { + local prompt="$1" var_name="$2" + local pw1 pw2 + while true; do + echo -ne "${BOLD}${prompt}${NC}: " + read -rs pw1; echo "" + echo -ne "${BOLD}Passwort bestätigen${NC}: " + read -rs pw2; echo "" + if [[ "$pw1" != "$pw2" ]]; then + warn "Passwörter stimmen nicht überein – bitte erneut eingeben." + else + printf -v "$var_name" '%s' "$pw1" + break + fi + done +} + # ── Storage-Auswahl (dynamisch) ──────────────────────────────────────────────── select_storage() { echo -e "${CYAN}── Storage-Auswahl ──────────────────────────────────────────${NC}" @@ -128,21 +144,87 @@ select_storage() { echo "" } +# ── Ubuntu-Template auswählen ────────────────────────────────────────────────── +select_ubuntu_template() { + echo -e "${CYAN}── Ubuntu-Template ──────────────────────────────────────────${NC}" + echo -e " Verfügbare Ubuntu-Templates:\n" + + # Alle Ubuntu-Templates aus PVE-Datenbank holen (lokal heruntergeladen + verfügbar) + mapfile -t AVAIL < <( + pveam available --section system 2>/dev/null \ + | awk '/ubuntu/ {print $2}' | sort -V + ) + mapfile -t LOCAL < <( + pveam list local 2>/dev/null \ + | awk '/ubuntu/ {print $1}' | sort -V + ) + + if [[ ${#AVAIL[@]} -eq 0 ]]; then + warn "Keine Ubuntu-Templates in der PVE-Datenbank. Versuche 'pveam update'." + UBUNTU_TEMPLATE="" + return + fi + + local i=1 + local -a TNAMES=() + local default_idx=1 + + printf " ${BOLD}%-4s %-55s %-12s${NC}\n" "Nr." "Template" "Status" + echo -e " ──────────────────────────────────────────────────────────────────" + + for t in "${AVAIL[@]}"; do + local status="${YELLOW}verfügbar${NC}" + local bold_start="" bold_end="" + # Prüfen ob lokal vorhanden + for l in "${LOCAL[@]}"; do + if [[ "$l" == *"$t"* ]]; then + status="${GREEN}lokal vorhanden${NC}" + break + fi + done + # 26.04 als Default vormerken + if [[ "$t" == *"26.04"* ]]; then + default_idx=$i + bold_start="${BOLD}" + bold_end="${NC}" + fi + printf " ${BOLD}%-4s${NC} ${bold_start}%-55s${bold_end} " "[$i]" "$t" + echo -e "$status" + TNAMES+=("$t") + (( i++ )) + done + + echo "" + while true; do + echo -ne "${BOLD}Auswahl (Nummer eingeben)${NC} [${YELLOW}${default_idx}${NC}]: " + read -r sel + sel="${sel:-$default_idx}" + if [[ "$sel" =~ ^[0-9]+$ ]] && (( sel >= 1 && sel <= ${#TNAMES[@]} )); then + UBUNTU_TEMPLATE="${TNAMES[$((sel-1))]}" + success "Template gewählt: ${BOLD}${UBUNTU_TEMPLATE}${NC}" + break + else + warn "Ungültige Eingabe." + 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 +ask "Container-ID" "$DEFAULT_CTID" CTID +ask "Hostname" "$DEFAULT_HOSTNAME" HOSTNAME +ask_password "Root-Passwort" 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 +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}" @@ -161,6 +243,31 @@ else UNPRIVILEGED=0 fi +echo "" +echo -e "${CYAN}── Zeitzone ──────────────────────────────────────────────────${NC}" +ask "Zeitzone" "Europe/Berlin" TIMEZONE + +echo "" +echo -e "${CYAN}── Ubuntu-spezifische Einstellungen ──────────────────────────${NC}" + +if ask_yn "Unattended-Upgrades aktivieren? (automatische Sicherheitsupdates)" "j"; then + ENABLE_UNATTENDED=true +else + ENABLE_UNATTENDED=false +fi + +if ask_yn "Snap-Dienst deaktivieren? (spart Ressourcen im LXC)" "j"; then + DISABLE_SNAP=true +else + DISABLE_SNAP=false +fi + +if ask_yn "Ubuntu Pro / ESM Werbemeldungen deaktivieren?" "j"; then + DISABLE_PRO_MOTD=true +else + DISABLE_PRO_MOTD=false +fi + echo "" echo -e "${CYAN}── Optionale Pakete ──────────────────────────────────────────${NC}" echo -e " Wähle zusätzliche Pakete die installiert werden sollen:\n" @@ -183,7 +290,7 @@ else INSTALL_EDITORS=false fi -if ask_yn "ufw (Firewall, deaktiviert)" "n"; then +if ask_yn "ufw (Firewall, vorkonfiguriert aber deaktiviert)" "n"; then INSTALL_UFW=true else INSTALL_UFW=false @@ -201,10 +308,6 @@ 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 @@ -241,25 +344,33 @@ else SSH_AUTH="password" fi +echo "" +echo -e "${CYAN}── Template-Auswahl ──────────────────────────────────────────${NC}" +select_ubuntu_template + # ── 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 -e "${BOLD}╔══════════════════════ Zusammenfassung ════════════════════════╗${NC}" +printf "${BOLD}║${NC} %-26s %-28s ${BOLD}║${NC}\n" "Container-ID:" "$CTID" +printf "${BOLD}║${NC} %-26s %-28s ${BOLD}║${NC}\n" "Hostname:" "$HOSTNAME" +printf "${BOLD}║${NC} %-26s %-28s ${BOLD}║${NC}\n" "Template:" "$UBUNTU_TEMPLATE" +printf "${BOLD}║${NC} %-26s %-28s ${BOLD}║${NC}\n" "Storage:" "$STORAGE" +printf "${BOLD}║${NC} %-26s %-28s ${BOLD}║${NC}\n" "Disk / RAM / Swap:" "${DISK} GB / ${RAM} MB / ${SWAP} MB" +printf "${BOLD}║${NC} %-26s %-28s ${BOLD}║${NC}\n" "CPU-Kerne:" "$CORES" +printf "${BOLD}║${NC} %-26s %-28s ${BOLD}║${NC}\n" "Netzwerk:" "$IP_ADDR" +printf "${BOLD}║${NC} %-26s %-28s ${BOLD}║${NC}\n" "Zeitzone:" "$TIMEZONE" +printf "${BOLD}║${NC} %-26s %-28s ${BOLD}║${NC}\n" "Unprivilegiert:" "$( [[ $UNPRIVILEGED -eq 1 ]] && echo "Ja" || echo "Nein" )" +printf "${BOLD}║${NC} %-26s %-28s ${BOLD}║${NC}\n" "Unattended-Upgrades:" "$( $ENABLE_UNATTENDED && echo "Ja" || echo "Nein" )" +printf "${BOLD}║${NC} %-26s %-28s ${BOLD}║${NC}\n" "Snap deaktiviert:" "$( $DISABLE_SNAP && echo "Ja" || echo "Nein" )" +printf "${BOLD}║${NC} %-26s %-28s ${BOLD}║${NC}\n" "Ubuntu-Pro-MOTD aus:" "$( $DISABLE_PRO_MOTD && echo "Ja" || echo "Nein" )" +printf "${BOLD}║${NC} %-26s %-28s ${BOLD}║${NC}\n" "Basis-Tools:" "$( $INSTALL_BASETOOLS && echo "Ja" || echo "Nein" )" +printf "${BOLD}║${NC} %-26s %-28s ${BOLD}║${NC}\n" "Monitoring-Tools:" "$( $INSTALL_MONITORING && echo "Ja" || echo "Nein" )" +printf "${BOLD}║${NC} %-26s %-28s ${BOLD}║${NC}\n" "Editoren:" "$( $INSTALL_EDITORS && echo "Ja" || echo "Nein" )" +printf "${BOLD}║${NC} %-26s %-28s ${BOLD}║${NC}\n" "UFW Firewall:" "$( $INSTALL_UFW && echo "Ja" || echo "Nein" )" +printf "${BOLD}║${NC} %-26s %-28s ${BOLD}║${NC}\n" "Cron/Logrotate:" "$( $INSTALL_CRON && echo "Ja" || echo "Nein" )" +printf "${BOLD}║${NC} %-26s %-28s ${BOLD}║${NC}\n" "fail2ban:" "$( $INSTALL_FAIL2BAN && echo "Ja" || echo "Nein" )" +printf "${BOLD}║${NC} %-26s %-28s ${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; } @@ -267,21 +378,18 @@ ask_yn "Jetzt installieren?" "j" || { echo "Abgebrochen."; exit 0; } # INSTALLATION # ══════════════════════════════════════════════════════════════════════════════ -# ── Ubuntu-Template herunterladen ────────────────────────────────────────────── -info "Suche aktuelles Ubuntu-LXC-Template …" +# ── Template herunterladen falls nötig ──────────────────────────────────────── +info "Prüfe Template: ${UBUNTU_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) +DOWNLOADED=$(pveam list "$TEMPLATE_STORAGE" 2>/dev/null | awk '{print $1}' | grep -F "$UBUNTU_TEMPLATE" || true) if [[ -z "$DOWNLOADED" ]]; then - info "Lade Template herunter: $TEMPLATE" - pveam download "$TEMPLATE_STORAGE" "$TEMPLATE" - success "Template geladen." + info "Lade Template herunter …" + pveam download "$TEMPLATE_STORAGE" "$UBUNTU_TEMPLATE" + success "Template heruntergeladen." else - success "Template bereits vorhanden: $TEMPLATE" + success "Template bereits vorhanden." fi -TEMPLATE_PATH="${TEMPLATE_STORAGE}:vztmpl/${TEMPLATE}" +TEMPLATE_PATH="${TEMPLATE_STORAGE}:vztmpl/${UBUNTU_TEMPLATE}" # ── LXC-Container erstellen ──────────────────────────────────────────────────── info "Erstelle LXC-Container $CTID …" @@ -313,20 +421,28 @@ success "Container $CTID erstellt." # ── Container starten ────────────────────────────────────────────────────────── info "Starte Container …" pct start "$CTID" -sleep 5 +sleep 6 # ── Hilfsfunktion ────────────────────────────────────────────────────────────── lxc_exec() { pct exec "$CTID" -- bash -c "$*"; } +# ── Ubuntu-spezifisch: DEBIAN_FRONTEND nichtinteraktiv setzen ───────────────── +lxc_exec "echo 'debconf debconf/frontend select Noninteractive' | debconf-set-selections 2>/dev/null || true" + # ── 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" +info "System aktualisieren (apt update & upgrade) …" +lxc_exec " +export DEBIAN_FRONTEND=noninteractive +apt-get update -qq +apt-get upgrade -y -qq -o Dpkg::Options::='--force-confold' +apt-get install -y -qq ca-certificates locales +" success "System aktuell." # ── Zeitzone setzen ──────────────────────────────────────────────────────────── info "Zeitzone setzen: ${TIMEZONE} …" lxc_exec " +export DEBIAN_FRONTEND=noninteractive ln -sf /usr/share/zoneinfo/${TIMEZONE} /etc/localtime echo '${TIMEZONE}' > /etc/timezone dpkg-reconfigure -f noninteractive tzdata 2>/dev/null || true @@ -334,44 +450,88 @@ 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) …" +info "Locale konfigurieren …" 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." +export DEBIAN_FRONTEND=noninteractive +sed -i 's/^# *de_DE.UTF-8/de_DE.UTF-8/' /etc/locale.gen 2>/dev/null || true +sed -i 's/^# *en_US.UTF-8/en_US.UTF-8/' /etc/locale.gen 2>/dev/null || true +locale-gen 2>/dev/null || true +update-locale LANG=de_DE.UTF-8 LC_MESSAGES=en_US.UTF-8 2>/dev/null || true +" 2>/dev/null success "Locale konfiguriert." +# ── Snap deaktivieren (Ubuntu-spezifisch) ───────────────────────────────────── +if $DISABLE_SNAP; then + info "Snap deaktivieren …" + lxc_exec " +# Snap läuft in LXC oft nicht korrekt und kostet Ressourcen +systemctl stop snapd 2>/dev/null || true +systemctl disable snapd 2>/dev/null || true +systemctl mask snapd 2>/dev/null || true +apt-get purge -y -qq snapd 2>/dev/null || true +rm -rf /snap /var/snap /var/lib/snapd /var/cache/snapd ~/snap 2>/dev/null || true +# Snap-APT-Pin setzen damit er nicht neu installiert wird +cat > /etc/apt/preferences.d/no-snapd << 'SNAP_PIN' +Package: snapd +Pin: release a=* +Pin-Priority: -10 +SNAP_PIN +" 2>/dev/null + success "Snap deaktiviert und gesperrt." +fi + +# ── Ubuntu Pro / ESM MOTD-Werbung deaktivieren ──────────────────────────────── +if $DISABLE_PRO_MOTD; then + info "Ubuntu Pro MOTD-Meldungen deaktivieren …" + lxc_exec " +# MOTD-Skripte die Ubuntu Pro bewerben deaktivieren +chmod -x /etc/update-motd.d/10-help-text 2>/dev/null || true +chmod -x /etc/update-motd.d/50-motd-news 2>/dev/null || true +chmod -x /etc/update-motd.d/88-esm-announce 2>/dev/null || true +chmod -x /etc/update-motd.d/91-contract-ua-esm-status 2>/dev/null || true +chmod -x /etc/update-motd.d/95-hwe-eol 2>/dev/null || true +# pro config falls vorhanden +command -v pro &>/dev/null && pro config set motd=false 2>/dev/null || true +" 2>/dev/null + success "Ubuntu Pro MOTD deaktiviert." +fi + +# ── Unattended-Upgrades konfigurieren ───────────────────────────────────────── +if $ENABLE_UNATTENDED; then + info "Unattended-Upgrades (automatische Sicherheitsupdates) konfigurieren …" + lxc_exec " +export DEBIAN_FRONTEND=noninteractive +apt-get install -y -qq unattended-upgrades update-notifier-common +cat > /etc/apt/apt.conf.d/20auto-upgrades << 'AUTO' +APT::Periodic::Update-Package-Lists \"1\"; +APT::Periodic::Unattended-Upgrade \"1\"; +APT::Periodic::AutocleanInterval \"7\"; +APT::Periodic::Download-Upgradeable-Packages \"1\"; +AUTO +# Nur Security-Updates automatisch einspielen +sed -i 's|//\s*\"\${distro_id}:\${distro_codename}-security\";|\"\${distro_id}:\${distro_codename}-security\";|' \ + /etc/apt/apt.conf.d/50unattended-upgrades 2>/dev/null || true +systemctl enable unattended-upgrades --now 2>/dev/null || true +" + success "Unattended-Upgrades aktiv (nur Security-Updates)." +fi + # ── 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 +$INSTALL_BASETOOLS && PKGS+=(curl wget git) +$INSTALL_MONITORING && PKGS+=(htop ncdu tree net-tools iputils-ping) +$INSTALL_EDITORS && PKGS+=(vim nano) +$INSTALL_CRON && PKGS+=(cron logrotate) +$INSTALL_FAIL2BAN && PKGS+=(fail2ban) +$INSTALL_UFW && PKGS+=(ufw) if [[ ${#PKGS[@]} -gt 0 ]]; then info "Installiere optionale Pakete: ${PKGS[*]} …" - lxc_exec "apt-get install -y -qq ${PKGS[*]}" + lxc_exec "export DEBIAN_FRONTEND=noninteractive && apt-get install -y -qq ${PKGS[*]}" success "Pakete installiert." fi -# ── fail2ban konfigurieren (falls installiert) ───────────────────────────────── +# ── fail2ban konfigurieren ───────────────────────────────────────────────────── if $INSTALL_FAIL2BAN; then info "fail2ban konfigurieren …" lxc_exec " @@ -385,19 +545,19 @@ backend = systemd [sshd] enabled = true F2B -systemctl enable fail2ban --now +systemctl enable fail2ban --now 2>/dev/null || true " success "fail2ban aktiv (SSH-Schutz: 5 Versuche / 10 Min → 1h Ban)." fi -# ── UFW konfigurieren (falls installiert) ────────────────────────────────────── +# ── UFW konfigurieren ────────────────────────────────────────────────────────── if $INSTALL_UFW; then - info "UFW vorbereiten (deaktiviert, SSH freigegeben) …" + info "UFW vorkonfigurieren (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 +# Bewusst nicht aktiviert – bitte manuell mit 'ufw enable' aktivieren " success "UFW konfiguriert (noch deaktiviert – mit 'ufw enable' aktivieren)." fi @@ -405,35 +565,33 @@ 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 "export DEBIAN_FRONTEND=noninteractive && apt-get install -y -qq openssh-server" + # Ubuntu 22.04+ nutzt /etc/ssh/sshd_config.d/ – wir schreiben eine Override-Datei 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 +mkdir -p /etc/ssh/sshd_config.d +cat > /etc/ssh/sshd_config.d/99-proxmox-lxc.conf << SSHCFG +PermitRootLogin yes +Port ${SSH_PORT} +SSHCFG " 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 +echo 'PasswordAuthentication yes' >> /etc/ssh/sshd_config.d/99-proxmox-lxc.conf +echo 'PubkeyAuthentication no' >> /etc/ssh/sshd_config.d/99-proxmox-lxc.conf " 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 +echo 'PasswordAuthentication no' >> /etc/ssh/sshd_config.d/99-proxmox-lxc.conf +echo 'PubkeyAuthentication yes' >> /etc/ssh/sshd_config.d/99-proxmox-lxc.conf 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 +echo 'PasswordAuthentication yes' >> /etc/ssh/sshd_config.d/99-proxmox-lxc.conf +echo 'PubkeyAuthentication yes' >> /etc/ssh/sshd_config.d/99-proxmox-lxc.conf mkdir -p /root/.ssh && chmod 700 /root/.ssh echo '${SSH_PUBKEY}' >> /root/.ssh/authorized_keys chmod 600 /root/.ssh/authorized_keys @@ -453,36 +611,19 @@ chmod 600 /root/.ssh/authorized_keys fi # ── Proxmox Hinweise-Panel setzen (Markdown) ────────────────────────────────── -info "Setze Proxmox-Hinweise (Notes) für Container $CTID …" - +info "Setze Proxmox-Hinweise (Notes) …" 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") +UBUNTU_VER=$(pct exec "$CTID" -- bash -c ". /etc/os-release && echo \$VERSION" 2>/dev/null || echo "Ubuntu 26.04 LTS") -# 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 + [[ "$SSH_PORT" == "22" ]] && SSH_LINE="ssh root@${NOTES_IP}" \ + || SSH_LINE="ssh root@${NOTES_IP} -p ${SSH_PORT}" 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 " @@ -490,14 +631,26 @@ $INSTALL_EDITORS && INSTALLED_LIST+="vim nano " $INSTALL_CRON && INSTALLED_LIST+="cron logrotate " $INSTALL_FAIL2BAN && INSTALLED_LIST+="fail2ban " $INSTALL_UFW && INSTALLED_LIST+="ufw " +$ENABLE_UNATTENDED && INSTALLED_LIST+="unattended-upgrades " + +NOTE="[![Ubuntu](https://img.shields.io/badge/Ubuntu%2026.04%20LTS-E95420?style=for-the-badge&logo=ubuntu&logoColor=white)](https://ubuntu.com/server)" +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 if [[ -n "$INSTALLED_LIST" ]]; then NOTE+="**📦 Pakete:** \`${INSTALLED_LIST% }\`"$'\n\n' fi - NOTE+="**🕐 Zeitzone:** ${TIMEZONE}"$'\n\n' +$DISABLE_SNAP && NOTE+="**🚫 Snap:** deaktiviert"$'\n\n' +$ENABLE_UNATTENDED && NOTE+="**🔒 Auto-Updates:** aktiv (Security)"$'\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 Server 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 \ @@ -506,38 +659,50 @@ pvesh set /nodes/$(hostname)/lxc/${CTID}/config --description "${NOTE}" 2>/dev/n # ── System aufräumen ─────────────────────────────────────────────────────────── info "System aufräumen …" -lxc_exec "apt-get autoremove -y -qq && apt-get autoclean -qq" +lxc_exec " +export DEBIAN_FRONTEND=noninteractive +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 "${BOLD}${GREEN}╔══════════════════════════════════════════════════════════╗${NC}" echo -e "${GREEN}║${NC} ${BOLD}Installation abgeschlossen!${NC}" -echo -e "${BOLD}${GREEN}╠══════════════════════════════════════════════════════╣${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" +printf "${GREEN}║${NC} %-22s ${BOLD}%s${NC}\n" "Container-ID:" "$CTID" +printf "${GREEN}║${NC} %-22s ${BOLD}%s${NC}\n" "Hostname:" "$HOSTNAME" +printf "${GREEN}║${NC} %-22s ${BOLD}%s${NC}\n" "IP-Adresse:" "$CONTAINER_IP" +printf "${GREEN}║${NC} %-22s ${BOLD}%s${NC}\n" "Template:" "$UBUNTU_TEMPLATE" +printf "${GREEN}║${NC} %-22s ${BOLD}%s${NC}\n" "Zeitzone:" "$TIMEZONE" echo -e "${GREEN}║${NC}" +if $ENABLE_UNATTENDED; then + printf "${GREEN}║${NC} %-22s ${BOLD}%s${NC}\n" "Auto-Updates:" "aktiv (nur Security)" +fi +if $DISABLE_SNAP; then + printf "${GREEN}║${NC} %-22s ${BOLD}%s${NC}\n" "Snap:" "deaktiviert & gesperrt" +fi if $ENABLE_ROOT_SSH; then - echo -e "${GREEN}║${NC} ${CYAN}── SSH-Verbindung ────────────────────────────────${NC}" + echo -e "${GREEN}║${NC}" + 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}" + printf "${GREEN}║${NC} %-22s ${BOLD}%s${NC}\n" "Auth-Methode:" "$SSH_AUTH" fi if $INSTALL_UFW; then + echo -e "${GREEN}║${NC}" 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}" echo -e "${GREEN}║${NC} ${YELLOW}⚠ Root-Passwort nach erstem Login bitte ändern!${NC}" echo -e "${GREEN}║${NC}" -echo -e "${BOLD}${GREEN}╚══════════════════════════════════════════════════════╝${NC}" -echo "" +echo -e "${BOLD}${GREEN}╚══════════════════════════════════════════════════════════╝${NC}" +echo "" \ No newline at end of file