From 17f551aa462d043781e565928b15ea21ca054480 Mon Sep 17 00:00:00 2001 From: Fedorov Vladimir Date: Sat, 3 Oct 2026 16:49:49 +0700 Subject: [PATCH] fix --- README.md | 21 ++++++++++++++++++++- accounts.txt | 2 ++ check.sh | 10 ++++++++++ destroy.sh | 18 ++++++++++++++++++ docker-compose.yml | 5 ++--- setup-mail-tls.sh | 12 +++++++++--- up.sh | 37 +++++++++++++++++++++++++++++++++++++ 7 files changed, 98 insertions(+), 7 deletions(-) create mode 100644 accounts.txt create mode 100755 check.sh create mode 100755 destroy.sh create mode 100755 up.sh diff --git a/README.md b/README.md index cc389a5..7ee08be 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,23 @@ -# mail server +# Mail server + +## Запуск + +```bash +./up.sh +``` + +Скрипт поднимет почтовый контейнер, запросит пароли для адресов из +`accounts.txt`, создаст DKIM и проверит TLS. Пароли не сохраняются в файлы. + +## Удаление старого сервера + +Удаляет контейнер и все почтовые volumes без возможности восстановления: + +```bash +DELETE_MAIL_DATA=YES ./destroy.sh +``` + +`reproxy` и игровые контейнеры скрипт не трогает. Папки: diff --git a/accounts.txt b/accounts.txt new file mode 100644 index 0000000..91baefe --- /dev/null +++ b/accounts.txt @@ -0,0 +1,2 @@ +evening_detective@crabs-games.art +admin@crabs-games.art diff --git a/check.sh b/check.sh new file mode 100755 index 0000000..d7e7351 --- /dev/null +++ b/check.sh @@ -0,0 +1,10 @@ +#!/usr/bin/env bash +set -euo pipefail + +DOMAIN="${MAIL_DOMAIN:-mail.crabs-games.art}" + +docker ps --filter name=^/mailserver$ --format 'mailserver: {{.Status}}' +openssl s_client \ + -connect "$DOMAIN:465" \ + -servername "$DOMAIN" /dev/null | + openssl x509 -noout -subject -issuer -dates diff --git a/destroy.sh b/destroy.sh new file mode 100755 index 0000000..cab645d --- /dev/null +++ b/destroy.sh @@ -0,0 +1,18 @@ +#!/usr/bin/env bash +set -euo pipefail + +SCRIPT_DIR="$(cd -- "$(dirname -- "${BASH_SOURCE[0]}")" && pwd)" +COMPOSE_FILE="$SCRIPT_DIR/docker-compose.yml" + +if [ "${DELETE_MAIL_DATA:-}" != "YES" ]; then + echo "This removes the mailserver container and all mail volumes." >&2 + echo "Run: DELETE_MAIL_DATA=YES ./destroy.sh" >&2 + exit 1 +fi + +docker compose -f "$COMPOSE_FILE" down --remove-orphans +docker volume rm \ + email_server_mail-data \ + email_server_mail-state \ + email_server_mail-logs 2>/dev/null || true +echo "Old mail server and mail data removed." diff --git a/docker-compose.yml b/docker-compose.yml index 0939263..0f71992 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -1,6 +1,6 @@ services: mailserver: - image: mailserver/docker-mailserver:latest + image: mailserver/docker-mailserver:v15.1.0 container_name: mailserver hostname: mail.crabs-games.art ports: @@ -25,7 +25,7 @@ services: - mail-data:/var/mail - mail-state:/var/mail-state - mail-logs:/var/log/mail - - /Users/vladimir/reproxy/var/ssl/certificates/acme-v02.api.letsencrypt.org-directory/mail.crabs-games.art:/etc/letsencrypt + - ${REPROXY_SSL_DIR:-/Users/vladimir/reproxy/var/ssl}/certificates/acme-v02.api.letsencrypt.org-directory/mail.crabs-games.art:/etc/letsencrypt restart: always networks: - crabs-network @@ -39,4 +39,3 @@ volumes: mail-data: mail-state: mail-logs: - diff --git a/setup-mail-tls.sh b/setup-mail-tls.sh index bc93233..f45ecdf 100755 --- a/setup-mail-tls.sh +++ b/setup-mail-tls.sh @@ -5,13 +5,15 @@ DOMAIN="${MAIL_DOMAIN:-mail.crabs-games.art}" EMAIL="${ACME_EMAIL:-admin@crabs-games.art}" REPROXY_CONTAINER="${REPROXY_CONTAINER:-reproxy}" SCRIPT_DIR="$(cd -- "$(dirname -- "${BASH_SOURCE[0]}")" && pwd)" -SSL_DIR="$SCRIPT_DIR/ssl" +REPROXY_SSL_DIR="${REPROXY_SSL_DIR:-/Users/vladimir/reproxy/var/ssl}" +CERTBOT_DIR="$REPROXY_SSL_DIR/certbot" +CERT_DIR="$REPROXY_SSL_DIR/certificates/acme-v02.api.letsencrypt.org-directory/$DOMAIN" COMPOSE_FILE="$SCRIPT_DIR/docker-compose.yml" command -v docker >/dev/null || { echo "docker is required" >&2; exit 1; } docker info >/dev/null || { echo "docker access is required" >&2; exit 1; } -mkdir -p "$SSL_DIR" +mkdir -p "$CERTBOT_DIR" "$CERT_DIR" reproxy_was_running=0 if docker inspect -f '{{.State.Running}}' "$REPROXY_CONTAINER" 2>/dev/null | grep -qx true; then @@ -28,15 +30,19 @@ trap restart_reproxy EXIT docker run --rm \ -p 80:80 \ - -v "$SSL_DIR:/etc/letsencrypt" \ + -v "$CERTBOT_DIR:/etc/letsencrypt" \ certbot/certbot:latest \ certonly --standalone \ --keep-until-expiring \ --non-interactive \ --agree-tos \ --email "$EMAIL" \ + --cert-name "$DOMAIN" \ -d "$DOMAIN" +cp "$CERTBOT_DIR/live/$DOMAIN/fullchain.pem" "$CERT_DIR/$DOMAIN.crt" +cp "$CERTBOT_DIR/live/$DOMAIN/privkey.pem" "$CERT_DIR/$DOMAIN.key" + docker compose -f "$COMPOSE_FILE" up -d --force-recreate mailserver echo "TLS certificate for $DOMAIN is installed." diff --git a/up.sh b/up.sh new file mode 100755 index 0000000..ab95279 --- /dev/null +++ b/up.sh @@ -0,0 +1,37 @@ +#!/usr/bin/env bash +set -euo pipefail + +SCRIPT_DIR="$(cd -- "$(dirname -- "${BASH_SOURCE[0]}")" && pwd)" +COMPOSE_FILE="$SCRIPT_DIR/docker-compose.yml" +ACCOUNTS_FILE="${ACCOUNTS_FILE:-$SCRIPT_DIR/accounts.txt}" +export REPROXY_SSL_DIR="${REPROXY_SSL_DIR:-/Users/vladimir/reproxy/var/ssl}" + +command -v docker >/dev/null || { echo "docker is required" >&2; exit 1; } +docker info >/dev/null || { echo "docker access is required" >&2; exit 1; } + +docker network inspect crabs-network >/dev/null 2>&1 || docker network create crabs-network >/dev/null + +CERT="$REPROXY_SSL_DIR/certificates/acme-v02.api.letsencrypt.org-directory/mail.crabs-games.art/mail.crabs-games.art.crt" +if [ ! -f "$CERT" ] || ! openssl x509 -in "$CERT" -noout -checkend 2592000 >/dev/null 2>&1; then + "$SCRIPT_DIR/setup-mail-tls.sh" +fi + +docker compose -f "$COMPOSE_FILE" up -d mailserver + +while IFS= read -r account || [ -n "$account" ]; do + [[ -z "$account" || "$account" == \#* ]] && continue + if docker exec mailserver setup email list 2>/dev/null | grep -Fq "$account"; then + echo "exists: $account" + continue + fi + + read -r -s -p "Password for $account: " password + echo + [ -n "$password" ] || { echo "empty password is not allowed" >&2; exit 1; } + docker exec mailserver setup email add "$account" "$password" + unset password +done < "$ACCOUNTS_FILE" + +docker exec mailserver setup config dkim +echo "Mail server is running." +"$SCRIPT_DIR/check.sh"