| .forgejo/workflows | ||
| .env.example | ||
| .gitignore | ||
| README.md | ||
Deploy (Forgejo Actions)
Push в main → сайт на твоём домене с SSL. Один файл .env, один пуш.
Флоу на Forgejo Actions. Один
.env+.forgejo/workflows/deploy.ymlв репе — и push. Никакого GitLab.
TL;DR
- Скопируй в свой репозиторий 2 файла из этого стартера:
.forgejo/workflows/deploy.yml(не трогать) и.env(из.env.example). Форкать/клонировать весь стартер не надо — он лишь источник этих файлов; деплой цепляется к твоей репе по самому факту наличияdeploy.yml. - Заполни
.env(см..env.example), минимум:DOMAIN=mysite.com - Пропиши A-запись домена на IP сервера платформы.
git pushвmain. Через ~30–90 сек сайт открыт наhttps://mysite.com.
Дальше любой push = редеплой. Файл .forgejo/workflows/deploy.yml трогать не нужно.
Три типа проектов
Тип определяется по .env (DEPLOY=...) или авто-детектом.
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 — ничего настраивать, дефолт.
- CRA —
BUILD_DIR=build. - Next.js static export — в
next.config:output: 'export',images: { unoptimized: true },trailingSlash: true;.env:BUILD_DIR=out. SSR / API routes / Server Actions не работают (только статика).
2. docker — фронт + бэкенд в контейнере
Положи Dockerfile в корень. Платформа собирает образ и поднимает контейнер,
проксирует домен на него. Контейнер должен слушать порт из APP_PORT.
DOMAIN=mysite.com
DEPLOY=docker # или просто наличие Dockerfile
APP_PORT=3000 # порт, который слушает контейнер (default 80)
3. docker-db — + персистентная база (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 — она ставится автоматически.
Доп. домены — один сайт на нескольких доменах
По умолчанию сайт отдаётся на DOMAIN (+ www. авто, если у www есть A-запись на
наш IP). Нужен тот же сайт ещё на других доменах — перечисли их через запятую:
DOMAIN=mysite.com
EXTRA_DOMAINS=mysite.io,app.mysite.com,promo.xyz
Платформа раздаёт сайт на всех доменах и на каждый выпускает свой SSL-серт
автоматически. От тебя — прописать A-запись каждого домена на IP платформы и
git push. www. для доп-доменов сам не добавляется — если нужен, впиши
www.mysite.io явным пунктом. Нет A-записи → в логе ::warning::, серт выпустится,
как только DNS укажет сюда.
One-liner
curl get.<domain> | sh— особый случай, см.INSTALL_SHв.env.example(отдаёт один файл-скрипт с сабдоменаget.).
Скорость билда
Платформа собирает фронт через bun (install в 10–30× быстрее npm). Закоммить lock-файл:
bun install # создаст bun.lock
git add bun.lock && git commit -m "chore: bun lock" && git push
package.json и твои npm run build скрипты bun понимает as-is. Не коммить
node_modules / dist (они в .gitignore).
docker-сайты — кеш слоёв и лёгкие образы
Платформа собирает с BuildKit и --cache-from предыдущего образа: если слои не
менялись, пересборка почти мгновенная. Чтобы это работало на полную:
- Коммить lockfile и ставь зависимости ДО копирования кода — слой install
кешируется, пока deps не менялись:
COPY package.json package-lock.json ./ RUN npm ci COPY . . RUN npm run build - Cache-mount'ы (BuildKit включён) — install/apt не качают заново между сборками,
а Next держит инкрементальный кеш компиляции:
# 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.js → лёгкий образ:
output: 'standalone'вnext.configроняет образ с ~1–3 ГБ до ~150–250 МБ → деплой заметно быстрее (меньше экспорт + запуск).
Секреты (DATABASE_URL, API-ключи)
.env в runtime контейнера не попадает (парсится только при деплое).
Секреты:
- Forgejo → репа → Settings → Actions → Secrets → Add Secret. Имя секрета =
имя переменной окружения, напр.
DATABASE_URL,JWT_SECRET. - В
.envперечисли, какие из них прокинуть:RUNTIME_KEYS=DATABASE_URL,JWT_SECRET - В коде:
process.env.DATABASE_URL.
Платформа берёт только ключи из RUNTIME_KEYS — ничего лишнего не утечёт.
(Только для docker/docker-db; у static-сайта runtime-секретов нет.)
Выключить сайт (kill-switch)
В .env:
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 на каждый) |
INSTALL_SH |
— | static: отдать файл-скрипт на get.<domain> (curl | sh) |
ENABLED |
true |
false — выключить сайт |
RUNTIME_KEYS |
— | docker: список секретов в контейнер |
Не открывай сайт в браузере, пока workflow не зелёный
Пока деплой идёт, по домену ещё может не быть валидного серта. Браузер может закешировать "сломанный SSL". Дождись зелёного run в Actions, потом открывай (или открой в инкогнито).