Files
schedule/deploy/nginx-site.sh

121 lines
4.5 KiB
Bash
Executable File
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#!/usr/bin/env bash
# Генерирует и включает конфиг nginx для сайта расписания.
#
# SSL обеспечивает сертификат родительского домена (обычно wildcard *.example.ru):
# отдельный certbot для поддомена не нужен — достаточно имени сертификата.
# Список имён: sudo ls /etc/letsencrypt/live/
#
# Имя сертификата берётся из --cert, иначе — родительский домен от --domain
# (schedule.example.ru -> example.ru). Порт фронта берётся из --port, иначе из
# FRONTEND_PORT файла .env в корне проекта, иначе 8090.
#
# Примеры:
# deploy/nginx-site.sh --print # показать конфиг, ничего не менять
# sudo deploy/nginx-site.sh # поставить и перечитать nginx
# sudo deploy/nginx-site.sh --domain sched.example.ru --cert example.ru
set -euo pipefail
usage() {
grep '^#' "$0" | sed 's/^# \{0,1\}//' | tail -n +2
}
DOMAIN="schedule.our-place.ru"
CERT_NAME=""
FRONTEND_PORT=""
PRINT=0
while [[ $# -gt 0 ]]; do
case "$1" in
--domain) DOMAIN="$2"; shift 2 ;;
--cert) CERT_NAME="$2"; shift 2 ;;
--port) FRONTEND_PORT="$2"; shift 2 ;;
--print) PRINT=1; shift ;;
-h|--help) usage; exit 0 ;;
*) echo "Неизвестный аргумент: $1 (см. --help)" >&2; exit 2 ;;
esac
done
[[ $DOMAIN =~ ^[a-zA-Z0-9.-]+$ ]] || { echo "Кривое имя домена: $DOMAIN" >&2; exit 2; }
if [[ -z $CERT_NAME ]]; then
CERT_NAME="${DOMAIN#*.}" # schedule.our-place.ru -> our-place.ru (wildcard родителя)
fi
[[ $CERT_NAME =~ ^[a-zA-Z0-9.-]+$ ]] || { echo "Кривое имя сертификата: $CERT_NAME" >&2; exit 2; }
if [[ -z $FRONTEND_PORT ]]; then
# FRONTEND_PORT из .env; значение вида «127.0.0.1:8090» трактуем как «порт после двоеточия»
FRONTEND_PORT=$(
grep -E '^FRONTEND_PORT=' .env 2>/dev/null | tail -1 | cut -d= -f2- \
| tr -d ' "' | awk -F: '{print $NF}'
) || FRONTEND_PORT=""
fi
FRONTEND_PORT=${FRONTEND_PORT:-8090}
[[ $FRONTEND_PORT =~ ^[0-9]+$ ]] || { echo "Не разобрал FRONTEND_PORT из .env, задайте --port" >&2; exit 2; }
read -r -d '' CONFIG <<'TEMPLATE' || true
# Сгенерировано deploy/nginx-site.sh — правки вносить в скрипт, не сюда.
server {
listen 80;
listen [::]:80;
server_name __DOMAIN__;
location /.well-known/acme-challenge/ {
root /var/www/html;
}
location / {
return 301 https://$host$request_uri;
}
}
server {
listen 443 ssl http2;
listen [::]:443 ssl http2;
server_name __DOMAIN__;
# сертификат родительского домена (обычно wildcard), обновляет certbot родителя
ssl_certificate /etc/letsencrypt/live/__CERT__/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/__CERT__/privkey.pem;
ssl_protocols TLSv1.2 TLSv1.3;
client_max_body_size 8m;
location / {
# порт FRONTEND_PORT из .env стенда
proxy_pass http://127.0.0.1:__PORT__;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto https;
# холодный кэш: бэкенд качает таблицу, до ~2 минут
proxy_read_timeout 300s;
proxy_send_timeout 300s;
}
}
TEMPLATE
CONFIG=${CONFIG//__DOMAIN__/$DOMAIN}
CONFIG=${CONFIG//__CERT__/$CERT_NAME}
CONFIG=${CONFIG//__PORT__/$FRONTEND_PORT}
if [[ $PRINT == 1 ]]; then
printf '%s\n' "$CONFIG"
exit 0
fi
if [[ $EUID -ne 0 ]]; then
echo "Установка требует root: sudo deploy/nginx-site.sh (посмотреть конфиг — deploy/nginx-site.sh --print)" >&2
exit 1
fi
DEST="/etc/nginx/sites-available/${DOMAIN}"
printf '%s\n' "$CONFIG" > "$DEST"
ln -sf "$DEST" "/etc/nginx/sites-enabled/${DOMAIN}"
if nginx -t 2>&1; then
systemctl reload nginx
echo "Готово: https://${DOMAIN} -> 127.0.0.1:${FRONTEND_PORT} (сертификат ${CERT_NAME})"
else
echo "nginx -t не прошёл: конфиг записан в ${DEST} и включён, но nginx НЕ перечитан. Разберитесь и выполните: sudo nginx -t && sudo systemctl reload nginx" >&2
exit 1
fi