Self-Hosting APIFold
APIFold is designed to be self-hosted on any server that supports Docker and Docker Compose. This guide will walk you through setting up the platform on your own infrastructure.
Prerequisites
Before you begin, ensure your server meets the following requirements:
- Docker: v24.0 or newer
- Docker Compose: v2.0 or newer
- Resources: Minimum 2 vCPU, 4GB RAM recommended
- Domain Name: Optional, but recommended for production (required for SSL)
Quick Start
Get APIFold running in minutes with these commands:
Your instance will be available at http://localhost:3000 (or your domain).
Configuration Reference
APIFold is configured via environment variables.
| Variable | Description | Default | Required |
|---|---|---|---|
DATABASE_URL | PostgreSQL connection string | - | Yes |
DATABASE_POOL_MAX | Max database connections | 20 | No |
POSTGRES_DB | Database name | apifold | No |
POSTGRES_USER | Database user | mt | No |
POSTGRES_PASSWORD | Database password | - | Yes |
REDIS_PASSWORD | Redis password | - | Yes |
REDIS_URL | Redis connection string | - | Yes |
VAULT_SECRET | Encryption key (32+ chars) | - | Yes |
VAULT_SALT | Encryption salt (32+ chars) | - | Yes |
MCP_RUNTIME_SECRET | Internal service auth secret | - | Yes |
NODE_ENV | Environment mode | development | No |
PORT | Web app port | 3000 | No |
RUNTIME_PORT | Runtime server port | 3001 | No |
MAX_SSE_SESSIONS | Max concurrent SSE connections | 10000 | No |
SSE_HEARTBEAT_INTERVAL_MS | Keep-alive ping interval | 30000 | No |
SSE_IDLE_TIMEOUT_MS | Disconnect idle clients after | 300000 | No |
CIRCUIT_BREAKER_THRESHOLD | Failures before opening circuit | 5 | No |
CIRCUIT_BREAKER_COOLDOWN_MS | Time before retrying upstream | 30000 | No |
UPSTREAM_TIMEOUT_MS | Max time for upstream response | 30000 | No |
CREDENTIAL_TTL_MS | Cache duration for credentials | 300000 | No |
FALLBACK_POLL_INTERVAL_MS | Database polling frequency | 30000 | No |
CORS_ORIGINS | Allowed CORS origins (comma-separated) | * | Yes (Prod) |
GLOBAL_RATE_LIMIT_WINDOW_MS | Rate limit window | 900000 | No |
GLOBAL_RATE_LIMIT_MAX | Max requests per window | 1000 | No |
DRAIN_TIMEOUT_MS | Graceful shutdown timeout | 30000 | No |
LOG_LEVEL | Logging verbosity | info | No |
TLS Setup
For production deployments, secure your instance with SSL/TLS using Certbot.
- Install Certbot on your host machine
- Generate certificates for your domain
- Mount the certificates into the nginx container:
- Update
infra/nginx/nginx.confwith your domain name in thessl_certificateandssl_certificate_keypaths.
Auto-Deploy
Keep your instance up-to-date automatically using Watchtower. Add this service to your docker-compose.yml:
Security note: Mounting
/var/run/docker.sockgrants the Watchtower container root-equivalent access to the host. Only use this in trusted environments. Consider restricting Watchtower to specific containers using--scopelabels, or use a CI/CD pipeline for production deployments instead.
Monitoring
APIFold exposes several endpoints for monitoring health and performance:
- Health Check:
GET /api/health(web) /GET /health(runtime) — Returns 200 OK - Liveness Probe:
GET /health/live - Readiness Probe:
GET /health/ready
Nginx access logs are output in JSON format for easy ingestion by logging systems like ELK, Datadog, or CloudWatch.
Backup & Restore
Regular backups are crucial. Use standard PostgreSQL tools to back up your data:
Ensure you also back up your .env file containing encryption keys. Without the VAULT_SECRET and VAULT_SALT, your encrypted credentials cannot be recovered.
Upgrading
To upgrade to the latest version of APIFold:
-
Pull the latest images:
-
Restart the containers:
Database migrations run automatically on startup.
Troubleshooting
Common issues and solutions:
| Issue | Possible Cause | Solution |
|---|---|---|
| Container won't start | Database not ready | Check docker logs for connection errors. Ensure Postgres is healthy. |
| Redis connection refused | Wrong host/password | Verify REDIS_URL matches the service name in Docker Compose (e.g., redis://:password@redis:6379). |
| SSE disconnects | Nginx timeout | Increase proxy_read_timeout in nginx config to match SSE_IDLE_TIMEOUT_MS. |
| 502 Bad Gateway | Runtime/Web down | Check container status with docker ps. View logs for crashes. |
| Encryption errors | Missing vault keys | Ensure VAULT_SECRET and VAULT_SALT are set and at least 32 characters. |