Homelab Staging with Coolify and Cloudflare Tunnel
Homelab Staging with Coolify and Cloudflare Tunnel
The Feature
Every merge to main deploys to a staging environment running on the developer’s homelab. The staging environment is accessible at staging.marketflow.app via Cloudflare Tunnel. It runs the same Docker Compose configuration as production, with a separate Supabase project and Stripe test mode keys.
The Decision
Staging on the homelab is free. No cloud compute costs. The homelab server runs continuously (a used mini-PC or an old laptop is sufficient), and the Cloudflare Tunnel makes it accessible without opening firewall ports. The staging environment uses Stripe test mode, a separate Supabase project, and test data. It mirrors production closely enough to catch deployment issues before they affect real customers.
The Implementation
Homelab Coolify Setup
# On the homelab server (any Linux machine with Docker)
curl -fsSL https://cdn.coollabs.io/coolify/install.sh | bash
# Configure Coolify at http://homelab-ip:8000
# 1. Add a new Server (localhost)
# 2. Create a Project: "Marketflow Staging"
# 3. Add the GitHub repository
# 4. Set deployment type: Docker Compose
# 5. Point to docker-compose.prod.yml
Staging Environment Variables
In Coolify’s UI, set these environment variables for the staging resource:
DATABASE_URL=postgresql+asyncpg://[email protected]/postgres
SUPABASE_URL=https://staging-project.supabase.co
SUPABASE_SERVICE_KEY=eyJ... (staging project key)
SUPABASE_JWT_SECRET=staging-jwt-secret
STRIPE_SECRET_KEY=sk_test_... (test mode key)
STRIPE_WEBHOOK_SECRET=whsec_... (staging webhook secret)
STRIPE_PRICE_ID=price_test_... (test mode price)
RESEND_API_KEY=re_test_... (test API key)
FRONTEND_URL=https://staging.marketflow.app
ENVIRONMENT=staging
Every service uses a separate test/staging instance. The staging database is a separate Supabase project. Stripe uses test mode keys. Resend uses a test API key that does not send real emails. There is zero risk of staging actions affecting production data or real customers.
Cloudflare Tunnel for Staging
# ~/.cloudflared/config.yml (on homelab)
tunnel: <STAGING_TUNNEL_ID>
credentials-file: /home/deploy/.cloudflared/<STAGING_TUNNEL_ID>.json
ingress:
- hostname: staging.marketflow.app
service: http://localhost:80
- hostname: api-staging.marketflow.app
service: http://localhost:8000
- service: http_status:404
# Add DNS records in Cloudflare
cloudflared tunnel route dns staging-tunnel staging.marketflow.app
cloudflared tunnel route dns staging-tunnel api-staging.marketflow.app
# Run as systemd service for persistence
sudo cloudflared service install
Staging Deployment Workflow
# .github/workflows/deploy-staging.yml
name: Deploy to Staging
on:
push:
branches: [main]
jobs:
deploy-staging:
runs-on: ubuntu-latest
steps:
- name: Trigger Coolify staging deployment
run: |
curl -X POST "${{ secrets.COOLIFY_STAGING_WEBHOOK_URL }}" \
-H "Authorization: Bearer ${{ secrets.COOLIFY_STAGING_API_TOKEN }}"
Staging deploys on every push to main. Production deploys are triggered manually (the production workflow runs on a workflow_dispatch event or when a release tag is created). This gives the developer a chance to verify the staging deployment before promoting to production.
The Trap
# TRAP: Using the same Supabase project for staging and production
# Staging data (test vendors, fake markets) appears in the production database
# A migration run on staging modifies the production schema
# SAFE: Separate Supabase projects
# Free tier allows 2 projects
# Staging: https://staging-project.supabase.co
# Production: https://production-project.supabase.co
Supabase’s free tier allows two projects. Use one for staging and one for production. If you need more projects, the Pro plan at $25/month allows unlimited projects.
The Cost
| Component | Cost |
|---|---|
| Homelab server | $0 (existing hardware) |
| Electricity | ~$5/month (mini-PC) |
| Coolify on homelab | $0 |
| Cloudflare Tunnel | $0 |
| Supabase staging project | $0 (free tier) |
| Stripe test mode | $0 |
The staging environment costs approximately $5/month in electricity. The alternative, a staging VPS, would cost another €4.51/month. The homelab approach saves that cost and provides a physical machine for other development purposes.