Files
ForbiddenStarsApp/deploy/pi/README.md
T
NotBigGhostandClaude Opus 5 8b400b76c6 Бэкап: убрать старые backup.sh/restore.sh, документация
deploy/backup/README.md — подробная пошаговая инструкция по всему, что делается вручную:
пароль шифрования, SSH-ключ, VPS (пользователь fsbackup только для SFTP, проверки sshd),
сборка образов, включение на Pi (с разбором каждой переменной и контрольными проверками),
доступ с ПК и выгрузка, учебное восстановление на тест-клоне, восстановление прода и из
архива, катастрофа «Pi умер», повседневные действия, таблица неполадок, справочник, чек-лист.
Команды разделов VPS и Pi прогнаны на локальном стенде.
deploy/pi, deploy/vps §8, deploy/README — ссылки на новую схему. Удалены scripts/backup.sh и
scripts/restore.sh (restore.sh ещё и оставлял БД root-овой: docker cp пишет файлы с uid 0);
их архивы fs_*.tar.gz восстанавливаются через fs-backup import. #64

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_013jBxs9nBCk5nBdTLzcGz91
2026-09-14 01:29:08 +03:00

135 lines
8.0 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.
# Raspberry Pi — ПРОД (`forbiddenstars.ru`)
На Pi нужны только **ДВА файла**: `docker-compose.yml` и `.env`. Репозиторий, сборка и файл
ключа туннеля не нужны:
- образы (`app` + `tunnel`) тянутся из Gitea-реестра (`pull_policy: always`);
- приватный ключ туннеля лежит в `.env` как `TUNNEL_KEY_B64` (base64).
`docker compose up` поднимает два контейнера: `app` (FastAPI+SPA, портов на хост нет) и
`tunnel` (`ssh -R 9000:app:8000` к VPS). Публичная точка — VPS, домен `forbiddenstars.ru`
(Pi за CGNAT — туннель стучится наружу сам).
---
## 0. Предпосылки (один раз, не на Pi)
1. **VPS настроен**: Caddy `forbiddenstars.ru` → `127.0.0.1:9000`, пользователь `tunnel`,
сертификаты, страница-заглушка — см. `deploy/vps/README.md`.
2. **Образы собраны и запушены в реестр** (на ПК с Docker Desktop):
```powershell
docker login gitea.arseniev.info
.\scripts\build-push.ps1
```
Без этого `docker compose up` на Pi не найдёт образы в реестре.
## 1. Система и Docker на Pi
```bash
ssh pi@<ip-пая>
sudo apt update && sudo apt -y full-upgrade
sudo apt -y install curl openssh-client # base64/ssh-keygen уже есть в системе
curl -fsSL https://get.docker.com | sudo sh # Docker Engine + compose-плагин (arm64)
sudo usermod -aG docker $USER
sudo systemctl enable --now docker # автозапуск после ребута
newgrp docker # применить группу (или перезайти по SSH)
docker version && docker compose version # проверка
```
## 2. SSH-ключ для туннеля
**Что это.** Отдельная пара ключей **только для туннеля** — ею контейнер `tunnel` логинится на
`tunnel@VPS`, чтобы открыть `ssh -R`. Это не системный ключ Pi, ты создаёшь его сам. Распределение:
- **приватный** ключ → в `.env` как `TUNNEL_KEY_B64` (base64, одной строкой);
- **публичный** (`.pub`) → в `authorized_keys` пользователя `tunnel` на VPS.
Сгенерировать прямо на Pi:
```bash
ssh-keygen -t ed25519 -f ~/fs_tunnel -N "" # создаст ~/fs_tunnel (приватный) и ~/fs_tunnel.pub
```
Добавить публичный ключ на VPS (Pi ходит наружу — это работает даже за CGNAT):
```bash
ssh-copy-id -i ~/fs_tunnel.pub tunnel@186.246.51.17
# Если у tunnel нет пароля (только ключ) — добавь вручную через свой админ-доступ к VPS:
# cat ~/fs_tunnel.pub # скопируй строку
# на VPS: echo '<строка>' >> /home/tunnel/.ssh/authorized_keys
```
Закодировать приватный ключ в base64 **одной строкой** — это значение для `TUNNEL_KEY_B64`:
```bash
base64 -w0 ~/fs_tunnel; echo # выведет длинную строку без переносов — скопируй её целиком
```
> Альтернатива: если ключ уже есть на ПК (`deploy/tunnel/id_tunnel`) и его pubkey уже на VPS —
> не плоди новый, закодируй тот:
> `[Convert]::ToBase64String([IO.File]::ReadAllBytes((Resolve-Path "deploy\tunnel\id_tunnel")))`
После того как base64 вставлен в `.env`, файлы ключа на Pi можно удалить — ключ теперь в `.env`,
а pubkey уже на VPS:
```bash
shred -u ~/fs_tunnel ~/fs_tunnel.pub # или просто rm
```
## 3. Два файла: docker-compose.yml + .env
```bash
mkdir -p ~/forbidden-stars && cd ~/forbidden-stars
# branch — main (или dev, если ещё не смёржено в main):
curl -fsSLO https://gitea.arseniev.info/NotBigGhost/ForbiddenStarsApp/raw/branch/main/docker-compose.yml
curl -fsSL https://gitea.arseniev.info/NotBigGhost/ForbiddenStarsApp/raw/branch/main/.env.example -o .env
nano .env
```
Заполнить в `.env`:
```
SECRET_KEY=... # python3 -c "import secrets;print(secrets.token_urlsafe(48))"
ADMIN_USERNAME=... # логин/пароль секретной админки
ADMIN_PASSWORD=...
TELEGRAM_BOT_TOKEN=... # бот @BotFather; затем /setdomain → forbiddenstars.ru
TELEGRAM_BOT_USERNAME=...
VPS_TUNNEL_HOST=186.246.51.17
TUNNEL_KEY_B64=... # длинная строка base64 из шага 2 (целиком, одной строкой)
IMAGE_REGISTRY=gitea.arseniev.info/notbigghost # уже значение по умолчанию
IMAGE_TAG=latest
```
`APP_ENV` (форсится в `production`) и `VPS_TUNNEL_PORT` (прод → 9000) не трогать.
## 4. Запуск
```bash
docker login gitea.arseniev.info # один раз, доступ к реестру
docker compose up -d # pull_policy: always → тянет образы из реестра, без сборки
docker compose ps # app healthy → поднимется tunnel
docker compose logs -f tunnel # ждём строку: [tunnel] -R 9000:app:8000 -> tunnel@...
```
На старте контейнер сам применит миграции, засидит справочники и создаст админа из `.env`.
## 5. Проверка
- Открой `https://forbiddenstars.ru` — должно отдать приложение (не заглушку).
- У @BotFather `/setdomain` → добавь `forbiddenstars.ru` (иначе Telegram-вход не заработает).
- Админка: удержать «Меню» 10 с → `/admin/login`, войти логином/паролём из `.env`.
## Обновление
```bash
# ПК: .\scripts\build-push.ps1
# Pi: docker compose up -d # always-pull подтянет свежий образ
```
## Автозапуск после перезагрузки
Уже обеспечен: `systemctl enable docker` + `restart: unless-stopped`. После `sudo reboot`
контейнеры поднимутся сами (используют локальный образ, без повторного pull).
## Бэкапы
Отдельный контейнер `backup` в том же `docker-compose.yml`: каждую ночь делает зашифрованный
снимок БД, `uploads` и `achievements` на Pi и на VPS. Дополнительных файлов на Pi не нужно,
всё настраивается блоком `BACKUP_*` в `.env`. Пока `BACKUP_PASSWORD` пуст, бэкапы выключены.
Пошаговая настройка, восстановление и действия при гибели Pi —
[`deploy/backup/README.md`](../backup/README.md).
```bash
docker compose exec backup fs-backup status # состояние
docker compose exec backup fs-backup list # хронология снимков
```
> Не выполняйте `docker compose down -v`: флаг `-v` удаляет тома с данными и локальными бэкапами.
## Если что-то не так
- `https://forbiddenstars.ru` отдаёт заглушку/502 → туннель не поднят: `docker compose logs tunnel`
(чаще: pubkey не в `authorized_keys` на VPS, пустой/битый `TUNNEL_KEY_B64`, либо на VPS занят
слот 9000 → на VPS `sudo fuser -k 9000/tcp`, затем `docker compose restart tunnel`).
- `pull` не проходит → проверь `docker login gitea.arseniev.info` и что реестр по HTTPS с валидным
сертификатом (иначе хост в `/etc/docker/daemon.json` → `insecure-registries`, `systemctl restart docker`).