What is Convex?
Convex is a reactive backend-as-a-service platform that combines a real-time database with serverless functions, providing automatic data synchronization across clients.
Key Features
- • Real-time data synchronization
- • TypeScript-native with full type safety
- • Serverless functions in TS/JS
- • Built-in file storage
- • Vector search capabilities
- • Scheduled functions
Integrations
- • First-class React hooks
- • Next.js support
- • Vue, Svelte, and more
- • Authentication providers
- • Component ecosystem
- • Full dashboard & CLI
Why Self-Host Convex?
Self-hosting Convex on RamNode offers several advantages over the cloud-hosted service:
💰 Cost Control
Small to medium applications can run on minimal resources (2-4GB RAM VPS), making it more cost-effective than per-usage cloud pricing.
🔒 Data Sovereignty
Keep sensitive data on your own infrastructure with complete control over data location and access policies.
⚙️ Custom Configuration
Fine-tune database settings, storage backends, and resource allocation to match your requirements.
🚀 Development Flexibility
Run local development environments without internet connectivity, with faster iteration cycles.
Prerequisites
Before starting, ensure you have:
RamNode VPS Requirements
- • Ubuntu 20.04 LTS or newer (22.04/24.04 recommended)
- • Minimum 2GB RAM (4GB recommended for production)
- • 20GB disk space minimum
- • Root or sudo access
Software Requirements
- • Docker and Docker Compose
- • Node.js v18 or newer
- • Basic command line familiarity
Production (Optional)
- • Domain name with DNS configured
- • SSL certificate (Let's Encrypt)
- • PostgreSQL database
Architecture Overview
A self-hosted Convex deployment consists of three main components:
Convex Backend (Port 3210)
The core database and compute engine that runs your serverless functions, manages data, and handles real-time synchronization.
Convex Dashboard (Port 6791)
Web-based interface for inspecting data, viewing logs, running functions, and managing your deployment.
Your Frontend Application
The client-facing application (React, Next.js, Vue, etc.) that connects to the Convex backend. Can be hosted anywhere.
Quick Start: SQLite Deployment
The SQLite deployment is ideal for development, testing, and small applications. All data is stored locally in a Docker volume.
Step 1: Prepare Your Environment
mkdir -p ~/convex-deployment
cd ~/convex-deploymentStep 2: Download Docker Compose Configuration
curl -o docker-compose.yml https://raw.githubusercontent.com/get-convex/convex-backend/main/self-hosted/docker/docker-compose.ymlStep 3: Generate Admin Key
docker compose run --rm backend ./generate_admin_key.sh⚠️ Important: Save your admin key securely! You'll need it for all administrative operations. Example output:
Admin key: 0135d8598650f8f5cb0f30c34ec2e2bb62793bc28717c8eb6fb577996d50be5f4281b59181095065c5d0f86a2c31ddbe9b597ec62Step 4: Start Convex Services
docker compose up -ddocker compose psStep 5: Access Your Deployment
✅ Dashboard: http://YOUR_VPS_IP:6791
✅ Backend API: http://YOUR_VPS_IP:3210
Step 6: Configure Your Local Development
In your local Convex project, create or update .env.local:
CONVEX_SELF_HOSTED_URL=http://YOUR_VPS_IP:3210
CONVEX_SELF_HOSTED_ADMIN_KEY=your_admin_key_hereStep 7: Deploy Your Functions
npx convex devProduction: PostgreSQL Setup
For production workloads, use PostgreSQL for better performance, reliability, and scalability.
Create Production Docker Compose
version: '3.8'
services:
backend:
image: ghcr.io/get-convex/convex-backend:latest
restart: unless-stopped
volumes:
- convex-data:/root/.convex
- ./local_storage:/var/convex/local_storage
ports:
- "3210:3210"
- "3211:3211"
environment:
- POSTGRES_URL=postgresql://convex_user:your_secure_password@172.17.0.1:5432/convex_self_hosted
- CONVEX_ORIGIN=https://your-domain.com
healthcheck:
test: ["CMD", "curl", "-f", "http://localhost:3210/api/health"]
interval: 30s
timeout: 10s
retries: 3
logging:
driver: "json-file"
options:
max-size: "10m"
max-file: "3"
dashboard:
image: ghcr.io/get-convex/convex-dashboard:latest
restart: unless-stopped
ports:
- "6791:6791"
environment:
- NEXT_PUBLIC_DEPLOYMENT_URL=https://your-domain.com
- NEXT_PUBLIC_LOAD_MONACO_INTERNALLY=true
depends_on:
backend:
condition: service_healthy
logging:
driver: "json-file"
options:
max-size: "10m"
max-file: "3"
volumes:
convex-data:Deploy Production Stack
docker compose -f docker-compose.prod.yml up -dConfiguration Options
Environment Variables
| Variable | Description | Required |
|---|---|---|
| POSTGRES_URL | PostgreSQL connection string | No (SQLite default) |
| CONVEX_ORIGIN | Public URL for deployment | Production |
| INSTANCE_NAME | Unique identifier for instance | No |
| PORT | Backend API port (default: 3210) | No |
S3-Compatible Storage
For production file storage, configure S3:
environment:
- AWS_ACCESS_KEY_ID=your_access_key
- AWS_SECRET_ACCESS_KEY=your_secret_key
- AWS_REGION=us-east-1
- CONVEX_FILES_STORAGE=s3://your-bucket-name/convex-files/
- CONVEX_SNAPSHOT_STORAGE=s3://your-bucket-name/convex-snapshots/
- CONVEX_SEARCH_STORAGE=s3://your-bucket-name/convex-search/Resource Limits
services:
backend:
deploy:
resources:
limits:
cpus: '2.0'
memory: 4G
reservations:
cpus: '1.0'
memory: 2GSecurity Hardening
1. Firewall Configuration
# Enable UFW
sudo ufw enable
# Allow SSH
sudo ufw allow 22/tcp
# Allow HTTP/HTTPS (for reverse proxy)
sudo ufw allow 80/tcp
sudo ufw allow 443/tcp
# Block direct access to Convex ports (use reverse proxy)
sudo ufw deny 3210/tcp
sudo ufw deny 3211/tcp
sudo ufw deny 6791/tcp
# Check status
sudo ufw status2. Nginx Reverse Proxy
sudo apt install nginx certbot python3-certbot-nginx -y# Backend API
server {
listen 80;
server_name api.your-domain.com;
location / {
proxy_pass http://127.0.0.1:3210;
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;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
# WebSocket support
proxy_read_timeout 86400;
proxy_buffering off;
}
}
# Dashboard
server {
listen 80;
server_name dashboard.your-domain.com;
location / {
proxy_pass http://127.0.0.1:6791;
proxy_http_version 1.1;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}
}sudo ln -s /etc/nginx/sites-available/convex /etc/nginx/sites-enabled/
sudo nginx -t
sudo systemctl reload nginx
sudo certbot --nginx -d api.your-domain.com -d dashboard.your-domain.com3. Admin Key Best Practices
- • Generate a strong, unique admin key
- • Store admin keys in a password manager
- • Rotate keys periodically (every 90 days)
- • Never commit keys to version control
- • Use different keys for dev and production
Connecting Frontend Applications
React/Next.js Setup
npm install convex# Development (connecting to self-hosted backend)
CONVEX_SELF_HOSTED_URL=https://api.your-domain.com
CONVEX_SELF_HOSTED_ADMIN_KEY=your_admin_key_here
# Production frontend
NEXT_PUBLIC_CONVEX_URL=https://api.your-domain.comDeploy Frontend to Vercel
vercel env add NEXT_PUBLIC_CONVEX_URL production
# Enter: https://api.your-domain.com
vercel --prodDeploy Frontend to Netlify
[build.environment]
NEXT_PUBLIC_CONVEX_URL = "https://api.your-domain.com"Monitoring and Maintenance
Health Checks
curl -f http://YOUR_VPS_IP:3210/api/health{"status": "ok"}View Logs
# Backend logs
docker compose logs -f backend
# Dashboard logs
docker compose logs -f dashboard
# All logs
docker compose logs -fResource Monitoring
# Docker container stats
docker stats
# Install htop for system monitoring
sudo apt install htop -y
htop
# Check disk usage
df -h
# Check memory
free -hPrometheus Integration
global:
scrape_interval: 15s
scrape_configs:
- job_name: 'convex'
static_configs:
- targets: ['YOUR_VPS_IP:3210']Backup and Recovery
PostgreSQL Backups
#!/bin/bash
BACKUP_DIR="/backups/convex"
TIMESTAMP=$(date +%Y%m%d_%H%M%S)
DB_NAME="convex_self_hosted"
DB_USER="convex_user"
mkdir -p $BACKUP_DIR
# Create backup
PGPASSWORD="your_password" pg_dump -h 172.17.0.1 -U $DB_USER $DB_NAME | \
gzip > "$BACKUP_DIR/convex_$TIMESTAMP.sql.gz"
# Keep only last 7 days of backups
find $BACKUP_DIR -name "convex_*.sql.gz" -mtime +7 -delete
echo "Backup completed: convex_$TIMESTAMP.sql.gz"chmod +x backup-convex.sh
crontab -e
# Add daily backup at 2 AM
0 2 * * * /path/to/backup-convex.shConvex Export/Import
# Export data
npx convex export --path ./backup.zip
# Import data
npx convex import --path ./backup.zipDisaster Recovery
# 1. Restore PostgreSQL database
PGPASSWORD="your_password" gunzip < convex_backup.sql.gz | \
psql -h 172.17.0.1 -U convex_user convex_self_hosted
# 2. Restart services
docker compose down
docker compose up -d
# 3. Verify recovery
curl -f http://localhost:3210/api/healthTroubleshooting
Deployment Complete!
You now have a fully functional self-hosted Convex deployment on your RamNode VPS with real-time data synchronization, serverless functions, and complete control over your infrastructure.
