# CryptoWallet API — Production Deploy Bundle Самодостаточная папка для деплоя на Linux-сервер. Содержит всё нужное для сборки и запуска продакшн-версии API. ## Состав ``` deployserver/ ├── Dockerfile # Multi-stage production build ├── docker-compose.yml # Только API (БД внешняя, из Vault) ├── .env.example # Шаблон переменных окружения ├── .dockerignore ├── start.sh # Автоматический deploy скрипт ├── db/ │ └── schema.sql # DDL таблиц (users, wallets, sessions) — идемпотентный ├── apps/api/ # Исходник API │ ├── src/ │ ├── package.json │ ├── tsconfig.json │ ├── swagger.json │ └── .eslintrc.json ├── package.json # Монорепо root ├── pnpm-workspace.yaml └── pnpm-lock.yaml ``` ## Требования - Ubuntu 20.04+ / Debian 11+ / любой Linux с Docker 24+ - Docker Compose plugin (`docker compose` команда) - Исходящий HTTPS на Vault (`corp.vault.elcsa.ru:443`) - Сетевой доступ к PostgreSQL (адрес приходит из Vault) ## Быстрый старт ```bash # 1. Скопировать папку на сервер scp -r deployserver user@server:/opt/cryptowallet ssh user@server cd /opt/cryptowallet # 2. Установить Docker (если нет) curl -fsSL https://get.docker.com | sudo sh sudo usermod -aG docker $USER newgrp docker # 3. Настроить .env cp .env.example .env nano .env # заполнить VAULT_ROLE_ID, VAULT_SECRET_ID # 4. Применить схему БД (один раз, на пустой БД) sudo apt install -y postgresql-client PGPASSWORD=<пароль_из_Vault> psql -h -U -d -f db/schema.sql # 5. Запустить chmod +x start.sh ./start.sh # 6. Открыть порт наружу sudo ufw allow 22/tcp sudo ufw allow 3001/tcp sudo ufw enable ``` ## Проверка ```bash curl http://localhost:3001/api/health # → {"success":true,"data":{"status":"ok"}} curl http://:3001/api/health # извне ``` Swagger UI: `http://:3001/api/docs` ## Порты | Порт | Назначение | Открыть наружу? | |------|-----------|-----------------| | 3001 | API HTTP | ✅ да (`ufw allow 3001`) | | 443 (out) | Vault | исходящий, обычно открыт | | 5432 (out) | PostgreSQL | исходящий к внешнему адресу БД | ## Управление ```bash docker compose logs -f api # смотреть логи docker compose restart api # рестарт (например после смены .env) docker compose down # остановить docker compose ps # статус docker compose up -d --build # пересобрать и запустить (после обновления кода) ``` ## Обновление ```bash # Скопировать новую версию deployserver/ (или git pull) docker compose build --pull api docker compose up -d ``` Схема БД не применяется автоматически — если добавились новые таблицы/колонки, выполни `schema.sql` вручную (он идемпотентный, безопасно запускать повторно). ## Ротация ключей JWT public keys и CSRF secret читаются из Vault при старте и **каждый час** обновляются автоматически (см. `key-rotation.service.ts`). При ошибках Vault сервис продолжает работать со старыми ключами — в логах будет `ERROR: Failed to refresh ...`. ## Безопасность Dockerfile - **Non-root user** (uid 1001) — контейнер не работает от root - **tini** как PID 1 — корректная обработка `SIGTERM` / `SIGKILL` - **Multi-stage build** — в финальный образ попадают только production deps + компилированный dist - **Alpine base** — минимальный образ (~150 MB) - **Healthcheck** — Docker рестартит контейнер если API упал - **Log rotation** — max 5×20MB логов, не забьёт диск ## Troubleshooting **`Vault AppRole login failed`** - Проверь VAULT_ROLE_ID / VAULT_SECRET_ID в .env - Проверь доступ: `curl -v https://corp.vault.elcsa.ru/v1/sys/health` **`password authentication failed for user "postgres_user"`** - Креды в `.env` не совпадают с тем что в Vault (или с реальной БД) - Решение: либо подставь пароль из Vault в `.env`, либо оставь пустыми — Vault перекроет при логине **Таблицы не существуют (relation does not exist)** - Не применён `db/schema.sql` — см. шаг 4 в Quick Start **Port 3001 занят** - `sudo lsof -i :3001` - Измени порт: в `docker-compose.yml` `"3002:3001"` и в `ufw allow 3002` **Нет места на диске** - `docker system prune -a` — удалит старые образы ## Автозапуск при reboot Restart policy `unless-stopped` уже настроен. Убедись что Docker стартует: ```bash sudo systemctl enable docker ```