---
title: "How I Deploy Static Sites With Nginx"
author: "James Pace"
date: "2024/01/14"
---

This article will describe how I built and deployed limbo.jpace121.net, including
the initial setup I had to do when setting the site up.

## Background

I decided I wanted to start self hosting certain web applications a few years ago for educational
purposes.

I live in an apartment and have internet provided through the complex, so I don't have
the ability to negotiate for a static IP from my internet provider.

What I do instead is run an Amazon Lightsail instance which runs NGINX and Wireguard.

For non-static sites, I use NGINX to proxy requests from the instance to the actual
services I run locally, which are all connected via Wireguard with the Ligthsail instance.

For static sites, proxying down into my home internet it a little silly, so I put any files
I need to host directly on the Lightsail instance and serve them from there.

I currently use Google Domains for hosting my domain and DNS.
(Though it sounds like that'll be transferred to Squarespace at some point in the near future...)

I get free HTTPS certs from LetsEncrypt.

## Step 1: Setting up DNS records.

The first step was to setup an A record on Google Domains for `limbo` pointing
to the IP of my Lightsail instance.

I do this first so the system has time to propagate the change around before we
need the domain name to resolve in the following steps.

## Step 2: Set up NGINX.

To set up nginx, I ssh'd into my Lightsail instance using my admin account.

Once I logged in, I cd'd to `/etc/nginx/sites-available` and copied one of the files that
was already there to `limbo.jpace121.net`.

I modified the file so it had the following the contents

```
server {
    listen 80;
    server_name limbo.jpace121.net;

    location /.well-known {
            alias /var/www/limbo.jpace121.net/.well-known;
    }

    location / {
        return 301 https://limbo.jpace121.net$request_uri;
    }
}

server {
    listen 443;
    server_name limbo.jpace121.net;

    ssl_certificate /etc/letsencrypt/live/limbo.jpace121.net/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/limbo.jpace121.net/privkey.pem;

    root /var/www/limbo.jpace121.net/;
    location / {
        try_files $uri /index.html;
    }
    location /.well-known {
            alias /var/www/limbo.jpace121.net/.well-known;
    }
}
```

and the commented out (using the `#` symbol) the second server block for now, since we haven't gotten
certs quite yet.

I then created a symbolic link between the new config file in `/etc/nginx/sites-enabled` which is where nginx
actually looks for server files to load (on Debian as configured by default) using the following command:
```
sudo ln -s /etc/nginx/sites-available/limbo.jpace121.net /etc/nginx/sites-enabled/limbo.jpace121.net
```

I then restarted the nginx service (using `sudo systemctl restart nginx`) so the new config would take effect.

The config file above is setup to host files from `/var/www/limbo.jpace121.net`, so we need to create that directory
(as root) and then change it's permissions so we can upload files to it as the admin user.
```
sudo mkdir /var/www/limbo.jpace121.net
sudo chown -R admin:admin /var/www.jpace121.net
```

# Step 3: Using certbot to get a cert from LetsEncrypt.

I use LetsEncrypt and certbot so I can ue https for all my self hosted sites, and so already have
it installed on my Lightsail instance.

To add my new site, I ran:
```
sudo certbot certonly --webroot -w /var/www/limbo.jpace121.net -d limbo.jpace121.net
```

Once the command finishes, we should have certs where they are being looked for in our https server configuration,
so we can open `/etc/nginx/sites-available/limbo.jpace121.net`, uncomment out the second server block, and then
restart nginx.

## Step 4: Build and Deploy the site

`limbo.jpace121.net` is written in TypeScript and uses `vite` and `yarn` for its build tool and package
manager respectively.

As configured by default, running `yarn build` from the package will use vite to create a production build
of the website, which is placed into the `dist` directory of the package.

Once we've built the package, to deploy it on the server we scp the files in dist to the `/var/www/limbo.jpace.net`
directory on the server. (I.E. `scp -r dist/. admin@vpn.jpace121.net:/var/www/limbo.jpace121.net/.`).
Once that's complete, we should be abel to load the webpage locally and see that the contents have changed.

Further updates to the site should only require completing Step 3.
To make that easier I've added the two commands required (one to build the project, and one
to deploy it) to my justfile for my web project so I can call a single command and have the
right thing happen.

## Conclusion

Once the initial set up is done, actually deploying the site is fairly easy.

A lot of times for static sites, hobbyists use something like Github Pages because it is
both easy and free.
I don't think the process is that much harder with my method, and I appreciate the extra control
I have on what gets published when.