BaasixBaasix

Deployment Guide

← Back to Documentation Home

Table of Contents

  1. Overview
  2. Prerequisites
  3. Environment Configuration
  4. Deployment Methods
  5. Production Considerations
  6. Monitoring and Maintenance
  7. 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=true

AWS 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.com

Production 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 production

Deployment 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 pm2

2. 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;
\q

3. 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 startup

4. 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=3

Method 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: ClusterIP

Production 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 = 64MB

Redis Configuration

# redis.conf production settings
maxmemory 256mb
maxmemory-policy allkeys-lru
save 900 1
save 300 10
save 60 10000

Nginx 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
fi

Log 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-*.log

Redis 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.log

Application Issues

# Check PM2 status
pm2 status
pm2 logs baasix-api

# Check application logs
tail -f logs/combined.log

# Restart application
pm2 restart baasix-api

Performance 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"

← Back to Documentation Home

On this page