DEPLOY_HOST, RELAY_HOST и TELEGRAM_BOT_ID обязательны и читаются из неотслеживаемого deploy/.env.local (образец — .env.local.example).
94 lines
4.4 KiB
Bash
Executable File
94 lines
4.4 KiB
Bash
Executable File
#!/usr/bin/env bash
|
|
# Однократная настройка nginx и HTTPS для kvarta.unuchak.com. Запускать локально из корня:
|
|
# CERTBOT_EMAIL=you@example.com deploy/setup-nginx.sh
|
|
# Хост: DEPLOY_HOST из deploy/.env.local или окружения. Повторный запуск безопасен.
|
|
#
|
|
# На сервере чужие боевые сайты: при ошибке `nginx -t` наш симлинк убирается
|
|
# и reload не делается — общий nginx не должен упасть из-за нашего конфига.
|
|
set -euo pipefail
|
|
|
|
# адреса серверов в репо не храним: deploy/.env.local (образец — deploy/.env.local.example)
|
|
# shellcheck source=/dev/null
|
|
[[ -f "$(dirname "$0")/.env.local" ]] && source "$(dirname "$0")/.env.local"
|
|
DEPLOY_HOST="${DEPLOY_HOST:?задайте DEPLOY_HOST в deploy/.env.local (см. deploy/.env.local.example)}"
|
|
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"
|