deploy/setup-tls.sh
Rama main · réplica de lectura del repositorio original.
#!/usr/bin/env bash
# Issues the Let's Encrypt certificate for the configured domain and installs
# the TLS vhost.
# Safety contract: never restarts Apache, never edits an existing vhost, and
# aborts before touching anything if configtest fails.
set -euo pipefail
HERE="$(cd "$(dirname "$0")" && pwd)"
# The domain comes from .env. It used to be hardcoded, which meant a fresh
# clone would try to issue a certificate for someone else's domain.
ENV_FILE="${ENV_FILE:-$HERE/../.env}"
[ -f "$ENV_FILE" ] || { echo "FAIL: $ENV_FILE not found - copy .env.example first"; exit 1; }
DOMAIN="$(grep -E '^MAIL_HOSTNAME=' "$ENV_FILE" | cut -d= -f2- | tr -d '"'"'"'[:space:]')"
[ -n "$DOMAIN" ] || { echo "FAIL: MAIL_HOSTNAME is not set in $ENV_FILE"; exit 1; }
say(){ printf '\n\033[1m==> %s\033[0m\n' "$*"; }
say "Preflight: DNS"
ip=$(dig +short A "$DOMAIN" | tail -1)
want=$(curl -s --max-time 10 https://api.ipify.org)
if [ -z "$ip" ]; then
echo "FAIL: $DOMAIN has no A record yet. Add it in Hostinger hPanel first:"
echo " A mail -> $want"
exit 1
fi
[ "$ip" = "$want" ] || { echo "FAIL: $DOMAIN resolves to $ip, expected $want"; exit 1; }
echo "ok: $DOMAIN -> $ip"
say "Preflight: required Apache modules"
missing=""
for m in proxy proxy_http proxy_wstunnel rewrite headers ssl; do
a2query -m "$m" >/dev/null 2>&1 && echo " ok $m" || { echo " MISS $m"; missing="$missing $m"; }
done
if [ -n "$missing" ]; then
echo "FAIL: missing modules:$missing"
echo " Enable with: a2enmod$missing && systemctl reload apache2"
exit 1
fi
say "Installing stage-1 HTTP vhost (ACME challenge)"
mkdir -p /var/www/letsencrypt/.well-known/acme-challenge
sed "s|@@DOMAIN@@|$DOMAIN|g" "$HERE/raymail-http.conf" > /etc/apache2/sites-available/raymail.conf
a2ensite raymail >/dev/null
apache2ctl configtest
systemctl reload apache2 # graceful: existing connections are not dropped
echo "ok: stage-1 live"
say "Requesting certificate (webroot — same method as your other vhosts)"
certbot certonly --webroot -w /var/www/letsencrypt -d "$DOMAIN" \
--non-interactive --agree-tos --register-unsafely-without-email --keep-until-expiring
say "Installing stage-2 TLS vhost"
sed "s|@@DOMAIN@@|$DOMAIN|g" "$HERE/raymail.conf" > /etc/apache2/sites-available/raymail.conf
if ! apache2ctl configtest; then
echo "FAIL: configtest rejected the TLS vhost — rolling back to stage 1"
sed "s|@@DOMAIN@@|$DOMAIN|g" "$HERE/raymail-http.conf" > /etc/apache2/sites-available/raymail.conf
apache2ctl configtest && systemctl reload apache2
exit 1
fi
systemctl reload apache2
echo "ok: https://$DOMAIN is live"
say "Reloading Stalwart so it picks up the new certificate"
docker restart raymail-stalwart >/dev/null 2>&1 || true
echo "done"