🚀 Deployment Guide
This guide covers deploying your StoneJS Framework application to production environments. We'll cover different hosting options, best practices, and security considerations.
Pre-Deployment Checklist
Before deploying to production, ensure you have:
- ✅ Set
NODE_ENV=production - ✅ Use
$cache.cacheSelf()for frequently accessed pages - ✅ Set a strong session secret
- ✅ Configured HTTPS (secure cookies)
- ✅ Set up database connection pooling
- ✅ Removed or secured the
/demodirectory - ✅ Configured proper error handling
- ✅ Set up logging and monitoring
- ✅ Tested all features in staging environment
1. Environment Configuration
Production .env File
# Environment
NODE_ENV=production
PORT=3000
# Session Security
SESSION_SECRET=your-very-long-random-secret-key-here
# Database
DB_TYPE=postgresql
DB_HOST=your-production-db-host.com
DB_PORT=5432
DB_USER=your_db_user
DB_PASSWORD=your_strong_password
DB_NAME=your_production_db
# Redis (for session storage and caching)
REDIS_HOST=your-redis-host.com
REDIS_PORT=6379
REDIS_PASSWORD=your_redis_password
# SSL/TLS
HTTPS_ENABLED=true
SSL_CERT_PATH=/path/to/cert.pem
SSL_KEY_PATH=/path/to/key.pem
# Logging
LOG_LEVEL=error
LOG_FILE=/var/log/stonejs/app.log
Production Server Configuration
require('dotenv').config();
const StoneJS = require('stonejs-framework');
const app = new StoneJS({
root: './pages',
port: process.env.PORT || 3000,
// Performance
autoReload: false, // Disable auto-reload in production
// Session with Redis
session: {
secret: process.env.SESSION_SECRET,
resave: false,
saveUninitialized: false,
store: new RedisStore({
host: process.env.REDIS_HOST,
port: process.env.REDIS_PORT,
password: process.env.REDIS_PASSWORD
}),
cookie: {
secure: true, // Require HTTPS
httpOnly: true,
maxAge: 86400000,
sameSite: 'strict'
}
},
// Cache with Redis
cache: {
store: 'redis',
host: process.env.REDIS_HOST,
port: process.env.REDIS_PORT,
password: process.env.REDIS_PASSWORD,
defaultTTL: 3600
},
// Database
database: {
type: 'postgresql',
host: process.env.DB_HOST,
port: process.env.DB_PORT,
user: process.env.DB_USER,
password: process.env.DB_PASSWORD,
database: process.env.DB_NAME,
ssl: true,
pool: {
min: 2,
max: 20
}
}
});
app.listen();
2. Deployment Options
Option A: Traditional VPS (DigitalOcean, Linode, AWS EC2)
Step 1: Set Up Server
# Update system
sudo apt update && sudo apt upgrade -y
# Install Node.js (via NodeSource)
curl -fsSL https://deb.nodesource.com/setup_18.x | sudo -E bash -
sudo apt install -y nodejs
# Install PM2 for process management
sudo npm install -g pm2
# Install Nginx for reverse proxy
sudo apt install -y nginx
# Install PostgreSQL
sudo apt install -y postgresql postgresql-contrib
# Install Redis
sudo apt install -y redis-server
Step 2: Deploy Application
# Clone your repository
git clone https://github.com/yourorg/your-app.git
cd your-app
# Install dependencies
npm install --production
# Set up environment variables
cp .env.example .env
nano .env # Edit with production values
# Start with PM2
pm2 start server.js --name stonejs-app
pm2 save
pm2 startup
Step 3: Configure Nginx Reverse Proxy
# Create Nginx config
sudo nano /etc/nginx/sites-available/stonejs-app
# Add this configuration:
server {
listen 80;
server_name yourdomain.com www.yourdomain.com;
location / {
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;
}
}
# Enable the site
sudo ln -s /etc/nginx/sites-available/stonejs-app /etc/nginx/sites-enabled/
sudo nginx -t
sudo systemctl restart nginx
Step 4: Set Up SSL with Let's Encrypt
# Install Certbot
sudo apt install -y certbot python3-certbot-nginx
# Get SSL certificate
sudo certbot --nginx -d yourdomain.com -d www.yourdomain.com
# Auto-renewal is set up automatically
Option B: Docker Deployment
Create Dockerfile
FROM node:18-alpine
# Create app directory
WORKDIR /usr/src/app
# Copy package files
COPY package*.json ./
# Install dependencies
RUN npm ci --only=production
# Copy application code
COPY . .
# Expose port
EXPOSE 3000
# Start application
CMD ["node", "server.js"]
Create docker-compose.yml
version: '3.8'
services:
app:
build: .
ports:
- "3000:3000"
environment:
- NODE_ENV=production
- DB_HOST=postgres
- REDIS_HOST=redis
depends_on:
- postgres
- redis
restart: unless-stopped
postgres:
image: postgres:15
environment:
POSTGRES_DB: your_database
POSTGRES_USER: your_user
POSTGRES_PASSWORD: your_password
volumes:
- postgres_data:/var/lib/postgresql/data
restart: unless-stopped
redis:
image: redis:7-alpine
restart: unless-stopped
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:
Deploy with Docker
# Build and start
docker-compose up -d
# View logs
docker-compose logs -f app
# Stop
docker-compose down
Option C: Platform as a Service (Heroku, Railway, Render)
Heroku Deployment
# Install Heroku CLI
curl https://cli-assets.heroku.com/install.sh | sh
# Login
heroku login
# Create app
heroku create your-app-name
# Add PostgreSQL addon
heroku addons:create heroku-postgresql:hobby-dev
# Add Redis addon
heroku addons:create heroku-redis:hobby-dev
# Set environment variables
heroku config:set NODE_ENV=production
heroku config:set SESSION_SECRET=your-secret-key
# Deploy
git push heroku main
# View logs
heroku logs --tail
Option D: Serverless (AWS Lambda, Vercel, Netlify)
Note: StoneJS Framework is designed for traditional server deployments. For serverless environments, you may need to adapt the architecture or consider using serverless-specific frameworks.
3. Security Best Practices
Critical Security Measures:
1. Remove Demo Directory
# Option 1: Delete it
rm -rf pages/demo
# Option 2: Protect with authentication (in autohandler)
if (!$session.isAdmin && $req.path.startsWith('/demo')) {
$res.status(403).send('Forbidden');
return;
}
2. Secure Session Configuration
session: {
secret: process.env.SESSION_SECRET, // Strong random value
resave: false,
saveUninitialized: false,
cookie: {
secure: true, // HTTPS only
httpOnly: true, // Prevent XSS
maxAge: 3600000, // 1 hour
sameSite: 'strict' // CSRF protection
}
}
3. Enable Helmet for HTTP Headers
npm install helmet
// In server.js
const helmet = require('helmet');
app.use(helmet());
4. Rate Limiting
npm install express-rate-limit
const rateLimit = require('express-rate-limit');
const limiter = rateLimit({
windowMs: 15 * 60 * 1000, // 15 minutes
max: 100 // limit each IP to 100 requests per windowMs
});
app.use(limiter);
5. Input Validation
- Always use parameterized queries for database operations
- Sanitize user input before displaying
- Validate all form inputs
- Use CSRF tokens for forms
6. Environment Variables
- Never commit .env files to version control
- Use strong, random secrets
- Rotate secrets periodically
- Use different credentials for each environment
4. Performance Optimization
Enable Compression
npm install compression
const compression = require('compression');
app.use(compression());
Static Asset Caching
// In Nginx config
location /static {
expires 1y;
add_header Cache-Control "public, immutable";
}
Database Connection Pooling
database: {
pool: {
min: 2,
max: 20,
idleTimeoutMillis: 30000,
connectionTimeoutMillis: 2000
}
}
Redis Caching
- Cache expensive database queries
- Cache API responses
- Use appropriate TTL values
- Monitor cache hit rates
5. Monitoring and Logging
Set Up PM2 Monitoring
# Monitor with PM2
pm2 monit
# Enable PM2 web dashboard
pm2 web
# View logs
pm2 logs stonejs-app
# Rotate logs
pm2 install pm2-logrotate
Application Logging
npm install winston
const winston = require('winston');
const logger = winston.createLogger({
level: process.env.LOG_LEVEL || 'info',
format: winston.format.json(),
transports: [
new winston.transports.File({ filename: 'error.log', level: 'error' }),
new winston.transports.File({ filename: 'combined.log' })
]
});
if (process.env.NODE_ENV !== 'production') {
logger.add(new winston.transports.Console({
format: winston.format.simple()
}));
}
Error Tracking (Sentry)
npm install @sentry/node
const Sentry = require('@sentry/node');
Sentry.init({
dsn: process.env.SENTRY_DSN,
environment: process.env.NODE_ENV
});
6. Backup and Recovery
Database Backups
# Automated daily backup script
#!/bin/bash
BACKUP_DIR="/backups/postgresql"
DATE=$(date +%Y%m%d_%H%M%S)
pg_dump -U your_user your_database > "$BACKUP_DIR/backup_$DATE.sql"
# Keep only last 7 days
find $BACKUP_DIR -name "backup_*.sql" -mtime +7 -delete
Application Backups
- Use Git for version control
- Tag releases
- Keep deployment artifacts
- Document rollback procedures
7. Continuous Deployment
GitHub Actions Example
# .github/workflows/deploy.yml
name: Deploy to Production
on:
push:
branches: [ main ]
jobs:
deploy:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- name: Deploy to server
uses: appleboy/ssh-action@master
with:
host: ${{ secrets.SERVER_HOST }}
username: ${{ secrets.SERVER_USER }}
key: ${{ secrets.SSH_PRIVATE_KEY }}
script: |
cd /var/www/your-app
git pull origin main
npm install --production
pm2 restart stonejs-app
8. Scaling Your Application
Horizontal Scaling with PM2 Cluster Mode
# ecosystem.config.js
module.exports = {
apps: [{
name: 'stonejs-app',
script: './server.js',
instances: 'max', // Use all CPU cores
exec_mode: 'cluster',
env: {
NODE_ENV: 'production'
}
}]
};
# Start cluster
pm2 start ecosystem.config.js
Load Balancing with Nginx
upstream stonejs_cluster {
least_conn;
server localhost:3000;
server localhost:3001;
server localhost:3002;
server localhost:3003;
}
server {
location / {
proxy_pass http://stonejs_cluster;
}
}
9. Health Checks and Uptime Monitoring
Add Health Check Endpoint
// Create pages/health
<%
$res.setHeader('Content-Type', 'application/json');
const health = {
status: 'healthy',
timestamp: new Date().toISOString(),
uptime: process.uptime(),
database: $db ? 'connected' : 'disconnected',
cache: $cache ? 'available' : 'unavailable'
};
$res.send(JSON.stringify(health));
%>
External Monitoring
- UptimeRobot - Free uptime monitoring
- Pingdom - Performance monitoring
- New Relic - Application performance monitoring
- Datadog - Infrastructure monitoring
10. Rollback Strategy
# Keep last 5 releases
/var/www/your-app/
├── current -> releases/20240121_120000
├── releases/
│ ├── 20240121_120000/
│ ├── 20240120_150000/
│ ├── 20240119_100000/
│ ├── 20240118_140000/
│ └── 20240117_110000/
# Rollback script
#!/bin/bash
cd /var/www/your-app
PREVIOUS=$(ls -t releases | sed -n '2p')
ln -snf releases/$PREVIOUS current
pm2 restart stonejs-app
Post-Deployment Checklist
After deployment, verify:
- ✅ Application starts without errors
- ✅ All pages load correctly
- ✅ Database connections work
- ✅ Session management functions
- ✅ Caching is operational
- ✅ SSL certificate is valid
- ✅ Environment variables are set
- ✅ Logs are being written
- ✅ Monitoring is active
- ✅ Backups are scheduled
- ✅ Health check endpoint responds
- ✅ Performance is acceptable
Resources
Need help with deployment? Join our community or consult with a DevOps professional for complex setups.