OS Trading Engine
Security
Network Security

Network Security

This page covers infrastructure security considerations for self-hosted Nexgent deployments.

Architecture Overview

┌──────────────────────────────────────────────────────────────────┐
│                         Internet                                  │
└──────────────────────────────┬───────────────────────────────────┘


┌──────────────────────────────────────────────────────────────────┐
│                    Load Balancer / CDN                           │
│                    (TLS termination)                             │
└──────────────────────────────┬───────────────────────────────────┘

                    ┌──────────┴──────────┐
                    ▼                     ▼
           ┌───────────────┐      ┌───────────────┐
           │   Frontend    │      │    Backend    │
           │   (Next.js)   │      │   (Express)   │
           │   Port 3000   │      │   Port 4000   │
           └───────────────┘      └───────┬───────┘

                    ┌─────────────────────┼─────────────────────┐
                    ▼                     ▼                     ▼
           ┌───────────────┐      ┌───────────────┐      ┌───────────────┐
           │  PostgreSQL   │      │    Redis      │      │   External    │
           │   Port 5432   │      │   Port 6379   │      │     APIs      │
           └───────────────┘      └───────────────┘      └───────────────┘

TLS/HTTPS

🚫

Always use HTTPS in production. Never expose the API over plain HTTP.

Configuration

TLS should be terminated at your load balancer or reverse proxy:

Railway/Vercel:

  • Automatic HTTPS with managed certificates

Nginx:

server {
    listen 443 ssl http2;
    server_name api.yourdomain.com;
    
    ssl_certificate /etc/letsencrypt/live/api.yourdomain.com/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/api.yourdomain.com/privkey.pem;
    
    # Modern TLS configuration
    ssl_protocols TLSv1.2 TLSv1.3;
    ssl_ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256;
    ssl_prefer_server_ciphers off;
    
    # HSTS
    add_header Strict-Transport-Security "max-age=31536000" always;
    
    location / {
        proxy_pass http://localhost:4000;
        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;
    }
}

Firewall Rules

Recommended Configuration

PortServiceAccess
443HTTPSPublic
80HTTP (redirect)Public
22SSHAdmin IPs only
5432PostgreSQLBackend only
6379RedisBackend only
4000Backend APILoad balancer only
3000FrontendLoad balancer only

Example (UFW)

# Default deny incoming
ufw default deny incoming
ufw default allow outgoing
 
# Allow SSH from specific IP
ufw allow from YOUR_IP to any port 22
 
# Allow HTTPS
ufw allow 443/tcp
 
# Allow HTTP (for redirect)
ufw allow 80/tcp
 
# Enable firewall
ufw enable

Example (AWS Security Groups)

Backend Security Group:
- Inbound: 4000 from Load Balancer SG
- Outbound: All (for external APIs)

Database Security Group:
- Inbound: 5432 from Backend SG only
- Outbound: None

Redis Security Group:
- Inbound: 6379 from Backend SG only
- Outbound: None

Database Security

PostgreSQL

Network:

  • Never expose to public internet
  • Use private networking (VPC)
  • Restrict to backend IP only

Authentication:

# Use strong, unique password
DATABASE_URL=postgresql://nexgent:STRONG_PASSWORD@localhost:5432/nexgent?sslmode=require

SSL:

# Require SSL for database connections
DATABASE_URL=...?sslmode=require

Redis

Network:

  • Never expose to public internet
  • Use private networking

Authentication:

REDIS_PASSWORD=STRONG_REDIS_PASSWORD

TLS (if exposed):

REDIS_TLS=true

WebSocket Security

The WebSocket server uses the same authentication as the REST API:

// WebSocket connection with auth
const ws = new WebSocket('wss://api.example.com/ws', {
  headers: {
    Authorization: `Bearer ${accessToken}`,
  },
});

Security measures:

  • Token validation on connection
  • Automatic disconnection on token expiry
  • Origin validation

Secrets Management

Environment Variables

Development:

# .env file (gitignored)
JWT_SECRET=development-secret-key
DATABASE_URL=postgresql://localhost/nexgent

Production (Railway):

  • Use Railway's encrypted environment variables
  • Reference private services for database URLs

Production (AWS):

  • Use AWS Secrets Manager
  • IAM roles for service access

Key Rotation

  1. Generate new secret
  2. Deploy with both old and new secrets accepted
  3. Roll out completely
  4. Remove old secret
  5. Invalidate sessions if needed

Logging and Monitoring

Recommended Logs

Log TypePurposeRetention
Access logsRequest tracking30 days
Auth logsLogin attempts90 days
Error logsDebugging30 days
Audit logsSecurity events1 year

Security Events to Monitor

  • Failed login attempts (>5 from same IP)
  • Invalid API key attempts
  • Unusual trading patterns
  • Large balance changes

Alerting

Set up alerts for:

  • Multiple failed logins
  • Error rate increases
  • Unusual API key usage

Backup Security

Database Backups

# Encrypted backup
pg_dump nexgent | gpg --encrypt -r backup@yourdomain.com > backup.sql.gpg
 
# Store in separate location
aws s3 cp backup.sql.gpg s3://your-backup-bucket/

Backup Guidelines

  1. Encrypt all backups
  2. Store in separate region/provider
  3. Test restoration regularly
  4. Limit backup access
  5. Rotate encryption keys

Security Checklist

Pre-Deployment

  • TLS/HTTPS configured
  • Firewall rules applied
  • Database not publicly accessible
  • Redis not publicly accessible
  • Strong passwords for all services
  • Secrets not in version control

Post-Deployment

  • SSL certificate auto-renewal
  • Log monitoring configured
  • Alerting set up
  • Backup schedule active
  • Security headers configured
  • CORS properly restricted