Deploy Next.js to Contabo VPS
Tags: nextjs, contabo, vps, namecheap
Published: 2024-01-23 17:44:09

## Introduction
A few days ago I experienced a significant increase users count on one of my web services.

The current server capabilities became insufficient, so I started thinking about scaling.

For hosting my service, I used PaaS (Platform as a Service) [render.com](http://render.com/)

For those who are unfamiliar with PaaS - it's a service that helps you deploy your code in just a few clicks. All you need to do is connect your GitHub repository and add a few settings to your environment variables (host, port, database URL, etc.). On the other hand, such ease of setup comes at a relatively high cost for maintenance. Here are the pricing plans of render.com.

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/1y0g6dypyrqa9gj3vbot.png)

And here are the pricing plans of [Contabo](https://contabo.com/).


![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/34p9xjz8kx3mc93mx0l7.png)

As you can see, the difference is huge!

I don't want to offend render.com in any case - if you need to quickly deploy an MVP and test the viability of your idea, it’s a great and very reliable service.

## Getting started

In this tutorial, I will cover the following topics:

* Setting VPS server with **Contabo**
* **Nginx** and **pm2**
* Installing a domain name with **Namecheap** and adding a SSL certificate to serve website through the HTTPS.

First of all, we need to visit [Contabo] (https://contabo.com/), register and choose a pricing plan.

I chose the simplest one for *$5.50*. Next, select the term length and region. I chose US East, which cost me an additional *$1.35*. Default one Storage Type and raw Ubuntu OS for the image.


![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/anlb016bmgw4bpey1o0g.png)

Then, choose a password for your `root` user. This information is essential to connect to your vps via ssh.

Next, visit the [https://my.contabo.com/vps](https://my.contabo.com/vps). You should see something like this.


![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/lh1tb2wwuecz1gzjw53e.png)

Now, let’s connect to our server. 

Open your terminal and type:
```bash 
ssh root@<ip address>
```
+ your password.

Update your server
```bash
sudo apt-get update
```
Install Node.js and npm
```bash
sudo apt-get install nodejs
sudo apt-get install npm
```
And check actual version
```bash
node -v
npm -v
```

In my case, Node.js version 10 was installed, which was not suitable for my needs. You might encounter the same issue, so I will show you an alternative way to install Node.js.

First, you need to add the NodeSource repository to your system. NodeSource provides up-to-date versions of Node.js. To do this, we need first to install curl and then run this command followed by a bash script from NodeSource.

```bash
sudo apt-get install curl
curl -fsSL https://deb.nodesource.com/setup_18.x | sudo -E bash -
sudo apt-get install nodejs
```
Instead of 18, you can chose any Node.js version you need.

Then, let’s add Next.js app to our VPS.

```bash
mkdir app && cd app
git clone <repository_name>
cd <repository_name>
```

Install dependencies, build and run our app.

```bash
npm install
npm run build
npm start
```

Now, by visiting `http://<ip_address>:3000`, you can see that your application is already running. The only issue is that we can't execute any other commands in the terminal. Also, if the terminal is closed, the application will stop working.

To resolve this issue, let's install pm2.
```bash
npm install -g pm2
```

PM2 is a popular process manager for Node.js applications. It's used to manage and keep Node.js applications online 24/7, ensuring they are kept running in the background even after the system reboots or crashes.

Then, let’s create a configuration file in our `<repository_name>` directory.

```bash
nano ecosystem.config.js
```

```js
module.exports = {
  apps: [{
    name: "next-app",
    script: "npm",
    args: "start",
    instances: 1,
    autorestart: true,
    watch: false,
    max_memory_restart: "8G",
    exec_mode: "cluster"
 }]
}
```

Here we define the name of our application for pm2. Number of instances to run. Also, we are setting that if the application uses more than *8 gigabytes* of memory, pm2 will restart it automatically.

`watch: false` is need to tell the pm2 to not restart our app every time when the files in the current directory change.

Now, let’s start our app.

```bash
pm2 start next-app
```

To stop, reload or get current status of the app you can use following commands.
```bash
pm2 stop next-app
pm2 reload next-app
pm2 status
```

Setting up Nginx

Nginx is a powerful open-source web server software. It's known for its high performance, stability, rich feature set, scalability, and low resource consumption. Nginx is used not just as a web server but also as a reverse proxy, load balancer, and HTTP cache. 

Install nginx
```bash
sudo apt-get install nginx
```
Add custom configuration file
```bash
cd /etc/nginx/conf.d
nano next_app.conf
```

```bash
server {
    server_name yourdomain.com www.yourdomain.com;

    location / {
        proxy_pass <ip_address>:<port>;
        proxy_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection 'upgrade';
        proxy_set_header Host $host;
        proxy_cache_bypass $http_upgrade;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-For $scheme;
    }

    error_page 405 =200 $uri;
}
```

This configuration sets up a reverse proxy for a web application, directing traffic from `yourdomain.com` and `www.yourdomain.com` to a Next.js app.

Setting up domain

We need to visit a [Namecheap](https://www.namecheap.com/), register and buy domain. 

For simplicity, I will use `yourdomain.com` as a placeholder for your domain.

After purchasing a domain, you should see something like this.


![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/2df088o9yxsewk9xfgxu.png)

Now, go back to the Contabo and navigate to the [https://my.contabo.com/dns](https://my.contabo.com/dns) (DNS Zone Management).

Here we need to put `yourdomain.com` and select ip address.


![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/jic9o8fe3vdhkk8703zp.png)

Then, visit edit DNS Zone for `yourdomain.com` page. If everything is fine you will see something like this.


![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/7vmnxh2p9un8s237oi9z.png)

Now, go back to the Namecheap and press **Manage** button for `yourdomain.com`.

In the nameservers section, select Custom DNS and put following values into it.


![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ruh1cc9otfbbczvdib27.png)

Please note that after adding your domain name from Namecheap and pointing it to a Contabo VPS server IP address, it may take up to 48 hours to complete the propagation process. But in most cases, the domain propagation process can occur in a few minutes.

SSL Certificate

We are planning to serve our app over the HTTPS, so it is essential to setup an ssl certificate at our server.

It can be done in two ways.

* Buy your own SSL certificate.
* Obtain Let's Encrypt certificate, which is free and much easier to setup.

In this tutorial I will use the second approach.

```bash
sudo apt-get update
sudo apt-get install certbot python3-certbot-nginx
sudo certbot --nginx -d  yourdomain.com -d www.yourdomain.com
```

Certbot will modify your Nginx configuration automatically and obtain the certificate.

Now all we have to do is to test our nginx configuration

```bash
sudo nginx -t
```
and run the server
```bash
sudo service nginx start
```