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 themake_cert.sh
script) to create SSL certificates for each domain and subdomain -
Use the
krash_renew.sh
script (which wraps therenew_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:
- https://git.charlesreid1.com - gitea service
- https://files.charlesreid1.com - static file hosting
Hosted on blackbeard:
- https://pages.charlesreid1.com - push-to-deploy static pages
- https://hooks.charlesreid1.com - webhook server
- https://bots.charlesreid1.com - info about bots