Deployment
Deploy AI OS to production with PM2 + Nginx (recommended) or Docker. Includes VPS provisioning, TLS setup, and a production hardening checklist.
Option 1 — PM2 + Nginx (Recommended)
The recommended production deployment uses PM2 for process management and Nginx as a reverse proxy with TLS termination.
VPS Provisioning
Run the automated install script on a fresh Ubuntu 22.04+ VPS:
sudo bash deploy/install-vps.sh yourdomain.com
This script automatically:
- Configures UFW firewall (allows SSH, HTTP, HTTPS only)
- Installs Node.js 20 LTS via NodeSource
- Installs PM2 globally with startup configuration
- Installs Nginx and deploys the reverse proxy config
- Installs Certbot for Let's Encrypt TLS certificates
- Creates a dedicated
aiossystem user
Application Setup
cd /opt/ai-os
npm install --production
cp .env.example .env
nano .env # Configure all required variables
pm2 start ecosystem.config.js --env production
pm2 save
TLS Certificate
sudo certbot --nginx -d yourdomain.com
Certbot auto-renews certificates. Nginx is configured to redirect HTTP to HTTPS.
Option 2 — Docker
docker compose up -d
The Docker setup uses node:20-alpine with:
- Non-root user for security
- Health check endpoint monitoring
- Volume mounts for
.magent/andlogs/persistence - Port binding to
127.0.0.1:3000(Nginx fronts external traffic)
Note: Docker is optional. The PM2 + Nginx path is simpler and recommended for most deployments.
Nginx Configuration
The included deploy/nginx.conf provides:
- TLS termination — SSL certificates via Certbot
- WebSocket upgrade — Proper
UpgradeandConnectionheaders for WS - Static caching — 7 days for CSS/JS, 30 days for images and fonts
- Rate limiting — 10 req/s burst with nodelay
- Security headers — X-Frame-Options, X-Content-Type-Options, Referrer-Policy
- Sensitive path blocking — Returns 404 for
/.magent/,/.claude/,/.env
PM2 Configuration
The ecosystem.config.js configures:
- Auto-restart — Restarts on crash with exponential backoff
- Memory limit — 512 MB max, restarts if exceeded
- Log rotation — Timestamped logs with daily rotation
- Environment separation — Distinct configs for development and production
- Watch mode — Disabled in production, enabled in development
Production Hardening Checklist
| Item | Status |
|---|---|
| Helmet CSP headers | Built-in |
| CORS origin restriction | Via CORS_ORIGIN env var |
| Response compression (gzip) | Built-in |
| Request logging (morgan) | Built-in (file in prod, console in dev) |
| API rate limiting | 120/min general, 10/min heavy |
| Input validation | Built-in on all POST endpoints |
| Bearer token auth | Via API_TOKEN env var |
| Session cookie auth | HTTP-only, 30-day expiry |
| Stripe webhook signature verification | Built-in |
| Graceful shutdown (SIGTERM/SIGINT) | Built-in |
| Uncaught exception handler | Built-in |
| State auto-save with debounce | Built-in |
| WebSocket heartbeat (30s) | Built-in |
| robots.txt (blocks /api, /.magent, /.claude) | Built-in |
| HOST binding (127.0.0.1 in production) | Built-in |
Environment Variables
See the Quick Start guide for the full environment variable reference. In production, ensure all STRIPE_* variables use live keys (prefix sk_live_) and set NODE_ENV=production.