Skip to content

Production Deployment

This guide covers deploying OpenSNS to a production environment with proper security, HTTPS, and monitoring.

Before going live, ensure:

  • Strong, unique secrets for JWT_SECRET_KEY and API_KEY_ENCRYPTION_KEY
  • HTTPS configured with valid SSL certificates
  • Database backups configured
  • Rate limiting enabled (built-in)
  • CORS configured for your domain
  • Monitoring and logging set up

Best for: Small to medium deployments, full control

Recommended providers: DigitalOcean, Linode, Vultr, Hetzner

Terminal window
# On your VPS
git clone https://github.com/yourusername/opensns.git
cd opensns
# Create production environment file
cp .env.example .env
# Edit .env with production values

Best for: Scaling, managed infrastructure

Recommended platforms:

  • Railway
  • Render
  • Fly.io
  • Google Cloud Run
  • AWS ECS

Best for: Large scale, complex requirements

See the Kubernetes section below.


Terminal window
# Generate JWT secret (64 characters)
openssl rand -base64 48
# Generate encryption key (exactly 32 characters for AES-256)
openssl rand -base64 24 | head -c 32
.env.production
NODE_ENV=production
# Security (REQUIRED - use your generated values)
JWT_SECRET_KEY=<your-64-char-random-string>
API_KEY_ENCRYPTION_KEY=<your-32-char-random-string>
# Database
DATABASE_URL=postgresql://user:password@db-host:5432/opensns
# CORS - restrict to your domain
CORS_ORIGINS=["https://yourdomain.com"]
# API Keys (optional - users can add their own)
OPENAI_API_KEY=
FAL_KEY=
# Engines
DEFAULT_LLM_ENGINE=openai
DEFAULT_IMAGE_ENGINE=fal
DEFAULT_VIDEO_ENGINE=fal-video
  1. Use a managed database (AWS RDS, DigitalOcean Managed Database, etc.)
  2. Enable SSL connections
  3. Use strong, unique passwords
  4. Restrict network access to only your application servers
Terminal window
# Example: PostgreSQL with SSL
DATABASE_URL=postgresql://user:pass@host:5432/opensns?sslmode=require

Terminal window
# Ubuntu/Debian
sudo apt update
sudo apt install nginx certbot python3-certbot-nginx

Create /etc/nginx/sites-available/opensns:

# Redirect HTTP to HTTPS
server {
listen 80;
server_name yourdomain.com;
return 301 https://$server_name$request_uri;
}
# Main HTTPS server
server {
listen 443 ssl http2;
server_name yourdomain.com;
# SSL certificates (managed by Certbot)
ssl_certificate /etc/letsencrypt/live/yourdomain.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/yourdomain.com/privkey.pem;
# SSL settings
ssl_protocols TLSv1.2 TLSv1.3;
ssl_ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256;
ssl_prefer_server_ciphers off;
# 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;
add_header Referrer-Policy "strict-origin-when-cross-origin" always;
# Frontend
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;
}
# Backend API
location /api/ {
rewrite ^/api/(.*) /$1 break;
proxy_pass http://localhost:8000;
proxy_http_version 1.1;
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;
# Timeouts for long-running requests
proxy_connect_timeout 60s;
proxy_send_timeout 60s;
proxy_read_timeout 300s; # 5 min for asset generation
}
# WebSocket support
location /ws {
proxy_pass http://localhost:8000;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_set_header Host $host;
proxy_read_timeout 86400;
}
}
Terminal window
# Enable site
sudo ln -s /etc/nginx/sites-available/opensns /etc/nginx/sites-enabled/
# Test configuration
sudo nginx -t
# Get SSL certificate
sudo certbot --nginx -d yourdomain.com
# Reload Nginx
sudo systemctl reload nginx

Create docker-compose.prod.yml:

