Wednesday, April 9, 2025
Complete Guide: Deploy Next.js to VPS with Nginx, PM2 & GitHub Auto-Deploy
Posted by

Complete Guide to Deploying Next.js on VPS
Deploying a Next.js application to a VPS is a common task for developers looking to run their app in a production environment. In this guide, we will walk through setting up the server, deploying your application, setting up a reverse proxy with Nginx, managing your application with PM2, and automating deployments with GitHub Actions. We’ll be using Ubuntu 22.04 LTS for the server setup and GitHub Actions for automating the deployment pipeline.
Before You Start:
This guide assumes you have basic knowledge of Linux commands and GitHub workflows. We will use Ubuntu 22.04 for demonstration, but the steps can be adapted for other distributions as well.
Prerequisites
Before we begin, make sure you have the following prerequisites:
1. VPS Requirements
- Ubuntu 22.04 server (or any other Ubuntu-based VPS) - Root SSH access to the server - Domain name pointed to the server IP for production use
2. Development Setup
- A Next.js project stored in a GitHub repository - A working production build of the project locally - An SSH key pair for GitHub access (so the server can securely fetch updates from GitHub)
Server Setup
Step 1: Initial Server Configuration
To begin, you need to connect to your VPS and set it up. We’ll start by logging in to the server, updating packages, and installing the required software.
# Connect to your server
ssh root@your_server_ip
# Update the system's package list and upgrade existing packages
apt update && apt upgrade -y
# Install necessary tools: Git for version control, Nginx for reverse proxy, Node.js and npm for running Next.js
apt install -y git nginx nodejs npm
# Set up the firewall to allow HTTP traffic (for Nginx) and SSH connections
ufw allow 'Nginx Full'
ufw allow ssh
ufw enable
Security Tip:
Important: Always use SSH keys for authentication and create a non-root user for deployment. This improves security and helps avoid any accidental system changes as the root user.
Step 2: Configure a Non-Root User
It’s a good practice to create a non-root user for application deployment. Running commands as root can be dangerous, as it allows accidental system-wide changes. You can create a user and grant them sudo privileges:
# Add a new user
adduser deploy
# Give the user sudo privileges
usermod -aG sudo deploy
# Switch to the new user
su - deploy
Application Deployment
Now that the server is prepared, let's focus on deploying the Next.js application.
Step 3: Clone the Repository and Install Dependencies
We’ll begin by cloning your Next.js project from GitHub and installing the necessary dependencies.
Clone Repository
# Clone your Next.js project repository from GitHub
git clone https://github.com/yourusername/your-nextjs-app.git
cd your-nextjs-app
Install Packages
# Install required Node.js packages and build the production version of the app
npm install
npm run build
Step 4: Configure PM2 to Manage the Application
Next.js runs as a Node.js process, so we will use PM2 (Process Manager 2) to keep the application running in the background. PM2 ensures that the app is restarted automatically if it crashes or when the server reboots.
# Install PM2 globally
npm install -g pm2
# Start the application in production mode using PM2
pm2 start npm --name "next-app" -- start
# Save the PM2 process list to ensure it persists across reboots
pm2 save
# Enable PM2 to start on system boot
pm2 startup systemd
Nginx Reverse Proxy Configuration
Nginx will act as a reverse proxy to forward incoming HTTP requests to the Next.js app, which will be running on a local port (3000). This setup ensures that Nginx handles incoming traffic and provides better performance, security, and scalability.
Step 5: Create Nginx Configuration File
We need to create a new Nginx configuration file for our application. This file will specify that Nginx should forward requests to the Next.js app running on port 3000.
server {
listen 80;
server_name yourdomain.com; # Replace with your domain
location / {
# Forward requests to the local Next.js app
proxy_pass http://localhost:3000;
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;
}
}
Step 6: Enable the Nginx Configuration
Now, let’s enable the new configuration and restart Nginx to apply the changes.
# Create a symbolic link to enable the site
ln -s /etc/nginx/sites-available/next-app.conf /etc/nginx/sites-enabled/
# Test Nginx configuration for errors
nginx -t
# Restart Nginx to apply changes
systemctl restart nginx
SSL Bonus:
Bonus: You can secure your site with HTTPS by using Let's Encrypt. Install
the required packages and run the following command to automatically configure
SSL certificates: bash apt install certbot python3-certbot-nginx certbot --nginx -d yourdomain.com
Automating Deployment with GitHub Actions
GitHub Actions allow us to automate deployments. Every time you push updates to your repository, GitHub will trigger a workflow to automatically deploy the changes to your VPS.
Step 7: Set Up GitHub Actions Workflow
Create a file .github/workflows/deploy.yml
in your repository. This workflow file will define the steps to deploy your Next.js app to the VPS using SSH.
name: Auto Deploy
on:
push:
branches:
- main # Trigger deployment when changes are pushed to the 'main' branch
jobs:
deploy:
runs-on: ubuntu-latest # Use the latest Ubuntu for the runner
steps:
- name: SSH Deploy
uses: appleboy/ssh-action@v1
with:
host: ${{ secrets.SSH_HOST }} # The server IP
username: ${{ secrets.SSH_USER }} # The deployment user
key: ${{ secrets.SSH_PRIVATE_KEY }} # SSH private key stored in GitHub secrets
script: |
# Navigate to the app directory
cd /var/www/your-nextjs-app
# Pull the latest changes from the repository
git pull origin main
# Install any new dependencies
npm install
# Build the app for production
npm run build
# Restart the app with PM2
pm2 restart next-app
Step 8: Configure GitHub Secrets
For security, store your server credentials (SSH keys, username, and host) as secrets in your GitHub repository. This prevents sensitive information from being exposed in your workflow.
- Go to your repository on GitHub.
- Navigate to Settings > Secrets > New Repository Secret.
- Add the following secrets:
- SSH_HOST: Your server IP address
- SSH_USER: The user with deployment permissions (e.g.,
deploy
) - SSH_PRIVATE_KEY: Your SSH private key used for authentication
Add these secrets in GitHub repo settings: - SSH_HOST: Server IP - SSH_USER: Deployment user - SSH_PRIVATE_KEY: SSH private key
Now, whenever you push to the main
branch, the GitHub Action will deploy the latest code to your server automatically!
🎉Conclusion
n this guide, we’ve walked through the process of setting up a production-grade environment for your Next.js application on a VPS. By leveraging Nginx as a reverse proxy, PM2 for process management, and automating deployments with GitHub Actions, we’ve built a robust, scalable, and easy-to-maintain infrastructure. 💻⚙️
Deploying applications to a VPS is an essential skill for developers looking to take control of their own infrastructure. With these steps, you can ensure your app runs smoothly with minimal downtime and optimized performance. 🌐💪
Happy coding and deploying! 🚀💙