| infra | ||
| starter | ||
| action.yml | ||
| README.md | ||
Запуск проекта на платформе
Кладёшь в репу .env с доменом, пушишь — платформа собирает проект и поднимает
сайт с SSL. Форкать этот репо не нужно: он тут как справка и как источник двух
файлов, которые копируешь к себе.
Быстрый старт
- Скопируй в свой репозиторий два файла из
starter/:.forgejo/workflows/deploy.yml— как есть, не редактируй.env— изstarter/.env.example
- В
.envукажи домен:DOMAIN=mysite.com - Пропиши A-запись домена на
51.161.128.94 - Запушь в основную ветку. Через минуту-полторы сайт открыт по HTTPS.
Дальше каждый push пересобирает и передеплоивает. deploy.yml больше не трогаешь.
Что происходит при пуше
Workflow дёргает платформенный action (action.yml из этого репо): он клонирует
твою репу, читает .env, определяет тип сборки, собирает и публикует, прописывает
домен в Caddy. Caddy сам выпускает сертификат Let's Encrypt.
Типы проектов
Тип берётся из DEPLOY в .env, либо определяется сам: есть Dockerfile — docker,
нет — static.
static
Фронт на Vite / CRA. Собирается через bun, раздаётся как статика, без контейнера — самый быстрый вариант.
DOMAIN=mysite.com
# BUILD_DIR=dist # Vite=dist, CRA=build
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 в .env не пиши — она ставится сама.
DOMAIN=mysite.com
DEPLOY=docker-db
APP_PORT=3000
Домен и SSL
DOMAINобязателен. Заранее пропиши A-запись домена на51.161.128.94.- Сертификат выпускается автоматически, обычно за полминуты после первого деплоя. На каждый домен — отдельный.
- Пока workflow не позеленел, не открывай сайт в обычном браузере: сертификата ещё может не быть, и браузер закеширует ошибку. Дождись зелёного run или открой в инкогнито.
Один сайт на нескольких доменах:
EXTRA_DOMAINS=mysite.io,app.mysite.com
На каждый домен — свой сертификат, для каждого пропиши A-запись. www для
доп-доменов сам не добавляется (нужен — впиши www.mysite.io отдельным пунктом).
Чтобы в админке рядом с сайтом показывался твиттер проекта:
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, и для docker. Настраивается без админа:
- Положи скрипт в репу — в корень или в
public/(напримерinstall.sh). - Пропиши A-запись
get→ наш IP. - Добавь
INSTALL_SH=install.shв.envи запушь.
Платформа поднимет get.домен, выпустит SSL и будет отдавать этот файл как
text/plain. Убрал INSTALL_SH — сабдомен снимется на следующем деплое.
Переменные окружения
Всё, что положишь в .env, автоматически прокидывается в контейнер (docker /
docker-db) как переменные окружения. Просто пиши в .env и пушь — ничего отдельно
настраивать не надо.
DOMAIN=mysite.com
DATABASE_URL=postgres://user:pass@host/db
JWT_SECRET=...
API_KEY=...
В коде читаешь как обычно — process.env.DATABASE_URL. Служебные ключи платформы
(DOMAIN, DEPLOY, BUILD_DIR, APP_PORT, WWW, EXTRA_DOMAINS, TWITTER_URL,
INSTALL_SH) в контейнер не попадают. Для docker-db переменную DATABASE_URL
писать не надо — она ставится сама.
Скорость сборки
Фронт собирается через bun — install в разы быстрее npm, закоммить bun.lock.
docker-образы собираются с BuildKit и кешем от предыдущего образа. Ставь зависимости до копирования кода, чтобы слой install кешировался:
COPY package.json package-lock.json ./
RUN npm ci
COPY . .
RUN npm run build
Собирай финальный образ в несколько стадий (multi-stage) и клади в него только рантайм — чем меньше образ, тем быстрее деплой.
Переменные .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 |
— | отдать скрипт на get.<domain> (static или docker) |
Любые другие ключи в .env (не из этой таблицы) уходят в контейнер как переменные
окружения.
Доступ к гиту
- Форж: https://git.extract.team, логин прежний.
- SSH:
git@git.extract.team:2223, ключ добавляешь в Settings → SSH/GPG Keys.
Ремоут:Host git.extract.team Port 2223 User gitgit remote set-url origin git@git.extract.team:<логин>/<репа>.git
Если не работает
- 502 сразу после пуша — деплой ещё идёт или выпускается сертификат, дождись зелёного run.
build output 'dist' not found— не таBUILD_DIR(CRA →build, монорепо → путь до вывода приложения).no .env/no package.json— оба файла должны лежать в корне репы.- Сертификат не выпускается — нет A-записи домена на
51.161.128.94. - Не разобрался — пиши админу.