launch/README.md
2026-07-17 11:59:36 +00:00

13 KiB
Raw Blame History

Как запустить свой проект на платформе

Один файл .env + один пуш → сайт на твоём домене с автоматическим SSL. Это единственный репозиторий, который нужно знать: тут и гайд, и файлы стартера, и сам платформенный action.


TL;DR — 4 шага

  1. Скопируй в свой репозиторий 2 файла из папки starter/ этого репо:

    • .forgejo/workflows/deploy.ymlне трогать (тянет платформенный action по ссылке)
    • .env — из starter/.env.example

    Форкать/клонировать этот репо не надо — деплой цепляется к твоей репе по самому факту наличия .forgejo/workflows/deploy.yml.

  2. Заполни .env, минимум:

    DOMAIN=mysite.com
    
  3. Пропиши A-запись домена → IP платформы 51.161.128.94.

  4. git push в дефолтную ветку. Через ~3090 сек сайт открыт на https://mysite.com.

Дальше любой push = редеплой. deploy.yml трогать не нужно никогда.


Как это работает (флоу)

git push
   │
   ▼
Forgejo Actions запускает .forgejo/workflows/deploy.yml
   │   (uses: https://git.extract.team/platform/launch@main)
   ▼
platform/launch action:
   ├─ клонирует твою репу
   ├─ читает .env → DOMAIN, тип деплоя (static / docker / docker-db)
   ├─ билд:  static → bun build      |  docker → docker build
   ├─ публикует статику в /srv/sites │  или поднимает контейнер
   └─ пишет фрагмент Caddy на твой домен
   ▼
Caddy автоматически выпускает SSL (Let's Encrypt) → https://mysite.com живой

Один репозиторий = один сайт (один .env, один DOMAIN).


Тип проекта: static / docker / docker-db

Тип определяется полем DEPLOY в .env или авто-детектом (по наличию Dockerfile).

1. static — фронт (90% проектов)

Vite / CRA / Next static export. bun build → статика раздаётся напрямую, без контейнера. Деплой за секунды; редеплой = только заливка новых файлов.

DOMAIN=mysite.com
# DEPLOY=static      # дефолт, если в корне НЕТ Dockerfile
# BUILD_DIR=dist     # Vite=dist (дефолт), CRA=build, Next export=out
  • Vite + React — ничего настраивать, дефолт.
  • CRABUILD_DIR=build.
  • Next.js static export — в next.config: output: 'export', images: { unoptimized: true }, trailingSlash: true; в .envBUILD_DIR=out. SSR / API routes / Server Actions в static-режиме не работают.

2. docker — фронт + бэкенд в контейнере

Положи Dockerfile в корень. Платформа собирает образ, поднимает контейнер и проксирует домен на него. Контейнер должен слушать порт из APP_PORT.

DOMAIN=mysite.com
DEPLOY=docker          # или просто наличие Dockerfile
APP_PORT=3000          # порт контейнера (default 80)

3. docker-db — docker + персистентная база (SQLite)

Как docker, плюс платформа монтирует named-volume в /data и прокидывает DATABASE_URL=file:/data/app.db. Том переживает редеплои.

DOMAIN=mysite.com
DEPLOY=docker-db
APP_PORT=3000

В коде читаешь process.env.DATABASE_URL. Миграции (drizzle/prisma) запускай в своём entrypoint — платформа их не делает. Не указывай DATABASE_URL в RUNTIME_KEYS (ставится автоматически).


Домен и SSL

  • DOMAIN — обязательное поле. Заранее пропиши A-запись домена на IP платформы 51.161.128.94 (у своего регистратора).
  • www. подключается автоматически, если у www.<domain> тоже есть A-запись на наш IP. Не нужен — поставь WWW=false.
  • SSL выпускается сам (Let's Encrypt), обычно за 3060 сек после первого деплоя, когда DNS уже указывает на наш IP. Отдельный серт на каждый домен. Ничего настраивать не надо.
  • Не открывай сайт в браузере, пока workflow не зелёный — пока идёт деплой, валидного серта ещё может не быть, и браузер закеширует «сломанный SSL». Дождись зелёного run в Actions (или открой в инкогнито).

Доп. домены — один сайт на нескольких доменах

DOMAIN=mysite.com
EXTRA_DOMAINS=mysite.io,app.mysite.com,promo.xyz

Тот же сайт на всех доменах, на каждый — свой авто-SSL. От тебя: A-запись каждого домена на наш IP. www. для доп-доменов сам не добавляется — если нужен, впиши www.mysite.io явным пунктом.


Twitter / X проекта

Хочешь, чтобы в админ-панели рядом с сайтом показывался его твиттер — добавь в .env:

TWITTER_URL=https://x.com/mysite

Принимается полный URL, @handle или голый handle (TWITTER= тоже работает). Платформа нормализует и покажет как 𝕏 @mysite. Ни на деплой, ни на сайт не влияет — только метаданные для админки.


Монорепозиторий

Платформа деплоит один сайт на репозиторий (один .env, один DOMAIN). Отдельного поля «папка приложения» нет — сборка идёт от корня репы. Поэтому для монорепо:

  • .env и package.json (или Dockerfile) — в корне репозитория.
  • static: корневой скрипт build должен собирать нужное приложение (через workspaces / turbo / nx), а BUILD_DIR — указывать на его вывод:
    DOMAIN=mysite.com
    BUILD_DIR=apps/web/dist        # куда собирается целевое приложение
    
    // package.json в корне
    { "scripts": { "build": "npm run build -w apps/web" } }
    
  • docker: Dockerfile в корне, контекст сборки = весь репозиторий, так что он спокойно COPY apps/web … и собирает нужный пакет. Задай APP_PORT.
  • Нужно задеплоить несколько приложений из одного монорепо на разные домены — сделай под каждое отдельный репозиторий (один репо = один сайт).

Установочный сабдомен curl get.<domain> | sh (self-service)

Красивый one-liner установки — делается сам, без админа, для static-сайтов:

  1. Положи скрипт в репу → public/install.sh (папка public/ у Vite попадает в dist/ как есть → окажется в корне сайта).
  2. DNS: A-запись get → IP платформы (host = get).
  3. В .env: INSTALL_SH=install.shgit push.

CI сам поднимет get.<domain>, выпустит SSL и будет отдавать install.sh как text/plain. Убери INSTALL_SH и запушь — сабдомен снимется. В админке этот сабдомен виден в строке «сабдомены».


Секреты (DATABASE_URL, API-ключи)

.env в runtime контейнера не попадает (парсится только при деплое). Секреты:

  1. Forgejo → репа → Settings → Actions → Secrets → Add Secret. Имя секрета = имя переменной окружения (DATABASE_URL, JWT_SECRET).
  2. В .env перечисли, какие прокинуть:
    RUNTIME_KEYS=DATABASE_URL,JWT_SECRET
    
  3. В коде: process.env.DATABASE_URL.

Платформа берёт только ключи из RUNTIME_KEYS. (Только для docker/docker-db.)


Скорость билда

Фронт собирается через bun (install в 1030× быстрее npm). Закоммить lock:

bun install                       # создаст bun.lock
git add bun.lock && git commit -m "chore: bun lock" && git push

docker-сайты — кеш слоёв и лёгкие образы

Сборка идёт с BuildKit и --cache-from предыдущего образа. Чтобы это работало:

  • ставь зависимости ДО копирования кода (слой install кешируется):
    COPY package.json package-lock.json ./
    RUN npm ci
    COPY . .
    RUN npm run build
    
  • cache-mount'ы:
    # syntax=docker/dockerfile:1.7
    RUN --mount=type=cache,target=/root/.npm npm ci
    RUN --mount=type=cache,target=/app/.next/cache npm run build
    
  • Next.jsoutput: 'standalone' в next.config роняет образ с ~13 ГБ до ~150250 МБ → деплой заметно быстрее.

Выключить сайт (kill-switch)

ENABLED=false

Push → контейнер/файлы удаляются, домен отдаёт 404. Убери строку (или true) + push → поднимается обратно. Том и секреты сохраняются. (Админ может выключить и без коммита — переменной ENABLED=false в Settings → Actions → Variables.)


Все переменные .env

Key Default Зачем
DOMAIN Обязательно (кроме ENABLED=false)
DEPLOY auto static / docker / docker-db
BUILD_DIR dist static: папка сборки (в монорепо — путь до вывода приложения)
APP_PORT 80 docker: порт контейнера
WWW auto false — не подключать www
EXTRA_DOMAINS доп. домены через запятую (тот же сайт, свой SSL на каждый)
TWITTER_URL твиттер/X проекта для админки (@handle / URL)
INSTALL_SH static: отдать файл-скрипт на get.<domain> (curl | sh)
RUNTIME_KEYS docker: список секретов в контейнер
ENABLED true false — выключить сайт

Доступ к гиту (один раз)

  • Форж: https://git.extract.team, логин — твой username.
  • SSH: git@git.extract.team:2223. Добавь ключ: Settings → SSH/GPG Keys, затем в ~/.ssh/config:
    Host git.extract.team
      Port 2223
      User git
    
    Ремоут: git remote set-url origin git@git.extract.team:<логин>/<репа>.git (или HTTPS — логин + пароль).

Частые проблемы

  • 502 / сайт не грузится сразу после пуша — деплой ещё идёт или серт выпускается. Дождись зелёного run в Actions.
  • build output 'dist' not found — не та BUILD_DIR (CRA → build, Next export → out, монорепо → путь до вывода приложения).
  • no .env / no package.jsonоба файла должны быть в корне репозитория.
  • SSL не выпускается — нет A-записи домена на 51.161.128.94 (в логе деплоя будет ::warning::). Пропиши DNS — серт выпустится сам.
  • Застрял — пиши админу.

Файлы для копирования — в starter/. Платформенный action — action.yml.