Building Catphysics.com

Putting together Catphysics.com has been a fun little learning experience!

I've seen lots of other people with cool websites [1] [2] [3] [4] [5] [6], so I thought it was about time to create one of my own (again...)! Also, I want to host some (planned, but not yet developed) web tools and I'll need a place to put them.

As I was putting things together and learning about things I could do, I settled on these rules for myself:

Tools #

Process #

  1. Decide upon a domain name.

  2. Decide upon a cloud VPS host. I went with Hetzner because they've been around a while and because of the low price.

  3. Create a fun placeholder page while I figure out what I actually want to put on the domain. I ended up tracing a vector of the cat and using it for the background.

  4. Mock up the design and upload it to Netlify. I decided to use Hetzner DNS, pointing catphysics.com to Netlify's load balancer, www.catphysics.com to the Netlify site [10], and *.catphysics.com to the VPS.

  5. Learn that I can use nginx as a reverse proxy, passing through traffic based on the requested domain [11]. This allows me to, for example, host a NodeJS application on port 8000 and a Django application on port 9000 and serve them from different subdomains. Additionally, I can:

    • Configure HTTPS solely for nginx and not have to worry about it for the other applications.
    • Configure Hetzner's firewall to open only ports 80 and 443.

    Here's a snippet of a sample configuration.

    • All requests on port 80 are redirected to port 443.
    • Requests to cool-app.example.com will be proxied to a locally running application on port 12345.
    • Requests to all other subdomains will be redirected to example.com with HTTP 307 [12].
     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    server {
        server_name *.example.com;
        listen [::]:443 ssl ipv6only=on;
        listen 443 ssl;
    
        # (SSL certificate directives omitted)
    
        root /var/www/html;
        index index.html index.htm;
    
        return 307 https://www.example.com;
    }
    
    server {
        server_name cool-app.example.com;
        listen [::]:443 ssl;
        listen 443 ssl;
    
        root /var/www/html;
        index index.html index.htm;
    
        location / {
            proxy_pass http://localhost:12345;
        }
    }
    
    server {
        server_name *.example.com;
        listen 80;
        listen [::]:80;
    
        if ($host ~ ^[^.]+\.example\.com$) {
            return 301 https://$host$request_uri;
        }
    }
    
  6. Learn that in order to obtain a Let's Encrypt certificate for *.catphysics.com, I need to complete a DNS challenge, because it's a wildcard certificate [13]. Certbot doesn't come with a DNS plugin for Hetzner DNS. There actually is a DNS plugin for Hetzner provided by a third party [14], but I feel a little more comfortable using an out-of-the-box plugin. So I decided to switch to CloudFlare DNS.

  7. Have CloudFlare attempt to automatically detect DNS entries to import and then realise that it automatically generated nearly 200 subdomain and DKIM entries. I suspect that these were produced by CloudFlare searching for commonly used subdomains, which matched on the existing A record for * and TXT record for *._domainkey.

    There was probably an easier way to get rid of them than deleting them all manually, but I didn't feel like leaving the page. Next time!

    Cleaning up CloudFlare DNS entries

    I chose to leave the CloudFlare proxy in front of Netlify. I don't expect to ever go over Netlify's free plan limit of 100 GB of traffic per month, but who knows? Maybe I'll make something that's a hit. Stay positive! 😊

  8. Decide upon a static site generator. I picked Pelican [9]. Building the theme was tedious, but in the end, rewarding.

  9. Write the first post, and in the course of doing so, tweak the stylesheet over and over to reposition elements (and combinations of elements) not used in the templates themselves, but in the post. For example, did you know that an inline element's margins won't collapse with its parent element's adjacent margins [15]?

What's next? #

Footnotes #

[1] meowni.ca ^

[2] robinwe.is ^

[3] mango.pdf.zone ^

[4] tom7.org ^

[5] mitxela.com/projects ^

[6] rachelbythebay.com ^

[7] I am a long-time user of NoScript, though I'm considering giving it up, because I usually end up enabling scripts anyway—and even when I enable all scripts, some sites still don't display properly. Maybe I'll just add filter lists for known tracking scripts to my content blocker. ^

[8] Web fonts, boy, I don't know (meowni.ca) ^

[9] Pelican Static Site Generator, Powered by Python (getpelican.com) ^a^b

[10] Configure external DNS for a custom domain (docs.netlify.com) ^

[11] NGINX Reverse Proxy (docs.nginx.com) ^

[12] 307 Temporary Redirect (developer.mozilla.org) ^

[13] Challenge Types (letsencrypt.org) ^

[14] Hetzner DNS Authenticator certbot plugin (github.com) ^

[15] Mastering margin collapsing (developer.mozilla.org) ^