Voralis Documentation

Voralis Web — VPS Deployment (Ubuntu/Debian)

Complete production guide for deploying voralis-web on a VPS with Node.js 22, PM2, Nginx, Let's Encrypt SSL, swap space, and zero-downtime updates.

Server requirements

Check your VPS before installing:

free -h # RAM df -h # Disk space nproc # CPU cores node -v # Node.js (need 20.9+) npm -v
ResourceMinimumRecommended
RAM2 GB4 GB (8 GB for builds)
Disk20 GB40 GB+
CPU2 cores2+ cores
Node.js20.9+22 LTS
FFmpegRequiredFor video/audio features

Works on DigitalOcean, Hetzner, Linode, Contabo, AWS EC2, and similar Ubuntu/Debian VPS providers.

Install required software

sudo apt update && sudo apt upgrade -y curl -fsSL https://deb.nodesource.com/setup_22.x | sudo -E bash - sudo apt install -y nodejs node -v npm -v sudo npm install -g pm2 sudo apt install -y nginx ffmpeg certbot python3-certbot-nginx git

Add swap space (prevent OOM kills)

Next.js production builds are memory-intensive. Add swap on 2–4 GB RAM instances:

sudo fallocate -l 4G /swapfile sudo chmod 600 /swapfile sudo mkswap /swapfile sudo swapon /swapfile echo '/swapfile none swap sw 0 0' | sudo tee -a /etc/fstab free -h

Upload project to VPS

Option A — Git (recommended)

sudo mkdir -p /var/www/voralis-web sudo chown $USER:$USER /var/www/voralis-web cd /var/www/voralis-web git clone https://github.com/your-username/your-project.git .

Option B — rsync from local machine

rsync -avz --exclude node_modules --exclude .next \ ./ root@your-vps-ip:/var/www/voralis-web/

Configure environment variables

cd /var/www/voralis-web cp deploy/env.example .env.production nano .env.production ln -sf .env.production .env.local openssl rand -base64 32

Minimum production values:

NODE_ENV=production NEXT_PUBLIC_APP_URL=https://yourdomain.com NEXTAUTH_URL=https://yourdomain.com NEXTAUTH_SECRET=generate_with_openssl_rand_base64_32 JWT_SECRET=generate_with_openssl_rand_base64_32 ENCRYPTION_KEY=generate_with_openssl_rand_base64_32 NEON_DATABASE_URL=postgresql://user:pass@host:5432/dbname?sslmode=require DATABASE_URL=postgresql://user:pass@host:5432/dbname?sslmode=require NEXT_PUBLIC_BRAIN_SERVER_URL=https://your-brain-server.com GEMINI_API_KEY=your-gemini-key # Optional — background video worker REDIS_URL=redis://127.0.0.1:6379

See deploy/env.example in the project for the full variable list.

Database setup

  1. Create a PostgreSQL database (Neon recommended).
  2. Run Prisma migrations on the VPS:
cd /var/www/voralis-web npm run prisma:generate npm run prisma:migrate:deploy

On first visit, complete the in-app License Setup Wizard (domain → license → migrate → admin seed).

Install dependencies and build

cd /var/www/voralis-web npm ci npx prisma generate pm2 stop all 2>/dev/null || true NODE_OPTIONS="--max-old-space-size=3072" npm run build cp -r .next/static .next/standalone/.next/static cp -r public .next/standalone/public cp -r lib/generated .next/standalone/lib/generated 2>/dev/null || true

Or run bash deploy/install-vps.sh which performs the same steps.

Create logs folder and start with PM2

mkdir -p /var/www/voralis-web/logs node -e "require('./ecosystem.config.cjs')" && echo "Config OK" cd /var/www/voralis-web pm2 start ecosystem.config.cjs pm2 save pm2 startup

Run the command printed by pm2 startup to enable boot on reboot. App listens on port 3000 (process name: voralis-web).

Optional — video worker (requires Redis)

sudo apt install -y redis-server # Set REDIS_URL=redis://127.0.0.1:6379 in .env.production pm2 restart ecosystem.config.cjs

Verify the app is running

pm2 list pm2 logs voralis-web --lines 30 curl http://127.0.0.1:3000/api/health

Configure Nginx and SSL

Point DNS A records to your VPS IP, then:

sudo nano /etc/nginx/sites-available/voralis

HTTPS example (after Certbot or manual cert paths):

server { listen 80; server_name yourdomain.com www.yourdomain.com; return 301 https://$host$request_uri; } server { listen 443 ssl; server_name yourdomain.com www.yourdomain.com; ssl_certificate /etc/letsencrypt/live/yourdomain.com/fullchain.pem; ssl_certificate_key /etc/letsencrypt/live/yourdomain.com/privkey.pem; access_log /var/log/nginx/voralis.access.log; error_log /var/log/nginx/voralis.error.log; client_max_body_size 50M; location / { proxy_pass http://127.0.0.1:3000; 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; proxy_cache_bypass $http_upgrade; proxy_read_timeout 300s; } }
sudo ln -s /etc/nginx/sites-available/voralis /etc/nginx/sites-enabled/ sudo nginx -t sudo systemctl reload nginx sudo certbot --nginx -d yourdomain.com -d www.yourdomain.com

SSL auto-renewal

sudo certbot renew --dry-run sudo systemctl status certbot.timer

Deployment workflow (future updates)

cd /var/www/voralis-web git pull origin main npm ci pm2 stop voralis-web NODE_OPTIONS="--max-old-space-size=3072" npm run build cp -r .next/static .next/standalone/.next/static cp -r public .next/standalone/public cp -r lib/generated .next/standalone/lib/generated 2>/dev/null || true pm2 restart voralis-web pm2 logs voralis-web --lines 20

Useful PM2 commands

pm2 list pm2 logs voralis-web pm2 logs voralis-web --lines 50 pm2 restart voralis-web pm2 stop voralis-web pm2 delete voralis-web pm2 monit pm2 reload voralis-web

Quick troubleshooting

ProblemFix
Build SIGKILL / OOMAdd swap, pm2 stop all, NODE_OPTIONS=--max-old-space-size=3072
App not on port 3000pm2 list; restart with ecosystem.config.cjs
Nginx 502Check pm2 logs voralis-web
SSL cert failsVerify DNS A records point to VPS IP
.env not loadingConfirm .env.production exists and is linked to .env.local
Permission deniedsudo chown -R $USER:$USER /var/www/voralis-web
License wizard stuckVerify NEXT_PUBLIC_BRAIN_SERVER_URL and database URL