Fix: LXC-Hostname-Bug ($HOSTNAME-Shadowing) + Dialog mit Container-Fragen & Sektionen

- Bug: Variable HOSTNAME ist in der Shell bereits gesetzt (Proxmox-Hostname,
  z.B. "tanin") -> LXC bekam falschen Namen. Umbenannt zu CT_HOSTNAME + abgefragt.
- Dialog fragt jetzt auch Hostname, CPU, RAM, Disk, Storage, Bridge.
- Schönerer Dialog: Banner + Abschnitte (Container/Netzwerk/Mail/Branding/Supabase/Hardening),
  Prompt nach stderr (Werte sauber capturebar), Passwort-Eingabe verdeckt.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
2026-06-02 02:43:19 +02:00
parent 4f0f7e62f1
commit be4906e2b5
+48 -32
View File
@@ -18,7 +18,8 @@ set -Eeuo pipefail
# Standard-Einstellungen (per ENV oder interaktiv überschreibbar) # Standard-Einstellungen (per ENV oder interaktiv überschreibbar)
# --------------------------------------------------------------------------- # ---------------------------------------------------------------------------
CTID="${CTID:-}" # leer => nächste freie ID CTID="${CTID:-}" # leer => nächste freie ID
HOSTNAME="${HOSTNAME:-mailserver}" # LXC-Hostname (Anzeigename) # ACHTUNG: NICHT $HOSTNAME nutzen — das ist in der Shell bereits der Host-Name!
CT_HOSTNAME="${CT_HOSTNAME:-mailserver}" # LXC-Hostname (Anzeigename)
MAIL_FQDN="${MAIL_FQDN:-}" # z.B. mail.example.com (PFLICHT) MAIL_FQDN="${MAIL_FQDN:-}" # z.B. mail.example.com (PFLICHT)
MAIL_DOMAIN="${MAIL_DOMAIN:-}" # primäre Domain, z.B. kgva.ch (leer => aus FQDN abgeleitet) MAIL_DOMAIN="${MAIL_DOMAIN:-}" # primäre Domain, z.B. kgva.ch (leer => aus FQDN abgeleitet)
MAIL_DOMAINS="${MAIL_DOMAINS:-}" # ALLE Mail-Domains (Leerzeichen-getrennt); leer => nur MAIL_DOMAIN MAIL_DOMAINS="${MAIL_DOMAINS:-}" # ALLE Mail-Domains (Leerzeichen-getrennt); leer => nur MAIL_DOMAIN
@@ -104,53 +105,68 @@ fi
[[ -f "$STACK_DIR/docker-compose.yml" ]] || die "stack/docker-compose.yml nicht gefunden unter $STACK_DIR" [[ -f "$STACK_DIR/docker-compose.yml" ]] || die "stack/docker-compose.yml nicht gefunden unter $STACK_DIR"
# --------------------------------------------------------------------------- # ---------------------------------------------------------------------------
# Interaktive Abfragen (nur wenn nicht per ENV gesetzt) # Interaktiver Dialog (Prompt -> stderr, Wert -> stdout, daher captureable)
# --------------------------------------------------------------------------- # ---------------------------------------------------------------------------
ask() { local p="$1" d="${2:-}" v; read -rp "$(echo -e "${BL}?${CL} $p ${d:+[$d] }")" v; echo "${v:-$d}"; } ask() { local p="$1" d="${2:-}" v; read -rp "$(echo -e " ${BL}?${CL} ${p}${d:+ ${YW}[$d]${CL}}: ")" v; echo "${v:-$d}"; }
asks() { local p="$1" v; read -rsp "$(echo -e " ${BL}?${CL} ${p}: ")" v; echo >&2; echo "$v"; }
section() { echo -e "\n${GN}┌──${CL} ${BL}$1${CL}"; }
cat <<EOF
${GN} ╔══════════════════════════════════════════════════════╗
║ docker-mailserver · LXC-Installer für Proxmox VE ║
╚══════════════════════════════════════════════════════╝${CL}
Mailserver · Admin-UI · Webmail (SnappyMail) · Rspamd
EOF
section "Container (LXC)"
if [[ -z "$CTID" ]]; then CTID="$(pvesh get /cluster/nextid)"; fi if [[ -z "$CTID" ]]; then CTID="$(pvesh get /cluster/nextid)"; fi
CTID="$(ask "Container-ID (CTID)" "$CTID")" CTID="$(ask "Container-ID (CTID)" "$CTID")"
CT_HOSTNAME="$(ask "LXC-Hostname (Anzeigename)" "$CT_HOSTNAME")"
CORES="$(ask "CPU-Kerne" "$CORES")"
RAM_MB="$(ask "RAM (MB)" "$RAM_MB")"
DISK_GB="$(ask "Disk (GB)" "$DISK_GB")"
STORAGE="$(ask "Storage (rootfs)" "$STORAGE")"
[[ -z "$MAIL_FQDN" ]] && MAIL_FQDN="$(ask "Mailserver-FQDN (z.B. mail.example.com)")" section "Netzwerk"
[[ -n "$MAIL_FQDN" ]] || die "MAIL_FQDN ist Pflicht." BRIDGE="$(ask "Bridge" "$BRIDGE")"
# Domain aus FQDN ableiten (alles nach dem ersten Punkt) falls nicht gesetzt
[[ -z "$MAIL_DOMAIN" ]] && MAIL_DOMAIN="${MAIL_FQDN#*.}"
MAIL_DOMAIN="$(ask "Primäre Mail-Domain" "$MAIL_DOMAIN")"
[[ -z "$MAIL_DOMAINS" ]] && MAIL_DOMAINS="$(ask "Alle Mail-Domains (Leerzeichen-getrennt)" "$MAIL_DOMAIN")"
# Primäre Domain sicher enthalten, Duplikate raus
MAIL_DOMAINS="$(echo "$MAIL_DOMAIN $MAIL_DOMAINS" | tr ' ' '\n' | awk 'NF && !seen[$0]++' | tr '\n' ' ' | sed 's/ *$//')"
# Branding + Web-Domains (Defaults aus der primären Domain abgeleitet)
[[ -z "$BRAND" ]] && BRAND="$(ask "Anzeigename / Brand (Dashboard)" "$MAIL_DOMAIN")"
[[ -z "$WEBMAIL_FQDN" ]] && WEBMAIL_FQDN="$(ask "Webmail-Domain (NPM-Proxy-Host)" "mail.${MAIL_DOMAIN}")"
[[ -z "$ADMIN_FQDN" ]] && ADMIN_FQDN="$(ask "Admin-UI-Domain (NPM-Proxy-Host)" "admin.${MAIL_DOMAIN}")"
[[ -z "$FIRST_EMAIL" ]] && FIRST_EMAIL="$(ask "Erstes Postfach (E-Mail)" "admin@${MAIL_DOMAIN}")"
if [[ -z "$FIRST_PASSWORD" ]]; then
read -rsp "$(echo -e "${BL}?${CL} Passwort für ${FIRST_EMAIL}: ")" FIRST_PASSWORD; echo
[[ -n "$FIRST_PASSWORD" ]] || die "Passwort darf nicht leer sein."
fi
NET_IP="$(ask "IP (dhcp oder CIDR z.B. 192.168.1.50/24)" "$NET_IP")" NET_IP="$(ask "IP (dhcp oder CIDR z.B. 192.168.1.50/24)" "$NET_IP")"
if [[ "$NET_IP" != "dhcp" && -z "$NET_GW" ]]; then if [[ "$NET_IP" != "dhcp" && -z "$NET_GW" ]]; then
NET_GW="$(ask "Gateway (für statische IP)")" NET_GW="$(ask "Gateway (für statische IP)")"
fi fi
# --- Admin-UI / Supabase --- section "Mail"
[[ -z "$ADMIN_ALLOWED_EMAILS" ]] && ADMIN_ALLOWED_EMAILS="$(ask "Admin-E-Mail(s) für UI-Login (Supabase, Komma-getrennt)" "$FIRST_EMAIL")" [[ -z "$MAIL_FQDN" ]] && MAIL_FQDN="$(ask "Mailserver-FQDN (z.B. mail.example.com)")"
[[ -z "$SUPABASE_URL" ]] && SUPABASE_URL="$(ask "Supabase URL (leer = später in .env eintragen)")" [[ -n "$MAIL_FQDN" ]] || die "MAIL_FQDN ist Pflicht."
[[ -z "$SUPABASE_ANON_KEY" ]] && SUPABASE_ANON_KEY="$(ask "Supabase anon key (leer = später in .env eintragen)")" [[ -z "$MAIL_DOMAIN" ]] && MAIL_DOMAIN="${MAIL_FQDN#*.}"
MAIL_DOMAIN="$(ask "Primäre Mail-Domain" "$MAIL_DOMAIN")"
[[ -z "$MAIL_DOMAINS" ]] && MAIL_DOMAINS="$(ask "Alle Mail-Domains (Leerzeichen-getrennt)" "$MAIL_DOMAIN")"
MAIL_DOMAINS="$(echo "$MAIL_DOMAIN $MAIL_DOMAINS" | tr ' ' '\n' | awk 'NF && !seen[$0]++' | tr '\n' ' ' | sed 's/ *$//')"
[[ -z "$FIRST_EMAIL" ]] && FIRST_EMAIL="$(ask "Erstes Postfach (E-Mail)" "admin@${MAIL_DOMAIN}")"
if [[ -z "$FIRST_PASSWORD" ]]; then
FIRST_PASSWORD="$(asks "Passwort für ${FIRST_EMAIL}")"
[[ -n "$FIRST_PASSWORD" ]] || die "Passwort darf nicht leer sein."
fi
# --- Hardening --- section "Branding & Web-Domains (später im Admin editierbar)"
[[ -z "$NPM_IP" ]] && NPM_IP="$(ask "IP des Nginx Proxy Manager (Web-Ports nur von dort; leer = offen)")" [[ -z "$BRAND" ]] && BRAND="$(ask "Anzeigename / Brand" "$MAIL_DOMAIN")"
# Rspamd-Controller-Passwort generieren, falls nicht gesetzt [[ -z "$WEBMAIL_FQDN" ]] && WEBMAIL_FQDN="$(ask "Webmail-Domain (NPM)" "mail.${MAIL_DOMAIN}")"
[[ -z "$ADMIN_FQDN" ]] && ADMIN_FQDN="$(ask "Admin-UI-Domain (NPM)" "admin.${MAIL_DOMAIN}")"
section "Admin-Login (Supabase)"
[[ -z "$ADMIN_ALLOWED_EMAILS" ]] && ADMIN_ALLOWED_EMAILS="$(ask "Erlaubte Admin-E-Mail(s), Komma-getrennt" "$FIRST_EMAIL")"
[[ -z "$SUPABASE_URL" ]] && SUPABASE_URL="$(ask "Supabase URL (leer = später in .env)")"
[[ -z "$SUPABASE_ANON_KEY" ]] && SUPABASE_ANON_KEY="$(ask "Supabase anon key (leer = später in .env)")"
section "Hardening"
[[ -z "$NPM_IP" ]] && NPM_IP="$(ask "IP des Nginx Proxy Manager (Web nur von dort; leer = offen)")"
[[ -z "$RSPAMD_PASSWORD" ]] && RSPAMD_PASSWORD="$(openssl rand -base64 24 | tr -dc 'A-Za-z0-9' | head -c 24)" [[ -z "$RSPAMD_PASSWORD" ]] && RSPAMD_PASSWORD="$(openssl rand -base64 24 | tr -dc 'A-Za-z0-9' | head -c 24)"
cat <<EOF cat <<EOF
${GN}── Zusammenfassung ─────────────────────────────${CL} ${GN}── Zusammenfassung ─────────────────────────────${CL}
CTID .............. $CTID CTID .............. $CTID
Hostname .......... $HOSTNAME Hostname .......... $CT_HOSTNAME
Mail-FQDN ......... $MAIL_FQDN Mail-FQDN ......... $MAIL_FQDN
Mail-Domains ...... $MAIL_DOMAINS Mail-Domains ...... $MAIL_DOMAINS
Erstes Postfach ... $FIRST_EMAIL Erstes Postfach ... $FIRST_EMAIL
@@ -202,7 +218,7 @@ fi
# --------------------------------------------------------------------------- # ---------------------------------------------------------------------------
msg_info "Erstelle LXC $CTID ..." msg_info "Erstelle LXC $CTID ..."
pct create "$CTID" "$TEMPLATE_REF" \ pct create "$CTID" "$TEMPLATE_REF" \
--hostname "$HOSTNAME" \ --hostname "$CT_HOSTNAME" \
--cores "$CORES" \ --cores "$CORES" \
--memory "$RAM_MB" \ --memory "$RAM_MB" \
--swap "$SWAP_MB" \ --swap "$SWAP_MB" \