Robin.te.Hofstee

Deploy Next.js App to Ubuntu with Apache2

Robin te Hofstee5 min readViews2
Deploy Next.js App to Ubuntu with Apache2

A step-by-step guide for deploying a Next.js application on an Ubuntu server with Apache2 as a reverse proxy, including setting up HTTPS with Let's Encrypt and updating deployment processes.

Deploying a Next.js App on Ubuntu with Apache2 Reverse Proxy

Deploying a modern web application such as Next.js on an Ubuntu server is a practical way to control your environment directly. This guide will walk you through the process of using Apache2 as a reverse proxy to serve your Next.js app, ensuring that it is accessible over HTTPS with Let's Encrypt.

Prerequisites

Before starting the deployment process, ensure you have:

  • An Ubuntu server
  • Node.js LTS installed
  • A domain name pointing to your server's IP address

Building the Next.js App for Production

npm run build

Building your Next.js app with npm run build packages up all the static files needed for production, optimizing images and assets to ensure a performant delivery.

Testing the Production Build

npm start

Start the development server to test the Next.js app on localhost. This step is crucial to verify that the app builds correctly and runs without issues.

Keeping the App Running with PM2

PM2 helps in keeping your app alive, ensuring it automatically restarts if it crashes or is restarted by a system reboot.

Install PM2

apt-get install pm2

Install PM2 using the package manager.

Starting the App with PM2

pm2 start app-name

Start your Next.js app with PM2, which will keep it running in the background.

Saving PM2 Processes

pm2 save

Save the current state of your app in PM2 for a quicker startup on the next boot.

Starting on Reboot

Edit the PM2 startup script to ensure your app starts automatically when the server boots up.

sudo pm2 startup -p [app_process_id]

Enabling Apache2 Reverse Proxy Modules

Enable the necessary Apache2 modules:

a2enmod proxy
a2enmod proxy_http
a2enmod headers
a2enmod rewrite

These modules are required to act as a reverse proxy, forwarding requests to the Node.js app.

Writing Apache2 Virtual Host Configuration

Create and edit a virtual host file for your domain:

sudo nano /etc/apache2/sites-available/example.com.conf

Include the following configuration in the virtual host file:

<VirtualHost *:80>
  ServerName example.com
  ServerAdmin webmaster@example.com
  DocumentRoot /var/www/html
  ErrorLog ${APACHE_LOG_DIR}/error.log
  CustomLog ${APACHE_LOG_DIR}/access.log combined
 
  RewriteEngine on
  RewriteCond %{HTTP:UPGRADE} !=0 [S]
  RewriteCond %{HTTP:CONNECTION} !=close [S]
  RewriteCond %{HTTP:PROXY} !^$
  RewriteRule .* https://%{HTTP:Host}%{REQUEST_URI} [P,QSA,R=1]
 
  ProxyPass / http://localhost:3000/
  ProxyPassReverse / http://localhost:3000/
</VirtualHost>

This configuration directs HTTP traffic to your Node.js app running on port 3000 and forwards it through the proxy.

Setting Up WebSocket and Headers

To ensure WebSocket connections and proper headers, include these directives:

Alias /websocket /var/www/html/websocket
<Directory /var/www/html/websocket>
    Require all granted
</Directory>
 
Header set X-Next-Js-Host "example.com"

Enabling HTTPS with Let's Encrypt

sudo certbot --apache -v 22

Run Certbot to obtain and install a free SSL certificate from Let's Encrypt. Certbot will set up an Apache virtual host configuration for SSL and reload Apache to apply the changes.

Updating Deployments

To deploy updates to your Next.js app:

rsync -avz ./static/ /var/www/html/

Or for production deployments:

npm run build

Then restart the app using PM2:

sudo systemctl restart apache2

Or for PM2:

pm2 restart app-name

Troubleshooting Common Problems

  • 502 Bad Gateway: Ensure the correct port is being forwarded to your Node.js app and that Apache2 is configured properly to pass requests to it.
  • Wrong Port: Check the port in your Apache2 configuration and make sure it matches the port your Node.js app is running on.
  • Permission Errors: Verify file and directory permissions, especially for the websocket directory.
  • App Not Surviving a Reboot: Ensure the PM2 process is set to start on reboot and that the PM2 process list is not empty.

Apache2 Configuration for Nginx

For Nginx, create a similar configuration in your server block with the appropriate proxy_pass directive and headers.

location / {
    proxy_pass http://localhost:3000/;
    proxy_http_version 1.1;
    proxy_set_header Host $http_host;
    proxy_set_header X-Real-IP $remote_addr;
    proxy_set_header X-Forward-S 1;
    proxy_set_header X-Forward-To $http_x_forwarded_for;
    proxy_set_header X-Forward-For $proxy_add_x_forwarded_for;
    proxy_set_header X-Forward-For IP:port;
    proxy_set end_tags;
}

Remember to replace IP:port with the actual server IP and port where your Next.js app is running.

This deployment tutorial provides a comprehensive guide to deploying a Next.js app on an Ubuntu server with Apache2 as a reverse proxy, complete with HTTPS setup using Let's Encrypt. By following these steps, you can ensure a secure and performant deployment of your web application.

Share this post
Robin te Hofstee

Written by Robin te Hofstee

Technology enthusiast with a deep love for programming. Sharing practical guides on React, Next.js, Linux and self-hosting.

Next.js App Router Deep Dive

2

A practical deep dive into the Next.js App Router: layouts, dynamic routes, Server and Client Components, data fetching, caching, Server Actions, route handlers, and the pitfalls to avoid.