Files
ForbiddenStarsApp/deploy/pi
NotBigGhostandClaude Opus 4.8 029a043bfc Прод на Pi: деплой из 2 файлов (compose + .env), ключ туннеля из .env
Теперь на Pi нужны только docker-compose.yml и .env — без репозитория, сборки и файла ключа.

- docker-compose.yml: pull_policy: always (образы тянутся из реестра, сборка не запускается);
  ключ туннеля больше не монтируется томом — берётся из .env (TUNNEL_KEY_B64, base64);
  у VPS_TUNNEL_HOST убран :? (ломал бы buildx bake на ПК, где переменная не задана) — проверка
  обязательности перенесена в tunnel.sh (рантайм).
- deploy/tunnel/tunnel.sh: приватный ключ из TUNNEL_KEY_B64 (base64) с фолбэком на смонтированный
  /key/id_tunnel (для dev/test, где репозиторий на хосте).
- .env.example: TUNNEL_KEY_B64 + как сгенерировать base64 (Git Bash / PowerShell).
- deploy/pi/README: полный поток «голый Pi → 2 файла»: Docker, curl compose+.env из Gitea, up;
  обновление, автозапуск, бэкап как опция.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-29 21:48:40 +03:00
..

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, туннель стучится наружу сам).

Предпосылки: VPS настроен (Caddy forbiddenstars.ru → :9000, юзер tunnel) — см. deploy/vps/README.md.


A. На ПК (один раз + при каждом релизе)

Ключ туннеля и его base64 для .env (один раз):

ssh-keygen -t ed25519 -f deploy/tunnel/id_tunnel -N ""
ssh-copy-id -i deploy/tunnel/id_tunnel.pub tunnel@186.246.51.17   # pubkey → authorized_keys на VPS
# base64 приватного ключа БЕЗ переносов строк (значение для TUNNEL_KEY_B64 в .env):
#   Git Bash / Linux:  base64 -w0 deploy/tunnel/id_tunnel
#   PowerShell:        [Convert]::ToBase64String([IO.File]::ReadAllBytes("deploy/tunnel/id_tunnel"))

Сборка и пуш образов под arm64 (при каждом релизе):

docker login gitea.arseniev.info
.\scripts\build-push.ps1          # *nix: bash scripts/build-push.sh

B. На Pi

1. Docker (один раз):

sudo apt update && sudo apt -y full-upgrade
curl -fsSL https://get.docker.com | sudo sh
sudo usermod -aG docker $USER
sudo systemctl enable --now docker      # автозапуск после ребута
newgrp docker                            # применить группу (или перезайти по SSH)

2. Положить два файла (любой каталог, напр. ~/forbidden-stars):

mkdir -p ~/forbidden-stars && cd ~/forbidden-stars
# docker-compose.yml из Gitea (raw); branch — main (или dev, если ещё не смёржено):
curl -fsSLO https://gitea.arseniev.info/NotBigGhost/ForbiddenStarsApp/raw/branch/main/docker-compose.yml
# .env: можно взять шаблон оттуда же и заполнить
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 ключа из шага A (одной строкой)
IMAGE_REGISTRY=gitea.arseniev.info/notbigghost   # уже значение по умолчанию
IMAGE_TAG=latest

APP_ENV менять не нужно (контейнер форсит production); VPS_TUNNEL_PORT — тоже (прод → 9000).

3. Запуск:

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. Открой https://forbiddenstars.ru. У @BotFather /setdomain → добавь forbiddenstars.ru.

Обновление

# ПК:  .\scripts\build-push.ps1
# Pi:  docker compose up -d          # always-pull подтянет свежий образ

Автозапуск после перезагрузки

Обеспечен: systemctl enable docker + restart: unless-stopped. После sudo reboot контейнеры поднимаются сами (используют локальный образ, без повторного pull).

Бэкап (опционально)

Бэкап-скриптам нужен доступ к Docker и к самому docker-compose.yml (он уже на Pi). Скопируй рядом ещё scripts/backup.sh и scripts/restore.sh (или склонируй репозиторий для бэкапов). Затем — отдельный ключ backup@VPS, BACKUP_VPS_HOST в .env, cron. Подробнее — комментарии в scripts/backup.sh и deploy/vps/README.md §8. Восстановление: scripts/restore.sh <архив>.

Если что-то не так

  • https://forbiddenstars.ru отдаёт заглушку/502 → туннель не поднят: docker compose logs tunnel (чаще: pubkey не в authorized_keys на VPS, пустой TUNNEL_KEY_B64, или на VPS занят слот 9000 → sudo fuser -k 9000/tcp на VPS, затем docker compose restart tunnel).
  • pull не проходит → проверь docker login gitea.arseniev.info и что реестр по HTTPS с валидным сертификатом (иначе хост в /etc/docker/daemon.json → insecure-registries, systemctl restart docker).