Backend Framework Guide

    Deploy Remix

    Deploy a production-ready Remix application with Node.js, PM2 cluster mode, Nginx reverse proxy, and SSL encryption on RamNode's VPS hosting.

    Node.js 22 LTS
    PM2 Cluster Mode
    Nginx Reverse Proxy
    Let's Encrypt SSL
    1

    Prerequisites

    • A RamNode VPS running Ubuntu 24.04 LTS (recommended: 2 GB RAM / 1 vCPU minimum — available starting at $10/month)
    • A registered domain name with DNS pointed to your VPS IP address
    • SSH access to your server with root or sudo privileges
    • Basic familiarity with the Linux command line
    2

    Initial Server Setup

    Connect and create application user
    ssh root@your_server_ip
    
    # Create a dedicated non-root user
    adduser remix
    usermod -aG sudo remix
    
    # Update system packages
    apt update && apt upgrade -y

    Configure the Firewall

    Enable UFW
    ufw allow OpenSSH
    ufw allow 'Nginx Full'
    ufw enable
    
    # Verify the rules are active
    ufw status
    3

    Install Node.js

    Install Node.js 22 LTS using the NodeSource repository. Remix requires Node.js 18 or later, and Node 22 provides the best performance and long-term support.

    Install Node.js 22 LTS
    curl -fsSL https://deb.nodesource.com/setup_22.x | sudo -E bash -
    apt install -y nodejs
    
    # Verify the installation
    node -v
    npm -v
    4

    Create and Build Remix Application

    Switch to application user
    su - remix

    New Project

    Scaffold a new Remix project
    npx create-remix@latest my-remix-app
    cd my-remix-app

    Existing Project

    Clone and install existing project
    git clone https://github.com/yourusername/your-remix-app.git
    cd your-remix-app
    npm install
    Build and test
    # Build for production
    npm run build
    
    # Test the production build
    npm start
    # Visit http://your_server_ip:3000 to confirm
    # Press Ctrl+C to stop
    5

    Configure PM2 for Process Management

    PM2 keeps your Remix app running in the background, automatically restarts it on crashes, and relaunches it after server reboots.

    Install PM2
    sudo npm install -g pm2
    Create ecosystem.config.js
    module.exports = {
      apps: [
        {
          name: "remix-app",
          script: "npm",
          args: "start",
          cwd: "/home/remix/my-remix-app",
          env: {
            NODE_ENV: "production",
            PORT: 3000,
          },
          instances: "max",
          exec_mode: "cluster",
          autorestart: true,
          watch: false,
          max_memory_restart: "512M",
          log_date_format: "YYYY-MM-DD HH:mm:ss Z",
          error_file: "/home/remix/.pm2/logs/remix-error.log",
          out_file: "/home/remix/.pm2/logs/remix-out.log",
        },
      ],
    };

    The instances: "max" setting runs one process per CPU core for maximum throughput. On a single-core RamNode VPS, this defaults to one instance. For multi-core plans, PM2 will automatically scale across all available cores.

    Start and configure boot persistence
    pm2 start ecosystem.config.js
    pm2 save
    sudo env PATH=$PATH:/usr/bin pm2 startup systemd -u remix --hp /home/remix
    Useful PM2 commands
    pm2 status           # View running processes
    pm2 logs remix-app   # Tail application logs
    pm2 monit            # Interactive monitoring dashboard
    pm2 restart remix-app # Restart the application
    pm2 reload remix-app  # Zero-downtime reload
    6

    Set Up Nginx Reverse Proxy

    Install Nginx
    sudo apt install -y nginx
    Create /etc/nginx/sites-available/remix-app
    server {
        listen 80;
        listen [::]:80;
        server_name yourdomain.com www.yourdomain.com;
    
        # 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;
    
        # Gzip compression
        gzip on;
        gzip_vary on;
        gzip_proxied any;
        gzip_comp_level 6;
        gzip_types text/plain text/css application/json application/javascript
                   text/xml application/xml application/xml+rss text/javascript
                   image/svg+xml;
    
        # Static asset caching — Remix fingerprints assets in /build/
        location /build/ {
            proxy_pass http://127.0.0.1:3000;
            proxy_http_version 1.1;
            expires 1y;
            add_header Cache-Control "public, immutable";
            access_log off;
        }
    
        # Favicon and static public files
        location /favicon.ico {
            proxy_pass http://127.0.0.1:3000;
            expires 30d;
            access_log off;
        }
    
        # All other requests — proxy to Remix
        location / {
            proxy_pass http://127.0.0.1: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;
            proxy_read_timeout 60s;
            proxy_send_timeout 60s;
        }
    }
    Enable site and test config
    sudo ln -s /etc/nginx/sites-available/remix-app /etc/nginx/sites-enabled/
    sudo rm /etc/nginx/sites-enabled/default
    sudo nginx -t
    sudo systemctl restart nginx
    7

    Secure with SSL Using Let's Encrypt

    Install Certbot and obtain certificate
    sudo apt install -y certbot python3-certbot-nginx
    
    # Obtain and install the SSL certificate
    sudo certbot --nginx -d yourdomain.com -d www.yourdomain.com
    
    # Verify auto-renewal is configured
    sudo certbot renew --dry-run

    Certbot will automatically modify your Nginx configuration to handle HTTPS and redirect HTTP traffic.

    8

    Configure Environment Variables

    Create .env file
    nano /home/remix/my-remix-app/.env
    Example .env configuration
    NODE_ENV=production
    PORT=3000
    DATABASE_URL=your_database_connection_string
    SESSION_SECRET=your_random_session_secret
    Generate a strong session secret and lock down permissions
    # Generate a strong session secret
    openssl rand -hex 32
    
    # Lock down file permissions
    chmod 600 /home/remix/my-remix-app/.env
    
    # Restart PM2 after environment variable changes
    pm2 restart remix-app
    9

    Automated Deployments (Optional)

    Create /home/remix/deploy.sh
    #!/bin/bash
    set -e
    
    APP_DIR="/home/remix/my-remix-app"
    BRANCH="main"
    
    echo "=== Deploying Remix Application ==="
    
    cd "$APP_DIR"
    
    echo "Pulling latest changes..."
    git pull origin "$BRANCH"
    
    echo "Installing dependencies..."
    npm ci --production=false
    
    echo "Building application..."
    npm run build
    
    echo "Reloading PM2 (zero-downtime)..."
    pm2 reload remix-app
    
    echo "=== Deployment complete ==="
    Make executable and run
    chmod +x /home/remix/deploy.sh
    
    # Run whenever you push updates
    /home/remix/deploy.sh

    For fully automated CI/CD, add a GitHub Actions workflow or a webhook that triggers this script on push to your main branch.

    10

    Monitoring & Maintenance

    Application and system logs
    # Application logs
    pm2 logs remix-app --lines 100
    
    # Nginx logs
    journalctl -u nginx --since today
    
    # Resource monitoring
    pm2 monit            # PM2 process dashboard
    htop                 # System resource usage
    df -h                # Disk usage

    Keeping Dependencies Updated

    Update system and audit dependencies
    sudo apt update && sudo apt upgrade -y
    cd /home/remix/my-remix-app && npm audit

    PM2 Log Rotation

    Install PM2 log rotation module
    pm2 install pm2-logrotate
    pm2 set pm2-logrotate:max_size 10M
    pm2 set pm2-logrotate:retain 7
    11

    Troubleshooting

    Application won't start

    Check PM2 error logs with pm2 logs remix-app --err --lines 50. Common issues include missing dependencies (run npm install) or incorrect PORT configuration.

    502 Bad Gateway from Nginx

    The Remix app isn't running or isn't listening on the expected port. Verify with pm2 status and ensure the port in your PM2 config matches the Nginx proxy_pass directive.

    SSL certificate renewal fails

    Ensure port 80 is open and Nginx is running. Test with sudo certbot renew --dry-run. Check that your DNS records still point to the correct IP.

    High memory usage

    Reduce PM2 cluster instances in ecosystem.config.js by setting instances: 1 on smaller VPS plans. Also ensure max_memory_restart is configured.

    Build fails with out of memory

    On VPS plans with 1 GB RAM, add swap space before building:

    Add swap space
    sudo fallocate -l 2G /swapfile
    sudo chmod 600 /swapfile
    sudo mkswap /swapfile
    sudo swapon /swapfile
    echo '/swapfile none swap sw 0 0' | sudo tee -a /etc/fstab

    Remix Application Deployed Successfully!

    Your Remix application is now running in production on a RamNode VPS with PM2 process management, Nginx reverse proxying, SSL encryption, and a deployment workflow. RamNode's SSD-backed VPS infrastructure provides the low-latency I/O and consistent performance that server-rendered frameworks like Remix depend on — starting at just $4/month.