Wire Coolify domain to SITE_NAME and document env template
SERVICE_FQDN_FRONTEND from the frontend domain drives site creation and nginx headers; coolify.env.example adds CUSTOM_IMAGE/CUSTOM_TAG for Jenkins registry pulls. Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
parent
cacbce384f
commit
f2f7e6355d
6 changed files with 102 additions and 63 deletions
|
|
@ -28,8 +28,8 @@ See [docs/JENKINS.md](docs/JENKINS.md).
|
|||
## Coolify deploy (you configure)
|
||||
|
||||
1. Docker Compose from this git repo, file `docker-compose.yml`
|
||||
2. Env vars from [`example.env`](example.env) — use `CUSTOM_TAG` from latest green Jenkins build
|
||||
3. Domain on service **`frontend`**, port **`8080`**
|
||||
2. Env vars from [`coolify.env.example`](coolify.env.example) — `CUSTOM_IMAGE`, `CUSTOM_TAG` from latest green Jenkins build (`dist/coolify-image.env`)
|
||||
3. Domain on service **`frontend`**, port **`8080`** — Coolify sets `SERVICE_FQDN_FRONTEND`; compose uses it for `SITE_NAME` / `FRAPPE_SITE_NAME_HEADER`
|
||||
|
||||
See [docs/COOLIFY_DEPLOY.md](docs/COOLIFY_DEPLOY.md).
|
||||
|
||||
|
|
|
|||
36
coolify.env.example
Normal file
36
coolify.env.example
Normal file
|
|
@ -0,0 +1,36 @@
|
|||
# Paste into Coolify → erpnext service → Environment Variables
|
||||
# After Jenkins green build, copy CUSTOM_IMAGE / CUSTOM_TAG from dist/coolify-image.env
|
||||
|
||||
# --- Custom image (required — from Jenkins Forgejo registry) ---
|
||||
CUSTOM_IMAGE=git.aexoradao.com/epistemophiliac/erpnext
|
||||
CUSTOM_TAG=main-26933f3
|
||||
PULL_POLICY=always
|
||||
|
||||
# --- Secrets (required — change before first deploy) ---
|
||||
DB_PASSWORD=replace-with-strong-secret
|
||||
ADMIN_PASSWORD=replace-with-strong-secret
|
||||
|
||||
# --- Domain (automatic — do NOT set unless overriding) ---
|
||||
# 1. In Coolify UI: add domain on service "frontend", port 8080
|
||||
# 2. Coolify sets SERVICE_FQDN_FRONTEND → compose uses it for SITE_NAME + nginx header
|
||||
# 3. Deploy AFTER domain is assigned (first deploy creates the Frappe site)
|
||||
#
|
||||
# SITE_NAME=
|
||||
# FRAPPE_SITE_NAME_HEADER=
|
||||
|
||||
# --- Apps installed on first site creation only (order matters) ---
|
||||
INSTALL_APPS=erpnext,payments,hrms,lending,lms
|
||||
|
||||
# --- Redeploy behaviour ---
|
||||
MIGRATE_SITES=true
|
||||
RESTART_POLICY=unless-stopped
|
||||
|
||||
# --- Optional tuning ---
|
||||
GUNICORN_THREADS=4
|
||||
GUNICORN_WORKERS=2
|
||||
GUNICORN_TIMEOUT=120
|
||||
PROXY_READ_TIMEOUT=120
|
||||
CLIENT_MAX_BODY_SIZE=50m
|
||||
UPSTREAM_REAL_IP_ADDRESS=127.0.0.1
|
||||
UPSTREAM_REAL_IP_HEADER=X-Forwarded-For
|
||||
UPSTREAM_REAL_IP_RECURSIVE=off
|
||||
|
|
@ -1,6 +1,7 @@
|
|||
# ERPNext production stack for Coolify.
|
||||
# Based on https://github.com/frappe/frappe_docker (compose.yaml + mariadb + redis).
|
||||
# Coolify: assign your domain to service `frontend` on port 8080.
|
||||
# Domain: assign in Coolify UI → service `frontend` → port 8080.
|
||||
# SITE_NAME + FRAPPE_SITE_NAME_HEADER use SERVICE_FQDN_FRONTEND automatically.
|
||||
# Image: set CUSTOM_IMAGE / CUSTOM_TAG from Jenkins (dist/coolify-image.env).
|
||||
# No ports: — routing uses SERVICE_URL_FRONTEND_8080.
|
||||
|
||||
x-customizable-image: &customizable_image
|
||||
|
|
@ -99,12 +100,13 @@ services:
|
|||
- >
|
||||
B=/usr/local/bin/bench;
|
||||
SITE=$$SITE_NAME;
|
||||
if [ -z "$$SITE" ]; then echo "[create-site] ERROR: SITE_NAME empty — assign domain to frontend:8080 in Coolify (SERVICE_FQDN_FRONTEND)"; exit 1; fi;
|
||||
wait-for-it -t 120 db:3306;
|
||||
wait-for-it -t 120 redis-cache:6379;
|
||||
wait-for-it -t 120 redis-queue:6379;
|
||||
if [ -d "sites/$$SITE" ]; then echo "[create-site] exists"; $$B use "$$SITE"; else echo "[create-site] creating"; INSTALL_ARGS=""; IFS=',' read -r -a apps <<< "$$INSTALL_APPS"; for app in "$${apps[@]}"; do INSTALL_ARGS="$$INSTALL_ARGS --install-app $$app"; done; $$B new-site "$$SITE" --mariadb-user-host-login-scope='%' --admin-password "$$ADMIN_PASSWORD" --db-root-password "$$DB_PASSWORD" $$INSTALL_ARGS --set-default; fi
|
||||
environment:
|
||||
- 'SITE_NAME=${SITE_NAME:-erp.example.com}'
|
||||
- 'SITE_NAME=${SITE_NAME:-${SERVICE_FQDN_FRONTEND}}'
|
||||
- 'ADMIN_PASSWORD=${ADMIN_PASSWORD:-changeme}'
|
||||
- 'DB_PASSWORD=${DB_PASSWORD:-changeme}'
|
||||
- 'INSTALL_APPS=${INSTALL_APPS:-erpnext,payments,hrms,lending,lms}'
|
||||
|
|
@ -172,9 +174,10 @@ services:
|
|||
- nginx-entrypoint.sh
|
||||
environment:
|
||||
- SERVICE_URL_FRONTEND_8080
|
||||
- SERVICE_FQDN_FRONTEND
|
||||
- 'BACKEND=backend:8000'
|
||||
- 'SOCKETIO=websocket:9000'
|
||||
- 'FRAPPE_SITE_NAME_HEADER=${FRAPPE_SITE_NAME_HEADER:-${SITE_NAME:-erp.example.com}}'
|
||||
- 'FRAPPE_SITE_NAME_HEADER=${FRAPPE_SITE_NAME_HEADER:-${SERVICE_FQDN_FRONTEND}}'
|
||||
- 'UPSTREAM_REAL_IP_ADDRESS=${UPSTREAM_REAL_IP_ADDRESS:-127.0.0.1}'
|
||||
- 'UPSTREAM_REAL_IP_HEADER=${UPSTREAM_REAL_IP_HEADER:-X-Forwarded-For}'
|
||||
- 'UPSTREAM_REAL_IP_RECURSIVE=${UPSTREAM_REAL_IP_RECURSIVE:-off}'
|
||||
|
|
|
|||
|
|
@ -3,11 +3,11 @@
|
|||
## Prerequisites
|
||||
|
||||
- Coolify v4+ with Docker Compose support
|
||||
- Jenkins green build published image to `git.aexoradao.com/epistemophiliac/erpnext`
|
||||
- Server: **minimum 4 GB RAM**, **8 GB+** recommended (custom image + LMS frontend assets)
|
||||
- Public domain (e.g. `erp.yourdomain.com`)
|
||||
- Jenkins green build → image in Forgejo Packages
|
||||
- **4 GB+ RAM** (8 GB+ recommended)
|
||||
- Compose file: `docker-compose.yml`
|
||||
|
||||
## 1. Create the Coolify service (you do this)
|
||||
## 1. Create the Coolify service
|
||||
|
||||
| Setting | Value |
|
||||
|---------|--------|
|
||||
|
|
@ -16,53 +16,55 @@
|
|||
| Branch | `main` |
|
||||
| Compose file | `docker-compose.yml` |
|
||||
|
||||
## 2. Environment variables
|
||||
## 2. Environment variables (Coolify UI)
|
||||
|
||||
From latest **green Jenkins build**, use `dist/coolify-image.env` or:
|
||||
Copy from [`coolify.env.example`](../coolify.env.example). **Required before first deploy:**
|
||||
|
||||
| Variable | Required | Example | Notes |
|
||||
|----------|----------|---------|-------|
|
||||
| `CUSTOM_IMAGE` | yes | `git.aexoradao.com/epistemophiliac/erpnext` | Forgejo registry |
|
||||
| `CUSTOM_TAG` | yes | `main-3eefb73` or `main` | Pin SHA for prod; `main` = latest CI |
|
||||
| `PULL_POLICY` | yes | `always` | Pull from registry on deploy |
|
||||
| `DB_PASSWORD` | yes | strong secret | MariaDB root |
|
||||
| `SITE_NAME` | yes | `erp.yourdomain.com` | Must match domain |
|
||||
| `ADMIN_PASSWORD` | yes | strong secret | Frappe login |
|
||||
| `FRAPPE_SITE_NAME_HEADER` | yes | same as `SITE_NAME` | Single-site routing |
|
||||
| `INSTALL_APPS` | yes | `erpnext,payments,hrms,lending,lms` | First site only |
|
||||
| `MIGRATE_SITES` | no | `true` | Migrate on redeploy |
|
||||
| Variable | Set in Coolify? | Source |
|
||||
|----------|----------------|--------|
|
||||
| `CUSTOM_IMAGE` | yes | Jenkins artifact / `dist/coolify-image.env` |
|
||||
| `CUSTOM_TAG` | yes | e.g. `main-26933f3` (pin) or `main` |
|
||||
| `PULL_POLICY` | yes | `always` |
|
||||
| `DB_PASSWORD` | yes | strong secret |
|
||||
| `ADMIN_PASSWORD` | yes | Frappe `Administrator` password |
|
||||
| `INSTALL_APPS` | yes | `erpnext,payments,hrms,lending,lms` |
|
||||
| `SITE_NAME` | **no** (auto) | From Coolify domain via `SERVICE_FQDN_FRONTEND` |
|
||||
| `FRAPPE_SITE_NAME_HEADER` | **no** (auto) | Same as domain via `SERVICE_FQDN_FRONTEND` |
|
||||
|
||||
> **Coolify env cache:** Changing defaults in `docker-compose.yml` does not update values already stored in Coolify. Edit them in the UI.
|
||||
> **Coolify env cache:** If you previously set `SITE_NAME=erp.example.com` in Coolify, **delete it** so compose defaults use your real domain. Changing `docker-compose.yml` defaults alone does not update stored values.
|
||||
|
||||
## 3. Domain routing
|
||||
## 3. Domain (before first deploy)
|
||||
|
||||
1. Add domain: `erp.yourdomain.com`
|
||||
2. Attach to service **`frontend`**
|
||||
3. Port **`8080`**
|
||||
1. Coolify → your service → **Domains**
|
||||
2. Add domain, e.g. `erp.aexoradao.com`
|
||||
3. Attach to service **`frontend`**, port **`8080`**
|
||||
4. Coolify writes `SERVICE_FQDN_FRONTEND=erp.aexoradao.com` into the stack `.env`
|
||||
5. Compose sets:
|
||||
- `create-site` → `SITE_NAME=erp.aexoradao.com`
|
||||
- `frontend` → `FRAPPE_SITE_NAME_HEADER=erp.aexoradao.com`
|
||||
|
||||
## 4. First deploy timeline
|
||||
**Order matters:** assign domain **then** deploy. If `create-site` runs with an empty site name, the stack exits with a clear error.
|
||||
|
||||
## 4. First deploy
|
||||
|
||||
```text
|
||||
pull custom image → db (healthy) → redis → configurator
|
||||
→ create-site (install erpnext + payments + hrms + lending + lms, ~10–20 min)
|
||||
pull CUSTOM_IMAGE:TAG → db → redis → configurator
|
||||
→ create-site (install apps, ~10–20 min)
|
||||
→ migrator → backend / workers / frontend
|
||||
```
|
||||
|
||||
Login: `https://your-domain` — user `Administrator`, password = `ADMIN_PASSWORD`.
|
||||
|
||||
## 5. Upgrades
|
||||
|
||||
1. Push app changes to git → Jenkins builds new image
|
||||
2. Set `CUSTOM_TAG` in Coolify to new `main-<sha>`
|
||||
3. Redeploy — `migrator` runs `bench migrate`
|
||||
|
||||
## Apps in the image
|
||||
|
||||
See [`apps.json`](../apps.json). Site install list: `INSTALL_APPS` in [`example.env`](../example.env).
|
||||
1. Jenkins builds new image → update `CUSTOM_TAG` in Coolify
|
||||
2. Redeploy — `migrator` runs `bench migrate`
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
| Symptom | Fix |
|
||||
|---------|-----|
|
||||
| Image pull failed | Check registry login on Coolify host; verify tag exists in Forgejo Packages |
|
||||
| create-site fails on LMS | Ensure `payments` is in `INSTALL_APPS` before `lms` |
|
||||
| 502 / unhealthy frontend | Wait for create-site; check `backend` health |
|
||||
| Wrong site | `SITE_NAME` and `FRAPPE_SITE_NAME_HEADER` must match Coolify domain |
|
||||
| `SITE_NAME empty` on create-site | Assign domain on `frontend:8080` before deploy |
|
||||
| Wrong site / 404 nginx | Delete old `SITE_NAME` in Coolify UI; ensure header matches domain |
|
||||
| Site created with wrong name | Wipe `sites` volume or rename site manually — env change alone won't rename |
|
||||
| Image pull failed | Check `CUSTOM_IMAGE` / `CUSTOM_TAG` in Forgejo Packages |
|
||||
|
|
|
|||
28
example.env
28
example.env
|
|
@ -1,38 +1,24 @@
|
|||
# Copy to Coolify Environment Variables (Service > Environment).
|
||||
# Image tags come from Jenkins (Forgejo container registry).
|
||||
# Reference for local testing (`docker compose --env-file example.env config`).
|
||||
# For Coolify, use coolify.env.example — domain comes from SERVICE_FQDN_FRONTEND.
|
||||
|
||||
# Custom image built by Jenkins (apps: ERPNext, HRMS, Lending, LMS + payments)
|
||||
# Custom image (match latest Jenkins build — see dist/coolify-image.env)
|
||||
CUSTOM_IMAGE=git.aexoradao.com/epistemophiliac/erpnext
|
||||
CUSTOM_TAG=main
|
||||
PULL_POLICY=always
|
||||
RESTART_POLICY=unless-stopped
|
||||
|
||||
# Frappe major line — must match apps.json branches (version-16)
|
||||
FRAPPE_BRANCH=version-16
|
||||
|
||||
# MariaDB root password (required — change before production)
|
||||
DB_PASSWORD=changeme
|
||||
|
||||
# Frappe site name — MUST match your Coolify domain
|
||||
# Local-only overrides when not using Coolify magic vars
|
||||
SITE_NAME=erp.example.com
|
||||
|
||||
# Frappe Administrator password
|
||||
ADMIN_PASSWORD=changeme
|
||||
|
||||
# Nginx site header — for single-site Coolify, same as SITE_NAME
|
||||
FRAPPE_SITE_NAME_HEADER=erp.example.com
|
||||
|
||||
# Apps installed on first site creation (comma-separated, order matters)
|
||||
DB_PASSWORD=changeme
|
||||
ADMIN_PASSWORD=changeme
|
||||
INSTALL_APPS=erpnext,payments,hrms,lending,lms
|
||||
|
||||
# Run bench migrate on every deploy (set false to skip)
|
||||
MIGRATE_SITES=true
|
||||
|
||||
# Gunicorn tuning (optional)
|
||||
GUNICORN_THREADS=4
|
||||
GUNICORN_WORKERS=2
|
||||
GUNICORN_TIMEOUT=120
|
||||
|
||||
# Proxy / upload limits (optional)
|
||||
PROXY_READ_TIMEOUT=120
|
||||
CLIENT_MAX_BODY_SIZE=50m
|
||||
UPSTREAM_REAL_IP_ADDRESS=127.0.0.1
|
||||
|
|
|
|||
|
|
@ -66,6 +66,18 @@ else
|
|||
err "[DC-03] missing SERVICE_URL_FRONTEND_8080 on frontend"
|
||||
fi
|
||||
|
||||
if grep -q 'SERVICE_FQDN_FRONTEND' "$COMPOSE_FILE"; then
|
||||
pass "[DC-07] SERVICE_FQDN_FRONTEND present (Coolify domain → SITE_NAME)"
|
||||
else
|
||||
warn "[DC-07] missing SERVICE_FQDN_FRONTEND — SITE_NAME will not track Coolify domain"
|
||||
fi
|
||||
|
||||
if grep -q 'CUSTOM_IMAGE' "$COMPOSE_FILE" && grep -q 'CUSTOM_TAG' "$COMPOSE_FILE"; then
|
||||
pass "[DC-10] CUSTOM_IMAGE / CUSTOM_TAG configured for Jenkins registry"
|
||||
else
|
||||
warn "[DC-10] missing CUSTOM_IMAGE or CUSTOM_TAG in compose"
|
||||
fi
|
||||
|
||||
# Bind mounts ./scripts on long-running services (heuristic)
|
||||
if grep -E '^\s+-\s+['\''"]?\./scripts' "$COMPOSE_FILE" >/dev/null 2>&1; then
|
||||
if grep -B30 './scripts' "$COMPOSE_FILE" | grep -qE 'restart:\s+(unless-stopped|always)'; then
|
||||
|
|
|
|||
Loading…
Reference in a new issue