Skip to content

Nginx

This describes the configuration of the main nginx container for the charlesreid1.com pod.

Configuration Files

The nginx container is critical to routing operations on charlesreid1.com, so we cover how the configuration files are split up and organized on this page, and include a summary of each file below.

Where are the nginx config files?

Nginx configuration files are located in the d-nginx-charlesreid1 submodule of this repository, which points to the docker/d-nginx-charlesreid1 repository.

Within that repository is the conf.d/ folder, which contains several .conf files.

What Files Are There?

We have three sets of files present:

HTTP config files that redirect HTTP traffic on port 80 to be HTTPS traffic on port 443, one for each top-level domain (charlesreid1.com, charlesreid1.blue, and charlesreid1.red):

  • http.com.charlesreid1.conf
  • http.red.charlesreid1.conf
  • http.blue.charlesreid1.conf

HTTPS rules for charlesreid1.com endpoints (the wiki, phpMyAdmin, and ignoring .git directories):

  • https.com.charlesreid1.conf
  • https.red.charlesreid1.conf
  • https.blue.charlesreid1.conf

HTTPS rules for subdomains (pages.charlesreid1.com, hooks.charlesreid1.com, bots.charlesreid1.com):

  • https.com.charlesreid1.subdomains.conf
  • https.red.charlesreid1.subdomains.conf
  • https.blue.charlesreid1.subdomains.conf

HTTP Config Files

The HTTP config files are listed below:

  • http.com.charlesreid1.conf
  • http.red.charlesreid1.conf
  • http.blue.charlesreid1.conf

The HTTP config files do the following:

  • Requests for port 80 (for a domain or subdomain) are always redirected to port 443 for the same domain/subdomain

HTTPS Config Files

The HTTPS config files are listed below:

  • https.com.charlesreid1.conf
  • https.red.charlesreid1.conf
  • https.blue.charlesreid1.conf

The HTTPS config files (without "subdomain" in their name) do the following:

  • Requests for / are redirected to the htdocs folders mentioned above

  • Requests for /w/ or /wiki/ are reverse-proxied to the local Apache+PHP container on port 8989

  • (Optional) requests for /phpMyAdmin/ are reverse-proxied to the local phpMyAdmin container on port 80

  • Requests for git.charlesreid1.com are reverse-proxied to the local Gitea container on port 3000

  • Requests for files.charlesreid1.com are reverse-proxied to the local Python files on port 8081

HTTPS Subdomain Config Files

The HTTPS subdomain config files are listed below:

  • https.com.charlesreid1.subdomains.conf
  • https.red.charlesreid1.subdomains.conf
  • https.blue.charlesreid1.subdomains.conf

The subdomains config files redirect requests for a set of subdomains on charlesreid1.com, namely:

  • pages.charlesreid1.com
  • hooks.charlesreid1.com
  • bots.charlesreid1.com

This charlesreid1.com docker pod will redirect requests for these subdomains to another server running another docker pod, called the webhook docker pod, available at docker/pod-webhooks).

The webhook docker pod runs an nginx server, both to serve up static sites that live under the https://pages.charlesreid1.com domain, and to handle webhook traffic - the container also runs a Python webhook server that receives webhooks from git.charlesreid1.com, which enables push-to-deploy functionality similar to Github Pages.

Also see https://pages.charlesreid1.com/pod-webhooks/.

Why All The Config Files?

If everything is stuffed into a smaller number of nginx config files, they become long and unwieldy, and more prone to mistakes.

  • HTTP config files only contain redirects
  • HTTPS (no subdomain) config files handle

Getting Configuration Files Into Container

The configuration files are mounted into the container by bind-mounting the conf.d folder of the d-nginx-charlesreid1 submodule at /et/nginx/conf.d in the container.

This is done in the charlesreid1 pod docker-compose file.

Static Content

The nginx container hosts static content, in addition to serving as a reverse-proxy for several other services. This section covers how static content is treated by the charlesreid1.com nginx container

Outside the Container: /www/

Static content hosted by the container is stored on the host machine in /www/.

Each site (e.g., charlesreid1.com) has its own folder, containing the source for the static site and an htdocs folder containing the static content actually being hosted.

Additionally, because the static content for the site is actually contained on the gh-pages branch of charlesreid1/charlesreid1.com, the htodcs folder is actually a git repository. When it is cloned, it is cloned such that the git repo's contents go into /www/charlesreid1.com/htdocs/ and the contents of the .git folder go into /www/charlesreid1.com/git.

