DEV Community

Muhammad Uzair
Muhammad Uzair

Posted on

VPS Deployment Guide (NEXT JS/REACT JS + GITHUB ACTIONS)

If you follow this exactly, your app will:

  • Deploy from GitHub with .env replaced each time
  • Serve over HTTPS automatically
  • Keep running after reboots
  • Renew SSL certs without downtime

0️⃣ Prerequisites

  • VPS with Ubuntu/Debian OR CentOS/AlmaLinux/Amazon Linux
  • Domain pointing to VPS IP (A record set in DNS)
  • GitHub repo with app code
  • SSH access to VPS
  • GitHub Actions enabled

1️⃣ Install Required Packages

Ubuntu/Debian

sudo apt update && sudo apt upgrade -y
sudo apt install curl git nginx ufw -y
curl -fsSL https://deb.nodesource.com/setup_22.x | sudo -E bash -
sudo apt install -y nodejs
sudo npm install -g pm2
Enter fullscreen mode Exit fullscreen mode

CentOS / AlmaLinux / Amazon Linux

sudo yum update -y
sudo yum install curl git nginx -y
curl -fsSL https://rpm.nodesource.com/setup_22.x | sudo bash -
sudo yum install -y nodejs
sudo npm install -g pm2
Enter fullscreen mode Exit fullscreen mode

2️⃣ Create a Repo-Level Deploy Key

ssh-keygen -t rsa -b 4096 -C "deploy-key"
# Save as: /home/ubuntu/.ssh/deploy_key_example
Enter fullscreen mode Exit fullscreen mode

Press Enter twice for no passphrase.


3️⃣ Add Public Key to GitHub Repo

cat ~/.ssh/deploy_key_example.pub
Enter fullscreen mode Exit fullscreen mode
  • GitHub Repo → Settings → Deploy Keys → Add Deploy Key
  • Name: VPS Deploy Key
  • Paste the public key
  • ✅ Check “Allow write access” (optional)
  • Save

4️⃣ Configure SSH for GitHub

nano ~/.ssh/config
Enter fullscreen mode Exit fullscreen mode

Paste:

Host github-example
  HostName github.com
  User git
  IdentityFile ~/.ssh/deploy_key_example
  IdentitiesOnly yes
Enter fullscreen mode Exit fullscreen mode

5️⃣ Clone the Repo

sudo mkdir -p /var/www
sudo chown $USER:$USER /var/www
cd /var/www
git clone git@github-example:username/repo-name.git example-app
cd example-app
Enter fullscreen mode Exit fullscreen mode

6️⃣ Install Dependencies

npm install
Enter fullscreen mode Exit fullscreen mode

7️⃣ Build the App

Next.js

npm run build
pm2 start npm --name "example-app" -- start
Enter fullscreen mode Exit fullscreen mode

React

npm run build
Enter fullscreen mode Exit fullscreen mode

8️⃣ Install SSL

Ubuntu/Debian

sudo apt install certbot python3-certbot-nginx -y
sudo certbot certonly --nginx -d example.com
Enter fullscreen mode Exit fullscreen mode

CentOS / AlmaLinux / Amazon Linux

sudo yum install certbot python3-certbot-nginx -y
sudo certbot certonly --nginx -d example.com
Enter fullscreen mode Exit fullscreen mode

9️⃣ Nginx Configuration (With SSL)

Ubuntu/Debian

sudo nano /etc/nginx/sites-available/example.com
Enter fullscreen mode Exit fullscreen mode

CentOS / AlmaLinux / Amazon Linux

sudo nano /etc/nginx/conf.d/example.com.conf
Enter fullscreen mode Exit fullscreen mode

Next.js (SSR)

server {
    listen 80;
    server_name example.com;
    return 301 https://$host$request_uri;
}

server {
    listen 443 ssl;
    server_name example.com;

    ssl_certificate /etc/letsencrypt/live/example.com/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/example.com/privkey.pem;

    location / {
        proxy_pass http://localhost:<PORT_OF_YOUR_APP>;
        proxy_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection 'upgrade';
        proxy_set_header Host $host;
        proxy_cache_bypass $http_upgrade;
    }
}
Enter fullscreen mode Exit fullscreen mode

React (Static)

server {
    listen 80;
    server_name example.com;
    return 301 https://$host$request_uri;
}

server {
    listen 443 ssl;
    server_name example.com;

    ssl_certificate /etc/letsencrypt/live/example.com/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/example.com/privkey.pem;

    root /var/www/example-app/build;
    index index.html index.htm;

    location / {
        try_files $uri /index.html;
    }
}
Enter fullscreen mode Exit fullscreen mode

🔟 Enable Config & Restart Nginx

Ubuntu/Debian

sudo ln -s /etc/nginx/sites-available/example.com /etc/nginx/sites-enabled
sudo nginx -t
sudo systemctl restart nginx
Enter fullscreen mode Exit fullscreen mode

CentOS / AlmaLinux / Amazon Linux

sudo nginx -t
sudo systemctl restart nginx
Enter fullscreen mode Exit fullscreen mode

1️⃣1️⃣ Enable PM2 Auto-Start (Next.js Only)

pm2 save
pm2 startup
Enter fullscreen mode Exit fullscreen mode

Follow the command PM2 outputs and run it.


1️⃣2️⃣ Enable Automatic SSL Renewal

sudo certbot renew --dry-run
Enter fullscreen mode Exit fullscreen mode

Add a cron job:

sudo crontab -e
Enter fullscreen mode Exit fullscreen mode

Paste:

0 3 * * * /usr/bin/certbot renew --quiet && /bin/systemctl reload nginx
Enter fullscreen mode Exit fullscreen mode

1️⃣3️⃣ GitHub Actions Deployment Pipeline

Next.js

name: Deploy Next.js to VPS

on:
  push:
    branches: [ main ]

jobs:
  deploy:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v3

      - name: Deploy via SSH
        uses: appleboy/ssh-action@master
        with:
          host: ${{ secrets.VPS_HOST }}
          username: ${{ secrets.VPS_USER }}
          key: ${{ secrets.VPS_KEY }}
          script: |
            cd /var/www/example-app
            git pull origin main
            rm -f .env
            echo "${{ secrets.ENV_FILE }}" > .env
            npm install
            npm run build
            pm2 restart example-app
Enter fullscreen mode Exit fullscreen mode

React

name: Deploy React to VPS

on:
  push:
    branches: [ main ]

jobs:
  deploy:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v3

      - name: Deploy via SSH
        uses: appleboy/ssh-action@master
        with:
          host: ${{ secrets.VPS_HOST }}
          username: ${{ secrets.VPS_USER }}
          key: ${{ secrets.VPS_KEY }}
          script: |
            cd /var/www/example-app
            git pull origin main
            rm -f .env
            echo "${{ secrets.ENV_FILE }}" > .env
            npm install
            npm run build
            sudo systemctl restart nginx
Enter fullscreen mode Exit fullscreen mode

1️⃣4️⃣ Add GitHub Secrets

In GitHub Repo → Settings → Secrets → Actions:

  • VPS_HOST → VPS IP
  • VPS_USERubuntu (or VPS username)
  • VPS_KEY → contents of ~/.ssh/deploy_key_example
  • ENV_FILE → entire .env file contents

✅ Key Differences

Feature Next.js (SSR) React (Static)
Build Command npm run build npm run build
Serve Method PM2 Node.js process Nginx static serve
Nginx Role Reverse proxy to Node server Directly serve /build
Port Required <PORT_OF_YOUR_APP>
PM2 Required

Top comments (0)