Self-Hosting Guide
Self-host EdgeBase using Docker containers or direct Node.js execution.
Why Self-Hosting is Still Fast
EdgeBase runs on workerd, an open-source JavaScript runtime built on the V8 engine. The exact same code that runs on the cloud edge also runs in Docker/Node.js.
| Traditional BaaS | EdgeBase (Self-Hosted) | |
|---|---|---|
| DB Access | Network round-trip (ms) | In-process SQLite (μs) |
| JS Performance | Node.js (V8) | workerd (V8) — same engine |
| Cold Start | Container boot (seconds) | Always running (0ms) |
| WebSocket | Per-connection memory | Hibernation API — $0 idle memory |
SQLite runs in the same thread as the application, so single-query latency is significantly lower than BaaS platforms using network databases. Self-hosting doesn't come with a performance penalty — it can even be faster due to zero network hops.
Deployment Methods
| Cloud Edge | Docker | Direct | |
|---|---|---|---|
| Command | npx edgebase deploy | npx edgebase docker run | npx edgebase dev |
| Requires | Cloudflare account | Docker | Node.js 20+ |
| Pros | Global edge, auto-scale, no server management | Single container, data sovereignty | Simplest, run on any VPS |
| Cons | Cloud account required | Docker required | Process management needed for production |
| Cost | ~$5/mo | VPS only (~$5/mo) | VPS only |
| Data Location | Edge data centers | Local server | Local server |
1. Running with Docker
Quick Start
# Build image
npx edgebase docker build
# Run container (background)
npx edgebase docker run -d
# Or use docker directly
docker build -t edgebase .
docker run -d -p 8787:8787 -v edgebase-data:/data --name edgebase edgebase
Docker Compose
# Start
docker compose up -d
# View logs
docker compose logs -f
# Stop
docker compose down
Environment Variables
Workers Secrets are mapped to environment variables in Docker:
# docker-compose.yml
services:
edgebase:
environment:
- JWT_USER_SECRET=your-secure-jwt-secret
- SERVICE_KEY=your-service-key
- JWT_ADMIN_SECRET=your-admin-jwt-secret
Or use an .env.release file (recommended — same file used by npx edgebase deploy):
# .env.release
JWT_USER_SECRET=your-secure-jwt-secret
SERVICE_KEY=your-service-key
JWT_ADMIN_SECRET=your-admin-jwt-secret
docker run --env-file .env.release -p 8787:8787 -v edgebase-data:/data edgebase
That SERVICE_KEY is the same credential consumed by all Admin SDKs.
For local Docker development, use .env.development instead:
docker run --env-file .env.development -p 8787:8787 -v edgebase-data:/data edgebase
Data Persistence
All data is stored in the /data volume:
| Data | Path | Description |
|---|---|---|
| DO SQLite | /data/v3/do/ | Database DO state (isolated namespaces, Room/Realtime support data) |
D1 Auth (AUTH_DB) | /data/v3/d1/ | Auth control plane (users, sessions, OAuth, MFA, admin data) |
D1 Control (CONTROL_DB) | /data/v3/d1/ | Internal operational metadata (plugin versions, cleanup/backup metadata) |
| R2 Files | /data/v3/r2/ | Uploaded files |
| KV Data | /data/v3/kv/ | OAuth state, membership cache |
AUTH_DB and CONTROL_DB are separate internal D1 databases that share the same persisted base directory. Keeping plugin/control-plane metadata in CONTROL_DB avoids mixing operational state into the auth hot path.
2. Direct workerd Execution
Run directly through the EdgeBase CLI (which starts wrangler dev) on a machine with Node.js:
# Clone or initialize a EdgeBase project
npx edgebase init my-project
cd my-project
# Start the local workerd runtime
npx edgebase dev --port 8787
# Or use wrangler directly
npx wrangler dev --port 8787 --persist-to ./data
Process Management (PM2 Recommended)
# Install PM2
npm install -g pm2
# Start EdgeBase
pm2 start "npx edgebase dev --port 8787" --name edgebase
# Configure auto-restart
pm2 startup
pm2 save
3. HTTPS Reverse Proxy
HTTPS is required for production. Use Caddy or Nginx as a reverse proxy.
EdgeBase uses the client IP address for rate limiting and brute-force protection. In self-hosted environments (Docker / Direct), the client IP is read from the X-Forwarded-For header set by your reverse proxy.
If EdgeBase is exposed directly to the internet without a reverse proxy, attackers can forge the X-Forwarded-For header to spoof any IP address, completely bypassing rate limits. Always place EdgeBase behind Nginx or Caddy in production.
On Cloudflare Edge deployments, the tamper-proof CF-Connecting-IP header is used instead, so this does not apply.
Caddy (Recommended — Auto HTTPS)
# Install Caddy
sudo apt install -y caddy
Caddyfile configuration:
your-domain.com {
reverse_proxy localhost:8787 {
# Caddy sets X-Forwarded-For to the real client IP by default.
# trusted_proxies ensures only legitimate proxy-set headers are accepted.
header_up X-Forwarded-For {remote_host}
}
}
sudo systemctl reload caddy
Caddy automatically configures Let's Encrypt. No manual SSL certificate management needed. It also sets
X-Forwarded-Forto the real client IP by default, which EdgeBase uses for rate limiting.
Nginx + Let's Encrypt
# Install Nginx + Certbot
sudo apt install -y nginx certbot python3-certbot-nginx
Nginx configuration (/etc/nginx/sites-available/edgebase):
server {
server_name your-domain.com;
location / {
proxy_pass http://localhost:8787;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
# IMPORTANT: Use $remote_addr (not $proxy_add_x_forwarded_for) to prevent
# clients from injecting fake IPs. This overwrites any client-sent header.
proxy_set_header X-Forwarded-For $remote_addr;
proxy_set_header X-Forwarded-Proto $scheme;
}
}
# Enable site + SSL
sudo ln -s /etc/nginx/sites-available/edgebase /etc/nginx/sites-enabled/
sudo certbot --nginx -d your-domain.com
sudo systemctl reload nginx
The Upgrade header configuration is required for WebSocket support.
4. Backups
EdgeBase provides two backup methods:
| Method | Use Case | Speed |
|---|---|---|
| Volume Copy | Restore within the same environment (Docker→Docker, Direct→Direct) | Fast |
| CLI Portable Backup | Cross-environment migration (Edge↔Docker↔Direct) | Moderate |
4.1 Volume Backup (Same Environment)
The fastest method — directly copy Docker volumes or the .wrangler/state/ directory.
Docker Volume Backup
# Backup volume (tar archive)
docker run --rm -v edgebase-data:/data -v $(pwd):/backup \
alpine tar czf /backup/edgebase-backup-$(date +%Y%m%d).tar.gz /data
# Restore volume
docker run --rm -v edgebase-data:/data -v $(pwd):/backup \
alpine tar xzf /backup/edgebase-backup-20260213.tar.gz -C /
Direct Execution Backup
# Backup the .wrangler/state/ directory
tar czf edgebase-backup-$(date +%Y%m%d).tar.gz .wrangler/state/
# Restore
tar xzf edgebase-backup-20260213.tar.gz
Volume copies only work within the same environment (Docker→Docker, Direct→Direct). For cross-environment migration (e.g., Docker→Edge), use the CLI portable backup below.
4.2 CLI Portable Backup (Cross-Environment)
# DB only (default, fast)
npx edgebase backup create --url <URL> --service-key <KEY>
# DB + secrets (for environment migration — preserves existing JWTs)
npx edgebase backup create --include-secrets
# DB + R2 files (large, slow)
npx edgebase backup create --include-storage
# Full backup (complete migration)
npx edgebase backup create --include-secrets --include-storage
# Backup from Edge environment (enumerates DOs via CF API)
npx edgebase backup create --account-id <CF_ACCOUNT_ID> --api-token <CF_API_TOKEN>
Restore:
# Restore (Wipe & Restore — replaces all existing data)
npx edgebase backup restore --from backup.json --url <target-URL> --service-key <KEY>
# Restore to Edge target
npx edgebase backup restore --from backup.json --account-id <ID> --api-token <TOKEN>
When using --include-secrets, the backup file contains sensitive information. File permissions are automatically set to 600.
4.3 Automated Backup (Cron)
# Daily backup at 3 AM (Docker Volume)
echo "0 3 * * * docker run --rm -v edgebase-data:/data -v /backups:/backup alpine tar czf /backup/edgebase-\$(date +\\%Y\\%m\\%d).tar.gz /data" | crontab -
5. Monitoring
Health Check
curl http://localhost:8787/api/health
# → {"status":"ok","version":"0.1.0"}
Docker Logs
# Real-time logs
docker logs -f edgebase
# Last 100 lines
docker logs --tail 100 edgebase
Admin Dashboard
The Admin Dashboard is built into self-hosted deployments:
http://your-domain.com/admin
An admin account setup screen is displayed on first access.
If you lose an admin password later, recover it with npx edgebase admin reset-password using a configured root Service Key. Admin recovery is CLI-based rather than email-based.
6. Troubleshooting
| Problem | Solution |
|---|---|
| Port conflict | Use --port to specify a different port |
| Data loss | Verify volume mount: -v edgebase-data:/data |
| WebSocket disconnects | Check reverse proxy Upgrade header configuration |
| Container not auto-restarting | Verify --restart unless-stopped flag |
| Out of memory | Set memory limit with --memory 512m |