ДОКУМЕНТАЦИЯ
УСТАНОВКА · § 010
Поднимем backend, admin-панель, магазин и PostgreSQL одной командой.
§ 010.01
Минимальные требования для production
СЕРВЕР
VPS с Linux
от 1 vCPU / 1 GB RAM / 10 GB SSD
DOCKER
Docker Engine + Compose
24.x+ / v2.20+
ДОМЕН
Доменное имя
3 поддомена: api, panel, shop
ПЛАТЕЖИ
Аккаунт YooKassa, Heleket или другой платёжной системы
нужно для приёма оплаты
§ 010.02
Если Docker уже стоит - пропускай
На Ubuntu/Debian проще всего поставить официальным скриптом:
SHELL
curl -fsSL https://get.docker.com | sh
※ Проверка установки: docker --version
§ 010.03
Один файл на все 4 сервиса: backend, panel, shop и PostgreSQL
Создай пустую папку под проект и положи в неё файл docker-compose.yml со следующим содержимым:
docker-compose.yml
services: backend: image: ghcr.io/fresh-donate/backend:latest pull_policy: always restart: unless-stopped env_file: [.env] volumes: - uploads_data:/app/uploads depends_on: postgres: { condition: service_healthy } networks: [fresh-network] panel: image: ghcr.io/fresh-donate/panel:latest pull_policy: always restart: unless-stopped env_file: [.env] depends_on: [backend] networks: [fresh-network] shop: image: ghcr.io/fresh-donate/shop:latest pull_policy: always restart: unless-stopped env_file: [.env] depends_on: [backend] networks: [fresh-network] postgres: image: postgres:17-alpine restart: unless-stopped environment: POSTGRES_DB: ${DB_NAME:-fresh_donate} POSTGRES_USER: ${DB_USER:-postgres} POSTGRES_PASSWORD: ${DB_PASSWORD:-postgres} volumes: - postgres_data:/var/lib/postgresql/data healthcheck: test: ["CMD-SHELL", "pg_isready -U ${DB_USER:-postgres} -d ${DB_NAME:-fresh_donate}"] interval: 5s timeout: 5s retries: 5 networks: [fresh-network] volumes: postgres_data: uploads_data: networks: fresh-network: driver: bridge
※ Образы ghcr.io/fresh-donate/* публикуются автоматически из main-ветки каждого репозитория. pull_policy: always заставит Compose качать свежий образ при каждом up.
※ Redis больше не нужен. Если он остался от старой версии инструкции, его можно не трогать: бекенд к нему не обращается. Чтобы убрать, удали сервис redis из docker-compose.yml и выполни docker compose up -d --remove-orphans.
§ 010.04
Секреты и публичные URL
Рядом с docker-compose.yml создай файл .env. Закомментированные значения можно оставить как есть, секреты обязательно замени.
.env
# === Frontend (panel + shop) === # Куда фронтенды ходят за API. Домен на котором стоит бекенд. NUXT_PUBLIC_API_BASE=https://api.your-domain.com # === Backend Server === HOST=0.0.0.0 PORT=3001 SERVER_PORT=3001 # === Database === DB_HOST=postgres DB_PORT=5432 DB_NAME=fresh_donate DB_USER=postgres DB_PASSWORD=сложный-пароль-postgres # === Admin Panel Credentials === ADMIN_LOGIN=admin ADMIN_PASSWORD=сильный-пароль-минимум-16-символов # === JWT === # Любая случайная строка ≥32 символов. Сгенерировать: openssl rand -hex 32 JWT_SECRET=замени-на-длинную-случайную-строку JWT_EXPIRES_IN=24h # === Rate Limiting === RATE_LIMIT_MAX=100 RATE_LIMIT_TIMEWINDOW=60000 # === Payment === # Куда возвращается игрок после оплаты (фронтенд магазина) PAYMENT_RETURN_URL=https://shop.your-domain.com # Публичный URL backend для вебхуков платёжных шлюзов WEBHOOK_BASE_URL=https://api.your-domain.com # Раскомментируй, если backend за прокси без x-forwarded-for или в тестовом режиме # YOOKASSA_SKIP_IP_CHECK=true # === CORS (через запятую) === CORS_ORIGIN=https://panel.your-domain.com,https://shop.your-domain.com
Важно
Не оставляй на проде дефолтный пароль БД, admin/admin и пустой JWT_SECRET. Любой, кто угадает JWT_SECRET, сможет выпустить себе токен админа.
DB_HOST=postgres указывает на имя сервиса из docker-compose.yml. Внутри docker-сети контейнеры обращаются друг к другу по именам сервисов, а не по localhost.
§ 010.05
Одной командой
SHELL
docker compose up -d
Compose:
Проверь, что контейнеры живы:
SHELL
docker compose ps
docker compose logs -f backend
§ 010.06
Compose поднимает сервисы во внутренней docker-сети. Наружу их выводит nginx (или любой другой reverse proxy)
Сервисы внутри сети:
backend
:3001
REST API, вебхуки
panel
:3000
Админ-панель
shop
:3002
Витрина для игроков
postgres
:5432
База данных (внутри docker-сети)
Пример конфига для nginx, по server-блоку на поддомен:
/etc/nginx/sites-available/fresh-donate.conf
# API server { listen 80; server_name api.your-domain.com; location / { proxy_pass http://backend:3001; proxy_http_version 1.1; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header X-Forwarded-Proto $scheme; } } # Админ-панель server { listen 80; server_name panel.your-domain.com; location / { proxy_pass http://panel:3000; proxy_http_version 1.1; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header X-Forwarded-Proto $scheme; } } # Магазин server { listen 80; server_name shop.your-domain.com; location / { proxy_pass http://shop:3002; proxy_http_version 1.1; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header X-Forwarded-Proto $scheme; } }
Активируй конфиг и проверь синтаксис:
SHELL
ln -s /etc/nginx/sites-available/fresh-donate.conf /etc/nginx/sites-enabled/
nginx -t # проверка конфига
systemctl reload nginx
HTTPS-сертификаты выпускает certbot, он сам пропишет 443 и редирект 80→443:
SHELL
certbot --nginx -d api.your-domain.com -d panel.your-domain.com -d shop.your-domain.com
※ Если nginx стоит на хосте (а не в compose), proxy_pass должен указывать на пробросы портов, например http://127.0.0.1:3001. Для этого добавь ports: ["3001:3001"] в нужный сервис compose. Если nginx в compose и в той же сети fresh-network, используй имена сервисов, как в примере.
§ 010.07
NUXT_PUBLIC_API_BASE
http://localhost:3001
URL backend для фронтендов panel и shop. Подставляется в Nuxt на этапе сборки.
HOST / PORT
0.0.0.0 / 3001
На каком интерфейсе и порту слушает backend внутри контейнера.
SERVER_PORT
3001
Внешний порт хоста, на который пробрасывается backend (если используешь ports вместо reverse-proxy).
DB_HOST / DB_PORT
postgres / 5432
Где живёт PostgreSQL. Внутри compose-сети это имя сервиса postgres.
DB_NAME / DB_USER / DB_PASSWORD
fresh_donate / postgres / postgres
Подключение к БД. Пароль на проде обязательно сменить.
ADMIN_LOGIN / ADMIN_PASSWORD
admin / admin
Учётные данные администратора панели. На проде сменить.
JWT_SECRET
change-me…
Случайная строка ≥32 символов. Используется для подписи токенов. Утечка = доступ админа.
JWT_EXPIRES_IN
24h
Сколько живёт токен админа (24h, 7d, …). Смена ADMIN_PASSWORD завершает все сессии.
RATE_LIMIT_MAX
100
Сколько запросов в окно разрешено с одного IP.
RATE_LIMIT_TIMEWINDOW
60000
Длительность окна rate-limit в миллисекундах.
PAYMENT_RETURN_URL
http://localhost:3002
Куда возвращается игрок после оплаты. Должно указывать на shop.
WEBHOOK_BASE_URL
http://localhost:3001
Публичный адрес бекенда, на него платёжные шлюзы шлют вебхуки. На проде обязательно HTTPS.
YOOKASSA_SKIP_IP_CHECK
false
Отключить проверку IP YooKassa. Включать только если backend за прокси без x-forwarded-for или в тестовом режиме.
CORS_ORIGIN
http://localhost:3000,http://localhost:3002
Адреса панели и магазина через запятую.
※ Полный список в backend/src/config/index.ts и в .env.example.
§ 010.08
Открой https://api.your-domain.com/health, должен ответить 200 OK.
Зайди в https://panel.your-domain.com, войди под ADMIN_LOGIN / ADMIN_PASSWORD. Создай первый товар.
Открой https://shop.your-domain.com, товар должен появиться в каталоге.
§ 010.09
Осталось подключить оплату и выдачу