Morphee Production Deployment with Coolify
Complete step-by-step guide to deploy Morphee v2.0 to production using Coolify
Status: ✅ Production-ready Last Updated: February 27, 2026 Estimated Time: 12-16 hours (over 2-3 days)
Table of Contents
- Overview
- Prerequisites
- Phase 1: Server Setup
- Phase 2: Domain Configuration
- Phase 3: Database & Auth
- Phase 4: Backend Deployment
- Phase 5: Verify Deployment
- Phase 6: Monitoring (Optional)
- Phase 7: Backups
- Phase 8: Testing
- Troubleshooting
- Cost Breakdown
Overview
What is Coolify?
Coolify is an open-source, self-hosted Platform-as-a-Service (PaaS) alternative to Heroku, Vercel, and Netlify. It provides:
- ✅ Docker Compose native support — deploy Morphee's multi-service architecture easily
- ✅ Built-in SSL via Let's Encrypt (automatic HTTPS)
- ✅ Built-in reverse proxy (Traefik) — routes traffic to your apps
- ✅ Environment variable management — secure secrets storage
- ✅ Zero-downtime deployments — rolling updates with health checks
- ✅ Git integration — auto-deploy on push to main
- ✅ Web UI — manage everything from a dashboard
Why Coolify for Morphee?
- Cost-effective: $17-42/mo vs $100+ on AWS
- Docker Compose ready: Morphee has
docker-compose.coolify.ymlwith Rust server + monitoring - Easy migration: Move to Kubernetes later if needed
- Open source: No vendor lock-in
Prerequisites
Required
- ✅ Domain name —
morphee.app(or your domain)- Registered and accessible
- DNS managed via Cloudflare, DigitalOcean, or Route53
- ✅ LLM API key — Anthropic (recommended) or OpenAI
- Get key from: https://console.anthropic.com/settings/keys
- Or OpenAI: https://platform.openai.com/api-keys
- ✅ GitHub account — for repository access
- Morphee repo:
https://github.com/your-org/morphee-beta
- Morphee repo:
- ✅ Email account — for Coolify admin + Let's Encrypt
Recommended
- ⚡ Supabase account (free) — for managed PostgreSQL + Auth
- Sign up: https://supabase.com/dashboard
- Alternative: self-host PostgreSQL in Coolify
- ⚡ Server provider account — Hetzner (cheapest), DigitalOcean (easiest), or AWS
- ⚡ Payment method — credit card for server billing
Optional
- 🔧 AWS account — for S3 offsite backups
- 🔧 Google OAuth credentials — for Calendar/Gmail integrations
- 🔧 Firebase account — for mobile push notifications
- 🔧 Apple Developer account — for iOS push notifications
Phase 1: Server Setup (1-2 hours)
1.1 Choose Server Provider
Recommended: Hetzner Cloud (best price/performance)
| Specs | Price | Use Case |
|---|---|---|
| CPX21 — 3 vCPU, 4GB RAM, 80GB SSD | €8.19/mo (~$9/mo) | Small (100-500 users) |
| CPX31 — 4 vCPU, 8GB RAM, 160GB SSD | €16.09/mo (~$17/mo) | Medium (500-2000 users) |
Alternative: DigitalOcean
| Specs | Price | Use Case |
|---|---|---|
| Basic — 2 vCPU, 4GB RAM, 80GB SSD | $24/mo | Small |
| Basic — 2 vCPU, 8GB RAM, 160GB SSD | $48/mo | Medium |
1.2 Create Server
Hetzner Example:
- Go to https://console.hetzner.cloud
- Create new project: "Morphee Production"
- Add server:
- Location: Closest to your users (e.g., Ashburn, VA for US)
- Image: Ubuntu 22.04 LTS
- Type: CPX31 (4 vCPU, 8GB RAM) — recommended
- Networking: Enable IPv4 + IPv6
- SSH keys: Add your public key (
~/.ssh/id_rsa.pub) - Name:
morphee-prod
- Create server (takes ~60 seconds)
- Copy server IP address:
YOUR_SERVER_IP
DigitalOcean Example:
- Go to https://cloud.digitalocean.com
- Create Droplet:
- Image: Ubuntu 22.04 LTS
- Plan: Basic, $48/mo (2 vCPU, 8GB RAM, 160GB SSD)
- Datacenter: Closest to users
- Authentication: SSH keys (recommended)
- Hostname:
morphee-prod
- Create Droplet
- Copy IP address
1.3 Initial Server Configuration
SSH into server:
ssh root@YOUR_SERVER_IP
Update system:
apt update && apt upgrade -y
apt install -y curl wget git vim ufw fail2ban
Configure firewall:
# Allow SSH
ufw allow 22/tcp
# Allow HTTP/HTTPS (for Coolify)
ufw allow 80/tcp
ufw allow 443/tcp
# Allow Coolify dashboard (port 8000)
ufw allow 8000/tcp
# Enable firewall
ufw --force enable
# Verify
ufw status
Optional: Create non-root user
# Create user
adduser morphee
usermod -aG sudo morphee
# Add SSH key for new user
mkdir -p /home/morphee/.ssh
cp /root/.ssh/authorized_keys /home/morphee/.ssh/
chown -R morphee:morphee /home/morphee/.ssh
chmod 700 /home/morphee/.ssh
chmod 600 /home/morphee/.ssh/authorized_keys
# Test login (from local machine)
ssh morphee@YOUR_SERVER_IP
# Disable root SSH login (security best practice)
sed -i 's/PermitRootLogin yes/PermitRootLogin no/' /etc/ssh/sshd_config
systemctl restart ssh
1.4 Install Coolify
One-line installer:
curl -fsSL https://cdn.coollabs.io/coolify/install.sh | bash
This installs:
- Docker Engine (latest)
- Docker Compose (v2)
- Coolify server (runs on port 8000)
- Traefik reverse proxy (for routing + SSL)
- PostgreSQL (Coolify's database)
- Redis (Coolify's cache)
Installation takes ~5-10 minutes.
Expected output:
✅ Docker installed
✅ Docker Compose installed
✅ Coolify installed
✅ Traefik proxy started
✅ Coolify server started
🎉 Coolify is now running!
Access dashboard: http://YOUR_SERVER_IP:8000
Verify installation:
docker ps
You should see containers:
coolifycoolify-dbcoolify-rediscoolify-proxy(Traefik)
1.5 Access Coolify Dashboard
- Open browser:
http://YOUR_SERVER_IP:8000 - First-time setup wizard:
- Email: your-email@example.com (for Let's Encrypt SSL notifications)
- Username: admin (or your preferred username)
- Password: Create strong password (min 12 characters)
- Root Domain:
morphee.app(your domain)
- Click Complete Setup
- You'll be redirected to Coolify dashboard
Security: Restrict Dashboard Access
After setup, restrict Coolify dashboard to your IP only:
# On server
sudo ufw delete allow 8000/tcp
sudo ufw allow from YOUR_HOME_IP to any port 8000 proto tcp
# Verify
sudo ufw status
Access dashboard via SSH tunnel instead:
# From local machine
ssh -L 8000:localhost:8000 morphee@YOUR_SERVER_IP
# Then open: http://localhost:8000
Phase 2: Domain Configuration (30 minutes)
2.1 DNS Records
You need 3 subdomains:
api.morphee.app— Backend APIapp.morphee.app— Frontend web appmonitoring.morphee.app— Grafana (optional)
Option A: Individual A records
| Type | Name | Value | TTL |
|---|---|---|---|
| A | api | YOUR_SERVER_IP | 300 |
| A | app | YOUR_SERVER_IP | 300 |
| A | monitoring | YOUR_SERVER_IP | 300 |
| A | www | YOUR_SERVER_IP | 300 |
| A | @ (root) | YOUR_SERVER_IP | 300 |
Option B: Wildcard (simpler)
| Type | Name | Value | TTL |
|---|---|---|---|
| A | * | YOUR_SERVER_IP | 300 |
| A | @ | YOUR_SERVER_IP | 300 |
Cloudflare Example:
- Go to https://dash.cloudflare.com
- Select your domain (
morphee.app) - Go to DNS → Records
- Click Add record
- Add records above
- Click Save
Verify DNS propagation:
# Test from local machine
dig api.morphee.app +short
# Should return: YOUR_SERVER_IP
dig app.morphee.app +short
# Should return: YOUR_SERVER_IP
DNS propagation takes 5-60 minutes (usually ~5 min with Cloudflare).
2.2 SSL Certificates
Coolify uses Let's Encrypt for automatic SSL certificates.
Wildcard SSL setup (recommended):
- Go to Coolify → Settings → SSL
- Choose DNS Provider: Cloudflare (or your provider)
- Add API Token:
- Cloudflare: Go to My Profile → API Tokens → Create Token
- Use template: Edit zone DNS
- Permissions:
Zone.DNS.Editformorphee.app - Copy token
- Paste token in Coolify
- Click Request Wildcard Certificate
- Coolify will request
*.morphee.appcert via DNS-01 challenge - Wait ~2 minutes for certificate issuance
Verify SSL:
curl -I https://api.morphee.app
# Should return "HTTP/2 200" (after backend is deployed)
Phase 3: Database & Auth (Automatic)
With docker-compose.coolify.yml, PostgreSQL and GoTrue are self-hosted in the same stack. No external Supabase account needed.
Everything is automatic on first deploy:
- PostgreSQL 15 with pgvector starts with auto-generated password (
SERVICE_PASSWORD_POSTGRES) - Migrations run automatically via the
migrationsone-shot container (tracks applied migrations in_migrationstable, safe to re-run) - GoTrue connects to PostgreSQL internally, uses auto-generated JWT secret shared with backend
- No manual setup — no
psql, noCREATE EXTENSION, no migration scripts to run
SMTP Configuration (required for email confirmation)
GoTrue sends confirmation emails on signup. You need an SMTP provider:
| Provider | Free Tier | Setup |
|---|---|---|
| Resend | 3,000 emails/mo | Set SMTP_HOST=smtp.resend.com, SMTP_USER=resend, SMTP_PASS=re_... |
| Mailgun | 1,000 emails/mo | Set SMTP_HOST=smtp.mailgun.org, user + pass from Mailgun dashboard |
| SendGrid | 100 emails/day | Set SMTP_HOST=smtp.sendgrid.net, SMTP_USER=apikey, SMTP_PASS=SG... |
Set these in Coolify UI:
SMTP_HOST=smtp.resend.com
SMTP_PORT=587
SMTP_USER=resend
SMTP_PASS=re_your_api_key
SMTP_FROM=noreply@morphee.app
Quick start without SMTP: Set GOTRUE_MAILER_AUTOCONFIRM=true to skip email confirmation (not recommended for production).
SSO Providers (optional)
To enable Google/Apple/Microsoft login, set in Coolify UI:
# Google SSO
GOOGLE_SSO_ENABLED=true
GOOGLE_CLIENT_ID=your-client-id.apps.googleusercontent.com
GOOGLE_CLIENT_SECRET=GOCSPX-your-client-secret
GOTRUE_GOOGLE_REDIRECT_URI=http://supabase-auth:9999/callback
# Apple SSO
APPLE_SSO_ENABLED=true
APPLE_CLIENT_ID=app.morphee.mobile
APPLE_CLIENT_SECRET=your-apple-secret
# Microsoft / Azure AD SSO
AZURE_SSO_ENABLED=true
AZURE_CLIENT_ID=your-azure-client-id
AZURE_CLIENT_SECRET=your-azure-secret
Optional: External Supabase Database
If you prefer managed PostgreSQL (automatic backups, point-in-time recovery), use Supabase Cloud ($25/mo) instead:
- Create a project at https://supabase.com/dashboard
- In Coolify UI, override these variables:
DATABASE_URL→ Supabase connection stringSUPABASE_AUTH_URL→https://[PROJECT_ID].supabase.co/auth/v1SUPABASE_JWT_SECRET→ from Supabase Settings → API
- Remove or stop the
supabase-db,supabase-auth, andmigrationsservices in Coolify
Phase 4: Application Deployment (2 hours)
4.1 Create Application in Coolify
-
Go to Coolify → Applications → New Application
-
Select deployment type:
- Choose Docker Compose
- Morphee has a Coolify-specific compose file
-
Connect Git repository:
- Source: GitHub
- Repository:
https://github.com/your-org/morphee-beta - Branch:
main - Compose file path:
docker-compose.coolify.yml(at root) - Click Connect
-
Assign domains to services:
- frontend:
https://app.morphee.app(port 80) - server:
https://api.morphee.app(port 3000) - grafana:
https://monitoring.morphee.app(port 3000) — optional - Coolify's Traefik proxy routes traffic automatically
- frontend:
4.2 Configure Environment Variables
In Coolify → Application → Environment, set the required variables.
Auto-generated secrets (do NOT set manually):
Coolify auto-generates and persists these across redeployments:
| Variable | Purpose |
|---|---|
SERVICE_PASSWORD_POSTGRES | PostgreSQL password |
SERVICE_PASSWORD_REDIS | Redis authentication |
Required variables (set in Coolify UI):
# Secrets (generate ONCE, never change)
JWT_SECRET=<base64-secret> # Generate: openssl rand -base64 32
MORPHEE_SIGNING_KEY=<base64-ed25519-key> # Generate: openssl rand -base64 32
# URLs
VITE_API_URL=https://api.morphee.app
VITE_WS_URL=wss://api.morphee.app
MORPHEE_CORS_ORIGINS=https://app.morphee.app,tauri://localhost,http://tauri.localhost,https://tauri.localhost
FRONTEND_URL=https://app.morphee.app
Optional variables:
# SMTP (strongly recommended — see Phase 3 for providers)
SMTP_HOST=smtp.resend.com
SMTP_PORT=587
SMTP_USER=resend
SMTP_PASS=re_your_api_key
SMTP_FROM=noreply@morphee.app
# Google SSO
GOOGLE_SSO_ENABLED=true
GOOGLE_CLIENT_ID=your-client-id.apps.googleusercontent.com
GOOGLE_CLIENT_SECRET=GOCSPX-your-client-secret
# Analytics (PostHog — opt-in)
MORPHEE_ANALYTICS_ENABLED=true
MORPHEE_POSTHOG_API_KEY=phc_your_key
# Grafana
GRAFANA_PASSWORD=your-secure-password
Important:
- Click the lock icon next to sensitive vars (API keys, signing key) — encrypts them at rest
- Mark
VITE_*variables as Build Variables — they are baked into the JS bundle at build time, not runtime
4.3 Persistent Volumes
Docker volumes are managed by Coolify. No manual directory creation needed.
| Volume | Container Path | Purpose |
|---|---|---|
pg-data | /var/lib/postgresql/data | PostgreSQL data |
redis-data | /data | Redis AOF persistence |
knowledge-data | /var/lib/morphee/knowledge | Git-backed knowledge repos |
model-cache | /var/lib/morphee/models | Cached ML models |
prometheus-data | /prometheus | Prometheus time-series data |
grafana-data | /var/lib/grafana | Grafana config + dashboards |
4.4 Deploy
- Click "Deploy" button in Coolify
- Monitor build logs:
- Coolify will:
- Clone repo
- Build Rust server image (using
Dockerfile.server— multi-stage cargo build) - Build frontend image (npm + nginx)
- Pull infrastructure images (PostgreSQL, GoTrue, Redis, Prometheus, Grafana)
- Start all services with health checks
- Coolify will:
- Wait for "Deployed" status (green checkmark)
- Check logs:
-
Coolify → Application → Logs
-
Look for:
INFO morphee-server: Starting morphee-server host=0.0.0.0 port=3000
INFO morphee-server: Database connected
INFO morphee-server: Migrations complete
INFO morphee-server: morphee-server listening addr=0.0.0.0:3000
-
Note: First build takes ~5-10 minutes (Rust compilation). Subsequent builds are faster due to Docker layer caching.
4.5 Verify Deployment
Using the deployment script (recommended):
export COOLIFY_URL=https://coolify.morphee.app
export COOLIFY_TOKEN=your-api-token
export COOLIFY_APP_UUID=your-app-uuid
./scripts/coolify-deploy.sh health
Manual verification:
# Health check
curl https://api.morphee.app/health
# Expected: {"status":"ok","version":"0.1.0","capabilities":[...]}
# Prometheus metrics
curl https://api.morphee.app/metrics | head -5
# Frontend
curl -I https://app.morphee.app
# Expected: HTTP/2 200
4.6 Troubleshooting Server
Issue: Build fails
# Check build logs in Coolify UI
# Common issues:
# - Cargo build OOM (increase server RAM to 8GB+)
# - Missing system deps (cmake, libssl-dev — already in Dockerfile)
# - Out of disk space
# Fix: SSH into server, check disk
df -h
# Clean up old Docker images if needed
docker system prune -a
Issue: Health check fails
# Check server logs
docker logs <server-container> -f
# Common issues:
# - MORPHEE_DATABASE_URL not set or incorrect
# - GoTrue not healthy (check supabase-auth container)
# - MORPHEE_SUPABASE_JWT_SECRET doesn't match GOTRUE_JWT_SECRET
# Verify environment variables
docker exec <server-container> env | grep MORPHEE_
Issue: 502 Bad Gateway
# Server is not listening on port 3000
docker logs <server-container> --tail 50
# Verify server is running
docker ps | grep server
# Check container health
docker inspect --format='{{.State.Health.Status}}' <server-container>
Phase 5: Verify Deployment (30 minutes)
With docker-compose.coolify.yml, all services deploy together as one stack: Rust server, frontend, PostgreSQL, GoTrue, Redis, Prometheus, Grafana.
5.1 Automated Verification
Use the deployment script for a complete health check:
export COOLIFY_URL=https://coolify.morphee.app
export COOLIFY_TOKEN=your-api-token
export COOLIFY_APP_UUID=your-app-uuid
export MORPHEE_API_URL=https://api.morphee.app
export MORPHEE_APP_URL=https://app.morphee.app
# Full health check
./scripts/coolify-deploy.sh health
# If issues found, auto-diagnose + fix
./scripts/coolify-deploy.sh diagnose
5.2 Manual Verification
Test frontend loads:
curl https://app.morphee.app | grep -i morphee
Open in browser: https://app.morphee.app — you should see the login page.
Test API connection (browser console):
fetch('https://api.morphee.app/health')
.then(r => r.json())
.then(console.log)
// Expected: {status: "ok", version: "0.1.0", capabilities: [...]}
5.3 Troubleshooting
Issue: Blank page
// Check browser console for errors
// Verify build args were applied
console.log(import.meta.env.VITE_API_URL)
// Should show: https://api.morphee.app
// If undefined: VITE_* vars need to be marked as Build Variables in Coolify
Issue: CORS errors
# Verify MORPHEE_CORS_ORIGINS includes frontend domain
docker exec <server-container> env | grep MORPHEE_CORS
# Should include: https://app.morphee.app
Issue: Assets 404
# Check nginx serves files
docker exec <frontend-container> ls -la /usr/share/nginx/html
Phase 6: Monitoring (Included in Stack)
Monitoring is built into the Coolify deployment — Prometheus + Grafana are included in docker-compose.coolify.yml.
What's Included
- Prometheus scrapes the Rust server's built-in
/metricsendpoint every 10s - Grafana provides dashboards for API performance, error rates, and system health
- The Rust server exposes metrics via
prometheus-client(HTTP request counts, latencies, etc.)
Setup
- Add DNS record:
monitoring.morphee.app→YOUR_SERVER_IP - Assign domain in Coolify: grafana service →
https://monitoring.morphee.app - Set Grafana password:
GRAFANA_PASSWORD=your-secure-passwordin Coolify env vars
Access Grafana
- Open:
https://monitoring.morphee.app - Login:
admin/YOUR_GRAFANA_PASSWORD
Import Dashboards
- Go to Dashboards → Import
- Import custom Morphee dashboard from
monitoring/grafana/dashboards/(auto-provisioned) - Optional community dashboards:
- 9628 — PostgreSQL Database
- 193 — Docker Container Metrics
Verify Metrics
# Check Prometheus scrapes the server
curl https://api.morphee.app/metrics | head -10
# Check Prometheus targets (from server)
curl http://localhost:9090/api/v1/targets
Optional: Full Monitoring Stack
For additional exporters (node-exporter, cAdvisor, postgres-exporter, Alertmanager, Loki), use the standalone monitoring compose:
docker compose -f docker-compose.monitoring.yml up -d
Phase 7: Backups (1 hour)
7.1 Database Backups
Option A: Supabase Automatic Backups (RECOMMENDED)
If using Supabase Database:
- ✅ Automatic daily backups included (7-day retention on Pro)
- ✅ Point-in-time recovery (restore to any minute within 7 days)
- ✅ Download backups via dashboard (Settings → Database → Backups)
Option B: Manual Backup Script
-
Upload backup script:
scp scripts/backup-morphee.sh morphee@YOUR_SERVER_IP:/root/ -
SSH into server and configure:
ssh morphee@YOUR_SERVER_IP
# Make executable
chmod +x /root/backup-morphee.sh
# Test run
DATABASE_URL="postgresql://..." /root/backup-morphee.sh
# Verify backup created
ls -lh /data/backups/morphee/ -
Schedule daily backups via cron:
# Edit crontab
crontab -e
# Add line (runs daily at 2 AM)
0 2 * * * DATABASE_URL="postgresql://..." /root/backup-morphee.sh >> /var/log/morphee-backup.log 2>&1 -
Optional: Upload to S3 for offsite storage:
# Install AWS CLI
apt install -y awscli
# Configure AWS credentials
aws configure
# Enter: Access Key ID, Secret Access Key, Region (us-east-1)
# Test S3 upload
DATABASE_URL="postgresql://..." \
S3_BUCKET="s3://your-morphee-backups" \
/root/backup-morphee.sh
7.2 Test Disaster Recovery
Simulate data loss and restore:
# SSH into server
ssh morphee@YOUR_SERVER_IP
# 1. Create test data
psql $DATABASE_URL -c "INSERT INTO conversations (id, title, user_id, group_id, space_id, created_at, updated_at) VALUES (gen_random_uuid(), 'Test Conversation', (SELECT id FROM users LIMIT 1), (SELECT id FROM groups LIMIT 1), (SELECT id FROM spaces LIMIT 1), NOW(), NOW());"
# 2. Backup
DATABASE_URL="postgresql://..." /root/backup-morphee.sh
# 3. Delete test data
psql $DATABASE_URL -c "DELETE FROM conversations WHERE title = 'Test Conversation';"
# 4. Restore from latest backup
LATEST_BACKUP=$(ls -t /data/backups/morphee/morphee_db_*.sql.gz | head -1)
gunzip -c $LATEST_BACKUP | psql $DATABASE_URL
# 5. Verify restoration
psql $DATABASE_URL -c "SELECT * FROM conversations WHERE title = 'Test Conversation';"
# Should return the restored row
Phase 8: Testing (1 hour)
8.1 Smoke Tests
Server API:
# Health check
curl https://api.morphee.app/health
# Expected: {"status":"ok","version":"0.1.0","capabilities":[...]}
# Prometheus metrics
curl https://api.morphee.app/metrics | head -5
# Auth (verify GoTrue proxy works)
curl -X POST https://api.morphee.app/v1/auth/verify \
-H "Content-Type: application/json" \
-d '{"token":"test"}'
# Expected: 401 (bad token — but endpoint is reachable)
# Capabilities
curl https://api.morphee.app/v1/capabilities
Frontend:
# Test HTML loads
curl https://app.morphee.app | grep -i morphee
# Test assets load
curl -I https://app.morphee.app/assets/index.js
# Should return 200 OK
WebSocket:
// In browser console (after login)
const ws = new WebSocket('wss://api.morphee.app/ws?token=YOUR_JWT_TOKEN');
ws.onopen = () => console.log('✅ WebSocket connected');
ws.onmessage = (e) => console.log('📨 Message:', e.data);
ws.onerror = (e) => console.error('❌ Error:', e);
8.2 End-to-End Test
Complete user flow:
- Open
https://app.morphee.appin browser - Click Sign Up
- Enter: email, password, name
- Click Create Account
- Should redirect to
/onboarding - Chat with AI: "I'm a parent with 2 kids"
- AI should create group + spaces
- Redirect to
/chat - Send message: "Hello Morphee!"
- AI should respond
- Check WebSocket events in DevTools → Network → WS
8.3 Load Test (Optional)
Install k6:
# macOS
brew install k6
# Linux
sudo gpg -k
sudo gpg --no-default-keyring --keyring /usr/share/keyrings/k6-archive-keyring.gpg --keyserver hkp://keyserver.ubuntu.com:80 --recv-keys C5AD17C747E3415A3642D57D77C6C491D6AC1D69
echo "deb [signed-by=/usr/share/keyrings/k6-archive-keyring.gpg] https://dl.k6.io/deb stable main" | sudo tee /etc/apt/sources.list.d/k6.list
sudo apt-get update
sudo apt-get install k6
Run load test:
// load-test.js
import http from 'k6/http';
import { check, sleep } from 'k6';
export let options = {
stages: [
{ duration: '2m', target: 100 }, // Ramp to 100 users
{ duration: '5m', target: 100 }, // Stay at 100
{ duration: '2m', target: 0 }, // Ramp down
],
thresholds: {
http_req_duration: ['p(95)<500'], // 95% < 500ms
http_req_failed: ['rate<0.01'], // <1% error rate
},
};
export default function () {
let response = http.get('https://api.morphee.app/health');
check(response, {
'status is 200': (r) => r.status === 200,
'response time < 500ms': (r) => r.timings.duration < 500,
});
sleep(1);
}
Run:
k6 run load-test.js
Expected results:
- ✅ 95th percentile < 500ms
- ✅ Error rate < 1%
- ✅ All checks pass
Troubleshooting
Common Issues
1. SSL certificate not provisioning
# Check Traefik logs
docker logs coolify-proxy -f
# Common issues:
# - DNS not propagated yet (wait 5-60 min)
# - Cloudflare DNS-only mode (should be "Proxied")
# - Rate limit (Let's Encrypt allows 5 certs/week per domain)
# Fix: Re-trigger certificate
# Coolify → Application → Domain → Re-issue Certificate
2. Server can't connect to database
# Check MORPHEE_DATABASE_URL format
# Correct: postgresql://user:pass@supabase-db:5432/postgres
# Incorrect: postgres://... (should be postgresql://)
# Check server logs for connection errors
docker logs <server-container> --tail 50 | grep -i "database\|connect\|error"
3. Frontend can't reach server (CORS)
# Check MORPHEE_CORS_ORIGINS in server
docker exec <server-container> env | grep MORPHEE_CORS
# Should include: https://app.morphee.app
# Update in Coolify → Environment → MORPHEE_CORS_ORIGINS
# Redeploy
4. WebSocket connection fails
// In browser console, check error
const ws = new WebSocket('wss://api.morphee.app/v1/ws?token=YOUR_TOKEN');
ws.onerror = (e) => console.error(e);
// Common issues:
// - Invalid JWT token
// - Server not listening on /v1/ws
// - Traefik not upgrading connection
5. Out of disk space
# Check disk usage
df -h
# Clean up Docker images/containers
docker system prune -a -f --volumes
# Remove old logs
journalctl --vacuum-time=7d
# Check large directories
du -sh /var/lib/docker
du -sh /data/coolify
Cost Breakdown
Option 1: Fully Self-Contained (Recommended)
Everything in docker-compose.coolify.yml — no external accounts.
| Service | Provider | Cost/mo |
|---|---|---|
| Server (8GB RAM) | Hetzner CPX31 | €16 (~$17) |
| Domain + SSL | Cloudflare | $0 (free) |
| SMTP | Resend | $0 (free tier: 3k emails/mo) |
| Total | ~$17/mo |
Pros: Cheapest, full control, data sovereignty, no vendor dependency Cons: Single server (no redundancy), manual backups
Option 2: Hybrid (Managed Database)
Self-hosted app + managed PostgreSQL for automatic backups.
| Service | Provider | Cost/mo |
|---|---|---|
| Server (4GB RAM) | Hetzner CPX21 | €8 (~$9) |
| Database + Auth | Supabase Pro | $25 |
| Domain + SSL | Cloudflare | $0 (free) |
| Total | ~$34/mo |
Pros: Automatic backups, point-in-time recovery Cons: Vendor dependency, higher cost
Option 3: Full Managed (Future)
| Service | Provider | Cost/mo |
|---|---|---|
| Database | AWS RDS | $30 |
| App Hosting | AWS ECS Fargate | $30 |
| Load Balancer | AWS ALB | $20 |
| Redis | ElastiCache | $15 |
| CDN | CloudFront | $5 |
| Total | ~$100/mo |
When to migrate: >10k users, multi-region, compliance needs
Next Steps
After successful deployment:
-
✅ Update documentation:
- Mark deployment.md as "✅ Deployed"
- Add production URLs to README.md
-
✅ Set up monitoring alerts:
- CPU > 80% for 5 min
- Disk > 90%
- HTTP error rate > 5%
-
✅ Enable CI/CD:
- GitHub Actions → Coolify webhook
- Auto-deploy on push to main
-
✅ User testing:
- Invite beta users
- Monitor errors in Sentry/Grafana
-
✅ Performance tuning:
- Add database indexes if slow
- Enable Redis caching
- Optimize Docker images
Support
Need help?
- Coolify Docs: https://coolify.io/docs
- Coolify Discord: https://coolify.io/discord
- Morphee Issues: https://github.com/your-org/morphee-beta/issues
Emergency contacts:
- On-call: (add phone number)
- Email: ops@morphee.app
Last updated: February 27, 2026 Deployment status: ✅ Production-ready (v2.0 — Rust server) Next review: After first production deployment