Deploy a Nuxt 3 App on a VPS (Minimal Setup)
Tags: vps, nuxt, devops, webdev
Published: 2023-08-07 15:36:07

In this tutorial I will cover how to quickly deploy your Nuxt 3 application on a virtual private server (VPS) of your choice with Ubuntu 22.04 installed.

I will use as little tools as possible for this to work so you can get your app up and running fast and understand basic concepts of deploying web apps.

From there you have a starting point for you to further improve your deployment processes as you need to.

## What you need for this tutorial:
- Nuxt 3 project, ready to deploy
- SSH access to a VPS with Ubuntu 22.04 installed and a user account with sudo privileges
- Basic knowledge of Linux terminal commands helps

I am running all of this on a Mac, but the commands I use here should also work on Windows and Linux. If you have trouble executing certain commands make sure to check if they are supported by your OS.

## Summary of all steps (detailed instructions below)
1. Connect to your server
2. Install Node.js
3. Install a web server
4. Copy your code to the VPS and run it
5. Improving this setup

## Step 1: Connect to your server
As a starting point, I am assuming that your VPS was freshly setup, it has Ubuntu 22.04 installed and you did not touch it yet.

By default most VPS providers will give you root access via password authentication.

Open a new terminal window and connect to your server with the following command:

```
ssh root@YOUR-VPS-IP-ADDRESS
```

When prompted to add the host to your known hosts file type `yes` and enter the root password of your server. You should now be connected to the server.

If you are using a different account other than root make sure to use the credentials that you have and execute all further commands with sudo privileges.

## Step 2: Install Node.js

Next, we need to install Node.js and NPM.

To install these dependencies you could run `apt update && apt install nodejs npm`. However this will only install the latest versions of Node and NPM.

In most cases your project uses a specific version of Node. That’s why we will use a tool called “nvm” which helps us to install the Node.js version that we need and be able to quickly switch it if necessary.

Install nvm by running:

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

Take note that this command fetches a script from the internet and runs it with bash. Always double check that script comes from a trusted source or even better: look through the script first, before running it on your hardware.

After that run

```
source ~/.bashrc
```

in order to load the script into your shell and be able to use it.

Install the Node version of your choice by running:

```
nvm install 18.3.0
```

I installed 18.3.0 but you can install any version you want and as many different Node versions as you want. To see if the installation was successful list all installed node versions with

```
nvm list
```

The output should contain the node version that you just installed. The first version you install will become the default version. If you installed more than one you have to specifiy which version your system should use by running:

```
nvm use 18.3.0
```

And verify that it worked and node is installed by typing

```
node -v
```

which should output `v18.3.0`. A compatible version of NPM will be installed automatically. You can check with

```
npm -v
```

## Step 3: Install a web server

Since your VPS is connected to the internet everyone can come by and knock on its doors.

A web server is like a receptionist. It will sit on your machine and wait for people to knock and then point them to the service that they asked for. In other words: it listens for connections on specific ports and forwards the request to a service handling the request.

Usually port 80 is used for http and 443 for https connections therefore you should open these ports on your VPS to the public.

When it comes to choosing a web server there are several good options. The most well known are Apache and Nginx. For most of us either of them is a good choice but we will opt for a different web server here.

It is called Caddy. Caddy is a production ready web server and it comes with the additional benefit of being super simple to setup and automatically providing SSL certificates for us. This saves some time setting up the server so let’s go.

On your VPS, install Caddy by running the following commands:

```
sudo apt install -y debian-keyring debian-archive-keyring apt-transport-https
curl -1sLf 'https://dl.cloudsmith.io/public/caddy/stable/gpg.key' | sudo gpg --dearmor -o /usr/share/keyrings/caddy-stable-archive-keyring.gpg
curl -1sLf 'https://dl.cloudsmith.io/public/caddy/stable/debian.deb.txt' | sudo tee /etc/apt/sources.list.d/caddy-stable.list
sudo apt update
sudo apt install caddy
```

After the installation, Caddy will be running as a systemd service named caddy in the background.

Next thing we need to do is point our server to our Nuxt.js app. By default Nuxt apps run on port 3000 so we’ll tell caddy to forward traffic to port 3000. Yes, the Nuxt app is still missing on the server but we will get to that soon.

Create a file in the home directory of your VPS called Caddyfile:

```
nano Caddyfile
```

Paste the following configuration into the Caddyfile:

```
:443
reverse_proxy :3000
```

This configuration specifies that every request coming in at port 443 (all https traffic) will be internally redirected to port 3000. This process is called reverse proxying. But what about http traffic hitting on port 80? This is handled by default, Caddy will automatically redirect http traffic to https.

