This guide covers how to deploy OpenLN to various platforms, from development to production environments.
OpenLN uses a multi-tier architecture that can be deployed in various configurations:
- Frontend: Static site hosting (Vercel, Netlify, AWS S3)
- Backend: Node.js hosting (Railway, Heroku, AWS EC2)
- Database: MongoDB Atlas or self-hosted MongoDB
- CDN: Asset delivery optimization
βββββββββββββββ βββββββββββββββ βββββββββββββββ
β CDN β β Frontend β β Backend β
β (Assets) βββββΊβ (Static) βββββΊβ (Node.js) β
βββββββββββββββ βββββββββββββββ βββββββββββββββ
β
βΌ
βββββββββββββββ
β Database β
β (MongoDB) β
βββββββββββββββ
# API Configuration
VITE_API_URL=https://api.yourdomain.com/api/v1
VITE_SERVER_URL=https://api.yourdomain.com
# Google AI (if used client-side)
VITE_GOOGLE_AI_API_KEY=your-google-ai-key
# Analytics (optional)
VITE_GOOGLE_ANALYTICS_ID=GA-XXXXXXXXX
VITE_SENTRY_DSN=your-sentry-dsn
# Environment
VITE_NODE_ENV=production# Server Configuration
NODE_ENV=production
PORT=5000
# Database
MONGODB_URI=mongodb+srv://user:password@cluster.mongodb.net/openln
# JWT Configuration
JWT_SECRET=your-super-secure-jwt-secret-key
JWT_EXPIRE=7d
# Google AI
GOOGLE_AI_API_KEY=your-google-ai-api-key
# OAuth
GOOGLE_CLIENT_ID=your-google-client-id
GOOGLE_CLIENT_SECRET=your-google-client-secret
# Email Service (optional)
SMTP_HOST=smtp.gmail.com
SMTP_PORT=587
SMTP_USER=your-email@gmail.com
SMTP_PASS=your-app-password
# CORS
CLIENT_URL=https://yourdomain.com
ALLOWED_ORIGINS=https://yourdomain.com,https://www.yourdomain.com
# Rate Limiting
RATE_LIMIT_WINDOW_MS=900000
RATE_LIMIT_MAX_REQUESTS=100
# Logging
LOG_LEVEL=info
LOG_FILE=logs/app.log-
Connect Repository:
- Go to Vercel Dashboard
- Click "Import Project"
- Connect your GitHub repository
-
Configure Build Settings:
{ "buildCommand": "cd client && npm run build", "outputDirectory": "client/dist", "installCommand": "cd client && npm install" } -
Environment Variables:
- Add all
VITE_*variables in Vercel dashboard - Set
NODE_ENV=production
- Add all
-
Custom Domain (optional):
- Add your domain in Vercel settings
- Configure DNS records
# Install Vercel CLI
npm install -g vercel
# Login to Vercel
vercel login
# Deploy from project directory
cd client
vercel --prod-
Connect Repository:
- Go to Netlify Dashboard
- Click "New site from Git"
- Connect repository
-
Build Settings:
Base directory: client Build command: npm run build Publish directory: dist -
Environment Variables:
- Add in Site Settings > Environment variables
# Install Netlify CLI
npm install -g netlify-cli
# Build the project
cd client
npm run build
# Deploy
netlify deploy --prod --dir=distcd client
npm run build# Create bucket
aws s3 mb s3://your-openln-bucket
# Configure for static website hosting
aws s3 website s3://your-openln-bucket --index-document index.html --error-document index.html# Sync build files
aws s3 sync dist/ s3://your-openln-bucket --delete
# Set public read permissions
aws s3api put-bucket-policy --bucket your-openln-bucket --policy file://bucket-policy.json{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "PublicReadGetObject",
"Effect": "Allow",
"Principal": "*",
"Action": "s3:GetObject",
"Resource": "arn:aws:s3:::your-openln-bucket/*"
}
]
}-
Connect Repository:
- Go to Railway Dashboard
- Click "Deploy from GitHub repo"
- Connect your repository
-
Configure Service:
Root Directory: server Build Command: npm install Start Command: npm start -
Environment Variables:
- Add all environment variables in Railway dashboard
- Railway provides
PORTautomatically
-
Database Setup:
- Add MongoDB plugin in Railway
- Or use external MongoDB Atlas
# Install Railway CLI
npm install -g @railway/cli
# Login
railway login
# Initialize project
railway init
# Deploy
railway up-
Create Procfile in server directory:
web: node index.js -
Update package.json:
{ "engines": { "node": "18.x", "npm": "9.x" } }
# Install Heroku CLI and login
heroku login
# Create Heroku app
heroku create your-openln-api
# Set environment variables
heroku config:set NODE_ENV=production
heroku config:set MONGODB_URI=your-mongodb-uri
heroku config:set JWT_SECRET=your-jwt-secret
# Deploy
git subtree push --prefix=server heroku main
# Or use GitHub integration in Heroku dashboard# Connect to EC2 instance
ssh -i your-key.pem ubuntu@your-ec2-ip
# Update system
sudo apt update && sudo apt upgrade -y
# Install Node.js
curl -fsSL https://deb.nodesource.com/setup_18.x | sudo -E bash -
sudo apt-get install -y nodejs
# Install PM2
sudo npm install -g pm2
# Install MongoDB (if needed)
wget -qO - https://www.mongodb.org/static/pgp/server-6.0.asc | sudo apt-key add -
echo "deb [ arch=amd64,arm64 ] https://repo.mongodb.org/apt/ubuntu focal/mongodb-org/6.0 multiverse" | sudo tee /etc/apt/sources.list.d/mongodb-org-6.0.list
sudo apt-get update
sudo apt-get install -y mongodb-org# Clone repository
git clone https://github.com/Openln-git/Openln-Engine.git
cd Openln-Engine/server
# Install dependencies
npm install --production
# Create environment file
sudo nano .env
# Add your environment variables
# Start with PM2
pm2 start index.js --name openln-api
pm2 startup
pm2 saveserver {
listen 80;
server_name your-domain.com;
location / {
proxy_pass http://localhost:5000;
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;
}
}# Install Certbot
sudo apt install certbot python3-certbot-nginx
# Get SSL certificate
sudo certbot --nginx -d your-domain.com
# Auto-renewal
sudo crontab -e
# Add: 0 12 * * * /usr/bin/certbot renew --quiet-
Create Cluster:
- Go to MongoDB Atlas
- Create free cluster
- Choose region close to your backend
-
Security Setup:
- Create database user
- Configure IP whitelist (0.0.0.0/0 for all IPs)
- Enable VPC peering if needed
-
Connection:
mongodb+srv://username:password@cluster.mongodb.net/openln?retryWrites=true&w=majority
# docker-compose.yml
version: '3.8'
services:
mongodb:
image: mongo:6.0
restart: always
ports:
- "27017:27017"
environment:
MONGO_INITDB_ROOT_USERNAME: admin
MONGO_INITDB_ROOT_PASSWORD: password
MONGO_INITDB_DATABASE: openln
volumes:
- mongodb_data:/data/db
- ./mongo-init.js:/docker-entrypoint-initdb.d/mongo-init.js:ro
volumes:
mongodb_data:# Start MongoDB
docker-compose up -d mongodbCreate .github/workflows/deploy.yml:
name: Deploy OpenLN
on:
push:
branches: [main]
jobs:
test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- name: Setup Node.js
uses: actions/setup-node@v3
with:
node-version: '18'
- name: Install client dependencies
run: cd client && npm ci
- name: Install server dependencies
run: cd server && npm ci
- name: Run client tests
run: cd client && npm test
- name: Run server tests
run: cd server && npm test
- name: Run client linting
run: cd client && npm run lint
deploy-frontend:
needs: test
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- name: Setup Node.js
uses: actions/setup-node@v3
with:
node-version: '18'
- name: Install dependencies
run: cd client && npm ci
- name: Build
run: cd client && npm run build
env:
VITE_API_URL: ${{ secrets.VITE_API_URL }}
VITE_GOOGLE_AI_API_KEY: ${{ secrets.VITE_GOOGLE_AI_API_KEY }}
- name: Deploy to Vercel
uses: amondnet/vercel-action@v20
with:
vercel-token: ${{ secrets.VERCEL_TOKEN }}
vercel-args: '--prod'
working-directory: client
deploy-backend:
needs: test
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- name: Deploy to Railway
uses: railway-deploy@v1
with:
token: ${{ secrets.RAILWAY_TOKEN }}
service: your-service-id// server/middleware/monitoring.js
import winston from 'winston';
export const logger = winston.createLogger({
level: process.env.LOG_LEVEL || 'info',
format: winston.format.combine(
winston.format.timestamp(),
winston.format.errors({ stack: true }),
winston.format.json()
),
transports: [
new winston.transports.File({ filename: 'logs/error.log', level: 'error' }),
new winston.transports.File({ filename: 'logs/combined.log' }),
new winston.transports.Console({
format: winston.format.simple()
})
]
});// server/routes/health.js
app.get('/health', (req, res) => {
const healthCheck = {
uptime: process.uptime(),
message: 'OK',
timestamp: Date.now(),
environment: process.env.NODE_ENV,
version: process.env.npm_package_version
};
res.status(200).json(healthCheck);
});// Install Sentry
npm install @sentry/node
// server/config/sentry.js
import * as Sentry from '@sentry/node';
Sentry.init({
dsn: process.env.SENTRY_DSN,
environment: process.env.NODE_ENV
});// server/config/database.js
mongoose.connection.on('connected', () => {
logger.info('MongoDB connected successfully');
});
mongoose.connection.on('error', (err) => {
logger.error('MongoDB connection error:', err);
});
mongoose.connection.on('disconnected', () => {
logger.warn('MongoDB disconnected');
});- Environment Variables: All sensitive data in environment variables
- HTTPS: SSL certificates configured
- CORS: Proper origin restrictions
- Rate Limiting: API rate limits in place
- JWT Secrets: Strong, unique JWT secrets
- Database Security: MongoDB authentication enabled
- Input Validation: All inputs validated and sanitized
- Error Handling: No sensitive information in error messages
- Dependencies: All dependencies updated and scanned
- Firewall: Proper firewall rules configured
// server/middleware/security.js
import helmet from 'helmet';
app.use(helmet({
contentSecurityPolicy: {
directives: {
defaultSrc: ["'self'"],
styleSrc: ["'self'", "'unsafe-inline'"],
scriptSrc: ["'self'"],
imgSrc: ["'self'", "data:", "https:"],
},
},
hsts: {
maxAge: 31536000,
includeSubDomains: true,
preload: true
}
}));# Clear cache and reinstall
rm -rf node_modules package-lock.json
npm install
# Check for TypeScript errors
npm run type-check
# Verify environment variables
npm run build# Check MongoDB connection
mongosh "your-connection-string"
# Verify environment variables
node -e "console.log(process.env)"
# Check server logs
tail -f logs/combined.log// Update CORS configuration
app.use(cors({
origin: process.env.CLIENT_URL || 'http://localhost:5173',
credentials: true
}));- Enable gzip compression
- Implement code splitting
- Optimize images and assets
- Use CDN for static assets
- Implement caching (Redis)
- Optimize database queries
- Use connection pooling
- Enable compression middleware
This deployment guide provides multiple options for hosting OpenLN in production. Choose the platform that best fits your needs and budget. For additional support, check our troubleshooting guide or open an issue.