This guide covers deploying the full stack on a fresh server using Coolify as the platform. Coolify installs and manages Traefik (reverse proxy + automatic TLS) and provides a Git-backed UI for deploying and updating each stack.
| Requirement | Notes |
|---|---|
| VPS or dedicated server | Ubuntu 22.04 / Debian 12 recommended |
| Docker 24+ and Docker Compose v2 | Coolify installs these if missing |
| Ports 80 and 443 open | In the server firewall / security group |
| A registered domain | With access to create DNS A records |
| DNS A records pointing to the server IP | One per service you want to expose |
| Git access to this repo | SSH key or HTTPS token |
Run this once on the server as root (or with sudo). The script installs Docker if it is not already present, creates the coolify Docker network, and starts Traefik + the Coolify management UI.
curl -fsSL https://cdn.coolify.io/install.sh | bashAfter the script completes, Coolify is accessible at http://<server-ip>:8000. Open it in a browser and complete the initial account setup (create the admin user, set the instance URL).
Each stack folder contains a .env.example. Copy it to .env inside the same folder and fill in credentials and domains. Docker Compose (and Coolify) auto-load .env from the folder containing docker-compose.yml — no extra flags needed.
cp stacks/databases/.env.example stacks/databases/.env
cp stacks/automation/.env.example stacks/automation/.env
cp stacks/monitoring/.env.example stacks/monitoring/.env
cp stacks/fuelrod/.env.example stacks/fuelrod/.env
cp stacks/akilimo/.env.example stacks/akilimo/.env
cp .backup-example .backupAll *_DOMAIN variables must be set to real FQDNs before deploying. Traefik uses these to route traffic and request TLS certificates.
fuelrod/.env (most frequently customised):
# Image tags
FUELROD_TAG=latest
PORTAL_TAG=latest
GATEWAY_TAG=latest
FARM_TAG=latest
SYNCER_TAG=latest
# Domains — replace example.com with your actual domain
FUELROD_DOMAIN=fuelrod.yourdomain.com
PORTAL_DOMAIN=portal.yourdomain.com
GATEWAY_DOMAIN=sms.yourdomain.com
FARM_API_DOMAIN=farm-api.yourdomain.com
FARM_WEB_DOMAIN=farm.yourdomain.com
SONAR_DOMAIN=sonar.yourdomain.com
METABASE_DOMAIN=metabase.yourdomain.com
DOZZLE_DOMAIN=logs.yourdomain.commonitoring/.env:
GRAFANA_DOMAIN=grafana.yourdomain.com
DOZZLE_DOMAIN=logs.yourdomain.com
BESZEL_DOMAIN=monitor.yourdomain.comautomation/.env:
N8N_DOMAIN=n8n.yourdomain.comakilimo/.env:
AKILIMO_DOMAIN=akilimo.yourdomain.com
METABASE_DOMAIN=metabase.yourdomain.com- In the Coolify UI, go to Sources → Add a new Source
- Select GitHub (or Gitea / GitLab if self-hosted)
- Follow the OAuth flow or paste a Personal Access Token with
reposcope - Coolify will now be able to clone this repository for each stack deployment
Each top-level compose file is a separate Coolify resource. Create them in deployment order — databases must be running before applications start.
For each resource: Project → + New Resource → Docker Compose, select your Git source, set the compose file path, and paste the relevant env vars in the Environment Variables tab.
| Resource name | Base directory | Compose file |
|---|---|---|
| Databases | stacks/databases/ |
docker-compose.yml |
This starts PostgreSQL, pgBouncer, MariaDB, and Redis. All join the coolify network so every other resource can reach them by hostname (postgres, maria, cache).
Wait for all four containers to show healthy in the Coolify UI before proceeding.
| Resource name | Base directory | Compose file |
|---|---|---|
| n8n | stacks/automation/ |
docker-compose.yml |
n8n connects to the postgres container from the databases resource via the shared coolify network.
| Resource name | Base directory | Compose file |
|---|---|---|
| Monitoring | stacks/monitoring/ |
docker-compose.yml |
Grafana, Prometheus, Loki, and Grafana Agent. The agent tails logs from the fuelrod-logs volume — deploy this after the Fuelrod stack if you need live log forwarding from day one.
| Resource name | Base directory | Compose file |
|---|---|---|
| Fuelrod | stacks/fuelrod/ |
docker-compose.yml |
| Akilimo | stacks/akilimo/ |
docker-compose.yml |
Set the base directory in Coolify to stacks/fuelrod/ or stacks/akilimo/. Coolify auto-detects docker-compose.yml and auto-loads .env from that directory — leave Coolify's env editor blank and manage vars in the .env file on the server instead.
Enable Auto-deploy on each resource if you want Coolify to redeploy automatically when commits land on develop.
Click Deploy on each resource in the order above. Coolify will:
- Clone the repository onto the server
- Pull all required Docker images
- Start containers and attach them to the
coolifyandinternalnetworks - Signal Traefik to pick up the new routing labels
- Traefik requests TLS certificates from Let's Encrypt (HTTP-01 challenge on port 80)
Allow 1–2 minutes for certificates to be issued on first deploy. Subsequent deploys reuse cached certs.
Check deployment logs in the Coolify UI under each resource's Logs tab.
# Check all containers are running
docker ps --format "table {{.Names}}\t{{.Status}}\t{{.Ports}}"
# Tail logs for a specific service
docker logs -f fuelrod
# Check Traefik has picked up all routers
curl -s http://localhost:8080/api/http/routers | jq '.[].rule'
# (Traefik dashboard is on port 8080 by default in Coolify)Open each domain in a browser and confirm HTTPS is working with a valid certificate.
Each domain variable in the stack .env files needs a corresponding DNS A record:
fuelrod.yourdomain.com → <server-ip>
portal.yourdomain.com → <server-ip>
sms.yourdomain.com → <server-ip>
farm.yourdomain.com → <server-ip>
farm-api.yourdomain.com → <server-ip>
n8n.yourdomain.com → <server-ip>
grafana.yourdomain.com → <server-ip>
...
TTL of 300s (5 min) is enough for initial setup. Increase to 3600s once everything is working.
Wildcard alternative: If all services share a subdomain (e.g.
*.apps.yourdomain.com), a single wildcard A record works. Traefik's HTTP-01 challenge does not support wildcard certs — you would need to switch to DNS-01 challenge with your DNS provider's API.
Push to the tracked branch (develop). If Auto-deploy is enabled, Coolify redeploys the affected stack automatically within seconds.
To trigger a manual redeploy: Coolify UI → Stack → Redeploy.
# Pull latest images and restart changed containers only
docker compose -f stacks/fuelrod/docker-compose.yml --project-directory . pull
docker compose -f stacks/fuelrod/docker-compose.yml --project-directory . up -d
# Restart a single service without rebuilding others
docker compose -f stacks/fuelrod/docker-compose.yml --project-directory . restart fuelrod- Create
compose/services/docker-compose.<name>.ymlfollowing the pattern of an existing service file - Add Traefik labels and connect to
coolify+internalnetworks (see any existing service file) - Add the new
*_DOMAINvariable to the relevant stack's.envand.env.example - Add the
include:line to the relevant stack'sdocker-compose.yml - Commit and push — Coolify redeploys automatically
If Coolify is unavailable, the stacks can be deployed directly. The coolify Docker network must exist first:
docker network create coolify
# Deploy in order (--project-directory . is required — all paths are repo-root-relative)
docker compose -f stacks/databases/docker-compose.yml --project-directory . up -d
docker compose -f stacks/automation/docker-compose.yml --project-directory . up -d
docker compose -f stacks/monitoring/docker-compose.yml --project-directory . up -d
docker compose -f stacks/fuelrod/docker-compose.yml --project-directory . up -d
docker compose -f stacks/akilimo/docker-compose.yml --project-directory . up -dWithout Coolify, Traefik is not running, so services are not reachable via their domains. To expose them temporarily, uncomment the
ports:sections in the relevant service files.
See the main README for backup commands. The backup scripts read from .backup (gitignored) which must be present on the server.
# Run a full backup
./autobackup.sh
# Restore postgres from latest backup
fuelrod-backup restore --db-type postgres- Confirm the DNS A record resolves to the server:
dig +short fuelrod.yourdomain.com - Confirm port 80 is reachable from the internet:
curl http://fuelrod.yourdomain.com - Check Traefik logs:
docker logs coolify-proxy - Let's Encrypt rate-limits failed attempts. If you've hit the limit, wait 1 hour before retrying.
# Check exit code and last log lines
docker inspect <container-name> | jq '.[0].State'
docker logs --tail 50 <container-name>- Confirm the container is on the
coolifynetwork:docker inspect <name> | jq '.[0].NetworkSettings.Networks' - Confirm
traefik.enable=trueis set in the service labels:docker inspect <name> | jq '.[0].Config.Labels' - Check that the
*_DOMAINenv var was actually substituted:docker compose config | grep traefik
docker network create coolify
# Then redeploy the affected stacksDatabases (postgres, maria, redis) are on the internal network only and have no host port binding by default. To allow direct access temporarily, uncomment the ports: block in the relevant service file and redeploy.