Deployment Guide
Table of Contents
- Overview
- Prerequisites
- Environment Configuration
- Deployment Methods
- Production Considerations
- Monitoring and Maintenance
- Troubleshooting
Overview
This guide provides comprehensive instructions for deploying BAASIX in various environments, from development to production. BAASIX is designed to be flexible and can be deployed using multiple methods.
Prerequisites
System Requirements
- Node.js: Version 16+ (recommended: 18.x LTS)
- PostgreSQL: Version 11+ (with PostGIS extension for geospatial features)
- Redis: Version 6+ (for caching and Socket.IO scaling)
- Memory: Minimum 512MB RAM (recommended: 2GB+ for production)
- Storage: Minimum 1GB available disk space
Optional Dependencies
- Docker: Version 20+ (for containerized deployment)
- PM2: For process management in production
- Nginx: For reverse proxy and load balancing
Environment Configuration
Core Environment Variables
Create a .env file in the API root directory:
# Application
NODE_ENV=production
PORT=3000
SECRET_KEY=your-super-secret-jwt-key-min-32-chars
COOKIE_SECRET=your-cookie-secret-key
# Database Configuration
DB_CLIENT=postgres
DB_HOST=localhost
DB_PORT=5432
DB_NAME=baasix_production
DB_USER=baasix_user
DB_PASSWORD=secure_database_password
DB_SSL=false
DB_POOL_MIN=2
DB_POOL_MAX=10
# Redis Cache Configuration
CACHE_REDIS_URL=redis://localhost:6379
CACHE_TTL=30000
CACHE_ENABLED=true
# Authentication & Security
AUTH_CORS_ALLOWED_ORIGINS=https://yourdomain.com,https://app.yourdomain.com
AUTH_CORS_ALLOW_ANY_PORT=false
AUTH_CORS_CREDENTIALS=true
SESSION_TIMEOUT=3600
COOKIE_SECURE=true
COOKIE_SAME_SITE=strict
# Rate Limiting
RATE_LIMIT=100
RATE_LIMIT_INTERVAL=5000
# Multi-tenant Configuration
MULTI_TENANT=false
TENANT_FIELD=tenant_id
# Socket.IO Configuration
SOCKET_ENABLED=true
SOCKET_PATH=/socket.io
SOCKET_CORS_ENABLED_ORIGINS=https://yourdomain.com
# File Storage Configuration
STORAGE_DEFAULT_SERVICE=local
LOCAL_STORAGE_PATH=/var/www/baasix/uploads
MAX_FILE_SIZE=52428800 # 50MB
# Email Configuration
SMTP_HOST=smtp.your-provider.com
SMTP_PORT=587
SMTP_SECURE=false
SMTP_USER=your-email@yourdomain.com
SMTP_PASSWORD=your-email-password
FROM_EMAIL=noreply@yourdomain.com
FROM_NAME=Your App Name
# Logging
DEBUGGING=false
LOG_LEVEL=info
# Features
PUBLIC_REGISTRATION=trueAWS S3 Storage Configuration
# S3 Storage (if using AWS S3)
STORAGE_DEFAULT_SERVICE=s3
S3_STORAGE_ACCESS_KEY_ID=your-access-key-id
S3_STORAGE_SECRET_ACCESS_KEY=your-secret-access-key
S3_STORAGE_REGION=us-east-1
S3_STORAGE_BUCKET=your-bucket-name
S3_STORAGE_ENDPOINT=https://s3.amazonaws.comProduction Environment Variables
# Production-specific settings
NODE_ENV=production
DEBUGGING=false
COOKIE_SECURE=true
DB_SSL=true
CACHE_TTL=300000 # 5 minutes
RATE_LIMIT=50 # More restrictive in productionDeployment Methods
Method 1: Manual Deployment
1. Prepare the Server
# Update system packages
sudo apt update && sudo apt upgrade -y
# Install Node.js (using NodeSource repository)
curl -fsSL https://deb.nodesource.com/setup_18.x | sudo -E bash -
sudo apt-get install -y nodejs
# Install PostgreSQL
sudo apt install postgresql postgresql-contrib postgis -y
# Install Redis
sudo apt install redis-server -y
# Install PM2 globally
sudo npm install -g pm22. Setup Database
# Create database user
sudo -u postgres createuser --interactive
# Enter: baasix_user
# Superuser: n
# Create databases: y
# Create roles: n
# Set password for user
sudo -u postgres psql
ALTER USER baasix_user PASSWORD 'secure_database_password';
# Create database
sudo -u postgres createdb -O baasix_user baasix_production
# Enable PostGIS extension
sudo -u postgres psql baasix_production
CREATE EXTENSION postgis;
\q3. Deploy Application
# Clone repository
git clone https://github.com/your-repo/baasix.git
cd baasix/api
# Install dependencies
npm ci --production
# Create environment file
cp .env.example .env
# Edit .env with your configuration
# Build application
npm run build
# Start with PM2
pm2 start ecosystem.config.js --env production
pm2 save
pm2 startup4. Create PM2 Ecosystem File
Create ecosystem.config.js:
module.exports = {
apps: [{
name: 'baasix-api',
script: './dist/index.js',
instances: 'max',
exec_mode: 'cluster',
env: {
NODE_ENV: 'development'
},
env_production: {
NODE_ENV: 'production',
PORT: 3000
},
error_file: './logs/err.log',
out_file: './logs/out.log',
log_file: './logs/combined.log',
time: true
}]
};Method 2: Docker Deployment
1. Create Dockerfile
FROM node:18-alpine
# Install system dependencies
RUN apk add --no-cache bash postgresql-client
# Set working directory
WORKDIR /app
# Copy package files
COPY api/package*.json ./
# Install dependencies
RUN npm ci --only=production
# Copy application code
COPY api/ ./
# Build application
RUN npm run build
# Create non-root user
RUN addgroup -g 1001 -S nodejs
RUN adduser -S nextjs -u 1001
# Change ownership
RUN chown -R nextjs:nodejs /app
USER nextjs
# Expose port
EXPOSE 3000
# Health check
HEALTHCHECK --interval=30s --timeout=3s --start-period=5s --retries=3 \
CMD curl -f http://localhost:3000/settings/info || exit 1
# Start application
CMD ["npm", "start"]2. Create Docker Compose
version: '3.8'
services:
app:
build: .
ports:
- "3000:3000"
environment:
- NODE_ENV=production
env_file:
- .env
depends_on:
- postgres
- redis
volumes:
- ./uploads:/app/uploads
restart: unless-stopped
postgres:
image: postgis/postgis:15-3.3
environment:
POSTGRES_DB: baasix_production
POSTGRES_USER: baasix_user
POSTGRES_PASSWORD: secure_database_password
volumes:
- postgres_data:/var/lib/postgresql/data
restart: unless-stopped
ports:
- "5432:5432"
redis:
image: redis:7-alpine
restart: unless-stopped
ports:
- "6379:6379"
volumes:
- redis_data:/data
nginx:
image: nginx:alpine
ports:
- "80:80"
- "443:443"
volumes:
- ./nginx.conf:/etc/nginx/nginx.conf:ro
- ./ssl:/etc/nginx/ssl:ro
depends_on:
- app
restart: unless-stopped
volumes:
postgres_data:
redis_data:3. Deploy with Docker
# Build and start services
docker-compose up -d
# View logs
docker-compose logs -f app
# Scale application
docker-compose up -d --scale app=3Method 3: Kubernetes Deployment
1. Create Kubernetes Manifests
# deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: baasix-api
spec:
replicas: 3
selector:
matchLabels:
app: baasix-api
template:
metadata:
labels:
app: baasix-api
spec:
containers:
- name: baasix-api
image: your-registry/baasix:latest
ports:
- containerPort: 3000
env:
- name: NODE_ENV
value: "production"
- name: DB_HOST
value: "postgres-service"
- name: CACHE_REDIS_URL
value: "redis://redis-service:6379"
envFrom:
- secretRef:
name: baasix-secrets
resources:
requests:
memory: "256Mi"
cpu: "250m"
limits:
memory: "512Mi"
cpu: "500m"
livenessProbe:
httpGet:
path: /settings/info
port: 3000
initialDelaySeconds: 30
periodSeconds: 10
readinessProbe:
httpGet:
path: /settings/info
port: 3000
initialDelaySeconds: 5
periodSeconds: 5
---
apiVersion: v1
kind: Service
metadata:
name: baasix-api-service
spec:
selector:
app: baasix-api
ports:
- port: 80
targetPort: 3000
type: ClusterIPProduction Considerations
Security Checklist
- Use HTTPS/TLS certificates
- Set secure cookie options (
COOKIE_SECURE=true) - Configure proper CORS origins
- Enable rate limiting
- Use strong, unique secrets
- Enable database SSL connection
- Implement proper firewall rules
- Keep dependencies updated
- Use environment variables for secrets
- Enable audit logging
Performance Optimization
Database Optimization
-- Create indexes for better performance
CREATE INDEX idx_items_created_at ON items(created_at);
CREATE INDEX idx_items_tenant_id ON items(tenant_id);
CREATE INDEX idx_notifications_user_seen ON notifications(user_id, seen);
-- Configure PostgreSQL for production
-- In postgresql.conf:
shared_buffers = 256MB
effective_cache_size = 1GB
maintenance_work_mem = 64MBRedis Configuration
# redis.conf production settings
maxmemory 256mb
maxmemory-policy allkeys-lru
save 900 1
save 300 10
save 60 10000Nginx Reverse Proxy
upstream baasix_backend {
server 127.0.0.1:3000;
}
server {
listen 80;
server_name yourdomain.com;
return 301 https://$server_name$request_uri;
}
server {
listen 443 ssl http2;
server_name yourdomain.com;
ssl_certificate /etc/ssl/certs/yourdomain.com.crt;
ssl_certificate_key /etc/ssl/private/yourdomain.com.key;
# Security headers
add_header X-Frame-Options DENY;
add_header X-Content-Type-Options nosniff;
add_header X-XSS-Protection "1; mode=block";
# Gzip compression
gzip on;
gzip_types text/plain application/json application/javascript text/css;
# File upload size
client_max_body_size 50M;
location / {
proxy_pass http://baasix_backend;
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;
}
# Socket.IO WebSocket support
location /socket.io/ {
proxy_pass http://baasix_backend;
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;
}
}Monitoring and Maintenance
Health Monitoring
# Create health check script
#!/bin/bash
# health-check.sh
RESPONSE=$(curl -s -o /dev/null -w "%{http_code}" http://localhost:3000/settings/info)
if [ $RESPONSE -eq 200 ]; then
echo "$(date): Service is healthy"
else
echo "$(date): Service is unhealthy - HTTP $RESPONSE"
# Restart service or send alert
fiLog Management
# Setup log rotation
sudo nano /etc/logrotate.d/baasix
/var/log/baasix/*.log {
daily
missingok
rotate 52
compress
delaycompress
notifempty
create 644 www-data www-data
postrotate
pm2 reloadLogs
endscript
}Backup Strategy
#!/bin/bash
# backup.sh
DATE=$(date +"%Y%m%d_%H%M%S")
BACKUP_DIR="/backups"
# Database backup
pg_dump -h localhost -U baasix_user baasix_production | gzip > "$BACKUP_DIR/db_backup_$DATE.sql.gz"
# Files backup
tar -czf "$BACKUP_DIR/files_backup_$DATE.tar.gz" /var/www/baasix/uploads
# Clean old backups (keep 30 days)
find $BACKUP_DIR -name "*.gz" -mtime +30 -delete
echo "Backup completed: $DATE"Troubleshooting
Common Issues
Database Connection Issues
# Check PostgreSQL status
sudo systemctl status postgresql
# Test database connection
psql -h localhost -U baasix_user -d baasix_production -c "SELECT version();"
# Check database logs
sudo tail -f /var/log/postgresql/postgresql-*.logRedis Connection Issues
# Check Redis status
sudo systemctl status redis
# Test Redis connection
redis-cli ping
# Check Redis logs
sudo tail -f /var/log/redis/redis-server.logApplication Issues
# Check PM2 status
pm2 status
pm2 logs baasix-api
# Check application logs
tail -f logs/combined.log
# Restart application
pm2 restart baasix-apiPerformance Issues
# Monitor system resources
htop
iotop
netstat -tulpn
# Check database performance
sudo -u postgres psql baasix_production
SELECT * FROM pg_stat_activity WHERE state = 'active';Emergency Recovery
#!/bin/bash
# emergency-recovery.sh
echo "Starting emergency recovery..."
# Stop application
pm2 stop baasix-api
# Restore latest database backup
LATEST_DB=$(ls -t /backups/db_backup_*.sql.gz | head -1)
gunzip -c "$LATEST_DB" | psql -h localhost -U baasix_user baasix_production
# Restore file uploads
LATEST_FILES=$(ls -t /backups/files_backup_*.tar.gz | head -1)
tar -xzf "$LATEST_FILES" -C /
# Start application
pm2 start baasix-api
echo "Recovery completed"Related Documentation
- Settings Routes - Application configuration
- Authentication Routes - Security setup
- Additional Features - Optional features