Files
ForbiddenStarsApp/deploy/vps/README.md
T
NotBigGhostandClaude Opus 4.8 32c74abc43 Бэкап: полный оффсайт-бэкап прода на VPS (БД + uploads + achievements) + восстановление
- scripts/backup.sh: консистентный снимок SQLite (.backup) + архив fs_<TS>.tar.gz с uploads и
  achievements в backups/, локальная ротация; при заданном BACKUP_VPS_HOST — push на VPS (scp
  отдельным ключом/юзером) с удалённой ротацией. Настройки читаются из .env (BACKUP_*).
- scripts/restore.sh: восстановление архива в прод (stop app → очистка тома → docker cp → start).
- .env.example: блок BACKUP_* (host/user/dir/key/keep). .gitignore: id_backup* (ключ бэкапа).
- deploy/pi/README, deploy/vps/README: настройка ключа и юзера backup, /srv/fs-backups, cron, restore.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-26 23:36:58 +03:00

126 lines
7.2 KiB
Markdown
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.
# VPS (186.246.51.17) — реверс-прокси Caddy + точка входа SSH-туннелей
Единственная публичная точка. На VPS: Caddy терминирует HTTPS твоими сертификатами
для двух доменов и проксирует трафик в SSH reverse-туннели от Pi (прод) и ПК (dev/test).
```
forbiddenstars.ru → 127.0.0.1:9000 ← Pi (autossh, постоянно) PROD
forbidden-stars.ru → 127.0.0.1:9001 ← ПК (по требованию) DEV/TEST
```
> Туннель `ssh -R` по умолчанию слушает на loopback VPS (127.0.0.1) — ровно туда смотрит
> Caddy. `GatewayPorts` включать НЕ нужно. Снаружи порты 9000/9001 недоступны.
## 0. DNS
A-записи обоих доменов → `186.246.51.17`:
```
forbiddenstars.ru A 186.246.51.17
forbidden-stars.ru A 186.246.51.17
```
Проверка: `dig +short forbiddenstars.ru` (и второго) должны вернуть этот IP.
## 1. Зайти на VPS
```bash
ssh root@186.246.51.17 # пароль введёшь сам
```
## 2. Обновление + файрвол
```bash
apt update && apt -y upgrade
apt -y install ufw curl gnupg
ufw allow OpenSSH
ufw allow 80/tcp
ufw allow 443/tcp
ufw --force enable
```
## 3. Установить Caddy (официальный репозиторий)
```bash
apt -y install debian-keyring debian-archive-keyring apt-transport-https
curl -1sLf 'https://dl.cloudsmith.io/public/caddy/stable/gpg.key' \
| gpg --dearmor -o /usr/share/keyrings/caddy-stable-archive-keyring.gpg
curl -1sLf 'https://dl.cloudsmith.io/public/caddy/stable/debian.deb.txt' \
| tee /etc/apt/sources.list.d/caddy-stable.list
apt update && apt -y install caddy
```
## 4. Пользователь под туннели
```bash
useradd -m -s /bin/bash tunnel
install -d -m 700 -o tunnel -g tunnel /home/tunnel/.ssh
install -m 600 -o tunnel -g tunnel /dev/null /home/tunnel/.ssh/authorized_keys
```
Публичные ключи Pi и ПК добавишь в `/home/tunnel/.ssh/authorized_keys` на шагах настройки
Pi (`deploy/pi/README.md`) и ПК (через `ssh-copy-id`).
## 5. Сертификаты
Caddy читает **PEM** (текст с `-----BEGIN CERTIFICATE-----`). Расширение неважно — `.crt`
от GlobalSign обычно УЖЕ PEM. Проверь первой строкой: `head -1 файл.crt`.
- если `-----BEGIN CERTIFICATE-----` → это PEM, конвертировать НЕ нужно;
- если бинарь/абракадабра → это DER, сконвертируй: `openssl x509 -inform DER -in файл.crt -out файл.pem`.
На каждый домен нужны два файла:
- `fullchain.pem` = твой сертификат (leaf) **+** промежуточный(е) GlobalSign, в одном файле,
именно в таком порядке (сначала leaf, потом промежуточный).
- `privkey.pem` = приватный ключ (`-----BEGIN PRIVATE KEY-----`, без пароля; обычно это `.key`).
Удобно собрать прямо на VPS — залей свои файлы и склей:
```bash
mkdir -p /etc/caddy/certs/forbidden-stars.ru /root/certs-tmp
# с локальной машины (пример для домена forbidden-stars.ru):
scp forbidden-stars.crt intermediate.crt forbidden-stars.key root@186.246.51.17:/root/certs-tmp/
# на VPS — собрать fullchain (leaf + промежуточный) и положить ключ:
cat /root/certs-tmp/www_forbidden_stars_ru_2026_12_31.crt /root/certs-tmp/intermediate_pem_globalsign_ssl_dv_free_1.crt \
> /etc/caddy/certs/forbidden-stars.ru/fullchain.pem
cp /root/certs-tmp/forbidden-stars.key /etc/caddy/certs/forbidden-stars.ru/privkey.pem
# то же для forbiddenstars.ru (свои crt/intermediate/key), затем права
# (папкам нужен x-бит → 750, файлам 640; иначе пользователь caddy не прочитает):
chown -R caddy:caddy /etc/caddy/certs
find /etc/caddy/certs -type d -exec chmod 750 {} \;
find /etc/caddy/certs -type f -exec chmod 640 {} \;
rm -rf /root/certs-tmp
```
> Если GlobalSign дал не отдельный промежуточный, а готовый bundle/chain — используй его
> как «промежуточную» часть. Если дал один файл, где leaf и chain уже вместе, — это и есть
> `fullchain.pem` (склейка не нужна).
## 6. Caddyfile + страница-заглушка
Скопируй `deploy/vps/Caddyfile` из репозитория в `/etc/caddy/Caddyfile` и положи страницу
«сайт недоступен» (показывается, когда туннель к хосту лежит — вместо зависшей «Загрузки» SPA):
```bash
mkdir -p /etc/caddy/maintenance
# с локальной машины:
scp deploy/vps/maintenance.html root@186.246.51.17:/etc/caddy/maintenance/maintenance.html
# на VPS:
caddy validate --config /etc/caddy/Caddyfile
systemctl reload caddy
```
> Заглушка живёт в сниппете `(offline)` Caddyfile: при ответе апстрима 502/503/504
> Caddy отдаёт `/etc/caddy/maintenance/maintenance.html` со статусом 503 и `Cache-Control: no-store`.
> Правки текста/вида — в `deploy/vps/maintenance.html`, затем повтори `scp` (reload Caddy не нужен,
> файл читается на каждый запрос).
## 7. Проверка
1. Подними туннель прода на Pi (см. `deploy/pi/README.md`) и/или dev/test на ПК (`run.ps1` при `LOCAL_PUBLIC=vps`).
2. Открой `https://forbiddenstars.ru` и `https://forbidden-stars.ru`.
3. Пока соответствующий туннель не поднят — Caddy отдаёт страницу-заглушку «Технические шоколадки»
(HTTP 503), это ожидаемо.
Логи Caddy: `journalctl -u caddy -f`.
## 8. Приём бэкапов с Pi (оффсайт-копии)
Pi ежедневно шлёт полный архив (`scripts/backup.sh`) на VPS отдельным пользователем `backup`
(не путать с `tunnel`). Каталог — **вне** веб-корней Caddy, права 700.
```bash
useradd -m -s /bin/bash backup
install -d -m 700 -o backup -g backup /home/backup/.ssh
install -m 600 -o backup -g backup /dev/null /home/backup/.ssh/authorized_keys
install -d -m 700 -o backup -g backup /srv/fs-backups
# Публичный ключ бэкапа с Pi (deploy/backup/id_backup.pub) добавь в authorized_keys:
# echo '<содержимое id_backup.pub>' >> /home/backup/.ssh/authorized_keys
```
> Ротацию на VPS делает сам скрипт с Pi (`BACKUP_KEEP_REMOTE`, по умолч. 30). Каталог
> `/srv/fs-backups` не отдаётся Caddy (нет `root`/`file_server` на него) → бэкапы не публичны.
> Проверка приёма: после `scripts/backup.sh` на Pi → `ls -1 /srv/fs-backups/` на VPS.