Skip to main content
ship before you scale

Homelab Staging with Coolify and Cloudflare Tunnel

3 min read Chapter 26 of 42

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

ComponentCost
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.