Vercel is a premier cloud platform for hosting modern JavaScript frameworks, most notably Next.js, React, SvelteKit, and Nuxt. However, as web traffic grows, developers and businesses often encounter high serverless execution costs, execution time limits, and bandwidth charges on managed serverless platforms. Moving your Next.js and Vercel-based projects to a dedicated Aveshost Linux Virtual Private Server (VPS) delivers significant cost savings, dedicated compute resources, custom caching, and full control over your server environment.

In this comprehensive, step-by-step tutorial, you will learn how to deploy and self-host a Next.js / Vercel application on a Linux VPS across Ubuntu, Debian, AlmaLinux, Rocky Linux, RHEL, and CentOS using Node.js, PM2 Process Manager, Nginx Reverse Proxy, and Let’s Encrypt SSL, along with automated CI/CD deployment via GitHub.


Prerequisites


Step 1: Install Node.js LTS and Build Essentials

Next.js requires Node.js (version 18.x, 20.x, or 22.x LTS). Install the latest NodeSource repository for your distribution:

On Ubuntu & Debian:

# Update system packages
sudo apt update && sudo apt upgrade -y

# Add NodeSource repository for Node.js 20.x LTS
curl -fsSL https://deb.nodesource.com/setup_20.x | sudo -E bash -

# Install Node.js, npm, git, and build tools
sudo apt install -y nodejs git build-essential

On AlmaLinux, Rocky Linux, RHEL & CentOS:

# Update system packages
sudo dnf upgrade -y

# Add NodeSource repository for Node.js 20.x LTS
curl -fsSL https://rpm.nodesource.com/setup_20.x | sudo bash -

# Install Node.js, npm, git, and development tools
sudo dnf install -y nodejs git gcc-c++ make

Verify your installation:

node -v && npm -v

Step 2: Install PM2 Process Manager

On Vercel, serverless functions run automatically. On a Linux VPS, we use PM2 (Production Process Manager) to keep your Next.js application running 24/7, restart it automatically if it crashes, and boot it on system restarts:

sudo npm install -g pm2

Step 3: Prepare Your Next.js Application for Self-Hosting

To optimize performance and reduce memory usage on a VPS, configure Next.js to use Standalone Output.

  1. In your project’s next.config.js (or next.config.mjs), add output: 'standalone':
    /** @type {import('next').NextConfig} */
    const nextConfig = {
      output: 'standalone', // Optimized standalone production server
      reactStrictMode: true,
    };
    
    module.exports = nextConfig;

Step 4: Clone and Build Your Project on the VPS

  1. Create a dedicated directory for your web applications:
    sudo mkdir -p /var/www/nextjs-app
    sudo chown -R $USER:$USER /var/www/nextjs-app
  2. Clone your repository from GitHub:
    git clone https://github.com/yourusername/your-repo.git /var/www/nextjs-app
    cd /var/www/nextjs-app
  3. Create your production environment variables file (matching your Vercel Environment Variables):
    nano .env.production

    Add your database URLs, API keys, and secrets:

    NODE_ENV=production
    PORT=3000
    DATABASE_URL=your_database_connection_string
    NEXT_PUBLIC_API_URL=https://domain.com/api
  4. Install dependencies and build the production bundle:
    npm ci
    npm run build

Step 5: Start the Next.js App with PM2

Launch the standalone production server using PM2:

# Start the application on port 3000
pm2 start npm --name "nextjs-app" -- start

# Save PM2 process list and configure auto-start on server boot
pm2 save
pm2 startup

(Copy and run the command generated by pm2 startup if prompted).

Check the live status and logs of your app:

pm2 status
pm2 logs nextjs-app

Step 6: Install and Configure Nginx as Reverse Proxy

Nginx will handle incoming HTTP/HTTPS traffic, serve static assets with ultra-fast caching, and forward dynamic Server-Side Rendered (SSR) requests to your Next.js application on port 3000.

1. Install Nginx:

# On Ubuntu / Debian:
sudo apt install -y nginx

# On AlmaLinux / Rocky Linux / RHEL:
sudo dnf install -y nginx
sudo systemctl enable --now nginx

2. Create the Nginx Server Block:

Create a new configuration file for your domain:

sudo nano /etc/nginx/conf.d/nextjs-app.conf

Paste the production reverse proxy configuration (replace domain.com with your actual domain):

server {
    listen 80;
    server_name domain.com www.domain.com;

    # Gzip Compression
    gzip on;
    gzip_types text/plain text/css application/json application/javascript text/xml application/xml application/xml+rss text/javascript;

    # Static assets caching (_next/static)
    location /_next/static {
        alias /var/www/nextjs-app/.next/static;
        expires 365d;
        access_log off;
    }

    # Public static files
    location /public {
        alias /var/www/nextjs-app/public;
        expires 30d;
        access_log off;
    }

    # Reverse proxy dynamic requests to PM2 Node.js server
    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;
    }
}

3. SELinux & Nginx Permissions (For AlmaLinux / Rocky Linux):

# Allow Nginx to proxy network connections to local ports
sudo setsebool -P httpd_can_network_connect 1

4. Test and Reload Nginx:

sudo nginx -t
sudo systemctl reload nginx

Step 7: Install Free Let's Encrypt SSL Certificate

Secure your website with automatic HTTPS encryption using Certbot:

# Install Certbot
# Ubuntu/Debian:
sudo apt install -y certbot python3-certbot-nginx

# AlmaLinux/Rocky Linux:
sudo dnf install -y epel-release
sudo dnf install -y certbot python3-certbot-nginx

# Obtain and install SSL certificate automatically
sudo certbot --nginx -d domain.com -d www.domain.com

Certbot will configure SSL certificates and enable automatic renewals via systemd timers.


Step 8: Set Up Automated GitHub CI/CD Deployment (Vercel-like Workflow)

To replicate Vercel’s automated deployment experience whenever you push code to GitHub:

  1. On your VPS, create a deployment script:
    nano /var/www/nextjs-app/deploy.sh
  2. Add the build and reload sequence:
    #!/bin/bash
    cd /var/www/nextjs-app
    git pull origin main
    npm ci
    npm run build
    pm2 reload nextjs-app
  3. Make the script executable:
    chmod +x /var/www/nextjs-app/deploy.sh
  4. In your GitHub Repository, add a GitHub Actions Workflow (.github/workflows/deploy.yml) to trigger SSH execution of ./deploy.sh on every commit to main.

Frequently Asked Questions & Troubleshooting

Q: Why does my app display 502 Bad Gateway?
A: A 502 Bad Gateway error indicates Nginx cannot connect to port 3000. Run pm2 status and pm2 logs to ensure your Next.js application is active, and confirm SELinux policy allows network connections (sudo setsebool -P httpd_can_network_connect 1).

Q: How do I handle image optimization (next/image) on a VPS?
A: Next.js handles on-demand image optimization automatically on your VPS using the built-in sharp library. Run npm install sharp in your project directory for high-speed image compression.


Need Further Assistance?

If you need assistance migrating your Next.js or Vercel projects to an Aveshost Linux VPS, our expert cloud engineering team is available 24/7. Feel free to submit a support ticket through your client area for prompt assistance.

Was dit antwoord nuttig? 0 gebruikers vonden dit artikel nuttig (0 Stemmen)