services:
backend:
build:
context: ./backend
dockerfile: Dockerfile
restart: always
environment:
DATABASE_URL: ${DATABASE_URL}
JWT_SECRET_KEY: ${JWT_SECRET_KEY}
API_KEY_ENCRYPTION_KEY: ${API_KEY_ENCRYPTION_KEY}
CORS_ORIGINS: '["https://yourdomain.com"]'
ports:
- "127.0.0.1:8000:8000" # Only localhost
logging:
driver: "json-file"
options:
max-size: "10m"
max-file: "3"
frontend:
build:
context: ./frontend
dockerfile: Dockerfile
args:
NEXT_PUBLIC_API_URL: https://yourdomain.com/api
restart: always
ports:
- "127.0.0.1:3000:3000" # Only localhost
logging:
driver: "json-file"
options:
max-size: "10m"
max-file: "3"

Start with:

Terminal window
docker-compose -f docker-compose.prod.yml up -d

Create /opt/opensns/backup.sh:

#!/bin/bash
set -e
BACKUP_DIR="/opt/opensns/backups"
TIMESTAMP=$(date +"%Y%m%d_%H%M%S")
BACKUP_FILE="$BACKUP_DIR/opensns_$TIMESTAMP.sql.gz"
# Create backup
pg_dump "$DATABASE_URL" | gzip > "$BACKUP_FILE"
# Keep only last 7 days
find "$BACKUP_DIR" -name "*.sql.gz" -mtime +7 -delete
echo "Backup created: $BACKUP_FILE"

Add to crontab:

Terminal window
# Run daily at 3 AM
0 3 * * * /opt/opensns/backup.sh >> /var/log/opensns-backup.log 2>&1

Upload to S3 or similar:

Terminal window
# Install AWS CLI
pip install awscli
# Add to backup script
aws s3 cp "$BACKUP_FILE" "s3://your-bucket/opensns-backups/"

The backend exposes a health endpoint:

Terminal window
curl https://yourdomain.com/api/health

Use services like:

Configure to check:

  • https://yourdomain.com (frontend)
  • https://yourdomain.com/api/health (backend)
Terminal window
# View logs
docker-compose logs -f --tail=100
# Ship to external service (example: Papertrail)
# Add to docker-compose.prod.yml:
logging:
driver: syslog
options:
syslog-address: "udp://logs.papertrailapp.com:12345"

For Kubernetes, create the following manifests:

namespace.yaml
apiVersion: v1
kind: Namespace
metadata:
name: opensns
secrets.yaml
apiVersion: v1
kind: Secret
metadata:
name: opensns-secrets
namespace: opensns
type: Opaque
stringData:
jwt-secret-key: "your-jwt-secret"
api-key-encryption-key: "your-encryption-key"
database-url: "postgresql://..."
backend-deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: backend
namespace: opensns
spec:
replicas: 2
selector:
matchLabels:
app: backend
template:
metadata:
labels:
app: backend
spec:
containers:
- name: backend
image: your-registry/opensns-backend:latest
ports:
- containerPort: 8000
env:
- name: DATABASE_URL
valueFrom:
secretKeyRef:
name: opensns-secrets
key: database-url
- name: JWT_SECRET_KEY
valueFrom:
secretKeyRef:
name: opensns-secrets
key: jwt-secret-key
resources:
requests:
memory: "256Mi"
cpu: "250m"
limits:
memory: "512Mi"
cpu: "500m"
livenessProbe:
httpGet:
path: /health
port: 8000
initialDelaySeconds: 10
periodSeconds: 10

  • Backend is stateless - scale with multiple replicas
  • Use a load balancer (Nginx, HAProxy, cloud LB)
  • Ensure database can handle connection pooling

Add Redis for session caching and rate limiting:

docker-compose.prod.yml
redis:
image: redis:7-alpine
restart: always
ports:
- "127.0.0.1:6379:6379"

Store generated images/videos on a CDN:

  • AWS S3 + CloudFront
  • Cloudflare R2
  • DigitalOcean Spaces

Backend not responding:

Terminal window
docker-compose logs backend
docker-compose restart backend
Terminal window
# Test database connection
docker-compose exec backend python -c "from app.db import engine; print(engine.url)"

Certbot auto-renews, but verify:

Terminal window
sudo certbot renew --dry-run

Generate ad creatives from any product URL. Open source, self-hostable, free tier available.

Try OpenSNS Free →