ДОКУМЕНТАЦИЯ

УСТАНОВКА · § 010

Установка сервера
через Docker Compose

Поднимем backend, admin-панель, магазин и PostgreSQL одной командой.

~10 минутDocker + Docker ComposeVPS 1 vCPU / 1 GB RAM

§ 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

Шаг 01 - Поставить Docker на сервер

Если Docker уже стоит - пропускай

На Ubuntu/Debian проще всего поставить официальным скриптом:

SHELL

curl -fsSL https://get.docker.com | sh

※ Проверка установки: docker --version

§ 010.03

Шаг 02 - Создать docker-compose.yml

Один файл на все 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

Шаг 03 - Создать .env

Секреты и публичные 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

Шаг 04 - Запуск

Одной командой

SHELL

docker compose up -d

Compose:

  • · скачает свежие образы backend / panel / shop с ghcr.io;
  • · поднимет PostgreSQL 17 с healthcheck;
  • · при первом старте создаст все таблицы, а после обновлений сам применит миграции;
  • · запустит сервисы с restart: unless-stopped, поэтому они переживут перезагрузку VPS.

Проверь, что контейнеры живы:

SHELL

docker compose ps

docker compose logs -f backend

§ 010.06

Шаг 05 - Reverse proxy и HTTPS

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

Шаг 06 - Проверка

01 -

Открой https://api.your-domain.com/health, должен ответить 200 OK.

02 -

Зайди в https://panel.your-domain.com, войди под ADMIN_LOGIN / ADMIN_PASSWORD. Создай первый товар.

03 -

Открой https://shop.your-domain.com, товар должен появиться в каталоге.

§ 010.09

Что дальше

Осталось подключить оплату и выдачу

※ Что-то не получилось? Напиши в Telegram @zWork1 или открой issue на Github.

FreshDonate