This allows the site static content to be updated to reflect the contents of the gh-pages branch by pulling the latest upstream changes into htdocs.

The directory structure used is as follows:

/www
    /charlesreid1.com
        /charlesreid1-src
            ...source for pelican site... 
        /htdocs
            ...static content...
        /git
            ...dot git folder...

    /charlesreid1.blue
        /charlesreid1-blue-src
            ...source for pelican site... 
        /htodcs
            ...static content...
        /git
            ...dot git folder...

    /charlesreid1.red
        /charlesreid1-red-src
            ...source for pelican site... 
        /htodcs
            ...static content...
        /git
            ...dot git folder...

This directory structure can be achieved using the following bash command:

REPOURL="https://git.charlesreid1.com/charlesreid1/charlesreid1.com.git"

git -C /www/example.com \
    clone \
    --separate-git-dir=git \
    -b gh-pages \
    $REPOURL htdocs

The dotfiles/debian repository contains scripts for krash, which runs the charlesreid1.com pod, to set up the directory structure as above, as well as scripts to pull the latest changes from upstream for each of the live web directories above.

Inside the Container: /usr/share/nginx/html

Once the contents of the /www/ directory have been set up, the content can be made avialable inside the container by bind-mounting the htdocs directories into the /www/ directory inside the container. This is done with the following volume directives in the docker-compose.yml file:

    volumes:
      - "/www/charlesreid1.blue/htdocs:/www/charlesreid1.blue/htdocs:ro"
      - "/www/charlesreid1.red/htdocs:/www/charlesreid1.red/htdocs:ro"
      - "/www/charlesreid1.com/htdocs:/www/charlesreid1.com/htdocs:ro"
      ...

Utility Scripts: Updating Site Contents

In the krash_scripts/ folder of the debian/dotfiles](https://git.charlesreid1.com/dotfiles/debian) repository, there are several utility scripts to help with setting up and updating this directory structure.

To set up the directory structure, use the git_clone_www.sh script.

1
2
3
4
5
6
7
8
9
#!/bin/bash

REPOURL="https://git.charlesreid1.com/charlesreid1/charlesreid1.com.git"

git -C /www/example.com \
    clone \
    --separate-git-dir=git \
    -b gh-pages \
    $REPOURL htdocs

To update the contents of the htdocs/ folder using the latest changes on the gh-pages branch, use the git_pull_www.sh script.

1
2
3
4
5
#!/bin/bash

git -C /www/example.com \
    --git-dir=git --work-tree=htdocs \
    pull origin gh-pages

SSL Certificates

We utilize Let's Encrypt to issue SSL certificates for our domain. This is a pain because of the need to automatically renew certificates every 90 days, and because of missing information in their documentation.

Where To Put Certificates

We leave the certificates where Let's Encrypt puts them, namely, in /etc/letsencrypt/live.

The certificates are bind-mounted into the container at the same location, /etc/letsencrypt/live. The docker-compose.yml file then contains the following:

    volumes:
      - "/etc/letsencrypt:/etc/letsencrypt"
      ...

Which Server Needs Certificates

Because the d-nginx-charlesreid1 docker container is serving as the front-end nginx server handling all incoming charlesreid1.com web requests, it is also the one negotiating HTTPS sessions with clients, so it is the container that needs the Let's Encrypt certificates.

This means that, for example, the SSL certificate for pages.charlesreid1.com is on krash, even though the content served up by the site is on blackbeard.

Getting and Renewing Certificates

Once you have worked everything out and gotten auto-renew cron scripts running smoothly, everything is unicorns and rainbows. But when you hit the Let's Encrypt rate limit because they did not explain it properly in the documentation, you may want everyone to die.

Let's Encrypt provides a command line utility called certbot that can be used to automate the process of creating and renewing certificates.

See the charlesreid1/certbot repository for scripts. The basic setup is as follows:

  • Use the krash_make_cert.sh script (which wraps the make_cert.sh script) to create SSL certificates for each domain and subdomain

  • Use the krash_renew.sh script (which wraps the renew_cert.sh script) to renew SSL certificates for each domain and subdomain

  • Certificates must be renewed every 90 days. I run the certificate renewal script in the root acount's crontab every 15 days so the certs never expire.

Domain Control

There are three top-level domains controlled by pod-charlesreid1:

There are several subdomains available on charlesreid1.com.

Hosted on krash:

Hosted on blackbeard: