# Production Installation
This guide covers deploying CloudPOS to a production server.
# Prerequisites
- ✅ Server with Ubuntu 22.04 LTS (or similar Linux distribution)
- ✅ Domain name configured
- ✅ SSL certificate (Let's Encrypt recommended)
- ✅ Node.js 18+ installed
- ✅ MySQL 8+ installed
- ✅ Nginx installed
- ✅ PM2 installed (
npm install -g pm2)
# Step 1: Server Preparation
# 1.1 Update System
sudo apt update
sudo apt upgrade -y
# 1.2 Install Required Software
# Install Node.js 18
curl -fsSL https://deb.nodesource.com/setup_18.x | sudo -E bash -
sudo apt-get install -y nodejs
# Install MySQL
sudo apt install mysql-server -y
sudo mysql_secure_installation
# Install Nginx
sudo apt install nginx -y
# Install PM2
sudo npm install -g pm2
# Install Git
sudo apt install git -y
# 1.3 Create Application User
# Create a non-root user for the application
sudo adduser cloudpos
sudo usermod -aG sudo cloudpos
# Switch to the new user
su - cloudpos
# Step 2: Deploy Application
# 2.1 Clone or Upload Project
# Option 1: Clone from Git
cd /var/www
sudo git clone <your-repo-url> cloudpos
sudo chown -R cloudpos:cloudpos cloudpos
cd cloudpos
# Option 2: Upload via SFTP/SCP
# Upload project files to /var/www/cloudpos
# 2.2 Install Dependencies
# Install root dependencies
npm install
# Install server dependencies
cd server
npm install --production
# Install client dependencies
cd ../client
npm install --production
# Step 3: Configure Environment
# 3.1 Create Production .env File
cd /var/www/cloudpos
nano .env
Add production environment variables (see Environment Configuration):
NODE_ENV=production
PORT=3000
# Database
DATABASE_URL="mysql://cloudpos:STRONG_PASSWORD@localhost:3306/cloudpos"
# JWT Secrets (generate strong random strings)
JWT_SECRET=your-super-secret-jwt-key-min-32-chars
JWT_EXPIRES_IN=15m
JWT_REFRESH_SECRET=your-super-secret-refresh-key-min-32-chars
JWT_REFRESH_EXPIRES_IN=7d
# CORS
CORS_ORIGIN=https://yourdomain.com
# Frontend URL
FRONTEND_URL=https://yourdomain.com
# Encryption Key (generate: openssl rand -base64 32)
ENCRYPTION_KEY=your-encryption-key-here
# SMTP (if using email)
SMTP_HOST=smtp.gmail.com
SMTP_PORT=587
SMTP_SECURE=false
SMTP_USER=your-email@gmail.com
SMTP_PASSWORD=your-app-password
SMTP_FROM_EMAIL=noreply@yourdomain.com
SMTP_FROM_NAME=CloudPOS
# Stripe (if using payments)
STRIPE_SECRET_KEY=sk_live_your_stripe_secret_key
STRIPE_WEBHOOK_SECRET=whsec_your_webhook_secret
# Demo Mode (set to false for production)
DEMO_MODE=false
# Client Configuration
VITE_API_URL=https://yourdomain.com/api
# 3.2 Secure .env File
# Set proper permissions
chmod 600 .env
chown cloudpos:cloudpos .env
# Step 4: Setup Database
# 4.1 Create Database and User
sudo mysql -u root -p
CREATE DATABASE cloudpos CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
CREATE USER 'cloudpos'@'localhost' IDENTIFIED BY 'STRONG_PASSWORD';
GRANT ALL PRIVILEGES ON cloudpos.* TO 'cloudpos'@'localhost';
FLUSH PRIVILEGES;
EXIT;
# 4.2 Run Migrations
cd /var/www/cloudpos/server
npm run prisma:generate
npm run prisma:migrate
# 4.3 Create Admin User
npm run prisma:seed:cms
# Or manually:
npx ts-node prisma/create-admin.ts
⚠️ Change default admin password immediately!
# Step 5: Build Application
# 5.1 Build Backend
cd /var/www/cloudpos/server
npm run build
# 5.2 Build Frontend
cd /var/www/cloudpos/client
npm run build
The built files will be in client/dist/.
# Step 6: Configure PM2
# 6.1 Create PM2 Ecosystem File
The project already includes ecosystem.config.js in the root. Update it if needed:
cd /var/www/cloudpos
nano ecosystem.config.js
# 6.2 Start Application with PM2
pm2 start ecosystem.config.js
pm2 save
pm2 startup
Follow the command output to enable PM2 on system boot.
# 6.3 Verify PM2 Status
pm2 status
pm2 logs cloudpos
# Step 7: Configure Nginx
# 7.1 Create Nginx Configuration
sudo nano /etc/nginx/sites-available/cloudpos
Add this configuration:
server {
listen 80;
server_name yourdomain.com www.yourdomain.com;
# Redirect HTTP to HTTPS
return 301 https://$server_name$request_uri;
}
server {
listen 443 ssl http2;
server_name yourdomain.com www.yourdomain.com;
# SSL Configuration
ssl_certificate /etc/letsencrypt/live/yourdomain.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/yourdomain.com/privkey.pem;
ssl_protocols TLSv1.2 TLSv1.3;
ssl_ciphers HIGH:!aNULL:!MD5;
# Security Headers
add_header X-Frame-Options "SAMEORIGIN" always;
add_header X-Content-Type-Options "nosniff" always;
add_header X-XSS-Protection "1; mode=block" always;
# Client max body size (for file uploads)
client_max_body_size 10M;
# Proxy to API server
location /api {
proxy_pass http://localhost: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;
}
# Serve static files (uploads)
location /uploads {
alias /var/www/cloudpos/server/uploads;
expires 30d;
add_header Cache-Control "public, immutable";
}
# Serve frontend (React app)
location / {
root /var/www/cloudpos/client/dist;
try_files $uri $uri/ /index.html;
expires -1;
add_header Cache-Control "no-cache, no-store, must-revalidate";
}
# Cache static assets
location ~* \.(js|css|png|jpg|jpeg|gif|ico|svg|woff|woff2|ttf|eot)$ {
root /var/www/cloudpos/client/dist;
expires 1y;
add_header Cache-Control "public, immutable";
}
}
# 7.2 Enable Site
sudo ln -s /etc/nginx/sites-available/cloudpos /etc/nginx/sites-enabled/
sudo nginx -t
sudo systemctl reload nginx
# Step 8: Setup SSL Certificate
# 8.1 Install Certbot
sudo apt install certbot python3-certbot-nginx -y
# 8.2 Obtain SSL Certificate
sudo certbot --nginx -d yourdomain.com -d www.yourdomain.com
Follow the prompts. Certbot will automatically configure Nginx.
# 8.3 Auto-Renewal
Certbot sets up auto-renewal automatically. Test it:
sudo certbot renew --dry-run
# Step 9: Configure Firewall
# Allow SSH
sudo ufw allow 22/tcp
# Allow HTTP and HTTPS
sudo ufw allow 80/tcp
sudo ufw allow 443/tcp
# Enable firewall
sudo ufw enable
sudo ufw status
# Step 10: File Permissions
# Set ownership
sudo chown -R cloudpos:cloudpos /var/www/cloudpos
# Set directory permissions
find /var/www/cloudpos -type d -exec chmod 755 {} \;
# Set file permissions
find /var/www/cloudpos -type f -exec chmod 644 {} \;
# Make uploads directory writable
chmod -R 775 /var/www/cloudpos/server/uploads
# Step 11: Verify Installation
# 11.1 Check Services
# Check PM2
pm2 status
# Check Nginx
sudo systemctl status nginx
# Check MySQL
sudo systemctl status mysql
# 11.2 Test URLs
- Frontend:
https://yourdomain.com - API:
https://yourdomain.com/api - Admin:
https://yourdomain.com/admin/login
# 11.3 Check Logs
# PM2 logs
pm2 logs cloudpos
# Nginx logs
sudo tail -f /var/log/nginx/error.log
sudo tail -f /var/log/nginx/access.log
# Application logs
tail -f /var/www/cloudpos/logs/pm2-out.log
tail -f /var/www/cloudpos/logs/pm2-error.log
# Step 12: Post-Installation
- ✅ Change default admin password
- ✅ Configure payment gateway (see Payment Gateway)
- ✅ Configure email (see Email Notifications)
- ✅ Review security settings (see Security & Demo Mode)
- ✅ Run production checklist (see Production Checklist)
# Maintenance Commands
# Update Application
cd /var/www/cloudpos
git pull # If using Git
npm install
cd server && npm install && npm run build
cd ../client && npm install && npm run build
pm2 restart cloudpos
# Database Backup
# Create backup
mysqldump -u cloudpos -p cloudpos > backup_$(date +%Y%m%d).sql
# Restore backup
mysql -u cloudpos -p cloudpos < backup_20240101.sql
# View Logs
# PM2 logs
pm2 logs cloudpos --lines 100
# Nginx logs
sudo tail -f /var/log/nginx/error.log
# Troubleshooting
# Application Not Starting
# Check PM2 status
pm2 status
# Check logs
pm2 logs cloudpos --err
# Restart application
pm2 restart cloudpos
# 502 Bad Gateway
- Check if API server is running:
pm2 status - Check API server logs:
pm2 logs cloudpos - Verify Nginx proxy configuration
# SSL Certificate Issues
# Renew certificate manually
sudo certbot renew
# Check certificate status
sudo certbot certificates
Next Steps: See Production Checklist for pre-launch verification.