#!/usr/bin/env bash set -Eeuo pipefail SCRIPT_DIR="$(cd -- "$(dirname -- "${BASH_SOURCE[0]}")" && pwd)" ROOT_DIR="$(cd -- "${SCRIPT_DIR}/.." && pwd)" APP_ENV_FILE="${ROOT_DIR}/.env" MAIL_ENV_FILE="${ROOT_DIR}/.env.mail" MAIL_ENV_EXAMPLE="${ROOT_DIR}/.env.mail.example" APP_COMPOSE_FILE="${ROOT_DIR}/compose.yaml" MAIL_COMPOSE_FILE="${ROOT_DIR}/compose.mail.yaml" MAIL_SERVICE="stalwart" usage() { cat <<'EOF' Использование: ./scripts/mail-server.sh init ./scripts/mail-server.sh up ./scripts/mail-server.sh down ./scripts/mail-server.sh restart ./scripts/mail-server.sh status ./scripts/mail-server.sh logs ./scripts/mail-server.sh credentials ./scripts/mail-server.sh shell Первый запуск: 1. ./scripts/mail-server.sh init 2. Проверь .env.mail 3. Создай A-запись mail.<домен> на IP сервера 4. ./scripts/mail-server.sh up 5. ./scripts/mail-server.sh credentials 6. Открой SSH-туннель к 127.0.0.1:8081 и заверши мастер настройки EOF } fail() { printf '[mail:error] %s\n' "$*" >&2 exit 1 } log() { printf '[mail] %s\n' "$*" } require_command() { command -v "$1" >/dev/null 2>&1 || fail "Не найдена команда: $1" } mail_env_value() { local key="$1" grep -E "^${key}=" "$MAIL_ENV_FILE" | tail -n 1 | cut -d '=' -f 2- | sed -e 's/^"//' -e 's/"$//' } compose() { local env_args=(--env-file "$MAIL_ENV_FILE") if [[ -f "$APP_ENV_FILE" ]]; then env_args=(--env-file "$APP_ENV_FILE" --env-file "$MAIL_ENV_FILE") fi docker compose \ "${env_args[@]}" \ -f "$APP_COMPOSE_FILE" \ -f "$MAIL_COMPOSE_FILE" \ --profile mail \ "$@" } init() { if [[ -f "$MAIL_ENV_FILE" ]]; then log "${MAIL_ENV_FILE} уже существует" return fi cp "$MAIL_ENV_EXAMPLE" "$MAIL_ENV_FILE" chmod 600 "$MAIL_ENV_FILE" log "Создан ${MAIL_ENV_FILE}; проверь домен перед запуском" } validate_config() { [[ -f "$MAIL_ENV_FILE" ]] || fail "Сначала выполни: ./scripts/mail-server.sh init" local hostname local domain hostname="$(mail_env_value MAIL_HOSTNAME)" domain="$(mail_env_value MAIL_DOMAIN)" [[ -n "$hostname" ]] || fail "MAIL_HOSTNAME не задан в .env.mail" [[ -n "$domain" ]] || fail "MAIL_DOMAIN не задан в .env.mail" [[ "$hostname" == *."$domain" ]] || fail "MAIL_HOSTNAME должен принадлежать MAIL_DOMAIN" } show_credentials() { compose logs "$MAIL_SERVICE" 2>&1 \ | sed -n '/bootstrap mode/,+20p' \ | tail -n 24 } main() { require_command docker docker compose version >/dev/null 2>&1 || fail "Не найден Docker Compose Plugin" local action="${1:-}" case "$action" in init) init ;; up) validate_config compose up -d "$MAIL_SERVICE" log "Stalwart запущен" log "Временные реквизиты: ./scripts/mail-server.sh credentials" ;; down) validate_config compose stop "$MAIL_SERVICE" ;; restart) validate_config compose restart "$MAIL_SERVICE" ;; status) validate_config compose ps "$MAIL_SERVICE" ;; logs) validate_config compose logs --tail=200 -f "$MAIL_SERVICE" ;; credentials) validate_config show_credentials ;; shell) validate_config compose exec "$MAIL_SERVICE" /bin/sh ;; -h|--help|help) usage ;; *) usage exit 1 ;; esac } main "$@"