The server's central mirror-nginx already owns 80/443 + manages TLS, so FlatRender
can't run its own Caddy there. Adapt the deploy to the host-port + reverse-proxy model:
- compose: Caddy moved behind `profiles: [edge]` (not started by default); frontend/
gateway/minio host ports are now EDGE_BIND + FRONTEND_PORT/GATEWAY_PORT/MINIO_PORT
(so they can avoid Gitea's :3000 etc.); postgres/render stay on HOST_BIND loopback.
- deploy/ENV_FILE.production.example: nginx model, pre-filled for flatrender.ir,
host ports 1600/1605/1610, no Caddy/ACME vars.
- deploy/mirror-nginx-flatrender.conf: ready-to-paste server blocks routing
flatrender.ir / api / storage → 171.22.25.73:{1600,1605,1610}.
- deploy/README.md: nginx integration + cert step.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
3.8 KiB
Deploying FlatRender (Gitea CI/CD → 171.22.25.73, behind mirror-nginx)
Push to Gitea triggers .gitea/workflows/ci-cd.yml: a frontend tsc check, then a
self-hosted deploy job that builds the whole compose stack and brings it up. The
existing central mirror-nginx (owns 80/443, manual TLS certs) reverse-proxies the
three public domains to FlatRender's host ports — FlatRender does not run Caddy here.
GitHub (origin) stays a backup and never deploys.
Stack: gateway · identity · content · studio (.NET/Go) · file · render · notification
(Go) · Next.js frontend · Postgres · MinIO. All package installs route through
mirror.soroushasadi.com (Nexus).
mirror-nginx (:443, /etc/ssl/flatrender)
flatrender.ir → 171.22.25.73:1600 (fr2-frontend)
api.flatrender.ir → 171.22.25.73:1605 (fr2-gateway)
storage.flatrender.ir → 171.22.25.73:1610 (fr2-minio)
One-time setup (do these BEFORE the first git push gitea master)
- DNS — three A-records → server IP:
flatrender.ir,api.flatrender.ir,storage.flatrender.ir(+ optionalwww). - TLS cert — place a cert covering all three names at
/etc/ssl/flatrender/fullchain.pem+/etc/ssl/flatrender/privateKey.pem(wildcard*.flatrender.ir+ apex, or a SAN cert — your usual issuance process). - mirror-nginx — add the server blocks from
mirror-nginx-flatrender.confto the proxy'shttp{}block, then:docker exec mirror-nginx nginx -t && docker exec mirror-nginx nginx -s reload. (Do this after the first deploy is up, or it'll 502 until the ports are live.) - ENV_FILE secret — at
…/soroushdes/flatrender/settings/secrets, createENV_FILEfromENV_FILE.production.example(already filled for flatrender.ir; generate each secret withopenssl rand -hex 32). - Gitea Actions enabled for this repo; act_runner has the
self-hosted:hostlabel (the standard box already has this). daemon.json already mirrors Docker Hub via Nexus.
Go live
git push gitea master # triggers CI + deploy
Watch https://git.soroushasadi.com/soroushdes/flatrender/actions. First run ~15–25 min
(cold Nexus cache + all images build). When the deploy is green, add/reload the nginx
blocks (step 3) and visit https://flatrender.ir.
Host ports (must be free on 171.22.25.73)
1600 frontend · 1605 gateway · 1610 MinIO · 1611 MinIO console. Postgres (5432)
and render (5010) bind to 127.0.0.1 only. Avoid :3000 (Gitea), :8081-8083 (Nexus),
:1500/1505/1520 (bargevasat), :3010/3101-3103/5080/5081 (meezi), :3020, :2569.
Change them via FRONTEND_PORT/GATEWAY_PORT/MINIO_PORT in the secret if any collide.
First-run notes
- Migrations auto-run once via
scripts/init-db.shwhen the Postgres volume is first created. Later schema changes are applied manually withpsql(the volume persists). - Rendering — no After Effects node on the server, so
RENDER_DEV_WORKER=false. Disable rendering in Admin → فارم رندر → موتور رندر so users see an "unavailable" notice instead of jobs that never finish. Point real render nodes at the server later. - MinIO public URLs — verify an uploaded image + a render download resolve over
https://storage.flatrender.ir. If not, recheckMINIO_HOST_ENDPOINT/MINIO_HOST_USE_SSL/NEXT_PUBLIC_MINIO_URLin the secret and redeploy.
Redeploy / rotate secrets
Edit ENV_FILE in Gitea (or push any commit) → the deploy re-runs. It backs up the DB to
/opt/flatrender-backups/ before each deploy and never runs docker compose down -v.
Changing a NEXT_PUBLIC_* value only takes effect after the redeploy (baked at build).