Trendy Coder Logo
  • Home
  • About
  • Blog
  • Newsletter

How To Install and Host Next.js With cPanel

Posted on: May 01 2024
By Dave Becker
Hero image for How To Install and Host Next.js With cPanel

If you're developing Next.js web applications, you might be considering what options are available for hosting. Is it really necessary to host in the Cloud or can you host on traditional Shared or VPS hosting solutions?

Surprisingly, I found that Shared and VPS hosting services offer a great way to install and host applications using Next.js with cPanel.

In this article I'll show how to easily install and host a Next.js application on a Shared hosting provider, including:

  • How to create a Node.js app using cPanel for your domain
  • How to manage Node.js versions
  • Create, build and deploy a Next.js application
  • How to use SSH to run NPM processes like a pro

What is Next.js Shared or VPS Hosting

Most websites and blogs these days are usually PHP based sites that use Shared or VPS hosting plans.

Since Next.js is a React based framework it requires a Node.js environment to run and host a React based web application. The good news is that most Shared and VPS hosting services support Node.js these days.

Why install Next.js on Shared or VPS Hosting?

There's a lot of advantages to using traditional hosting, including:

  • More affordable budget for sites just starting out
  • Moving to the cloud can require more complex setup and knowledge, where Shared and VPS hosting providers have everything ready to go to get up and running quickly.
  • A wide range of services in cPanel.
  • Most developers are familiar with cPanel and configuring services.

Next.js is a highly performant framework for building next generation web applications and can serve static or server side rendered HTML payloads in most cases making it highly optimal for SEO performance and ranking.

Requirements to Install Next.js

For this article, you need access to the following:

  • A hosting provider that supports Node.js in cPanel, in this tutorial I'm using A2 Hosting which uses CloudLinux Node.js services but any provider should be relatively similar using cPanel.
  • Admin access to cPanel and hosting information for SSH, FTP and SFTP access.

Step 1 Create a Node.js Application

The first step is to create a new Node.js application using the cPanel Node.js Application Manager.

  1. Log into cPanel and scroll down to the > Tools > Software section

  2. Select the Setup Node.js App link.

Setup Node.js Application
  1. This will take you to a page listing all of your applications. The table will be empty if you don't have any applications created yet. Click on the Create Application button.
Create Application
  1. Fill in the form with information about your site. I will use the yourdomain.com placeholder to illustrate how to use an actual registered domain name and also replace username with your actual username.
Node.js application

Here's some details on what these fields are used for.

  • Node.js version: I would recommend setting the node version to at least v18, since earlier versions <= v14 are not maintained by Node.js any longer. Also, setting v18 will use a higher version of npm. However, pick the version that your application requires.

  • Application mode: This is the value of the process.env.NODE_ENV that a Node.js might use for configuration.

  • Application root: This is the folder where the application code will be located. I typically use the domain name for this folder name, in this case yourdomain.com but it can be any directory name. This directory is not automatically created, so it will have to manually be added. Generally, I use the home directory on the server. For example, /home/username/yourdomain.com.

  • Application URL: Select one of the available registered domain names from the drop down menu. Generally you can leave the second text box empty, unless you want to have an application context path. For example, adding /blog will append to the domain as yourdomain.com/blog. This will be the url to access the new application.

  • Application startup file: Set this value to server.js for now because we're going to create this file in following section. This will be the file that Node.js will execute when starting your application.

  • Passenger log file: This is the log file location for all of the log and error outputs.

Press the Create button to create the application. The new application will now show in Web Applications tab.

Step 2 Creating a Next.js Application

Now, let's create a Next.js application that we can use to install and run.

Let's create the application locally and then we'll zip it up and upload it to the remote server under the directory we designated in the Application root setting in the previous section.

Run the following command in a terminal to generate a new Next.js application.


npx create-next-app@latest

Currently the create-next-app@latest is at version 14.x.x and requires at least Node.js v18.17 or later


It will prompt for some user input. Let's give it a project name of demo-app for now. Just accept all of the remaining prompts using defaults for now or select the options you prefer.


