Прод на 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>
This commit is contained in:
2026-06-29 21:48:40 +03:00
co-authored by Claude Opus 4.8
parent c544f72063
commit 029a043bfc
4 changed files with 102 additions and 79 deletions
+10 -7
View File
@@ -1,9 +1,11 @@
# ─────────────────────────────────────────────────────────────────────────────
# ПРОД на Raspberry Pi (forbiddenstars.ru) — единый compose: приложение + туннель.
# Все настройки и секреты — в корневом .env (см. .env.example). Этот файл их только
# пробрасывает; ничего секретного тут нет.
# На Pi нужны только ДВА файла: этот docker-compose.yml и .env. Репозиторий, сборка и
# файл ключа не нужны: образы тянутся из реестра (pull_policy: always), а приватный ключ
# туннеля лежит в .env (TUNNEL_KEY_B64, base64). build: оставлен для сборки/пуша на ПК
# (scripts/build-push.*) — на Pi он не используется.
#
# Запуск/обновление: docker compose up -d --build
# Запуск/обновление: docker compose up -d (сам тянет свежие образы)
# Логи: docker compose logs -f app (или: ... tunnel)
# Остановка: docker compose down (данные в томах сохраняются)
# Бэкап/restore: scripts/backup.sh / scripts/restore.sh
@@ -18,6 +20,7 @@ services:
# Образ из реестра (Gitea): собирается под arm64 на ПК (scripts/build-push.sh) и тянется
# на Pi через `docker compose pull`. build: оставлен как локальный фолбэк (сборка на Pi).
image: ${IMAGE_REGISTRY:-gitea.arseniev.info/notbigghost}/forbidden-stars:${IMAGE_TAG:-latest}
pull_policy: always # на Pi всегда тянем образ из реестра (без сборки)
restart: unless-stopped
init: true # PID 1 пробрасывает сигналы → корректный SIGTERM
stop_grace_period: 30s # время на чек-пойнт WAL SQLite перед остановкой
@@ -46,22 +49,22 @@ services:
max-file: "5"
# SSH reverse-туннель: VPS:${VPS_TUNNEL_PORT:-9000} → app:8000 (домен forbiddenstars.ru).
# Ключ — ./deploy/tunnel/id_tunnel (в git не идёт); его pubkey в authorized_keys у tunnel@VPS.
# Приватный ключ — в .env как TUNNEL_KEY_B64 (base64); pubkey — в authorized_keys у tunnel@VPS.
tunnel:
build: ./deploy/tunnel
image: ${IMAGE_REGISTRY:-gitea.arseniev.info/notbigghost}/forbidden-stars-tunnel:${IMAGE_TAG:-latest}
pull_policy: always
restart: unless-stopped
init: true
depends_on:
app:
condition: service_healthy
environment:
VPS_TUNNEL_HOST: ${VPS_TUNNEL_HOST:?VPS_TUNNEL_HOST is required in .env}
VPS_TUNNEL_HOST: ${VPS_TUNNEL_HOST} # обязателен; tunnel.sh упадёт с ошибкой, если пуст
VPS_TUNNEL_USER: ${VPS_TUNNEL_USER:-tunnel}
VPS_TUNNEL_PORT: ${VPS_TUNNEL_PORT:-9000} # прод-слот (forbiddenstars.ru)
UPSTREAM: app:8000
volumes:
- ./deploy/tunnel/id_tunnel:/key/id_tunnel:ro
TUNNEL_KEY_B64: ${TUNNEL_KEY_B64:-} # приватный ключ туннеля (base64), из .env
mem_limit: 64m
security_opt:
- no-new-privileges:true