Skip to content

API Deploy ​

Швидкий деплой ​

bash
./deploy.sh

Скрипт виконує:

  1. git push pisduk main — пуш коду на сервер
  2. SSH до Hetzner → git pull → docker compose build --no-cache → docker compose up -d

WARNING

Пушимо в pisduk, а не в origin. Це різні GitHub-репозиторії.

Ручний деплой ​

bash
# Push до деплой-ремоуту
git push pisduk main

# SSH rebuild
ssh -i ~/.ssh/hetzner root@37.27.202.249 \
  "cd /opt/pisd/pisduk && git pull --ff-only && docker compose build --no-cache && docker compose up -d"

Docker Compose ​

На сервері в /opt/pisd/pisduk/:

yaml
services:
  api:
    build: .
    ports:
      - "3000:3000"
    env_file: .env
    depends_on:
      - postgres
      - redis

  postgres:
    image: postgis/postgis:16-3.4
    volumes:
      - pgdata:/var/lib/postgresql/data

  redis:
    image: redis:7-alpine
    volumes:
      - redisdata:/data

Змінні середовища (.env) ​

ЗміннаОписЗначення prod
NODE_ENVСередовищеproduction
DATABASE_URLPostgreSQL URLpostgresql://pisd:***@postgres:5432/pisd
REDIS_URLRedis URLredis://redis:6379
JWT_SECRETJWT підписСильний випадковий рядок
JWT_REFRESH_SECRETRefresh JWT підписОкремий сильний рядок
TURBO_SMS_KEYTurboSMS API ключВід провайдера
TURBO_SMS_SENDERВідправник SMSPEACED
CORS_ORIGINSДозволені originhttps://m.pisd.uk,https://admin.pisd.uk,https://partner.peaced.uk
OTP_ALLOW_DEV_CODEDev-escape OTPfalse (ніколи в prod)
R2_ACCOUNT_IDCloudflare R2Від Cloudflare
R2_ACCESS_KEY_IDR2 ключВід Cloudflare
R2_SECRET_ACCESS_KEYR2 секретВід Cloudflare
R2_BUCKETR2 bucketpisd-media
R2_PUBLIC_URLПублічний CDNhttps://cdn.pisd.uk

DANGER

OTP_ALLOW_DEV_CODE=true — тільки для локальної розробки. На prod ніколи.

Міграції бази даних ​

synchronize: false у production. Всі зміни схеми — через onModuleInit у відповідному сервісі.

Патерн міграції ​

typescript
async onModuleInit() {
  await this.dataSource.query(`
    ALTER TABLE events
      ADD COLUMN IF NOT EXISTS template_id uuid REFERENCES event_templates(id),
      ADD COLUMN IF NOT EXISTS enabled_modules text[] DEFAULT '{}';
  `);
}

Правило

Завжди використовуй ADD COLUMN IF NOT EXISTS і CREATE TABLE IF NOT EXISTS — безпечно для повторних деплоїв.

Типові помилки ​

ПомилкаПричинаРішення
column already existsВідсутній IF NOT EXISTSДодай перевірку
relation does not existТаблиця ще не створенаПеревір порядок onModuleInit
duplicate keySeed виконався двічіДодай ON CONFLICT DO NOTHING

Логи ​

bash
# Real-time логи API
ssh -i ~/.ssh/hetzner root@37.27.202.249 \
  "cd /opt/pisd/pisduk && docker compose logs -f api"

# Останні 100 рядків
ssh -i ~/.ssh/hetzner root@37.27.202.249 \
  "cd /opt/pisd/pisduk && docker compose logs --tail=100 api"

Peaced — платформа подій