Files
kvarta_project/deploy/setup-nginx.sh
T

91 lines
4.1 KiB
Bash
Executable File

#!/usr/bin/env bash
# Однократная настройка nginx и HTTPS для kvarta.unuchak.com. Запускать локально из корня:
# CERTBOT_EMAIL=you@example.com deploy/setup-nginx.sh
# Хост: DEPLOY_HOST (по умолчанию root@185.5.249.52). Повторный запуск безопасен.
#
# На сервере чужие боевые сайты: при ошибке `nginx -t` наш симлинк убирается
# и reload не делается — общий nginx не должен упасть из-за нашего конфига.
set -euo pipefail
DEPLOY_HOST="${DEPLOY_HOST:-root@185.5.249.52}"
DOMAIN=kvarta.unuchak.com
CONF_SRC="deploy/nginx/$DOMAIN.conf"
AVAILABLE="/etc/nginx/sites-available/$DOMAIN"
ENABLED="/etc/nginx/sites-enabled/$DOMAIN"
SSH_OPTS=(-o BatchMode=yes -o ConnectTimeout=10
-o ControlMaster=auto -o "ControlPath=$HOME/.ssh/kvarta-nginx-%C" -o ControlPersist=60)
STEP=0
step() { STEP=$((STEP + 1)); printf '\n\033[1m[%d] %s\033[0m\n' "$STEP" "$*"; }
info() { printf ' %s\n' "$*"; }
die() { printf '\033[31mОШИБКА: %s\033[0m\n' "$*" >&2; exit 1; }
# shellcheck disable=SC2029 # команды для сервера собираются локально намеренно
remote() { ssh "${SSH_OPTS[@]}" "$DEPLOY_HOST" "$@"; }
cd "$(dirname "$0")/.."
step "Проверка параметров"
if [[ -z ${CERTBOT_EMAIL:-} ]]; then
die "задайте CERTBOT_EMAIL — на него Let's Encrypt шлёт предупреждения об истечении сертификата:
CERTBOT_EMAIL=you@example.com deploy/setup-nginx.sh"
fi
[[ $CERTBOT_EMAIL =~ ^[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Za-z]{2,}$ ]] \
|| die "CERTBOT_EMAIL не похож на email: $CERTBOT_EMAIL"
[[ -f $CONF_SRC ]] || die "нет $CONF_SRC"
info "хост $DEPLOY_HOST, домен $DOMAIN, email $CERTBOT_EMAIL"
step "Проверка сервера"
remote true || die "нет ssh-доступа к $DEPLOY_HOST"
remote 'command -v nginx >/dev/null && command -v certbot >/dev/null' \
|| die "на сервере нет nginx или certbot"
# общий nginx должен быть исправен до нас — иначе мы не отличим свою ошибку от чужой
remote 'nginx -t 2>&1' >/dev/null || die "nginx -t падает ещё до наших изменений — разберитесь вручную, скрипт ничего не трогал"
step "Конфиг в $AVAILABLE"
# если certbot уже дописал в конфиг 443-блок — не затираем его исходным 80-м
if remote "grep -q 'managed by Certbot' $AVAILABLE 2>/dev/null"; then
info "конфиг уже обработан certbot — оставляю как есть"
else
# прежняя версия нашего конфига — чтобы вернуть её, если новая не пройдёт nginx -t
remote "[ ! -e $AVAILABLE ] || cp -a $AVAILABLE $AVAILABLE.bak"
scp -q "${SSH_OPTS[@]}" "$CONF_SRC" "$DEPLOY_HOST:$AVAILABLE"
info "скопирован"
fi
step "Симлинк в sites-enabled"
created_link=0
if remote "[ -e $ENABLED ] || [ -L $ENABLED ]"; then
info "уже есть — не трогаю"
else
remote "ln -s $AVAILABLE $ENABLED"
created_link=1
info "создан $ENABLED"
fi
step "nginx -t"
if ! remote 'nginx -t'; then
if ((created_link)); then
remote "rm -f $ENABLED"
info "наш симлинк удалён"
fi
if remote "[ -e $AVAILABLE.bak ]"; then
remote "mv -f $AVAILABLE.bak $AVAILABLE"
info "восстановлена прежняя версия $AVAILABLE"
fi
die "конфиг не прошёл nginx -t — reload не выполнен"
fi
remote "rm -f $AVAILABLE.bak"
step "systemctl reload nginx"
remote 'systemctl reload nginx'
step "Сертификат Let's Encrypt (certbot --nginx)"
remote "certbot --nginx -d $DOMAIN --non-interactive --agree-tos --redirect -m '$CERTBOT_EMAIL'"
step "Итоговая проверка"
remote 'nginx -t' && remote "curl -fsS -o /dev/null -w 'https://$DOMAIN/ → %{http_code}\n' https://$DOMAIN/ || true"
printf '\nГотово: https://%s\n' "$DOMAIN"