Files
proxmox-mailserver/start_network.sh
2025-12-22 19:54:56 -08:00

243 lines
7.5 KiB
Bash

#!/bin/bash
# ==========================================
# PROXMOX LXC MAILSERVER WRAPPER (FINAL)
# ==========================================
# --- CONFIGURATION ---
IP=${STATIC_IP:-"192.168.0.124/24"}
CONFIG_DIR="/tmp/docker-mailserver"
ACCOUNTS_FILE="$CONFIG_DIR/postfix-accounts.cf"
SECRETS_FILE="/mnt/secrets/mailserver.env"
echo "--- Mailserver Proxmox Init ---"
# 0. LOAD SECRETS
if [ -f "$SECRETS_FILE" ]; then
echo "🔐 Loading secrets from $SECRETS_FILE..."
set -a
source "$SECRETS_FILE"
set +a
# CRITICAL: Explicitly export SSL variables for the vendor script
export SSL_TYPE="${SSL_TYPE:-manual}"
export SSL_CERT_PATH="${SSL_CERT_PATH:-/tmp/docker-mailserver/ssl/cert.pem}"
export SSL_KEY_PATH="${SSL_KEY_PATH:-/tmp/docker-mailserver/ssl/key.pem}"
echo " -> SSL Mode: $SSL_TYPE"
else
echo "⚠️ Warning: Secrets file not found at $SECRETS_FILE"
fi
# 1. NETWORK SETUP
CURRENT_IP=$(ip -o -4 addr show eth0 | awk '{print $4}')
if [[ "$CURRENT_IP" == *"$IP"* ]]; then
echo "Network active ($CURRENT_IP). Skipping config."
else
echo "Configuring Network: $IP..."
cat <<EOF > /etc/network/interfaces
auto lo
iface lo inet loopback
auto eth0
iface eth0 inet static
address $IP
EOF
ifup eth0 || ip addr add $IP dev eth0 || true
fi
# 2. STATE & MIGRATION REPAIR
echo "--- Ensuring State Integrity ---"
rm -f /CONTAINER_START
rm -f /var/mail-state/container-id
migrate_to_state() {
NAME=$1
ORIGIN=$2
DEST="/var/mail-state/$NAME"
if [ ! -L "$ORIGIN" ]; then
echo "Migrating $NAME to persistent storage..."
mkdir -p "$DEST"
if [ -d "$ORIGIN" ]; then
cp -a "$ORIGIN/." "$DEST/"
rm -rf "$ORIGIN"
fi
ln -s "$DEST" "$ORIGIN"
fi
}
migrate_to_state "lib-amavis" "/var/lib/amavis"
migrate_to_state "lib-dovecot" "/var/lib/dovecot"
migrate_to_state "lib-logrotate" "/var/lib/logrotate"
migrate_to_state "lib-postfix" "/var/lib/postfix"
migrate_to_state "spool-postfix" "/var/spool/postfix"
# Fix Missing SSL (Snakeoil) for initial boot safety
if [ ! -f /etc/ssl/private/ssl-cert-snakeoil.key ]; then
echo "Generating default SSL certificate..."
openssl req -x509 -nodes -days 3650 -newkey rsa:2048 \
-keyout /etc/ssl/private/ssl-cert-snakeoil.key \
-out /etc/ssl/certs/ssl-cert-snakeoil.pem \
-subj '/CN=localhost'
fi
# Clean stale sockets
rm -f /dev/shm/supervisor.sock
rm -rf /var/run/supervisor/*
mkdir -p /dev/shm
chmod 1777 /dev/shm
mkdir -p /var/run/supervisor /var/log/supervisor /var/run/saslauthd
chmod 755 /var/run/supervisor /var/log/supervisor
# 3. SUPERVISOR SHIM v2
if [ ! -f /usr/bin/supervisorctl_original ]; then
echo "--- Shiming supervisorctl ---"
mv /usr/bin/supervisorctl /usr/bin/supervisorctl_original
cat <<'EOF' > /usr/bin/supervisorctl
#!/bin/bash
if ! pgrep -x "supervisord" > /dev/null; then
echo "Shim: Supervisord died. Kickstarting..."
/usr/bin/supervisord -c /etc/supervisor/supervisord.conf
fi
for i in {1..10}; do
if [ -S /dev/shm/supervisor.sock ]; then break; fi
sleep 1
done
exec /usr/bin/supervisorctl_original "$@"
EOF
chmod +x /usr/bin/supervisorctl
fi
# 4. ACCOUNT CREATION (Admin + USERS_JSON)
if [ -f "$ACCOUNTS_FILE" ]; then
echo "✅ Accounts file exists. Skipping creation."
else
echo "⚠️ Accounts file missing. Initializing..."
mkdir -p "$CONFIG_DIR"
# --- A. Create Admin Account ---
if [[ -n "$DMS_ADMIN_EMAIL" ]] && [[ -n "$DMS_ADMIN_PASSWORD" ]]; then
echo "📝 Creating Admin: $DMS_ADMIN_EMAIL..."
HASH=$(doveadm pw -s SHA512-CRYPT -p "$DMS_ADMIN_PASSWORD")
echo "$DMS_ADMIN_EMAIL|$HASH" > "$ACCOUNTS_FILE"
else
echo "❌ No DMS_ADMIN_EMAIL found. Creating empty accounts file."
touch "$ACCOUNTS_FILE"
fi
# --- B. Process USERS_JSON ---
if [[ -n "${USERS_JSON:-}" ]]; then
echo "📋 Found USERS_JSON. Parsing..."
# Determine Domain (from Admin Email or default)
DOMAIN_SUFFIX=$(echo "$DMS_ADMIN_EMAIL" | cut -d'@' -f2)
if [[ -z "$DOMAIN_SUFFIX" ]]; then DOMAIN_SUFFIX="poppyglen.cc"; fi
# Loop through users and append to file
echo "$USERS_JSON" | jq -c '.[]' | while read -r user_entry; do
U=$(echo "$user_entry" | jq -r '.username')
P=$(echo "$user_entry" | jq -r '.password')
if [[ -n "$U" && -n "$P" ]]; then
# Hash using local doveadm
UHASH=$(doveadm pw -s SHA512-CRYPT -p "$P")
# Check if username already has @domain, if not add it
if [[ "$U" != *"@"* ]]; then
FULL_USER="$U@$DOMAIN_SUFFIX"
else
FULL_USER="$U"
fi
echo "$FULL_USER|$UHASH" >> "$ACCOUNTS_FILE"
echo " -> Added User: $FULL_USER"
fi
done
fi
fi
# 5. NEW: PRE-FLIGHT FIXES (Permissions & Auth)
echo "🔧 Applying Security & Auth Patches..."
# A. Fix Certificate Permissions
# Ensures the 'dovecot' user (non-root in LXC) can read the host-mounted keys
if [ -f "$SSL_KEY_PATH" ]; then
chmod 644 "$SSL_KEY_PATH"
chmod 644 "$SSL_CERT_PATH"
echo " -> Fixed SSL certificate permissions (644)"
fi
# B. Configure SASL Auth Socket
# Creates the missing link allowing Postfix to ask Dovecot for password verification
echo " -> Creating SASL Auth Socket config..."
cat > /etc/dovecot/conf.d/99-postfix-auth.conf <<EOF
service auth {
unix_listener /var/spool/postfix/private/auth {
mode = 0660
user = postfix
group = postfix
}
}
EOF
# 6. START THE SERVER (Backgrounded)
echo "🚀 Starting Docker Mailserver..."
# Run in background (&) so script continues to step 7
if [ $# -eq 0 ]; then
/usr/local/bin/start-mailserver.sh supervisord -c /etc/supervisor/supervisord.conf &
else
/usr/local/bin/start-mailserver.sh "$@" &
fi
PID=$!
# 7. POST-START CONFIG ENFORCEMENT
echo "⏳ Waiting 15s for config generation..."
sleep 15
echo "🔧 Enforcing Postfix SASL & Dovecot SSL..."
# --- A. Force Dovecot SSL Required ---
if [ -f /etc/dovecot/conf.d/10-ssl.conf ]; then
sed -i 's/^ssl =.*/ssl = required/' /etc/dovecot/conf.d/10-ssl.conf
fi
# --- B. Configure PHONE Authentication (Incoming) ---
# This allows your phone to log in to port 587/465
echo " -> Enabling Phone Authentication (smtpd)..."
postconf -e 'smtpd_sasl_type = dovecot'
postconf -e 'smtpd_sasl_path = private/auth'
postconf -e 'smtpd_sasl_auth_enable = yes' # <--- THIS IS THE FIX
postconf -e 'smtpd_tls_auth_only = yes'
# --- C. Configure BREVO Authentication (Outgoing) ---
# This allows the server to log in to Brevo to send mail
if [[ -n "$RELAY_HOST" ]]; then
echo "🔗 Configuring SMTP Relay: $RELAY_HOST..."
# Configure Relay Host
postconf -e "relayhost = [$RELAY_HOST]:$RELAY_PORT"
# Configure Relay Auth
if [[ -n "$RELAY_USER" ]] && [[ -n "$RELAY_PASSWORD" ]]; then
echo " -> Setting Relay Authentication..."
# Create password file
echo "[$RELAY_HOST]:$RELAY_PORT $RELAY_USER:$RELAY_PASSWORD" > /etc/postfix/sasl_passwd
chmod 600 /etc/postfix/sasl_passwd
postmap /etc/postfix/sasl_passwd
# Enable Client Auth
postconf -e 'smtp_sasl_auth_enable = yes'
postconf -e 'smtp_sasl_password_maps = hash:/etc/postfix/sasl_passwd'
postconf -e 'smtp_sasl_security_options = noanonymous'
fi
fi
echo "🔄 Reloading services..."
supervisorctl restart dovecot
supervisorctl restart postfix
wait $PID