What is your project named? demo-app
Would you like to use TypeScript? No / Yes
Would you like to use ESLint? No / Yes
Would you like to use Tailwind CSS? No / Yes
Would you like to use `src/` directory? No / Yes
Would you like to use App Router? (recommended) No / Yes
Would you like to customize the default import alias (@/*)? No / Yes
What import alias would you like configured? @/*

Once this completes, the Next.js application will be ready and there will be a new directory demo-app with the following contents.

# This content is likely to change depending on generator version

├── .eslint.json
├── .gitignore
├── app
├── next-env.d.ts
├── next.config.mjs
├── node_modules
├── package.json
├── package-lock.json
├── postcss.config.js
├── public
├── README.md
├── tailwind.config.ts 
└── tsconfig.json


Step 3 Create the startup file

As I mentioned earlier, we'll need to add a startup.js file in the root of the project directory.

The Node.js application in cPanel will execute this file to start the server.

It's recommended not to use package.json script tasks to start and stop the Node.js server.

Using a server.js file gives that control over to the Node.js Application Manager to start and stop the application.

You can think of it as running Node.js the traditional way.

node server.js

To create the startup.js file enter the following command inside the demo-app directory.


touch server.js

Copy this custom server code into the server.js file and save it.

This is the recommended sample code from the Next.js team. You can further customize it as needed but this is usually sufficient.


/server.js
const { createServer } = require('http')
const { parse } = require('url')
const next = require('next')
 
const dev = process.env.NODE_ENV !== 'production'
const hostname = 'localhost'
const port = 3000
// when using middleware `hostname` and `port` must be provided below
const app = next({ dev, hostname, port })
const handle = app.getRequestHandler()
 
app.prepare().then(() => {
  createServer(async (req, res) => {
    try {
      // Be sure to pass `true` as the second argument to `url.parse`.
      // This tells it to parse the query portion of the URL.
      const parsedUrl = parse(req.url, true)
      const { pathname, query } = parsedUrl
 
      if (pathname === '/a') {
        await app.render(req, res, '/a', query)
      } else if (pathname === '/b') {
        await app.render(req, res, '/b', query)
      } else {
        await handle(req, res, parsedUrl)
      }
    } catch (err) {
      console.error('Error occurred handling', req.url, err)
      res.statusCode = 500
      res.end('internal server error')
    }
  })
    .once('error', (err) => {
      console.error(err)
      process.exit(1)
    })
    .listen(port, () => {
      console.log(`> Ready on http://${hostname}:${port}`)
    })
});

You'll find it's easier to just check this file into your code repo and just make sure to always include it when deploying.


Step 4 Deploying the Next.js application

The first thing to do is build the Next.js application

cd demo-app 

npm run build

This will create an optimized build for a production deployment and create a new directory named .next which is were all of the bundled code is located.

Once the build is done, we'll need to upload the files to the remote server.

You could use a utility like FileZilla or SFTP if you prefer. For this step, I'm just going to zip up the contents and use cPanel File Manager to move the files.

Here are the only resources we'll need to upload to the remote server:

├── .next
├── next.config.mjs
├── package.json
├── package-lock.json
├── public
└── server.js

There's no need to include node_modules since we'll need to run the install process once the code is uploaded on the remote server.

You can use whatever utility for compressing the files. I'm just using the built-in compression tool in Mac to select and zip these files.

Compress Next.js Files

Now, just upload the zip (or tar) file to the /home/username/yourdomain.com directory on the remote server.


Step 5 Install the Next.js application

As a good practice, it's always best to stop your Node.js application in the Node.js Application Manager if it's running and restart it after a successful install.

Also, you'll want to make sure the directory is empty before deploying new content.

As you rollout and deploy more changes, it's a good practice to make a backup of the previous contents of this directory for a rollback restore point if there are any unforseen issues.

Example of a rollback zip/tar file demo-app--rollback-4-4-2024.zip

Extract the new content into the clean Application root directory /home/username/yourdomain.com.

The directory should now have the following content.


└── yourdomain.com
    ├── .next
    ├── next.config.mjs
    ├── package.json
    ├── package-lock.json
    ├── public
    └── server.js

Now, the npm install can be ran so all of the node_modules are available. There's a couple options on how to run this command.

  • Use the cPanel Node.js Application Manager interface
  • Use an SSH terminal session (Recommended)

Running NPM install in cPanel

You can run the install process in the cPanel Node.js Application Manager interface by clicking the Edit link. You'll see the following screen to start the install process.

Install npm modules

Running NPM install using SSH

I highly recommend running npm install from the command line using an SSH configured connection to your remote server.

If your hosting provider is running CloudLinux Node.js, you'll need to run the following command to activate the nodeenv for the session. This just makes sure the npm command is available in your SSH session terminal.

Just replace the username and yourdomain.com with your account details.

SSH terminal session

# activate the `nodeenv`
source /home/username/nodevenv/yourdomain.com/18/bin/activate && cd /home/username/yourdomain.com


The Node.js Application Manager interface provides a copy link on the Edit page for these commands to activate nodeenv.

Now you can use npm commands as you normally do on your local development.

npm install

Just for reference I'm including some additional npm install flags that you might need to use at times if the install hangs or fails.

At a bare minimum I always run npm install --omit=optional since certain binaries are usually blocked by networks for security reasons.

# Does not install optionalDependencies like large binaries 
# that are usually blocked by networks from downloading and can
# cause the npm install process to hang and timeout.  
npm install --omit=optional

# Installs the dependencies regardless of the peerDependencies.  
# Sometimes this is necessary when using higer versions of Node.js
# and the peerDependencies "engines" settings do not match. 
# You'll get errors. 
npm install --legacy-peer-deps

# Installs the dependencies by force, similar to --legacy-peer-deps.
npm install --force


It's very important to get a successful npm install before proceeding, otherwise you may see "Module not found issues" or you won't be able to start your application successfully.


Starting the Node.js Application

Now that the code has been deployed and all the packages are now installed, we are ready to start up the application.

On the Edit page of Node.js Application Manager interface, you'll see the start button.

Install npm modules

Once the application starts, open a new browser window and point to your domain url and you will see the running demo-app Next.js application.

That's it! Pretty easy to get your Next.js applications up and running on Shared or VPS hosting services.


Overview of Node.js and CloudLinux

Some hosting providers use CloudLinux behind the scenes to virtually manage all of the Node.js applications in cPanel. This section will cover some details about the nodeenv environment when using command line, such as:

  • How nodeenv manages different Node versions.
  • How nodeenv manages node_modules.
  • How package.json and package-lock.json referenced.

Hopefully this section will help to avoid any downtime because of deployment issues. By following some basic guidelines, you'll be able to easily deploy with confidence.

Since these environments are usually virtual, running NPM processes is not like normal NPM operations on local environments.

Linking the Node.js Environment

When we ran the following command earlier to link and activate the nodeenv when using a SSH to do the npm install, it does a couple things behind the scenes worth mentioning.

If you follow the source path, it links to the nodeenv directory under the /home/username directory, where cPanel Node.js adds all of the Node.js and npm executables.

  • username: Your account username
  • yourdomain.com: This is the path to your Application root we set earlier when creating a Node.js application.
source /home/username/nodevenv/yourdomain.com/18/bin/activate && cd /home/username/yourdomain.com

Since we've set the Node.js version to v18.18.2 when we created the application earlier, it will do the following:

  • Adds a version folder (i.e. yourdomain.com/18).
  • creates a subdirectory for bin binaries.
  • creates a subdirectory for lib which is where node_modules is actually located.

Since we only created one nodeenv for Node.js version 18, we should see the following.


└── nodeenv
    └── yourdomain.com 
        └── 18
            ├── bin
            │   ├── activate
            │   ├── node
            │   ├── npm
            │   └── set_env_vars.py
            └── lib  #lib directory
                ├── node_modules (link)
                ├── package.json (link /home/username/yourdomain.com/package.json)
                └── package-lock.json (link /home/username/yourdomain.com/package-lock.json)
    

After running the npm install process, you'll see that it added a node_modules symlink to the application root directory /home/username/yourdomain.com.

It also added symlinks to the package.json and package-lock.json files.


└── yourdomain.com
    ├── .next
    ├── next.config.mjs
    ├── node_modules (link ~/nodevenv/yourdomain.com/18/lib/node_modules)
    ├── package.json
    ├── package-lock.json
    ├── public
    └── server.js

One thing to keep in mind is that everytime you run the npm install command it will reestablish this linking.

As most Javascript Node.js developers know, sometimes you may need to remove the node_modules and reinstall for various reasons. The best place to do this is in the lib directory.

To avoid any downtime, here's a few suggestions when running the install process:

  • Don't remove node_modules unless absolutely necessary since it can be quite large and use up metered system bandwidth resources to reinstall.
  • Use a package-lock.json that is in sync with the package.json when deploying new changes.
  • Only deploy incremental package changes in package.json, this way the install process will only update whats needed.

General guidelines using Node.js in cPanel

As a general rule of thumb and to avoid any issues, I recommend to follow some simple guidelines.


└── nodeenv
    └── yourdomain.com 
        └── 18
            ├── bin
            └── lib
    

  • bin: Should not be removed or changed manually ever, let the cPanel Node.js application maintain this directory based on your application settings.
  • lib: Anything inside this directoy can be removed as needed for development needs but always make sure to run npm install after any changes to reinstall and reestablish the symlinks to node_modules.

Trying to remove the node_module symlink in the actual Application root directory is not the same and will just break the link and leave your application without a way to resolve npm modules.

So if you keep these basic guidelines in mind, you should have a great experience setting up multiple Node.js apps running Next.js under one domain or subdomains if needed.

Conclusion

I hope this article has provided some useful information on how to host Next.js applications using traditional hosting providers. Moving to a cloud platform is really going to be based on your application and business requirements.

The other aspect is that you would need a fair amount of DevOps and Cloud Engineering experience to even setup all of the services needed, where a traditional hosting solution is quickly manageable using cPanel.

So there will be some tradeoffs here and there but at least you have some alternative options.

Topics

SEOLinuxSecuritySSHEmail MarketingMore posts...

Related Posts

Hero image for Boost Payload CMS with Search: Step-by-Step Tutorial
Posted on: August 11 2025
By Dave Becker
Boost Payload CMS with Search: Step-by-Step Tutorial
Hero image for Server-Side Pagination Made Easy in Payload CMS
Posted on: August 11 2025
By Dave Becker
Server-Side Pagination Made Easy in Payload CMS
Hero image for Payload CMS: Getting Started Using the New Join Field
Posted on: August 11 2025
By Dave Becker
Payload CMS: Getting Started Using the New Join Field
Hero image for Maximizing Efficiency: The Power of Payload CMS Blocks
Posted on: August 11 2025
By Dave Becker
Maximizing Efficiency: The Power of Payload CMS Blocks
Hero image for Create Custom Forms Using Payload CMS Form Builder Plugin
Posted on: August 11 2025
By Dave Becker
Create Custom Forms Using Payload CMS Form Builder Plugin
Hero image for Payload CMS SEO Plugin: Boosting Your Site's Search Ranking
Posted on: April 04 2025
By Dave Becker
Payload CMS SEO Plugin: Boosting Your Site's Search Ranking
Hero image for GraphQL Optimization in Payload CMS
Posted on: April 04 2025
By Dave Becker
GraphQL Optimization in Payload CMS
Hero image for Exploring the Game-Changing Features of Payload CMS 3.0
Posted on: April 04 2025
By Dave Becker
Exploring the Game-Changing Features of Payload CMS 3.0
Hero image for Document Nesting With Payload's Nested Docs Plugin
Posted on: April 04 2025
By Dave Becker
Document Nesting With Payload's Nested Docs Plugin
Hero image for Payload CMS Collections: How They Streamline Content Management
Posted on: April 04 2025
By Dave Becker
Payload CMS Collections: How They Streamline Content Management
Trendy Coder Logo
Resources
  • Blog
Website
  • Home
  • About us
Subscribe

Get the latest news and articles to your inbox periodically.

We respect your email privacy

© TrendyCoder.com. All rights reserved.