Deploy Next.js on Ubuntu with Git, PM2, Nginx, and Certbot
Production-ready guide to deploy a Next.js app on Ubuntu using Git for code, PM2 for process management, Nginx as reverse proxy, and Certbot for HTTPS.
Deploy Next.js on Ubuntu with Git, PM2, Nginx, and Certbot
This guide walks through a production-ready deployment of a Next.js app on Ubuntu using:
- Git for pulling code
- PM2 for process management and restarts
- Nginx as reverse proxy
- Certbot (Let's Encrypt) for HTTPS
Replace placeholders like
<domain>,<repo_url>, and<project_name>with your values.
1) Install Node.js and PM2
sudo apt-get update
# If Node is missing, install from NodeSource (recommended) or apt
# NodeSource example for Node 20 (optional, better than old apt repo):
# curl -fsSL https://deb.nodesource.com/setup_20.x | sudo -E bash -
# sudo apt-get install -y nodejs
# Or use apt's nodejs (ensure it's recent enough for Next.js)
sudo apt-get install -y nodejs npm
# PM2 global
sudo npm install -g pm2
pm2 --version
2) Pull Your Project from Git
cd /var/www
sudo mkdir -p /var/www/<project_name>
sudo chown $USER:$USER /var/www/<project_name>
cd /var/www/<project_name>
git clone <repo_url> .
3) Install Dependencies and Build
npm install
npm run build
4) Start with PM2
pm2 start "npm run start" --name <project_name>
pm2 save
pm2 status
# (Optional) Enable startup at boot
pm2 startup systemd
# Follow PM2's printed command to enable the service, then:
pm2 save
- Default Next.js
npm run startlistens on port 3000. You can setPORT=3000in your env if needed.
5) Install and Configure Nginx
sudo apt install -y nginx
Create a site config (e.g., /etc/nginx/conf.d/<domain>.conf):
server {
root /var/www/html;
server_name <domain>;
location /doc {
try_files $uri $uri/ =404;
}
location / {
proxy_set_header X-Forwarded-For $remote_addr;
proxy_set_header Host $http_host;
proxy_pass http://127.0.0.1:3000;
}
}
Test and reload Nginx:
sudo nginx -t
sudo systemctl reload nginx
If you used
/etc/nginx/sites-available/+ symlink tosites-enabled/, place the file there instead.
6) Get HTTPS with Certbot (Let's Encrypt)
sudo apt-get install -y certbot python3-certbot-nginx
sudo certbot --nginx -d <domain>
Certbot will inject SSL directives and create a redirect server block automatically. A typical HTTPS config looks like:
server {
root /var/www/html;
server_name <domain>;
location /doc {
try_files $uri $uri/ =404;
}
location / {
proxy_set_header X-Forwarded-For $remote_addr;
proxy_set_header Host $http_host;
proxy_pass http://127.0.0.1:3000;
}
listen 443 ssl; # managed by Certbot
ssl_certificate /etc/letsencrypt/live/<domain>/fullchain.pem; # managed by Certbot
ssl_certificate_key /etc/letsencrypt/live/<domain>/privkey.pem; # managed by Certbot
include /etc/letsencrypt/options-ssl-nginx.conf; # managed by Certbot
ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem; # managed by Certbot
}
server {
if ($host = <domain>) {
return 301 https://$host$request_uri;
} # managed by Certbot
server_name <domain>;
listen 80;
return 404; # managed by Certbot
}
Test and reload:
sudo nginx -t
sudo systemctl reload nginx
7) Firewall and Health Checks
# UFW examples
sudo ufw allow OpenSSH
sudo ufw allow 'Nginx Full'
# or specifically ports: sudo ufw allow 80, sudo ufw allow 443
sudo ufw enable
sudo ufw status
Verify:
curl -I http://<domain>should return301to HTTPS.curl -I https://<domain>should return200.pm2 logs <project_name>shows app output.
8) Updates and Zero‑Downtime Restarts
cd /var/www/<project_name>
git pull
npm install
npm run build
pm2 reload <project_name>
pm2 save
Troubleshooting Tips
- Blank page / 502: ensure PM2 app is listening on 127.0.0.1:3000 and Nginx proxy points to the same port.
- Permissions: ensure project dir ownership is correct for the deploy user.
- SSL renewal: Certbot installs a systemd timer/cron for auto-renewal; verify with
sudo systemctl list-timers | grep certbot. - Environment variables: place them in a
.envfile and load via your start script or PM2 ecosystem file.
You're now running Next.js in production with process supervision, reverse proxy, and HTTPS. 🎉
Post Details
Navigation
Related posts
Essential Security Practices to Protect Your Web Applications
Practical, easy-to-apply security improvements for any online project — from security headers, rate limiting, login protection, to safe file uploads and more.
Read more →Generate a Self‑Signed SSL Certificate on Ubuntu (Nginx)
Step-by-step guide to creating a self-signed certificate with OpenSSL and configuring Nginx with secure defaults.
Read more →Automated MongoDB Backup to S3 with Shell Script on Ubuntu
Learn how to create an automated MongoDB backup system using shell scripts that dump databases, compress them, and upload to AWS S3 with automatic cleanup.
Read more →