Next.js Deployment with Apache HTTP Server, PM2, and Systemd
DevOps18 min read

By Akshay Singh

Share this article:

How to Host a Next.js App on a VPS Using Apache, PM2, and Systemd

While Nginx is often the go-to choice for modern Node.js applications, Apache remains one of the most widely used and reliable web servers in the world. If you already have an Apache infrastructure, or if you prefer its rich module ecosystem and .htaccess flexibility, you can easily use it to host a Next.js application.

When deploying Next.js to production, you cannot simply run npm run start in a detached terminal. You need a robust architecture:

  1. A Process Manager (PM2 or Systemd) to keep the Next.js process alive, restart it on crashes, and start it automatically when the server reboots.
  2. A Reverse Proxy (Apache) to handle incoming HTTP/HTTPS connections, manage SSL certificates, and efficiently route traffic to your Node.js application.

In this guide, we will walk through the entire process of deploying a Server-Side Rendered (SSR) Next.js application on a Linux VPS using Apache.


Prerequisites

Before diving in, ensure you have:

  • A Linux VPS running Ubuntu 22.04 LTS or 24.04 LTS.
  • SSH access with a non-root user that has sudo privileges.
  • Node.js and npm installed on your server.
  • A domain name pointing to your server's public IP address.
  • A Next.js application ready for deployment.

Step 1: Prepare and Build Your Next.js Application

First, SSH into your server:

ssh your-username@your-server-ip

Create a directory for your application. The standard location for web applications in Linux is /var/www/.

sudo mkdir -p /var/www/my-next-app
sudo chown -R $USER:$USER /var/www/my-next-app
cd /var/www/my-next-app

Upload or clone your Next.js project into this directory. Once your code is present, install the dependencies:

npm install

Next.js requires a build step for production. This compiles your React code, optimizes assets, and prepares the Server-Side Rendering (SSR) output:

npm run build

Step 2: Process Management (PM2 or Systemd)

Next, we need to run the application in the background and ensure it stays alive. You have two excellent options: PM2 (a feature-rich Node.js process manager) or Systemd (the native Linux service manager). Choose the one that best fits your workflow.

Option A: Using PM2

PM2 is incredibly popular in the Node ecosystem because it is easy to use and provides great logging and monitoring tools.

  1. Install PM2 globally:
sudo npm install -g pm2
  1. Start your Next.js application:

We instruct PM2 to run the npm command and pass start as an argument.

pm2 start npm --name "my-next-app" -- start
  1. Ensure PM2 Restarts on Server Boot:

Run PM2's startup script generator:

pm2 startup

PM2 will output a command (e.g., sudo env PATH=$PATH:/usr/bin pm2 startup systemd -u your-username...). Copy and paste that exact command into your terminal.

Finally, save your current process list:

pm2 save

Option B: Using Native Systemd

If you prefer not to install global npm packages and want to rely on native Linux tooling, Systemd is the perfect choice.

  1. Create a new Systemd service file:
sudo nano /etc/systemd/system/my-next-app.service
  1. Add the following configuration:

Make sure to replace your-username with your actual Linux user, and verify your Node.js path (usually /usr/bin/node or /usr/bin/npm).

[Unit]
Description=My Next.js App
After=network.target

[Service]
Environment=NODE_ENV=production
Type=simple
User=your-username
WorkingDirectory=/var/www/my-next-app
ExecStart=/usr/bin/npm run start
Restart=on-failure
RestartSec=10

[Install]
WantedBy=multi-user.target
  1. Enable and start the service:

Reload the systemd daemon, start the service, and enable it on boot:

sudo systemctl daemon-reload
sudo systemctl start my-next-app
sudo systemctl enable my-next-app

You can check the status at any time with sudo systemctl status my-next-app.


Step 3: Install and Configure Apache

Now that Next.js is running on port 3000, we need Apache to listen on port 80 (HTTP) and route the traffic to it.

  1. Install Apache:
sudo apt update
sudo apt install apache2 -y
  1. Enable Required Apache Modules:

To act as a reverse proxy, Apache needs specific modules enabled:

sudo a2enmod proxy
sudo a2enmod proxy_http
sudo a2enmod proxy_wstunnel
sudo a2enmod rewrite

Restart Apache to apply the changes:

sudo systemctl restart apache2
  1. Create an Apache Virtual Host:

Create a configuration file for your domain:

sudo nano /etc/apache2/sites-available/my-next-app.conf

Add the following configuration, replacing example.com with your domain:

<VirtualHost *:80>
    ServerName example.com
    ServerAlias www.example.com

    # Route traffic to the Next.js app on port 3000
    ProxyPreserveHost On
    ProxyPass / http://localhost:3000/
    ProxyPassReverse / http://localhost:3000/

    # Support for WebSockets (essential for Next.js features)
    RewriteEngine On
    RewriteCond %{HTTP:Upgrade} =websocket [NC]
    RewriteRule /(.*)           ws://localhost:3000/$1 [P,L]

    ErrorLog ${APACHE_LOG_DIR}/my-next-app-error.log
    CustomLog ${APACHE_LOG_DIR}/my-next-app-access.log combined
</VirtualHost>

Understanding the Configuration:

  • ProxyPreserveHost On ensures the original Host header from the client is passed to Next.js.
  • ProxyPass and ProxyPassReverse forward the standard HTTP requests to port 3000.
  • The RewriteEngine block detects WebSocket connections (used by Next.js for features like Hot Module Replacement in dev, or specific real-time library integrations) and routes them using the ws:// protocol.
  1. Enable the Virtual Host:
sudo a2ensite my-next-app.conf

Test your Apache configuration for syntax errors:

sudo apache2ctl configtest

If it returns Syntax OK, restart Apache:

sudo systemctl restart apache2

Navigate to your domain in a browser. Your Next.js application should now be live!


Step 4: Secure with SSL (Let's Encrypt)

Serving production traffic over plain HTTP is a security risk. Let's secure it with a free SSL certificate using Certbot.

  1. Install Certbot and the Apache plugin:
sudo apt install certbot python3-certbot-apache -y
  1. Obtain the SSL Certificate:

Run Certbot, which will automatically verify your domain and update your Apache configuration.

sudo certbot --apache -d example.com -d www.example.com

Follow the prompts. Certbot will configure SSL, update your Virtual Host file, and set up automatic HTTP-to-HTTPS redirection.


Conclusion

Deploying a Next.js application on Apache requires configuring a process manager and setting up a reverse proxy, but the result is a highly stable and performant production environment.

By using PM2 or Systemd, your application is guaranteed to stay online through crashes and reboots. By placing it behind Apache, you benefit from a mature, enterprise-grade web server capable of handling SSL termination, logging, and robust traffic routing.

nextjsapachepm2systemdvpsdevopsdeployment
TheDailyDevsTheDailyDevs
TheDailyDevs is a developer-first blog and knowledge hub created by passionate engineers to share real-world development tips, deep-dive tutorials, industry insights, and hands-on solutions to everyday coding challenges. Whether you're building apps, exploring new frameworks, or leveling up your dev game, you'll find practical, no-fluff content here, updated daily.