Deploying your Node.js app on Digital Ocean VPS
Tags: javascript, node, devops
Published: 2019-12-27 05:45:56

So you wrote your Node.js application and need a way to launch it online? Here, I present a guide on setting things up that doesn't require prior knowledge of anything OS-related.

First, let's go through the pros and cons of hosting your app on VPS.

Pros:

* it's cheap
* you can host multiple projects on the same server (perfect for side projects)
* you have a lot of control over server administration

Cons:

* it takes longer to set everything up
* it adds some time to maintain your server

Ultimately, I recommend going this route if you like trying new things and want to learn some DevOps.

For the sake of this guide, you will need your app, a VPS, and a domain name.

## Installing required software

Assuming you're just started with a fresh VPS, you'll likely have a clean Ubuntu. We will need to install Node.js (to run your app), nginx (to set up a reverse proxy; more on that later), and certbot (to issue an SSL certificate). You will also likely need a DB (e.g. MySQL or PostgreSQL), but that's up to you.

The easiest way to install these packages is to use `apt`. Look into documentation of the corresponding projects to get up-to-date instructions.

Once you're done, you will also need to install `pm2`, Node.js process manager:

```sh
npm install pm2
```

And we're done! Now let's set it all up.

## Downloading and running your app

Well, assuming you already have your code hosted on GitHub, this should be easy. `git clone` should make its job.

One thing I should mention is that you will need to [create an SSH key and link it to your GitHub](https://help.github.com/en/github/authenticating-to-github/connecting-to-github-with-ssh). That way, your server will be able to pull your private repository without password input. It's also much faster than type password manually each time you're pulling the newest code on your server.

Let's test an app by running it.

```sh
npm install
node src/app.js
```

## pm2

As I mentioned, pm2 is a process management tool for your Node.js apps. It can do a lot of stuff like logging your app's output, recording hardware resource usage, restarting your app in case it goes down, but right now we're interested in starting an app in "daemon" mode. In short, "daemon" means your app won't stop when you press Ctrl+C or close a console window. Instead, it will run in the background until you explicitly tell it to stop.

To start an app, run

```sh
pm2 start src/app.js --name nodejs-app
```

And that's it! Your app is running in the background, forever.

Now you can control your app by its name:

```sh
pm2 stop nodejs-app
pm2 start nodejs-app
pm2 restart nodejs-app
```

## nginx

Now, nginx is a lot of things, really. Here, we will only scratch its surface by setting up a reverse proxy for our app.

So what's a reverse proxy? Here's one way to put it: reverse proxy is a middleman between client and server that transforms an external route into an internal route. Say, if nginx catches request `http://app1.example.org` it will route that request to an app deployed on port 3000, which is the port that we are using for our app. `http://app2.example.org` can route to an app on port 3001, and so forth.

Our config will include the domain we're expecting requests from, `http://app.example.org`, and the port at which our app is deployed, `3000`.

First, create a configuration for your app:

```
nano /etc/nginx/sites-enabled/app.example.org.conf
```

Then, paste the following:

```
server {
    server_name app.example.org;
    listen 80;
    
    location / {
        proxy_pass http://localhost:3000/;
        proxy_set_header Host $host;
        proxy_cache_bypass $http_upgrade;
    }
}
```

Finally, test that our config is ok and restart nginx.

```
nginx -t
systemctl restart nginx
```

Now, if you actually want to test this thing, you will need a domain. The subdomain will also work fine, just replace all `app.example.org` above with your full domain name.

Woohoo! You (and everyone else!) should now be able to access your app by typing its URL in a browser bar.

## certbot

We're almost done! The final step is to set up an SSL certificate for your app so you can access it via `https`.

We will do this via `certbot` — a CLI tool for the awesome certificate service called Let's Encrypt.

Start by simply typing

```
certbot
```

You will see a list of domains. Likely you will have only one, the one we configured above, so it will be hard to choose the wrong one. Follow the guide, as certbot will create a certificate and update your nginx configuration.

And that's it. Now, when you type your URL, it will work with https. Not only that, but it will also redirect non-secure http calls to https as well (if you chose that during configuration).

## Wrapping up

I hope you didn't get lost in the process and successfully launched your app. If you found yourself spending an hour or two, don't worry: it will be much faster next time. Once you master it, you will be able to push projects to the Web in minutes!