Skip to content

Deploying HeritageGraph on Coolify

This guide explains how to deploy the full HeritageGraph stack on Coolify.


Prerequisites

  • Coolify installed on your VM (v4.x recommended)
  • A domain pointing to your VM (e.g., heritagegraph.xyz)
  • GitHub repository access configured in Coolify

Architecture on Coolify

┌─────────────────────────────────────────────────────────────────┐
│                        COOLIFY VM                               │
├─────────────────────────────────────────────────────────────────┤
│                                                                 │
│  ┌─────────────────┐                                           │
│  │  coolify-proxy  │  ← Traefik (managed by Coolify)           │
│  │  (ports 80/443) │    Handles SSL, routing, domains          │
│  └────────┬────────┘                                           │
│           │                                                     │
│           ├──────────────┬──────────────┬─────────────────┐    │
│           ▼              ▼              ▼                 ▼    │
│  ┌──────────────┐ ┌──────────────┐ ┌──────────────┐ ┌─────────┐│
│  │   frontend   │ │   backend    │ │   landing    │ │postgres ││
│  │  (Next.js)   │ │   (Django)   │ │  (Next.js)   │ │  (DB)   ││
│  │   :3000      │ │   :8000      │ │   :3000      │ │  :5432  ││
│  └──────────────┘ └──────────────┘ └──────────────┘ └─────────┘│
│                                                                 │
└─────────────────────────────────────────────────────────────────┘

Key Point: Coolify's own Traefik proxy (coolify-proxy) handles all routing and SSL. We do NOT include Traefik in our compose file.


Step 1: Create the Resource in Coolify

  1. Go to your Coolify dashboard
  2. Create a new Project (or use existing)
  3. Add a new Resource → Select Docker Compose
  4. Choose Git Repository as the source
  5. Connect your HeritageGraph repository
  6. Set the Docker Compose file path to: docker-compose-coolify.yml

Step 2: Configure Environment Variables

In Coolify's Environment Variables section, add:

Required Variables

Variable Example Description
POSTGRES_PASSWORD your-secure-password-123 Database password (generate a strong one)
DJANGO_SECRET_KEY your-50-char-random-string Django secret key
NEXTAUTH_SECRET your-32-char-random-string NextAuth session secret
NEXTAUTH_URL http://heritagegraph.xyz Frontend public URL
NEXT_PUBLIC_API_URL http://api.heritagegraph.xyz Backend API URL

Optional Variables (for Google OAuth)

Variable Example Description
GOOGLE_CLIENT_ID xxx.apps.googleusercontent.com Google OAuth client ID
GOOGLE_CLIENT_SECRET GOCSPX-xxx Google OAuth secret

Other Variables

Variable Default Description
POSTGRES_DB heritage_db Database name
POSTGRES_USER heritage_user Database user
ALLOWED_HOSTS * Django allowed hosts (Coolify handles this)
CORS_ALLOWED_ORIGINS http://heritagegraph.xyz CORS origins

Generate Secrets

# Generate DJANGO_SECRET_KEY
openssl rand -base64 50 | tr -d '\n'

# Generate NEXTAUTH_SECRET
openssl rand -base64 32 | tr -d '\n'

# Generate POSTGRES_PASSWORD
openssl rand -base64 24 | tr -d '\n'

Step 3: Configure Domains in Coolify

Coolify manages domains through its UI, NOT through Docker labels. For each service that needs a public domain:

Frontend Service

  1. Click on frontend service in Coolify
  2. Go to NetworkDomains
  3. Add: http://heritagegraph.xyz (or your domain)
  4. Port: 3000
  5. Enable HTTPS if you have SSL configured

Backend Service

  1. Click on backend service
  2. Go to NetworkDomains
  3. Add: http://api.heritagegraph.xyz (or your domain)
  4. Port: 8000
  5. Enable HTTPS if you have SSL configured

Landing Service (Optional)

  1. Click on landing service
  2. Go to NetworkDomains
  3. Add: http://landing.heritagegraph.xyz (or your preferred subdomain)
  4. Port: 3000
  5. Enable HTTPS if you have SSL configured

Step 4: Configure Service Dependencies

In Coolify, set up health check dependencies:

  1. backend depends on postgres (healthy)
  2. frontend can start independently
  3. landing can start independently

This is already defined in the compose file via depends_on.


Step 5: Deploy

  1. Click Deploy in Coolify
  2. Watch the build logs for each service
  3. Wait for all health checks to pass (green status)

Step 6: Post-Deployment Setup

Run Django Migrations

After first deployment, you may need to run migrations manually:

# SSH into your Coolify VM
ssh your-vm

