Overview
Kuest Prediction Market can be deployed to various cloud providers beyond Vercel. This guide covers deployment to Google Cloud Run, Fly.io, DigitalOcean App Platform, and generic VPS providers.All cloud deployments use the same Docker image from
infra/docker/Dockerfile and support both Supabase and Postgres+S3 storage modes.Google Cloud Run
Google Cloud Run provides fully managed, serverless containers with automatic scaling.Prerequisites
- GCP project with billing enabled
gcloudCLI installed and authenticated- Required APIs enabled:
- Cloud Build API
- Artifact Registry API
- Cloud Run Admin API
- Secret Manager API
Setup
echo -n "your-postgres-url" | gcloud secrets create POSTGRES_URL --data-file=-
echo -n "your-cron-secret" | gcloud secrets create CRON_SECRET --data-file=-
echo -n "your-auth-secret" | gcloud secrets create BETTER_AUTH_SECRET --data-file=-
echo -n "your-reown-id" | gcloud secrets create REOWN_APPKIT_PROJECT_ID --data-file=-
echo -n "0x123..." | gcloud secrets create ADMIN_WALLETS --data-file=-
echo -n "0x456..." | gcloud secrets create KUEST_ADDRESS --data-file=-
echo -n "your-api-key" | gcloud secrets create KUEST_API_KEY --data-file=-
echo -n "your-api-secret" | gcloud secrets create KUEST_API_SECRET --data-file=-
echo -n "your-passphrase" | gcloud secrets create KUEST_PASSPHRASE --data-file=-
echo -n "https://xxx.supabase.co" | gcloud secrets create SUPABASE_URL --data-file=-
echo -n "eyJhbGc..." | gcloud secrets create SUPABASE_SERVICE_ROLE_KEY --data-file=-
echo -n "kuest-assets" | gcloud secrets create S3_BUCKET --data-file=-
echo -n "your-key-id" | gcloud secrets create S3_ACCESS_KEY_ID --data-file=-
echo -n "your-secret-key" | gcloud secrets create S3_SECRET_ACCESS_KEY --data-file=-
infra/docker/Dockerfilegcloud run services add-iam-policy-binding kuest-web \
--region=us-central1 \
--member="allUsers" \
--role="roles/run.invoker"
gcloud run services update kuest-web \
--region=us-central1 \
--custom-audience="https://markets.example.com"
SITE_URL=https://markets.example.com
CRON_SECRET=your-cron-secret
gcloud scheduler jobs create http kuest-sync-events \
--location=us-central1 \
--schedule="1-59/5 * * * *" \
--uri="${SITE_URL}/api/sync/events" \
--http-method=GET \
--headers="Authorization=Bearer ${CRON_SECRET}"
gcloud scheduler jobs create http kuest-sync-resolution \
--location=us-central1 \
--schedule="3-59/5 * * * *" \
--uri="${SITE_URL}/api/sync/resolution" \
--http-method=GET \
--headers="Authorization=Bearer ${CRON_SECRET}"
gcloud scheduler jobs create http kuest-sync-translations \
--location=us-central1 \
--schedule="*/10 * * * *" \
--uri="${SITE_URL}/api/sync/translations" \
--http-method=GET \
--headers="Authorization=Bearer ${CRON_SECRET}"
gcloud scheduler jobs create http kuest-sync-volume \
--location=us-central1 \
--schedule="14,44 * * * *" \
--uri="${SITE_URL}/api/sync/volume" \
--http-method=GET \
--headers="Authorization=Bearer ${CRON_SECRET}"
Cloud Build Configuration
Theinfra/cloud-run/cloudbuild.yaml includes:
Fly.io
Fly.io provides edge deployment with global distribution.Prerequisites
- Fly.io account
flyctlCLI installed and authenticated- Fly app created:
fly apps create <app-name>
Setup
fly secrets set \
KUEST_ADDRESS="0x..." \
KUEST_API_KEY="xxx" \
KUEST_API_SECRET="xxx" \
KUEST_PASSPHRASE="xxx" \
ADMIN_WALLETS="0x..." \
REOWN_APPKIT_PROJECT_ID="xxx" \
BETTER_AUTH_SECRET="xxx" \
CRON_SECRET="xxx" \
POSTGRES_URL="postgresql://..." \
SUPABASE_URL="https://xxx.supabase.co" \
SUPABASE_SERVICE_ROLE_KEY="eyJhbGc..." \
SITE_URL="https://your-app.fly.dev" \
--app <app-name>
flyctl deploy \
--app <app-name> \
--config infra/fly/fly.toml \
--image ghcr.io/kuestcom/prediction-market@sha256:<digest>
Fly.io Configuration
Fly.io deployment requires an external scheduler for
/api/sync/* endpoints when not using Supabase mode. Use GitHub Actions, Cloud Scheduler, or any cron service.DigitalOcean
DigitalOcean offers both App Platform (PaaS) and Droplets (VPS).App Platform
<your-username>/prediction-marketmaininfra/docker/Dockerfile.3000KUEST_ADDRESS=0x...
KUEST_API_KEY=xxx
KUEST_API_SECRET=xxx
KUEST_PASSPHRASE=xxx
ADMIN_WALLETS=0x...
REOWN_APPKIT_PROJECT_ID=xxx
BETTER_AUTH_SECRET=xxx
CRON_SECRET=xxx
POSTGRES_URL=postgresql://...
SUPABASE_URL=https://xxx.supabase.co
SUPABASE_SERVICE_ROLE_KEY=eyJhbGc...
SITE_URL=https://your-app.ondigitalocean.app
NODE_ENV=production
VPS Deployment (Droplets, Vultr, Hetzner, EC2)
For VPS providers, use Docker Compose with production configuration.# Update system
sudo apt update && sudo apt upgrade -y
sudo timedatectl set-timezone UTC
# Configure firewall
sudo ufw allow OpenSSH
sudo ufw allow 80/tcp
sudo ufw allow 443/tcp
sudo ufw --force enable
curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo gpg --dearmor -o /etc/apt/keyrings/docker.gpg
echo "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.gpg] https://download.docker.com/linux/ubuntu $(. /etc/os-release && echo "$VERSION_CODENAME") stable" | sudo tee /etc/apt/sources.list.d/docker.list > /dev/null
sudo apt-get update
sudo apt-get install -y docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin git
sudo usermod -aG docker "$USER"
newgrp docker
sudo mkdir -p /opt/kuest
sudo chown "$USER":"$USER" /opt/kuest
cd /opt/kuest
git clone https://github.com/<your-org>/prediction-market.git
cd prediction-market
cp .env.example .env
docker compose --env-file .env -f infra/docker/docker-compose.production.yml exec web npm run db:push
1-59/5 * * * * curl -fsS -H "Authorization: Bearer your-cron-secret" "https://markets.example.com/api/sync/events" >/dev/null 2>&1
3-59/5 * * * * curl -fsS -H "Authorization: Bearer your-cron-secret" "https://markets.example.com/api/sync/resolution" >/dev/null 2>&1
*/10 * * * * curl -fsS -H "Authorization: Bearer your-cron-secret" "https://markets.example.com/api/sync/translations" >/dev/null 2>&1
14,44 * * * * curl -fsS -H "Authorization: Bearer your-cron-secret" "https://markets.example.com/api/sync/volume" >/dev/null 2>&1
VPS Management
Storage Mode Comparison
| Feature | Supabase Mode | Postgres + S3 Mode |
|---|---|---|
| Database | Supabase PostgreSQL | Any PostgreSQL |
| Object Storage | Supabase Storage | S3-compatible |
| Cron Scheduler | Built-in (Supabase) | External required |
| Complexity | Lower | Higher |
| Vendor Lock-in | Moderate | Lower |
| Cost | Free tier available | Pay per resource |
Supabase Mode
Required variables:- Automatic cron scheduling
- Integrated storage and database
- Generous free tier
Postgres + S3 Mode
Required variables:- Full control over infrastructure
- Any S3-compatible provider (AWS, MinIO, Backblaze, etc.)
- Better for high-scale deployments
- Must implement scheduler contract for
/api/sync/*endpoints - See scheduler options: Cloud Scheduler, GitHub Actions, cron jobs
Troubleshooting
Image Pull Failures
Cloud Run/GCP:Environment Variables Not Loading
- Verify secrets are created in provider’s secret manager
- Check case sensitivity (some providers are case-sensitive)
- Redeploy after adding new variables
- Check logs for missing variable errors
Domain SSL Issues
- Verify DNS propagation:
dig markets.example.com - Wait 24-48 hours for full propagation
- Check SSL certificate status in provider dashboard
- Ensure domain verification is complete
Scheduler Not Running
- Verify
CRON_SECRETmatches in scheduler and app - Check scheduler logs in cloud provider console
- Test endpoint manually with curl
- Ensure scheduler has network access to app
Cost Optimization
Cloud Run
- Use minimum instances (0 or 1)
- Set max instances to prevent runaway costs
- Enable CPU throttling
- Use shared CPU tier
Fly.io
- Use
auto_stop_machines = "suspend"for dev environments - Single region for lower costs
- Shared CPU instances
DigitalOcean
- Start with Basic tier ($5/month droplet)
- Use managed database free tier
- Enable CDN for static assets
VPS General
- Use reserved instances for 30-50% savings
- Monitor resource usage and downsize if possible
- Use object storage for media (cheaper than disk)
- Enable log rotation to save disk space
Next Steps
- Configure monitoring for production
- Set up CI/CD for automated deployments
- Review security best practices