Skip to main content

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 BaaSEdgeBase (Self-Hosted)
DB AccessNetwork round-trip (ms)In-process SQLite (μs)
JS PerformanceNode.js (V8)workerd (V8) — same engine
Cold StartContainer boot (seconds)Always running (0ms)
WebSocketPer-connection memoryHibernation 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 EdgeDockerDirect
Commandnpx edgebase deploynpx edgebase docker runnpx edgebase dev
RequiresCloudflare accountDockerNode.js 20+
ProsGlobal edge, auto-scale, no server managementSingle container, data sovereigntySimplest, run on any VPS
ConsCloud account requiredDocker requiredProcess management needed for production
Cost~$5/moVPS only (~$5/mo)VPS only
Data LocationEdge data centersLocal serverLocal 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.

tip

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:

DataPathDescription
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
# 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.

Security: Reverse Proxy Required

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.

# 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-For to 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
warning

The Upgrade header configuration is required for WebSocket support.


4. Backups

EdgeBase provides two backup methods:

MethodUse CaseSpeed
Volume CopyRestore within the same environment (Docker→Docker, Direct→Direct)Fast
CLI Portable BackupCross-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
warning

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>
warning

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

ProblemSolution
Port conflictUse --port to specify a different port
Data lossVerify volume mount: -v edgebase-data:/data
WebSocket disconnectsCheck reverse proxy Upgrade header configuration
Container not auto-restartingVerify --restart unless-stopped flag
Out of memorySet memory limit with --memory 512m