Backend Framework Guide

    Deploy SvelteKit

    SvelteKit is a modern full-stack framework with server-side rendering, static site generation, and minimal JavaScript overhead. Deploy production-ready on RamNode's VPS hosting.

    Node.js 22 LTS
    PM2 Cluster Mode
    Nginx + HTTP/2
    Let's Encrypt SSL
    1

    Prerequisites

    • A RamNode VPS with Ubuntu 24.04 LTS installed (1 GB RAM minimum, 2 GB recommended)
    • SSH access to your VPS as root or a sudo-enabled user
    • A domain name pointed to your VPS IP address (A record configured in DNS)
    • A SvelteKit project ready to deploy (using the Node adapter)
    • Basic familiarity with the Linux command line

    💡 Tip: For most SvelteKit applications, RamNode's 2 GB RAM plan provides more than enough headroom for Node.js, Nginx, and your application. Scale up only when your traffic demands it.

    2

    Initial Server Setup

    Connect and update system
    ssh root@your-server-ip
    apt update && apt upgrade -y

    Create a Deploy User

    Running applications as root is a security risk. Create a dedicated deploy user:

    Create deploy user
    adduser deploy
    usermod -aG sudo deploy
    su - deploy

    Configure the Firewall

    Enable UFW
    sudo ufw allow OpenSSH
    sudo ufw allow 80/tcp
    sudo ufw allow 443/tcp
    sudo ufw enable
    sudo ufw status
    3

    Install Node.js

    SvelteKit requires Node.js 18.13 or later. Node.js 22 LTS provides excellent performance improvements for SSR workloads and long-term support through April 2027.

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

    Prepare Your SvelteKit Project

    Install the Node Adapter

    SvelteKit uses adapters to target different deployment environments. For a VPS deployment with SSR, you need the Node adapter:

    Install adapter
    npm install -D @sveltejs/adapter-node

    Configure svelte.config.js

    svelte.config.js
    import adapter from '@sveltejs/adapter-node';
    
    /** @type {import('@sveltejs/kit').Config} */
    const config = {
      kit: {
        adapter: adapter({
          // Output directory for the build
          out: 'build',
          // Precompress assets with gzip and brotli
          precompress: true,
          // Environment variable prefix
          envPrefix: 'APP_'
        })
      }
    };
    
    export default config;

    Add Environment Variables

    Create a .env file in your project root (do NOT commit to version control):

    .env
    APP_HOST=127.0.0.1
    APP_PORT=3000
    NODE_ENV=production
    ORIGIN=https://yourdomain.com
    5

    Deploy to Your VPS

    Option A: Deploy with Git (Recommended)

    Clone and build on VPS
    # On your VPS as the deploy user
    cd /home/deploy
    git clone https://github.com/yourusername/your-sveltekit-app.git app
    cd app
    
    # Install dependencies and build
    npm ci --omit=dev
    npm run build

    Option B: Upload a Pre-Built Bundle

    Build locally and transfer
    # On your local machine
    npm run build
    
    # Transfer the build output to your VPS
    scp -r build package.json package-lock.json deploy@your-server-ip:~/app/
    
    # On the VPS, install production dependencies
    cd ~/app && npm ci --omit=dev

    Test the Build

    Verify the app starts
    cd ~/app
    PORT=3000 HOST=127.0.0.1 node build/index.js
    # Press Ctrl+C once confirmed
    6

    PM2 Process Management

    PM2 keeps your SvelteKit app running continuously, restarts it on crashes, and manages log rotation.

    Install PM2
    sudo npm install -g pm2

    Create Ecosystem File

    ~/app/ecosystem.config.cjs
    module.exports = {
      apps: [{
        name: 'sveltekit-app',
        script: 'build/index.js',
        cwd: '/home/deploy/app',
        instances: 'max',
        exec_mode: 'cluster',
        env: {
          NODE_ENV: 'production',
          PORT: 3000,
          HOST: '127.0.0.1',
          ORIGIN: 'https://yourdomain.com'
        },
        max_memory_restart: '300M',
        log_date_format: 'YYYY-MM-DD HH:mm:ss',
        error_file: '/home/deploy/logs/sveltekit-error.log',
        out_file: '/home/deploy/logs/sveltekit-out.log'
      }]
    };

    Cluster mode with instances: 'max' spawns one process per CPU core. On RamNode's 2-core VPS plans, this gives you two worker processes for better request handling.

    Start and persist the application
    # Create the logs directory
    mkdir -p ~/logs
    
    # Start the app with PM2
    cd ~/app
    pm2 start ecosystem.config.cjs
    
    # Verify it's running
    pm2 status
    pm2 logs sveltekit-app --lines 20
    
    # Save the process list and enable startup on boot
    pm2 save
    sudo env PATH=$PATH:/usr/bin pm2 startup systemd -u deploy --hp /home/deploy
    7

    Configure Nginx Reverse Proxy

    Nginx handles SSL termination, static asset caching, and HTTP/2 connections in front of your Node.js application.

    Install Nginx
    sudo apt install -y nginx
    Create /etc/nginx/sites-available/sveltekit
    server {
        listen 80;
        listen [::]:80;
        server_name yourdomain.com www.yourdomain.com;
    
        # Redirect all HTTP to HTTPS
        return 301 https://$host$request_uri;
    }
    
    server {
        listen 443 ssl http2;
        listen [::]:443 ssl http2;
        server_name yourdomain.com www.yourdomain.com;
    
        # SSL certificates (added by Certbot in Step 8)
        # ssl_certificate /etc/letsencrypt/live/yourdomain.com/fullchain.pem;
        # ssl_certificate_key /etc/letsencrypt/live/yourdomain.com/privkey.pem;
    
        # Security headers
        add_header X-Frame-Options "SAMEORIGIN" always;
        add_header X-Content-Type-Options "nosniff" 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
                   image/svg+xml;
    
        # Proxy to SvelteKit
        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;
        }
    
        # Cache immutable static assets aggressively
        location /immutable/ {
            proxy_pass http://127.0.0.1:3000;
            expires 1y;
            add_header Cache-Control "public, immutable";
        }
    }
    Enable the site
    sudo ln -s /etc/nginx/sites-available/sveltekit /etc/nginx/sites-enabled/
    sudo rm /etc/nginx/sites-enabled/default
    sudo nginx -t
    sudo systemctl reload nginx
    8

    SSL with Let's Encrypt

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

    Certbot automatically installs a systemd timer that checks for certificate renewal twice daily. No cron job is needed.

    9

    Automated Deployments

    Create ~/deploy.sh
    #!/bin/bash
    set -e
    
    APP_DIR=/home/deploy/app
    echo "[$(date)] Starting deployment..."
    
    cd $APP_DIR
    git pull origin main
    npm ci --omit=dev
    npm run build
    
    pm2 reload ecosystem.config.cjs
    echo "[$(date)] Deployment complete!"
    Make executable and run
    chmod +x ~/deploy.sh
    
    # Run whenever you push changes
    ./deploy.sh

    For automated CI/CD, trigger this script via a GitHub Actions workflow using SSH, or set up a webhook endpoint that calls it on push events.

    10

    Security Hardening

    1. Disable root SSH login

    Edit /etc/ssh/sshd_config and set PermitRootLogin no, then restart the SSH service.

    2. Set up SSH key authentication

    Copy your public key with ssh-copy-id deploy@your-server-ip, then disable password authentication in sshd_config.

    3. Install Fail2Ban

    Run sudo apt install -y fail2ban to automatically block repeated failed login attempts.

    4. Enable automatic security updates

    Run sudo apt install -y unattended-upgrades and configure it to apply security patches automatically.

    5. Set up log rotation

    PM2 handles its own log rotation with pm2 install pm2-logrotate, keeping your disk space in check.

    11

    Performance Tuning

    Node.js Memory Settings

    For a 2 GB RAM VPS, set appropriate memory limits to prevent out-of-memory issues:

    Add to ecosystem.config.cjs env section
    NODE_OPTIONS: '--max-old-space-size=512'

    Nginx Tuning

    Optimize /etc/nginx/nginx.conf
    worker_processes auto;
    worker_connections 1024;
    
    # Enable sendfile for static assets
    sendfile on;
    tcp_nopush on;
    tcp_nodelay on;
    
    # Keepalive settings
    keepalive_timeout 65;
    keepalive_requests 100;

    SvelteKit Precompression

    With precompress: true in your adapter config, SvelteKit generates .gz and .br files at build time. Nginx can serve these directly:

    Add to Nginx server block
    location /immutable/ {
        proxy_pass http://127.0.0.1:3000;
        gzip_static on;
        brotli_static on;     # Requires nginx-mod-brotli
        expires 1y;
        add_header Cache-Control "public, immutable";
    }
    12

    Troubleshooting

    IssueSolution
    502 Bad GatewayVerify PM2 is running with pm2 status. Check that port 3000 matches in both ecosystem config and Nginx proxy_pass.
    App crashes on startCheck pm2 logs sveltekit-app. Common causes: missing ORIGIN env variable, incorrect build path, or missing dependencies.
    CORS errorsSet the ORIGIN environment variable to your exact domain URL including protocol (https://yourdomain.com).
    SSL certificate issuesRun sudo certbot renew --force-renewal. Check that DNS A records point to your VPS IP.
    High memory usageReduce PM2 cluster instances or lower max-old-space-size. Monitor with pm2 monit.
    Slow buildsEnsure your VPS has at least 2 GB RAM. SvelteKit's Vite bundler benefits from available memory during compilation.

    Quick Reference Commands

    CommandDescription
    pm2 statusView running processes
    pm2 logs sveltekit-appTail application logs
    pm2 reload ecosystem.config.cjsZero-downtime restart
    pm2 monitReal-time resource monitoring
    sudo nginx -tTest Nginx configuration
    sudo systemctl reload nginxApply Nginx changes
    sudo certbot renewRenew SSL certificates
    sudo ufw statusCheck firewall rules

    SvelteKit Application Deployed Successfully!

    Your SvelteKit application is now running in production on a RamNode VPS with PM2 process management, Nginx reverse proxy with HTTP/2, SSL encryption, and an automated deployment workflow. Consider adding a CDN like Cloudflare for edge caching and explore RamNode's higher-tier plans as your traffic grows.