What You'll Build
A working data pipe between a Supabase stack (Kong + PostgREST) and a PostHog-compatible event receiver, deployed on Hetzner Cloud with Stacker. Events flow from Supabase through Kong to PostHog - all self-hosted.
- Supabase with Kong API gateway, PostgREST, Auth, Realtime, Storage
- PostHog-compatible event receiver
- Stacker PIPE connecting both services
- Deployed on Hetzner Cloud with status panel agent
Quick Answer
# Deploy the stack
stacker deploy --target cloud --key htz-0
# Create the pipe
stacker pipe create supabase-posthog posthog --manual
# Test the connection
curl -X POST http://<SERVER_IP>:8000/posthog/capture \
-H "Content-Type: application/json" \
-d '{"event":"test","properties":{"source":"pipe-demo"}}'
Events flow from Supabase through Kong to PostHog.
Prerequisites
- Stacker CLI installed and authenticated (
stacker login) - Hetzner cloud credentials configured (
stacker clouds) - Docker running locally (for image transfer if needed)
Step 1: Create the Project
stacker init supabase-posthog
Set the project identity in stacker.yml:
name: supabase-posthog
project:
identity: supabase-posthog
Step 2: Define the Stack
Configure Kong as the API gateway, Supabase services, and a PostHog-compatible event receiver in stacker.yml.
app:
type: custom
image: kong/kong:3.9.1
ports:
- "8000:8000"
- "8443:8443"
services:
- name: db
image: supabase/postgres:17.6.1.136
# ... database init, healthcheck, volumes
- name: posthog
image: python:3.11-alpine
ports:
- "8001:8000"
volumes:
- ./posthog-receiver/app.py:/app/app.py:ro
command: python /app/app.py
Kong Route Configuration
Create kong.yml with upstream timeouts to avoid probe hangs. Without explicit timeouts, Kong defaults to 60 seconds per upstream operation - probes hitting a down service would hang for the full duration.
services:
- name: rest-v1
url: http://rest:3000
connect_timeout: 5000
write_timeout: 5000
read_timeout: 5000
routes:
- name: rest-all
paths:
- /rest/v1/
- name: posthog-v1
url: http://posthog:8000
connect_timeout: 5000
write_timeout: 5000
read_timeout: 5000
routes:
- name: posthog-capture
paths:
- /posthog/
Step 3: Deploy to Cloud
stacker deploy --target cloud --key htz-0
Stacker provisions a Hetzner server, installs Docker and the status panel agent, copies the config bundle, and starts all containers.
After deployment completes, verify everything is running:
stacker status
stacker agent status
stacker agent containers
All services should show running. If some are restarting, check their logs:
stacker agent logs rest --limit 20
Step 4: Create the Pipe
The pipe connects Supabase PostgREST (source) to PostHog's /capture endpoint (target). First, scan for endpoints - note the probe takes 3-5 minutes, so the CLI timeout may need extending.
# Using pipe scan (may time out if probe takes long)
stacker pipe scan --app supabase-posthog
# Alternative: use agent exec with a longer timeout
stacker agent exec probe_endpoints \
--params '{"app_code":"supabase-posthog","capture_samples":true}' \
--timeout 600 --json
Then create the pipe:
stacker pipe create supabase-posthog posthog --manual
Step 5: Test the Pipe
Verify the PostHog receiver accepts events:
# Direct to PostHog
curl -X POST http://<SERVER_IP>:8001/capture \
-H "Content-Type: application/json" \
-d '{"event":"test","properties":{"source":"pipe-demo"}}'
# Through Kong gateway
curl -X POST http://<SERVER_IP>:8000/posthog/capture \
-H "Content-Type: application/json" \
-d '{"event":"test","properties":{"source":"pipe-demo"}}'
Check the PostHog logs to confirm receipt:
stacker agent logs posthog --limit 10
# Expected: Received capture event: {"event": "test", "properties": {"source": "pipe-demo"}}
Troubleshooting
Probe Hangs or Times Out
Most common cause: The remote docker-compose.yml is invalid - missing volume definitions, undefined networks, or file ownership issues. Run docker compose ps on the server to check.
ssh trydirect@<SERVER_IP>
cd /home/trydirect/project
docker compose ps
# Validate compose file
docker compose config
Probe Works but Endpoints Are Empty
Check Kong upstream timeouts. If Kong's upstream connections hang (default 60s), the probe waits for each timeout. Set connect_timeout, write_timeout, read_timeout to 5000ms on all Kong services.
Container Name Not Resolved
The agent needs access to Docker and a valid compose file. Run docker compose ps directly on the server. If it errors with "refers to undefined network" or "refers to undefined volume", the compose file is broken.
Agent Responds Slowly
If the compose file is invalid, every agent operation that validates the compose will hang. Fix the compose file first, then restart the agent:
ssh trydirect@<SERVER_IP>
sudo docker compose -f /home/trydirect/statuspanel/docker-compose.yml up -d
Verification Checklist
stacker deploymentsshows all deploymentsstacker statusshows last deployment statusstacker agent containerslists all services asrunningstacker agent exec probe_endpointsreturns endpoints with operations- Direct curl to PostHog
/capturereturns{"status": "ok"} - Events appear in
stacker agent logs posthog
Frequently Asked Questions
Why use Kong as the API gateway?
Kong routes traffic to multiple Supabase services (PostgREST, Auth, Realtime, Storage) through a single entry point. It also handles timeouts, rate limiting, and CORS.
Can I use the real PostHog instead of a receiver?
Yes. Replace the Python receiver with the official PostHog Docker image. The pipe endpoint remains the same - /capture.
How do I extend the probe timeout?
Use stacker agent exec probe_endpoints --timeout 600 for a 10-minute timeout. The default CLI timeout may be too short for complex stacks.
Do I need to open firewall ports?
Yes. After cloud deploy, open the ports you need: stacker cloud firewall add --public-ports 8000/tcp,8001/tcp.
Key Takeaways
- Supabase + PostHog deploys as a single Stacker project
- Kong upstream timeouts must be set explicitly to avoid probe hangs
- Invalid compose files cause agent slowness - validate with
docker compose config - The pipe works through Kong gateway or directly to the PostHog receiver
- Source: github.com/trydirect/stacker