Serving a Gatsby site from DigitalOcean using Nginx
Tags: gatsby, digitalocean, nginx
Published: 2020-01-04 13:29:48

---
title: Serving a Gatsby site from DigitalOcean using Nginx
published: true
date: 2020-01-03 00:00:00 UTC
tags: "gatsby, digitalocean, nginx"
canonical_url: https://www.delvalle.dev/posts/serving-gatsby-from-digital-ocean-nginx/serving-gatsby-from-digital-ocean-nginx/
---

It is well known that sites made with Gatsby can be deployed to Netlify. This blog is hosted on Netlify for free! But you could as well be in the need to deploy a Gatsby site to another service like DigitalOcean.

I have been working on a Node + React application for some months now and it is hosted on DigitalOcean. A couple of weeks ago I stumbled upon a new requirement. I had to deploy a Gatsby blog to that same server and access it through the same domain.

The process was very straightforward but I had to do some tweaks to both my Gatsby and Nginx configurations. I’ll describe it here step by step. It shouldn’t take you more than an hour to set everything up.

Before moving on:

- I assume you already have a DigitalOcean account and an Ubuntu Droplet created. The commands used in this guide may also work on other Linux Droplets but I worked with an Ubuntu one. 
- Make sure you have [Nginx installed on your Droplet](https://www.digitalocean.com/community/tutorials/how-to-install-nginx-on-ubuntu-18-04) as we are gonna use it to serve our Gatsby generated static files. 
- You have your Gatsby project hosted on a remote repository like Github. For this guide, I’m just gonna clone a Gatsby starter from the starters library. You’ll need Git installed on your Droplet to clone your repo. 
- Optional: Install Node and Npm on your Droplet. I chose to perform the build on my Droplet so I needed NPM installed for both installing all the dependencies and performing the build but you can also just build your Gatsby site locally, push the built files to your repo and pull them from your Droplet. 

## <svg aria-hidden="true" focusable="false" height="16" version="1.1" viewbox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg>SSH into your Droplet

So to perform all the cloning, building and setup we’ll need to remotely connect to our Droplet via SSH. Here’s the [guide](https://www.digitalocean.com/docs/droplets/how-to/connect-with-ssh/) for doing so if you’ve never done it.

## <svg aria-hidden="true" focusable="false" height="16" version="1.1" viewbox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg>Clone your Gatsby project

Once in your Droplet, clone your Gatsby project from your remote repo. I did this at the root to keep it simple. For this guide, I’m just gonna clone a [gatsby starter I liked](https://www.gatsbyjs.org/starters/justinformentin/gatsby-v2-tutorial-starter/) by [Justin Formentin](https://github.com/justinformentin)

`git clone https://github.com/justinformentin/gatsby-v2-tutorial-starter.git`

## <svg aria-hidden="true" focusable="false" height="16" version="1.1" viewbox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg>Install dependencies and build project

You can ignore this step if you already had your built files pushed to your repo. This way you can avoid installing the dependencies and building on your Droplet. I preferred to perform all this on my Droplet.

On the terminal, go into your project folder

`cd gatsby-v2-tutorial-starter`

Let’s first install gatsby-cli globally:

`npm i -g gatsby-cli`

Then install all the project dependencies:

`npm install`

Now perform the build with either:

`gatsby build`

Or

`npm run build`

If everything went well, a `/public` folder should’ve been created. It includes the static files that we’re gonna serve through Nginx.

## <svg aria-hidden="true" focusable="false" height="16" version="1.1" viewbox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg>Configure Nginx to serve your Gatsby static files

Before configuring Nginx, we have to create a symbolic link from where your Gatsby static files are to where Nginx expects to serve these files.

Nginx serves files that are in the var/www folder but instead of moving our files over there we just create a symlink:

`sudo ln -s /home/jose/blog/public /var/www/blog/html`

Remember to put the path where your Gatsby files are as the first parameter. As for the second parameter, make sure you created a directory in there, in my case I created a `/blog` directory and an `/html` directory inside it.

Now, to configure Nginx to serve those files we have to open the default Nginx config file and make some tweaks. Let’s first open the file using nano:

`sudo nano /etc/nginx/sites-available/default`

Paste the following config in there. Preferably after the **server\_name** property.

```
location / {
    alias /var/www/blog/html/public;
    index index.html;
}
```

About the **server\_name** ; the default value is an underscore, this means you’ll need to access your site using the server’s IP address. If you are using a domain, that’s where you should put it. For example:

`server_name example.com www.example.com;`

Save and exit nano and then restart nginx using the following command:

`sudo systemctl restart nginx`

And that’s it!

## <svg aria-hidden="true" focusable="false" height="16" version="1.1" viewbox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg>Test your site!

If everything was configured properly, you should be able to access your blog either through your domain (if you configured Nginx to use it) or through the server’s IP address.

## <svg aria-hidden="true" focusable="false" height="16" version="1.1" viewbox="0 0 16 16" width="16"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg>Nginx bonus: Configure Nginx to serve two sites from the same domain

As I mentioned above, the reason I had to deploy a Gatsby site to Digital Ocean rather than Netlify was that I already had a Node + React app running in Digital Ocean and I had to deploy the blog to the same server and use the same domain for both apps.

I used the following Nginx configuration to accomplish this:

```
location / {
    proxy_pass http://localhost:4000;
    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;
}

location /blog {
    alias /var/www/blog/html/public;
    index index.html;
}
```

What I have there is the Node + React app being served at the root and the blog being served at `/blog`.

Now, there's a small change we have to do to our Gatsby config. We have to add a path prefix so our blog's routing works with a `/blog` prefix before the rest of the path. This is a very simple change described [here](https://www.gatsbyjs.org/docs/path-prefix/).

This way our articles' url will look like: `example.com/blog/posts/post-slug`.

* * *

And that’s it! I hope this was useful and if you have any comments or feedback feel free to reach out.

Cheers!