# Find the backend container
docker ps | grep backend

# Run migrations
docker exec -it <container_id> python manage.py migrate

# Create superuser (optional)
docker exec -it <container_id> python manage.py createsuperuser

API homepage, admin, and documentation

After the backend domain resolves to the Django container, open it in a browser:

What URL (replace with your API host)
Entry page (links to everything below) https://api.example.com/
Same as JSON https://api.example.com/?format=json
Django admin https://api.example.com/admin/
Swagger UI (interactive API docs) https://api.example.com/docs or /docs/
ReDoc https://api.example.com/redoc/
OpenAPI schema https://api.example.com/schema/
Health https://api.example.com/health/

If /admin/ or /docs return 404, the domain is almost certainly mapped to the frontend (port 3000) instead of backend (8000). Fix the service mapping in Coolify.

Verify Services

# Check backend health
curl http://api.heritagegraph.xyz/health/

# Check API index (HTML or JSON)
curl -s http://api.heritagegraph.xyz/?format=json

# Check frontend
curl http://heritagegraph.xyz

# Check landing
curl http://landing.heritagegraph.xyz

DNS Configuration

Point your domains to your Coolify VM's IP address:

Record Type Name Value
A heritagegraph.xyz <VM_IP>
A api.heritagegraph.xyz <VM_IP>

Or use a wildcard:

Record Type Name Value
A *.heritagegraph.xyz <VM_IP>
A heritagegraph.xyz <VM_IP>

Troubleshooting

Build Fails

  1. Check Dockerfile paths are correct
  2. Ensure heritage_graph_ui/Dockerfile and heritage_graph_landing/Dockerfile exist
  3. Check Coolify build logs for specific errors

Services Won't Start

  1. Check environment variables are set correctly
  2. Verify postgres is healthy before backend starts
  3. Check container logs in Coolify

SSL Issues

  1. Ensure DNS is pointing to Coolify VM
  2. Let's Encrypt needs ports 80 and 443 open
  3. Wait a few minutes for certificate provisioning

Database Connection Errors

  1. Check POSTGRES_PASSWORD matches in both places
  2. Ensure postgres health check passes
  3. Backend should wait for postgres via depends_on

InconsistentMigrationHistory: admin.0001_initial … users.0001_initial

The backend entrypoint runs migrate on every start. If Postgres was initialized with a bad migration order (or a restored dump), migrations loop forever.

  1. Disposable data: drop and recreate the public schema or delete the Postgres volume, then redeploy (see TROUBLESHOOTING.md §10 — PostgreSQL / Coolify).
  2. Keep data: DELETE FROM django_migrations WHERE app = 'admin'; then migrate from the backend container; use --fake-initial for users only if tables already exist and match.

Full steps: TROUBLESHOOTING.md → section 10.

CORS Errors

  1. Update CORS_ALLOWED_ORIGINS to include your actual frontend domain
  2. Include both http://heritagegraph.xyz and https://heritagegraph.xyz if needed

Updating the Deployment

Code Updates

  1. Push changes to your Git repository
  2. In Coolify, click Redeploy on the affected service
  3. Or enable Auto Deploy for automatic deployments on push

Environment Variable Changes

  1. Update variables in Coolify UI
  2. Click Restart on affected services

Database Migrations

docker exec -it <backend_container> python manage.py migrate

Backup & Recovery

Database Backup

# Create backup
docker exec heritage-postgres pg_dump -U heritage_user heritage_db > backup.sql

# Restore backup
docker exec -i heritage-postgres psql -U heritage_user heritage_db < backup.sql

Volume Backup

Coolify stores volumes in /var/lib/docker/volumes/. Back up: - postgres-data (database) - backend-media (uploaded files) - backend-static (static files)


Security Checklist

  • [ ] Strong POSTGRES_PASSWORD (24+ characters)
  • [ ] Strong DJANGO_SECRET_KEY (50+ characters)
  • [ ] Strong NEXTAUTH_SECRET (32+ characters)
  • [ ] HTTPS enabled on all public services
  • [ ] DEBUG=False in production
  • [ ] Restricted ALLOWED_HOSTS (not * in production)
  • [ ] Proper CORS_ALLOWED_ORIGINS
  • [ ] Firewall rules (80, 443 open; other ports closed)

Architecture Differences from Local Development

Aspect Local (docker-compose.yml) Coolify
Reverse Proxy Own Traefik container Coolify's coolify-proxy
SSL Manual or self-signed Auto Let's Encrypt
Domains *.localhost Real domains
Routing Traefik labels Coolify UI
Env Vars .env file Coolify UI
Builds Local Docker Coolify build system
Monitoring Manual Coolify dashboard