launch/README.md

9.3 KiB
Raw Blame History

Запуск проекта на платформе

Кладёшь в репу .env с доменом, пушишь — платформа собирает проект и поднимает сайт с SSL. Форкать этот репо не нужно: он тут как справка и как источник двух файлов, которые копируешь к себе.

Быстрый старт

  1. Скопируй в свой репозиторий два файла из starter/:
    • .forgejo/workflows/deploy.yml — как есть, не редактируй
    • .env — из starter/.env.example
  2. В .env укажи домен: DOMAIN=mysite.com
  3. Пропиши A-запись домена на 51.161.128.94
  4. Запушь в основную ветку. Через минуту-полторы сайт открыт по HTTPS.

Дальше каждый push пересобирает и передеплоивает. deploy.yml больше не трогаешь.

Что происходит при пуше

Workflow дёргает платформенный action (action.yml из этого репо): он клонирует твою репу, читает .env, определяет тип сборки, собирает и публикует, прописывает домен в Caddy. Caddy сам выпускает сертификат Let's Encrypt.

Типы проектов

Тип берётся из DEPLOY в .env, либо определяется сам: есть Dockerfile — docker, нет — static.

static

Фронт на Vite / CRA / Next export. Собирается через bun, раздаётся как статика, без контейнера — самый быстрый вариант.

DOMAIN=mysite.com
# BUILD_DIR=dist    # Vite=dist, CRA=build, Next export=out

Для Next.js в static-режиме нужно в next.config: output: 'export', images.unoptimized: true, trailingSlash: true, и BUILD_DIR=out. SSR и API routes в этом режиме не работают.

docker

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

DOMAIN=mysite.com
DEPLOY=docker
APP_PORT=3000

docker-db

То же, что docker, плюс SQLite: том монтируется в /data, в контейнер прокидывается DATABASE_URL=file:/data/app.db. Том переживает редеплои. Миграции гоняешь сам в entrypoint. DATABASE_URL в RUNTIME_KEYS добавлять не надо — она ставится сама.

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

Домен и SSL

  • DOMAIN обязателен. Заранее пропиши A-запись домена на 51.161.128.94.
  • www подключается сам, если у него тоже есть A-запись на наш IP. Не нужен — поставь WWW=false.
  • Сертификат выпускается автоматически, обычно за полминуты после первого деплоя. На каждый домен — отдельный.
  • Пока workflow не позеленел, не открывай сайт в обычном браузере: сертификата ещё может не быть, и браузер закеширует ошибку. Дождись зелёного run или открой в инкогнито.

Один сайт на нескольких доменах:

EXTRA_DOMAINS=mysite.io,app.mysite.com

На каждый домен — свой сертификат, для каждого пропиши A-запись. www для доп-доменов сам не добавляется (нужен — впиши www.mysite.io отдельным пунктом).

Twitter

Чтобы в админке рядом с сайтом показывался твиттер проекта:

TWITTER_URL=https://x.com/mysite

Принимается URL, @handle или просто handle. На сам сайт не влияет — только метка в панели.

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

Один репозиторий = один сайт. Отдельного поля под папку приложения нет — сборка идёт от корня репы. Поэтому:

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

Установочный сабдомен (curl get.домен | sh)

Только для static, настраивается без админа:

  1. Положи скрипт в public/install.sh (папка public/ у Vite попадает в корень сборки).
  2. Пропиши A-запись get → наш IP.
  3. Добавь INSTALL_SH=install.sh в .env и запушь.

Платформа поднимет get.домен, выпустит SSL и будет отдавать этот файл как text/plain. Убрал INSTALL_SH — сабдомен снимется на следующем деплое.

Секреты

.env в контейнер не попадает — он читается только при деплое. Секреты заводишь в Forgejo: репа → Settings → Actions → Secrets, имя секрета = имя переменной. Потом перечисляешь нужные:

RUNTIME_KEYS=DATABASE_URL,JWT_SECRET

В контейнер попадут только они. В коде читаешь как обычно — process.env.DATABASE_URL.

Скорость сборки

Фронт собирается через bun — install в разы быстрее npm, закоммить bun.lock.

docker-образы собираются с BuildKit и кешем от предыдущего образа. Ставь зависимости до копирования кода, чтобы слой install кешировался:

COPY package.json package-lock.json ./
RUN npm ci
COPY . .
RUN npm run build

Для Next.js output: 'standalone' в next.config роняет образ с гигабайтов до ~200 МБ — деплой заметно быстрее.

Выключить сайт

ENABLED=false

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

Переменные .env

Ключ Дефолт Зачем
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 для админки
INSTALL_SH static: отдать скрипт на get.<domain>
RUNTIME_KEYS docker: какие секреты прокинуть в контейнер
ENABLED true false — выключить сайт

Доступ к гиту

  • Форж: https://git.extract.team, логин прежний.
  • SSH: git@git.extract.team:2223, ключ добавляешь в Settings → SSH/GPG Keys.
    Host git.extract.team
      Port 2223
      User git
    
    Ремоут: git remote set-url origin git@git.extract.team:<логин>/<репа>.git

Если не работает

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