Complete rewrite of mailinaboxctl with comprehensive features: Container Management: - install, check, update, status, logs, shell commands - Better prerequisite checking and Docker integration Email Account Management: - user-add/del/list/passwd for email accounts - alias-add/del/list for email aliases - Uses docker-mailserver setup command Domain & SSL: - domain-add/list for virtual domains - ssl-status/renew for certificate management - Let's Encrypt integration Backup & Restore: - Full backup with automatic container stop - Restore with confirmation prompt Diagnostics: - health: comprehensive health check - dns-check: verify MX, SPF, DMARC records - ports: check listening ports - config: show current configuration - test-email: send test message Updated configuration with: - Separate hostname and domain options - Feature flags for ClamAV, SpamAssassin, Fail2ban, POP3 - SSL type selection (letsencrypt, manual, self-signed) - Complete port mapping options Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
726 lines
19 KiB
Bash
Executable File
726 lines
19 KiB
Bash
Executable File
#!/bin/sh
|
|
# SecuBox Mail-in-a-Box manager - Docker Mailserver Edition
|
|
# Copyright (C) 2024 CyberMind.fr
|
|
#
|
|
# Based on docker-mailserver for lightweight email hosting
|
|
|
|
CONFIG="mailinabox"
|
|
CONTAINER_NAME="secbx-mailserver"
|
|
OPKG_UPDATED=0
|
|
|
|
# Paths
|
|
DATA_BASE="/srv/mailserver"
|
|
|
|
usage() {
|
|
cat <<'EOF'
|
|
Usage: mailinaboxctl <command>
|
|
|
|
Container Management:
|
|
install Install prerequisites, prepare directories, pull image
|
|
check Run prerequisite checks (ports, DNS, storage)
|
|
update Pull new image and restart
|
|
status Show container and service status
|
|
logs Show container logs (use -f to follow)
|
|
shell Open shell in container
|
|
service-run Internal: run container via procd
|
|
service-stop Stop container
|
|
|
|
Email Account Management:
|
|
user-add <email> [password] Add email account
|
|
user-del <email> Remove email account
|
|
user-list List all email accounts
|
|
user-passwd <email> Change user password
|
|
alias-add <alias> <target> Add email alias
|
|
alias-del <alias> Remove email alias
|
|
alias-list List all aliases
|
|
|
|
Domain & SSL:
|
|
domain-add <domain> Add email domain
|
|
domain-list List configured domains
|
|
ssl-status Show SSL certificate status
|
|
ssl-renew Force SSL certificate renewal
|
|
|
|
Backup & Restore:
|
|
backup [path] Backup mail data and config
|
|
restore <backup-file> Restore from backup
|
|
|
|
Diagnostics:
|
|
health Run health checks
|
|
dns-check [domain] Verify DNS records for domain
|
|
ports Check required ports
|
|
config Show current configuration
|
|
test-email <to> Send test email
|
|
|
|
Post-Installation:
|
|
1. Configure hostname and domain in /etc/config/mailinabox
|
|
2. Set proper DNS records (A, MX, SPF, DKIM, DMARC)
|
|
3. Start with: /etc/init.d/mailinabox start
|
|
4. Add users with: mailinaboxctl user-add admin@yourdomain.com
|
|
|
|
Required DNS Records:
|
|
A mail.domain.com -> your-public-ip
|
|
MX domain.com -> mail.domain.com (priority 10)
|
|
TXT domain.com -> "v=spf1 mx -all"
|
|
TXT _dmarc.domain.com -> "v=DMARC1; p=quarantine"
|
|
TXT mail._domainkey.domain.com -> (DKIM key from container)
|
|
EOF
|
|
}
|
|
|
|
require_root() { [ "$(id -u)" -eq 0 ] || { echo "Root required" >&2; exit 1; }; }
|
|
|
|
log_info() { echo "[INFO] $*"; }
|
|
log_warn() { echo "[WARN] $*" >&2; }
|
|
log_error() { echo "[ERROR] $*" >&2; }
|
|
|
|
uci_get() { uci -q get ${CONFIG}.main.$1; }
|
|
uci_set() { uci set ${CONFIG}.main.$1="$2" && uci commit ${CONFIG}; }
|
|
|
|
# Load configuration with defaults
|
|
load_config() {
|
|
enabled="$(uci_get enabled || echo 0)"
|
|
image="$(uci_get image || echo ghcr.io/docker-mailserver/docker-mailserver:latest)"
|
|
data_path="$(uci_get data_path || echo /srv/mailserver)"
|
|
hostname="$(uci_get hostname || echo mail.example.com)"
|
|
domain="$(uci_get domain || echo example.com)"
|
|
timezone="$(uci_get timezone || cat /etc/TZ 2>/dev/null || echo UTC)"
|
|
|
|
# Ports
|
|
smtp_port="$(uci_get smtp_port || echo 25)"
|
|
submission_port="$(uci_get submission_port || echo 587)"
|
|
submissions_port="$(uci_get submissions_port || echo 465)"
|
|
imap_port="$(uci_get imap_port || echo 143)"
|
|
imaps_port="$(uci_get imaps_port || echo 993)"
|
|
pop3_port="$(uci_get pop3_port || echo 110)"
|
|
pop3s_port="$(uci_get pop3s_port || echo 995)"
|
|
|
|
# Features
|
|
enable_pop3="$(uci_get enable_pop3 || echo 0)"
|
|
enable_clamav="$(uci_get enable_clamav || echo 0)"
|
|
enable_spamassassin="$(uci_get enable_spamassassin || echo 1)"
|
|
enable_fail2ban="$(uci_get enable_fail2ban || echo 1)"
|
|
ssl_type="$(uci_get ssl_type || echo letsencrypt)"
|
|
letsencrypt_email="$(uci_get letsencrypt_email)"
|
|
}
|
|
|
|
ensure_dir() { [ -d "$1" ] || mkdir -p "$1"; }
|
|
|
|
# =============================================================================
|
|
# Docker Functions
|
|
# =============================================================================
|
|
|
|
ensure_packages() {
|
|
for pkg in "$@"; do
|
|
if ! opkg list-installed 2>/dev/null | grep -q "^$pkg "; then
|
|
if [ "$OPKG_UPDATED" -eq 0 ]; then
|
|
opkg update || return 1
|
|
OPKG_UPDATED=1
|
|
fi
|
|
opkg install "$pkg" || return 1
|
|
fi
|
|
done
|
|
}
|
|
|
|
docker_ready() {
|
|
command -v docker >/dev/null 2>&1 && [ -S /var/run/docker.sock ]
|
|
}
|
|
|
|
check_prereqs() {
|
|
load_config
|
|
log_info "Checking prerequisites..."
|
|
|
|
# Check hostname configuration
|
|
if [ "$hostname" = "mail.example.com" ] || [ "$domain" = "example.com" ]; then
|
|
log_warn "Please configure hostname and domain in /etc/config/mailinabox"
|
|
log_warn "docker-mailserver requires a valid domain name"
|
|
fi
|
|
|
|
# Check cgroups
|
|
[ -d /sys/fs/cgroup ] || { log_error "/sys/fs/cgroup missing"; return 1; }
|
|
|
|
# Install Docker
|
|
ensure_packages dockerd docker containerd || return 1
|
|
|
|
# Enable and start Docker
|
|
/etc/init.d/dockerd enable >/dev/null 2>&1
|
|
if ! /etc/init.d/dockerd status >/dev/null 2>&1; then
|
|
/etc/init.d/dockerd start || return 1
|
|
sleep 3
|
|
fi
|
|
|
|
# Wait for Docker socket
|
|
local retry=0
|
|
while [ ! -S /var/run/docker.sock ] && [ $retry -lt 30 ]; do
|
|
sleep 1
|
|
retry=$((retry + 1))
|
|
done
|
|
|
|
[ -S /var/run/docker.sock ] || { log_error "Docker socket not available"; return 1; }
|
|
|
|
# Create data directories
|
|
ensure_dir "$data_path"
|
|
ensure_dir "$data_path/mail-data"
|
|
ensure_dir "$data_path/mail-state"
|
|
ensure_dir "$data_path/mail-logs"
|
|
ensure_dir "$data_path/config"
|
|
|
|
log_info "Docker ready, directories created"
|
|
return 0
|
|
}
|
|
|
|
pull_image() {
|
|
load_config
|
|
log_info "Pulling Docker image: $image"
|
|
docker pull "$image"
|
|
}
|
|
|
|
stop_container() {
|
|
docker stop "$CONTAINER_NAME" >/dev/null 2>&1 || true
|
|
docker rm "$CONTAINER_NAME" >/dev/null 2>&1 || true
|
|
}
|
|
|
|
container_running() {
|
|
docker ps --format '{{.Names}}' 2>/dev/null | grep -q "^${CONTAINER_NAME}$"
|
|
}
|
|
|
|
# Execute setup.sh in container
|
|
docker_setup() {
|
|
if ! container_running; then
|
|
log_error "Container not running. Start with: /etc/init.d/mailinabox start"
|
|
return 1
|
|
fi
|
|
docker exec -it "$CONTAINER_NAME" setup "$@"
|
|
}
|
|
|
|
# =============================================================================
|
|
# User Management Commands
|
|
# =============================================================================
|
|
|
|
cmd_user_add() {
|
|
local email="$1"
|
|
local password="$2"
|
|
|
|
[ -z "$email" ] && { log_error "Usage: mailinaboxctl user-add <email> [password]"; return 1; }
|
|
|
|
if [ -n "$password" ]; then
|
|
docker_setup email add "$email" "$password"
|
|
else
|
|
docker_setup email add "$email"
|
|
fi
|
|
}
|
|
|
|
cmd_user_del() {
|
|
local email="$1"
|
|
[ -z "$email" ] && { log_error "Usage: mailinaboxctl user-del <email>"; return 1; }
|
|
docker_setup email del "$email"
|
|
}
|
|
|
|
cmd_user_list() {
|
|
docker_setup email list
|
|
}
|
|
|
|
cmd_user_passwd() {
|
|
local email="$1"
|
|
[ -z "$email" ] && { log_error "Usage: mailinaboxctl user-passwd <email>"; return 1; }
|
|
docker_setup email update "$email"
|
|
}
|
|
|
|
cmd_alias_add() {
|
|
local alias="$1"
|
|
local target="$2"
|
|
[ -z "$alias" ] || [ -z "$target" ] && { log_error "Usage: mailinaboxctl alias-add <alias> <target>"; return 1; }
|
|
docker_setup alias add "$alias" "$target"
|
|
}
|
|
|
|
cmd_alias_del() {
|
|
local alias="$1"
|
|
[ -z "$alias" ] && { log_error "Usage: mailinaboxctl alias-del <alias>"; return 1; }
|
|
docker_setup alias del "$alias"
|
|
}
|
|
|
|
cmd_alias_list() {
|
|
docker_setup alias list
|
|
}
|
|
|
|
# =============================================================================
|
|
# Domain & SSL Commands
|
|
# =============================================================================
|
|
|
|
cmd_domain_add() {
|
|
local domain="$1"
|
|
[ -z "$domain" ] && { log_error "Usage: mailinaboxctl domain-add <domain>"; return 1; }
|
|
|
|
# Create virtual domain entry
|
|
load_config
|
|
local vhost_file="$data_path/config/postfix-virtual.cf"
|
|
if ! grep -q "^$domain" "$vhost_file" 2>/dev/null; then
|
|
echo "$domain" >> "$vhost_file"
|
|
log_info "Domain $domain added. Restart service to apply."
|
|
else
|
|
log_warn "Domain $domain already exists"
|
|
fi
|
|
}
|
|
|
|
cmd_domain_list() {
|
|
load_config
|
|
log_info "Configured domains:"
|
|
if [ -f "$data_path/config/postfix-virtual.cf" ]; then
|
|
cat "$data_path/config/postfix-virtual.cf" | grep -v "^#" | grep -v "^$"
|
|
fi
|
|
echo ""
|
|
echo "Primary domain: $domain"
|
|
echo "Mail hostname: $hostname"
|
|
}
|
|
|
|
cmd_ssl_status() {
|
|
load_config
|
|
log_info "SSL Configuration:"
|
|
echo " Type: $ssl_type"
|
|
|
|
if container_running; then
|
|
docker_setup debug show-mail-logs | grep -i "ssl\|cert\|tls" | tail -20
|
|
fi
|
|
|
|
# Check certificate files
|
|
if [ -d "$data_path/config/ssl" ]; then
|
|
echo ""
|
|
echo "Certificate files:"
|
|
ls -la "$data_path/config/ssl/" 2>/dev/null || echo " No certificates found"
|
|
fi
|
|
}
|
|
|
|
cmd_ssl_renew() {
|
|
load_config
|
|
if [ "$ssl_type" = "letsencrypt" ]; then
|
|
log_info "Triggering Let's Encrypt renewal..."
|
|
if container_running; then
|
|
docker exec "$CONTAINER_NAME" certbot renew
|
|
else
|
|
log_error "Container not running"
|
|
fi
|
|
else
|
|
log_warn "SSL type is not letsencrypt"
|
|
fi
|
|
}
|
|
|
|
# =============================================================================
|
|
# Backup & Restore Commands
|
|
# =============================================================================
|
|
|
|
cmd_backup() {
|
|
require_root
|
|
load_config
|
|
|
|
local backup_path="${1:-/tmp}"
|
|
local timestamp=$(date +%Y%m%d_%H%M%S)
|
|
local backup_file="$backup_path/mailserver_backup_$timestamp.tar.gz"
|
|
|
|
log_info "Creating backup..."
|
|
|
|
# Stop container for consistent backup
|
|
local was_running=0
|
|
if container_running; then
|
|
was_running=1
|
|
log_info "Stopping container for backup..."
|
|
stop_container
|
|
fi
|
|
|
|
# Create backup
|
|
tar czf "$backup_file" -C "$(dirname $data_path)" "$(basename $data_path)" 2>/dev/null || {
|
|
log_error "Backup failed"
|
|
[ $was_running -eq 1 ] && /etc/init.d/mailinabox start
|
|
return 1
|
|
}
|
|
|
|
# Restart if was running
|
|
[ $was_running -eq 1 ] && /etc/init.d/mailinabox start
|
|
|
|
log_info "Backup created: $backup_file"
|
|
ls -lh "$backup_file"
|
|
}
|
|
|
|
cmd_restore() {
|
|
require_root
|
|
load_config
|
|
|
|
local backup_file="$1"
|
|
[ -z "$backup_file" ] || [ ! -f "$backup_file" ] && {
|
|
log_error "Usage: mailinaboxctl restore <backup-file>"
|
|
return 1
|
|
}
|
|
|
|
log_warn "This will OVERWRITE existing mail data!"
|
|
echo -n "Continue? [y/N] "
|
|
read answer
|
|
[ "$answer" != "y" ] && [ "$answer" != "Y" ] && { echo "Aborted"; return 1; }
|
|
|
|
# Stop container
|
|
if container_running; then
|
|
log_info "Stopping container..."
|
|
stop_container
|
|
fi
|
|
|
|
# Remove existing data
|
|
log_info "Removing existing data..."
|
|
rm -rf "$data_path"
|
|
|
|
# Restore
|
|
log_info "Restoring from backup..."
|
|
tar xzf "$backup_file" -C "$(dirname $data_path)" || {
|
|
log_error "Restore failed"
|
|
return 1
|
|
}
|
|
|
|
log_info "Restore complete. Start service with: /etc/init.d/mailinabox start"
|
|
}
|
|
|
|
# =============================================================================
|
|
# Diagnostic Commands
|
|
# =============================================================================
|
|
|
|
cmd_health() {
|
|
load_config
|
|
|
|
echo "=== Mail Server Health Check ==="
|
|
echo ""
|
|
|
|
# Container status
|
|
echo "Container Status:"
|
|
if container_running; then
|
|
echo " [OK] Container is running"
|
|
local uptime=$(docker inspect --format='{{.State.StartedAt}}' "$CONTAINER_NAME" 2>/dev/null)
|
|
echo " Started: $uptime"
|
|
else
|
|
echo " [FAIL] Container is not running"
|
|
fi
|
|
echo ""
|
|
|
|
# Port checks
|
|
echo "Port Status:"
|
|
for port in $smtp_port $submission_port $imaps_port; do
|
|
if netstat -tln 2>/dev/null | grep -q ":$port "; then
|
|
echo " [OK] Port $port is listening"
|
|
else
|
|
echo " [WARN] Port $port is not listening"
|
|
fi
|
|
done
|
|
echo ""
|
|
|
|
# Service checks inside container
|
|
if container_running; then
|
|
echo "Services Status:"
|
|
docker exec "$CONTAINER_NAME" supervisorctl status 2>/dev/null || echo " Unable to check services"
|
|
fi
|
|
echo ""
|
|
|
|
# Disk usage
|
|
echo "Disk Usage:"
|
|
if [ -d "$data_path" ]; then
|
|
du -sh "$data_path" 2>/dev/null
|
|
du -sh "$data_path"/* 2>/dev/null | head -10
|
|
fi
|
|
}
|
|
|
|
cmd_dns_check() {
|
|
load_config
|
|
local check_domain="${1:-$domain}"
|
|
|
|
echo "=== DNS Check for $check_domain ==="
|
|
echo ""
|
|
|
|
# A record
|
|
echo "A Record (mail.$check_domain):"
|
|
local a_record=$(nslookup "mail.$check_domain" 2>/dev/null | grep -A1 "Name:" | tail -1)
|
|
if [ -n "$a_record" ]; then
|
|
echo " [OK] $a_record"
|
|
else
|
|
echo " [FAIL] No A record found"
|
|
fi
|
|
echo ""
|
|
|
|
# MX record
|
|
echo "MX Record ($check_domain):"
|
|
local mx_record=$(nslookup -type=mx "$check_domain" 2>/dev/null | grep "mail exchanger")
|
|
if [ -n "$mx_record" ]; then
|
|
echo " [OK] $mx_record"
|
|
else
|
|
echo " [FAIL] No MX record found"
|
|
fi
|
|
echo ""
|
|
|
|
# SPF record
|
|
echo "SPF Record ($check_domain):"
|
|
local spf=$(nslookup -type=txt "$check_domain" 2>/dev/null | grep "v=spf1")
|
|
if [ -n "$spf" ]; then
|
|
echo " [OK] $spf"
|
|
else
|
|
echo " [WARN] No SPF record found"
|
|
echo " Recommended: \"v=spf1 mx -all\""
|
|
fi
|
|
echo ""
|
|
|
|
# DMARC record
|
|
echo "DMARC Record (_dmarc.$check_domain):"
|
|
local dmarc=$(nslookup -type=txt "_dmarc.$check_domain" 2>/dev/null | grep "v=DMARC1")
|
|
if [ -n "$dmarc" ]; then
|
|
echo " [OK] $dmarc"
|
|
else
|
|
echo " [WARN] No DMARC record found"
|
|
echo " Recommended: \"v=DMARC1; p=quarantine; rua=mailto:postmaster@$check_domain\""
|
|
fi
|
|
}
|
|
|
|
cmd_ports() {
|
|
load_config
|
|
|
|
echo "=== Port Status ==="
|
|
echo ""
|
|
echo "Required ports for mail server:"
|
|
echo ""
|
|
|
|
local ports="25:SMTP 587:Submission 465:SMTPS 143:IMAP 993:IMAPS"
|
|
[ "$enable_pop3" = "1" ] && ports="$ports 110:POP3 995:POP3S"
|
|
|
|
for entry in $ports; do
|
|
local port=$(echo "$entry" | cut -d: -f1)
|
|
local name=$(echo "$entry" | cut -d: -f2)
|
|
|
|
printf " %-6s %-12s " "$port" "$name"
|
|
|
|
if netstat -tln 2>/dev/null | grep -q ":$port "; then
|
|
echo "[LISTENING]"
|
|
else
|
|
echo "[NOT LISTENING]"
|
|
fi
|
|
done
|
|
|
|
echo ""
|
|
echo "Note: Port 25 may be blocked by some ISPs"
|
|
}
|
|
|
|
cmd_config() {
|
|
load_config
|
|
|
|
echo "=== Mail Server Configuration ==="
|
|
echo ""
|
|
echo "General:"
|
|
echo " Enabled: $enabled"
|
|
echo " Image: $image"
|
|
echo " Hostname: $hostname"
|
|
echo " Domain: $domain"
|
|
echo " Data path: $data_path"
|
|
echo " Timezone: $timezone"
|
|
echo ""
|
|
echo "Features:"
|
|
echo " SpamAssassin: $enable_spamassassin"
|
|
echo " ClamAV: $enable_clamav"
|
|
echo " Fail2ban: $enable_fail2ban"
|
|
echo " POP3: $enable_pop3"
|
|
echo " SSL Type: $ssl_type"
|
|
echo ""
|
|
echo "Ports:"
|
|
echo " SMTP: $smtp_port"
|
|
echo " Submission: $submission_port"
|
|
echo " IMAPS: $imaps_port"
|
|
}
|
|
|
|
cmd_test_email() {
|
|
local to="$1"
|
|
[ -z "$to" ] && { log_error "Usage: mailinaboxctl test-email <to-address>"; return 1; }
|
|
|
|
load_config
|
|
|
|
if ! container_running; then
|
|
log_error "Container not running"
|
|
return 1
|
|
fi
|
|
|
|
log_info "Sending test email to $to..."
|
|
docker exec "$CONTAINER_NAME" sh -c "echo 'Test email from SecuBox Mail Server' | mail -s 'Test from $hostname' $to"
|
|
|
|
log_info "Test email sent (check spam folder if not received)"
|
|
}
|
|
|
|
# =============================================================================
|
|
# Main Container Commands
|
|
# =============================================================================
|
|
|
|
cmd_install() {
|
|
require_root
|
|
check_prereqs || exit 1
|
|
pull_image || exit 1
|
|
|
|
uci_set enabled '1'
|
|
uci commit ${CONFIG}
|
|
/etc/init.d/mailinabox enable
|
|
|
|
load_config
|
|
echo ""
|
|
log_info "Mail server installed successfully!"
|
|
echo ""
|
|
echo "NEXT STEPS:"
|
|
echo " 1. Edit /etc/config/mailinabox and configure:"
|
|
echo " - hostname (e.g., mail.yourdomain.com)"
|
|
echo " - domain (e.g., yourdomain.com)"
|
|
echo " 2. Set up DNS records (see 'mailinaboxctl dns-check')"
|
|
echo " 3. Start: /etc/init.d/mailinabox start"
|
|
echo " 4. Add first user: mailinaboxctl user-add admin@$domain"
|
|
echo ""
|
|
}
|
|
|
|
cmd_check() {
|
|
check_prereqs
|
|
echo ""
|
|
cmd_config
|
|
echo ""
|
|
cmd_ports
|
|
}
|
|
|
|
cmd_update() {
|
|
require_root
|
|
pull_image || exit 1
|
|
|
|
if container_running; then
|
|
/etc/init.d/mailinabox restart
|
|
else
|
|
log_info "Image updated. Start manually when ready."
|
|
fi
|
|
}
|
|
|
|
cmd_status() {
|
|
echo "=== Container Status ==="
|
|
docker ps -a --filter "name=$CONTAINER_NAME" --format "table {{.Names}}\t{{.Status}}\t{{.Ports}}"
|
|
echo ""
|
|
|
|
if container_running; then
|
|
echo "=== Service Status ==="
|
|
docker exec "$CONTAINER_NAME" supervisorctl status 2>/dev/null || true
|
|
fi
|
|
}
|
|
|
|
cmd_logs() {
|
|
docker logs "$@" "$CONTAINER_NAME"
|
|
}
|
|
|
|
cmd_shell() {
|
|
if container_running; then
|
|
docker exec -it "$CONTAINER_NAME" /bin/bash
|
|
else
|
|
log_error "Container not running"
|
|
fi
|
|
}
|
|
|
|
cmd_service_run() {
|
|
require_root
|
|
check_prereqs || exit 1
|
|
load_config
|
|
stop_container
|
|
|
|
log_info "Starting mail server container..."
|
|
|
|
# Build docker run command
|
|
local docker_args="--name $CONTAINER_NAME"
|
|
|
|
# Hostname
|
|
docker_args="$docker_args --hostname $hostname"
|
|
docker_args="$docker_args --domainname $domain"
|
|
|
|
# Ports
|
|
docker_args="$docker_args -p $smtp_port:25"
|
|
docker_args="$docker_args -p $submission_port:587"
|
|
docker_args="$docker_args -p $submissions_port:465"
|
|
docker_args="$docker_args -p $imap_port:143"
|
|
docker_args="$docker_args -p $imaps_port:993"
|
|
|
|
if [ "$enable_pop3" = "1" ]; then
|
|
docker_args="$docker_args -p $pop3_port:110"
|
|
docker_args="$docker_args -p $pop3s_port:995"
|
|
fi
|
|
|
|
# Volumes
|
|
docker_args="$docker_args -v $data_path/mail-data:/var/mail"
|
|
docker_args="$docker_args -v $data_path/mail-state:/var/mail-state"
|
|
docker_args="$docker_args -v $data_path/mail-logs:/var/log/mail"
|
|
docker_args="$docker_args -v $data_path/config:/tmp/docker-mailserver"
|
|
|
|
# Let's Encrypt volume if using certbot
|
|
if [ "$ssl_type" = "letsencrypt" ]; then
|
|
ensure_dir "$data_path/letsencrypt"
|
|
docker_args="$docker_args -v $data_path/letsencrypt:/etc/letsencrypt"
|
|
fi
|
|
|
|
# Environment variables
|
|
docker_args="$docker_args -e TZ=$timezone"
|
|
docker_args="$docker_args -e OVERRIDE_HOSTNAME=$hostname"
|
|
docker_args="$docker_args -e ENABLE_SPAMASSASSIN=$enable_spamassassin"
|
|
docker_args="$docker_args -e ENABLE_CLAMAV=$enable_clamav"
|
|
docker_args="$docker_args -e ENABLE_FAIL2BAN=$enable_fail2ban"
|
|
docker_args="$docker_args -e ENABLE_POP3=$enable_pop3"
|
|
docker_args="$docker_args -e SSL_TYPE=$ssl_type"
|
|
docker_args="$docker_args -e PERMIT_DOCKER=network"
|
|
docker_args="$docker_args -e ONE_DIR=1"
|
|
docker_args="$docker_args -e POSTMASTER_ADDRESS=postmaster@$domain"
|
|
|
|
if [ -n "$letsencrypt_email" ]; then
|
|
docker_args="$docker_args -e LETSENCRYPT_EMAIL=$letsencrypt_email"
|
|
fi
|
|
|
|
# Capabilities
|
|
docker_args="$docker_args --cap-add=NET_ADMIN"
|
|
docker_args="$docker_args --cap-add=SYS_PTRACE"
|
|
|
|
# Restart policy
|
|
docker_args="$docker_args --restart=unless-stopped"
|
|
|
|
exec docker run --rm $docker_args "$image"
|
|
}
|
|
|
|
cmd_service_stop() {
|
|
require_root
|
|
stop_container
|
|
}
|
|
|
|
# =============================================================================
|
|
# Main Entry Point
|
|
# =============================================================================
|
|
|
|
case "${1:-}" in
|
|
# Container management
|
|
install) shift; cmd_install "$@" ;;
|
|
check) shift; cmd_check "$@" ;;
|
|
update) shift; cmd_update "$@" ;;
|
|
status) shift; cmd_status "$@" ;;
|
|
logs) shift; cmd_logs "$@" ;;
|
|
shell) shift; cmd_shell "$@" ;;
|
|
service-run) shift; cmd_service_run "$@" ;;
|
|
service-stop) shift; cmd_service_stop "$@" ;;
|
|
|
|
# User management
|
|
user-add) shift; cmd_user_add "$@" ;;
|
|
user-del) shift; cmd_user_del "$@" ;;
|
|
user-list) shift; cmd_user_list "$@" ;;
|
|
user-passwd) shift; cmd_user_passwd "$@" ;;
|
|
alias-add) shift; cmd_alias_add "$@" ;;
|
|
alias-del) shift; cmd_alias_del "$@" ;;
|
|
alias-list) shift; cmd_alias_list "$@" ;;
|
|
|
|
# Domain & SSL
|
|
domain-add) shift; cmd_domain_add "$@" ;;
|
|
domain-list) shift; cmd_domain_list "$@" ;;
|
|
ssl-status) shift; cmd_ssl_status "$@" ;;
|
|
ssl-renew) shift; cmd_ssl_renew "$@" ;;
|
|
|
|
# Backup & restore
|
|
backup) shift; cmd_backup "$@" ;;
|
|
restore) shift; cmd_restore "$@" ;;
|
|
|
|
# Diagnostics
|
|
health) shift; cmd_health "$@" ;;
|
|
dns-check) shift; cmd_dns_check "$@" ;;
|
|
ports) shift; cmd_ports "$@" ;;
|
|
config) shift; cmd_config "$@" ;;
|
|
test-email) shift; cmd_test_email "$@" ;;
|
|
|
|
help|--help|-h|'') usage ;;
|
|
*) echo "Unknown command: $1" >&2; usage >&2; exit 1 ;;
|
|
esac
|