Take note, that in order to accept https traffic, you have to connect a custom domain. To do so, buy a domain from a provider of your choice and update the A record to point to the IP address of your server. 

Exit the configuration file with CTRL + X and save your changes by confirming with y. To apply the configuration restart the web server with

```
caddy restart
```

Make sure to run this commands from the same folder where your Caddyfile is located. And that’s it. Your server is ready to roll.



## Step 4: Copy Your Code

Now it’s time to copy your code to the server.

We will only put on the server what is minimally required to run our code. We build our Nuxt app first on our local machine and then only transfer the .output folder to the server.

Since Nuxt 3 this output folder contains everything we need and the code in it can be executed standalone by default.

When your app is ready to deploy, jump into your project folder and run

```
npm run build
```

or whatever build command you use on your local machine. You should find a folder called .output in the root of your project. If you don’t see that folder, it could be its name starts with a . which means it is hidden in the filesystem so make sure you display hidden files.

Now we transfer the folder to our server. You can use the scp command for that. In your Nuxt project folder run:

```
scp -r root@YOUR-VPS-IP-ADDRESS:~/.output .output
```

This will copy our local .output folder to the home directory on your VPS.

SSH back onto your webserver by running:

```
ssh root@YOUR-VPS-IP-ADDRESS
```

Check that the folder has arrived with a quick

```
ls -a
```

The terminal should list your .output folder and the Caddyfile configuration file.

Finally run your Nuxt app with

```
node .output/server/index.mjs
```

## Improvements
This was a pretty minimal setup and while it’s enough to get you going, in a production ready environment you usually want something more secure, robust and scalable. Here are some Ideas of how to improve this:


1. Setup backups: Backups are one of the most basic ways to protect yourself from dataloss and having to set up your server again in case of an issue. Most VPS providers give you the option to create onsite backups with the click of a button. For more serious projects it makes sense to also come up with an offsite backup plan.
2. Security: There are a bunch of tweaks and settings that you can apply on your VPS in order to make it harder for hackers to break into your machine. This process is called hardening. Just to name a few these measures include: disable root ssh access, create another user with limited permissions instead, disable password authentication and use key based authentication instead, change default ports, disable all unused services (like e.g. USB connections), uninstall all unused software, install a firewall and only open ports that you really need, limit permissions on files and folders… If you plan on running a production ready application that handles sensitive data, you should definitively dive into this topic and apply these measures first.
3. Add secrets management: In most projects you want to be able to quickly swap out some configuration without having to rebuild and redeploy your application. This is where secrets manger come into play.
4. Autorestart: Sometimes your application crashes, your server breaks down, there is a power outage or you need to restart your server after an upgrade. To improve the reliability of your Nuxt app make sure to include some kind of auto restart that quickly revives your systems.
5. Automate stuff: The steps are the same over and over again. If you need to deal with frequent deployments it makes sense to automate stuff. Write a bash script that executes the steps listed above for you or use an automation tool like Ansible (https://www.ansible.com/) in order to simplify your server setup. However take note that coding these scripts and learning automation software is a hustle and will take time and effort.
6. Containerize you application: One way of improving the scalability of your app is by running it inside a container with a tool like Docker (https://www.docker.com/). Using docker comes with additional benefits but simply speaking a container houses all dependencies necessary to run your application like e.g. Node.js. By using containers you don’t always have to setup servers from scratch over and over again but you just quickly throw your container on a server and the app will run.
7. Setup a CI/ CD pipeline: In order to further automate your deploys you can start integrating some sort of continuous integration or continuous deployment strategy. Connect a Github repository and run your deploy scripts with every push to the repo. That way your application will always be up to date and you can very easily ship new features.
These are just a few ideas on how to improve your deployment process. The possibilities are endless and so will be the time that you will spend with working on these processes.

That’s why we created a little tool that gives you all these features out of the box and breaks down deploying your app directly from a GitHub repository to your own VPS to just a few clicks. On top it enables you to run multiple apps on a single machine saving you some money. Check it out under [https://sliplane.io](https://sliplane.io?utm_source=deploy-nuxt3-on-vps)

## Summary
Deploying a Nuxt 3 app on a VPS can be done fairly quickly. After installing Node.js and a Webserver like Caddy, just add some minimal config, build your app locally, copy your code to the Server and execute it there.

However this is only the beginning. As listed above the possibilities to improve your setup are endless and so is the amount of time you could spend with it. If you want to save yourself some hassle check out our tool https://sliplane.io that provides you with professional tools to simplify deploying to your own VPS.