Skip to main content

Control Center Setup

Step-by-step guide for installing and deploying the UniPulse Control Center on a VPS.


Prerequisites

RequirementVersionPurpose
Node.js>= 20Runtime
PM2LatestProcess manager (npm install -g pm2)
NginxLatestReverse proxy with SSL
GitLatestSource control

Installation

1. Clone and Setup

cd UniPulse-Control-Center
./setup.sh

The setup.sh script performs:

StepAction
1Install npm dependencies
2Build frontend (Vite) and backend (TypeScript)
3Initialize SQLite database
4Run Prisma migrations (creates 7 tables)
5Configure PM2 process

2. Configure Environment

cp apps/server/.env.example apps/server/.env

Edit the .env file:

VariableRequiredDescriptionExample
JWT_SECRETYesJWT signing secret (min 32 chars)your-cc-jwt-secret-min-32-chars
JWT_REFRESH_SECRETYesRefresh token secretyour-cc-refresh-secret
GOOGLE_CLIENT_IDYesGoogle OAuth client ID123456.apps.googleusercontent.com
GOOGLE_CLIENT_SECRETYesGoogle OAuth client secretGOCSPX-xxxxx
GITHUB_TOKENFor CI/CDGitHub personal access token (repo scope)ghp_xxxxxxxxxxxx
ALLOWED_EMAILSYesComma-separated whitelist of authorized emailsadmin@example.com,dev@example.com
PORTNoServer port (default: 3001)3001
DATABASE_URLNoSQLite path (default: file:./dev.db)file:./prod.db
ALLOWED_EMAILS

This is a critical security control. Only listed emails can access the Control Center. Make sure this is set correctly before starting the application.

3. Start with PM2

pm2 start ecosystem.config.js

PM2 Configuration:

// ecosystem.config.js
module.exports = {
apps: [{
name: 'control-center',
script: './apps/server/dist/index.js',
max_memory_restart: '500M', // Restart if memory exceeds 500MB
max_restarts: 10, // Max restart attempts
log_type: 'json', // Structured JSON logging
env: {
NODE_ENV: 'production',
PORT: 3001,
},
}],
};

4. Configure Nginx

# Copy the Nginx config
cp nginx/control-center.conf /etc/nginx/sites-available/control-center
ln -s /etc/nginx/sites-available/control-center /etc/nginx/sites-enabled/

# Test configuration
nginx -t

# Reload Nginx
systemctl reload nginx

The Nginx config provides:

FeatureConfiguration
SSLLet's Encrypt certificates
Rate limiting (auth)5 requests/second
Rate limiting (API)30 requests/second
WebSocket proxySocket.IO /socket.io/ path
Security headersX-Frame-Options, CSP, HSTS
.env blockingDeny access to .env files

5. Generate SSL Certificate

certbot certonly --webroot -w /var/www/certbot -d ops.unipulse.tech

PM2 Management Commands

# View running processes
pm2 list

# View logs (real-time)
pm2 logs control-center

# View last 100 log lines
pm2 logs control-center --lines 100

# Restart
pm2 restart control-center

# Stop
pm2 stop control-center

# Monitor (interactive dashboard)
pm2 monit

# Save process list for auto-start on reboot
pm2 save
pm2 startup

Deployment (Updates)

cd UniPulse-Control-Center
./deploy.sh

deploy.sh performs:

StepCommand
1git pull origin main
2npm install
3npm run build
4npx prisma migrate deploy (if schema changed)
5pm2 restart ecosystem.config.js

Verification

After setup or deployment, verify everything is working:

CheckCommand / URLExpected
PM2 processpm2 listcontrol-center status "online"
API healthcurl http://localhost:3001/api/health200 OK
Nginx proxycurl https://ops.unipulse.techFrontend loads
WebSocketBrowser console -- no WS errorsSocket connects
Docker accessDocker Manager pageContainers listed
VPS metricsVPS Monitor pageLive charts updating
GitHubPR Tracking pagePRs listed (if GITHUB_TOKEN set)
LoginLogin pageGoogle OAuth works

Troubleshooting

IssueSolution
PM2 process keeps restartingCheck logs: pm2 logs control-center
WebSocket connection failedVerify Nginx WebSocket proxy config
Google OAuth redirect errorCheck GOOGLE_CLIENT_ID and callback URL
Docker containers not listedEnsure the PM2 process user has Docker socket access
SQLite lock errorsOnly one instance should run at a time
502 Bad GatewayPM2 process not running or wrong port

Cross-Reference