Step-by-Step Guide: Deploying a NextJS App on a VPS
Tags: nextjs, github, vps, nginx
Published: 2023-07-01 19:47:32

Hello, today we will explore how we can deploy a Next.js website on a Ubuntu Virtual Private Server (VPS). A VPS provides the user with the flexibility and control of a dedicated server, allowing them to install and configure their preferred software and applications while sharing the underlying hardware infrastructure with other VPS instances. It offers a cost-effective solution for hosting websites, running applications, and managing online services with improved scalability, security, and customization options.

**To begin to deploy your Next.js app on a VPS, you’ll need to fulfill the following prerequisites:**

1. A Next.js project: If you don't already have a Next.js project, you can create one in your terminal using the command `npx create next-app@latest`.

2. Git & GitHub: You'll need to create a [GitHub](https://github.com/) repository and push your code to that repository using [git](https://git-scm.com/).

3. VPS: Research and select a VPS provider that suits your needs in terms of pricing, features, server location, performance, and customer support. I personally like DigitalOcean's Droplet.

4. Create an SSH key: Create an SSH key on your local machine and add it to your VPS provider.

**Now, let’s dive into the process of deploying your Next.js application to a VPS:**

## 1. Point your domain to the server
Once you have created a VPS, you will be provided with an IP address. Copy this IP address and go to the dashboard of your domain website. In the DNS settings, or if you have changed the nameservers to Cloudflare and are using [Cloudflare DNS](https://www.cloudflare.com/) (which is recommended & free), find the @ record and modify it to point to the IP address of your VPS server. This ensures that your domain is correctly pointed to your VPS, allowing it to be accessible through your domain name.

## 2. Connect to your server
To access the server via SSH, you can use the command `ssh root@your_vps_ip.` However, it is important to note that without an SSH key, you won't be able to connect to the server using your terminal. To enable SSH access, you need to create an SSH key on your local machine and add the corresponding public key to your VPS provider's SSH settings. 

## 3. Update the server
Now we can update the Ubuntu server using the command `sudo apt update && sudo apt upgrade` in your terminal, it will usually take some time. If you see `Configuring openssh-server` just click ok.

## 4. Install NGINX & Certbot
We can install NGINX and Certbot using the command `sudo apt install nginx certbot python3-certbot-nginx`. Certbot will allow you to use let's encrypt which will give your domain an SSL certificate for free.

## 5. Allow firewall access
Run these commands in order

1. `sudo ufw allow "Nginx Full"`

2. `ufw allow OpenSSH`

3. `ufw enable`

## 6. Install NPM
`apt install npm`

## 7. Install pm2 & check if it's working
pm2 is a process manager for Node.js which basically tells Next.js to start or stop running. Install it using the command `npm install -g pm2` and check if it's working by using the following command `pm2 status`. You should see a table with nothing running.

## 8. Install NVM & Node.js
Now you need to run the following command `cd /var/www` and then run these commands in order.

1. `curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.39.1/install.sh | bash`

2. `exec $SHELL`

3. `nvm install --lts`

## 9. Create an SSH key in your VPS server and place in GitHub

1. `cd ~/.ssh`

2. Run this command to create an SSH key `ssh-keygen -t rsa -b 4096 -C your@github_email.com`, replace the email address `your@github_email.com` with the email address that is associated with your GitHub account.

4. Run the command `ls` to see what files exists.

5. `cat id_rsa.pub` And copy the text, it will look something like this `ssh-rsa long_random_text your@github_email.com`.

6. Go to GitHub and click on your avatar upper right corner then click settings, then on the left sidebar click `SSH and GPG keys`, then upper right click `New SSH key`, and paste the key and name it something like `vps_key`.

7. Now run this command `cd /var/www` in your terminal to got back to the root folder.

## 10. Clone Next.js project inside a new folder & install dependencies

Go to your GitHub's project repository and click the green button `Code` and select SSH. It should look something like this.

![Github Code clone](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/e0ovqt1pfrakmm2tv3va.png)

Copy it and edit to look like this `git clone git@github.com:your_github_name/your_repository_name.git your_app_name`.

Now we can clone it into our VPS. Make sure you have run the command `cd /var/www` and then run the command `git clone git@github.com:your_github_name/your_repository_name.git your_app_name` Ensure that you provide a name at the end; otherwise, it will clone into the `var/www` folder, which is not what we want.

Now we can check if it has created a folder using `ls` and then cd into the folder using `cd your_app_name`, and then run the command `npm install` to install all the required dependencies. Then we can run `npm run build` to build the application.

## 11. Create NGINX file and configure it
Run this command `cd /etc/nginx/sites-available` then run `touch your_app_name` the name of the folder u cloned your repository to. Then we can run the command `nano your_app_name`.

Change `domainname.com` in `server_name domainname.com;` to your domain name you pointed to the server and keep `;` and change the `your_app_name` in `alias /var/www/your_app_name/.next/static/;` to folder name you created with git clone. You can use arrow keys to go up and down and to save you can press `CTRL + s` and to exit press `CTRL + X`.

```
server {
        listen 80;
        server_name domainname.com;

        gzip on;
        gzip_proxied any;
        gzip_types application/javascript application/x-javascript text/css text/javascript;
        gzip_comp_level 5;
        gzip_buffers 16 8k;
        gzip_min_length 256;

        location /_next/static/ {
                alias /var/www/your_app_name/.next/static/;
                expires 365d;
                access_log off;
        }

        location / {
                proxy_pass http://127.0.0.1:3000; #change to 3001 for second app, but make sure second nextjs app starts on new port in packages.json "start": "next start -p 3001",
                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;
        }
}


```

Now we need to run `nano /etc/nginx/nginx.conf` in the terminal and change `include /etc/nginx/sites-enabled/*;` to `include /etc/nginx/sites-available/*;`

Then we need to make sure everything is ok, we can run the command `nginx -t`. Next we need to remove default config files, run these commands.

1. `cd /etc/nginx/sites-available`

2. `rm default` 

3. `cd /etc/nginx/sites-enabled`

4. `rm default`

Now we can restart NGINX using the command `systemctl restart nginx`.

## 12. Launch app and create an SSL with let's encrypt

Now we need to go back to the directory of our project using `cd /var/www/name_of_app` and then run the command `pm2 start npm --name name_of_app -- start` but change `name_of_app` to the name of the directory of your project. Last we need to create an SSL using Certbot `sudo certbot --nginx -d domainname.com`. Congratulations you have now successfully deployed an Next.js application on a VPS server 🎉.

### Helpful commands

- Starts the app: `pm2 start npm --name name_of_app -- start` You need to be inside of the application directory.

- Restarts NGINX: `systemctl restart nginx`.

- Adds a SSL using Let's encrypt for a specified domain: `sudo certbot --nginx -d domainname.com`.