Published On
From Zero to SSL: A Practical Guide to Deploying a Next.js App on a VPS using PM2 and Nginx

Mastering Full-Stack Deployment: Next.js, PM2, and Nginx
As a full-stack developer, I, Saad, often tell clients that a project isn't truly complete until it's running reliably and securely on a live server. While serverless platforms are popular, there are many advantages—cost, control, and custom configuration—to deploying a production Next.js application on a Virtual Private Server (VPS).
This guide details the robust, tried-and-true method I use to deploy complex Next.js applications, ensuring high availability with PM2 and secure serving with Nginx and Certbot. This approach is ideal for the custom web apps and dashboard systems I build for my clients.
Step 1: Prepare Your Next.js Application for Production
Before deployment, ensure your application is built correctly for production.
Build the Project: Run the following command locally or on the server. This creates the .next folder, which contains all the compiled static files and server-side code.
Bash
1npm run build2# or3yarn build
Use start Script: Ensure your package.json has a standard start script that correctly executes the production build:
JSON
1"scripts": {2 "dev": "next dev",3 "build": "next build",4 "start": "next start -p 3000" // Specifies the port for PM25}
Transfer Files: Copy the essential directories (.next, public, and node_modules) and files (package.json, .env.production) to your VPS.
Step 2: Use PM2 for Process Management
Next.js is a Node.js application, and it should never be run directly using node server.js in production. If the process crashes or the server reboots, your app goes down. PM2 (Process Manager 2) solves this by keeping your application process running 24/7, automatically restarting it when it fails, and managing logs.
Install PM2 Globally:
Bash
1npm install -g pm2
Start the Next.js App with PM2: Navigate to your application directory on the VPS and run the start script:
Bash
1pm2 start npm --name "my-next-app" -- start
pm2 start npm: Tells PM2 to run an npm script.
--name "my-next-app": Assigns an easy-to-read name.
-- start: Specifies the start script defined in your package.json.
Ensure Startup: Use pm2 startup and pm2 save to configure PM2 to automatically launch your application processes after a system reboot.
Step 3: Configure Nginx as a Reverse Proxy
Nginx is an incredibly fast, stable web server and, more importantly in this context, a reverse proxy. Since PM2 is running your Next.js app on a specific port (e.g., 3000), Nginx will listen on standard ports (80 for HTTP, 443 for HTTPS) and forward requests to the Node.js process.
Create an Nginx Configuration File: Create a new file, typically located at /etc/nginx/sites-available/yourdomain.conf.
Add Configuration: This basic configuration routes all traffic for your domain to the Next.js app running on port 3000.
Nginx
1server {2 listen 80;3 server_name yourdomain.com www.yourdomain.com;45 location / {6 proxy_pass http://localhost:3000;7 proxy_http_version 1.1;8 proxy_set_header Upgrade $http_upgrade;9 proxy_set_header Connection 'upgrade';10 proxy_set_header Host $host;11 proxy_cache_bypass $http_upgrade;12 }13}
Enable the Configuration: Create a symbolic link to enable the site:
Bash
1sudo ln -s /etc/nginx/sites-available/yourdomain.conf /etc/nginx/sites-enabled/
Test and Restart Nginx:
Bash
1sudo nginx -t2sudo systemctl restart nginx
Step 4: Secure Your Application with HTTPS/SSL (Certbot)
Serving applications over HTTP is a major security risk. As a professional developer, I always ensure my clients' applications are secured with an SSL certificate. Certbot, provided by the Electronic Frontier Foundation (EFF), makes getting a free SSL certificate from Let's Encrypt simple.
Install Certbot: Install Certbot and the Nginx plugin on your VPS.
Bash
1sudo apt install certbot python3-certbot-nginx
Run Certbot: The Nginx plugin automatically reads your Nginx configuration, obtains the certificate, and modifies the Nginx file to redirect HTTP traffic to HTTPS.
Bash
1sudo certbot --nginx -d yourdomain.com -d www.yourdomain.com
Automate Renewal: Certbot automatically creates a cron job to renew the certificate before it expires, ensuring long-term security.
By following these four steps, you achieve a fully production-ready deployment: Fast loading (Nginx), highly available (PM2), and secure (Certbot/SSL). This is the quality and stability I bring to every project, whether it's a small custom web app or a large dashboard system.

Learn Saad's essential tips for secure and scalable Express.js backend design: JWT, Helmet.js, rate limiting, and database injection prevention.

Full-stack developer Saad breaks down the key architectural differences between Node.js/Express.js APIs and Next.js full-stack applications.

Full-stack engineer Saad shares 4 key lessons for transitioning a freelance business into a scalable software agency, focusing on delegation and quality systems
