121 lines
4.5 KiB
Bash
Executable File
121 lines
4.5 KiB
Bash
Executable File
#!/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
|