PapaScott Savin' it up for Friday night 🥁

Use Caddy to map HTTPS to PagePark

I've started a GitHub repository at papascott/DrummerNotes for my notes and code about Drummer. I'm cross-posting my first note on using Caddy with PagePark here. PagePark is a"simple Node.js folder-based HTTP server that serves static and dynamic pages for domains". It isn't about Drummer per se, but would be a possible path for Drummer itself to run under HTTPS. This post is also a test of uploading Markdown from Drummer directly to a Gatsby blog.

Caddy is a very easy way to implement HTTPS for your PagePage domains. It is a web server that can do automatic HTTPS, automatically provisioning TLS certificates (from Let's Encrypt) for a domain and keep them renewed. It can even obtain TLS certificates on demand for your PagePark domains, without out having to configure the domains in Caddy.

How to

Here is an example of setting up Caddy on an existing PagePark installation on a Digital Ocean server running Ubuntu (assuming you have domains in your domains folder and have mapped port 80 to PagePark using iptables as in the instructions).

  1. Install the official Caddy package für Ubuntu per their instructions. This automatically starts and runs Caddy as a systemd service.

  2. Open the Caddy configuration file in the nano editor with sudo nano /etc/caddy/Caddyfile

  3. Replace the entire contents with:

    {
      on_demand_tls {
        ask http://localhost:1339/isdomainvalid
        interval 2m
        burst    5
      }
    }
    https:// {
      tls {
        on_demand
      }
      reverse_proxy localhost:1339
    }
    
  4. Restart the Caddy service with sudo service caddy restart

  5. Test https for one of your domains in the terminal with curl: e.g. curl https://www.example.com. This first time it will take several seconds for Caddy to request and obtain a certificate. It may even fail the first time, but then try again. The content of the index page of your domain should be printed to the terminal. That means it works!

This configuration means that both HTTP (over iptables) and HTTPS (over Caddy) will work for your domains!

Further cases and questions

Running Caddy without iptables mapping

If you have not mapped port 80 to PagePark, the configuration above will also listen to port 80 and redirect HTTP requests to HTTPS.

If you'd rather not redirect port 80, you can add a section for HTTP and disable redirects like this:

{
  auto_https disable_redirects
  on_demand_tls {
    ask http://localhost:1339/isdomainvalid
    interval 2m
    burst    5
  }
}
http:// {
  reverse_proxy localhost:1339
}
https:// {
  tls {
    on_demand
  }
  reverse_proxy localhost:1339
}

Removing iptables mapping so Caddy can handle HTTP

To delete an iptables rule you have to know the rule number. You can list the nat rules with

sudo iptables -t nat -v -L -n --line-number

The output will look something like this:

The number in front of the rule is the rule number. To delete these two rules, we need two commands

sudo iptables -t nat -D PREROUTING 1
sudo iptables -t nat -D OUTPUT 1

(changing the 1 at the end if your rule number is different).

What are the 'ask', 'interval' and 'burst' in the configuration?

They are for security purposes. They limit certificate requests to only domains configured in PagePage, and limits the rate of those requests. Otherwise an attacker can bombard your server with certificate requests for domains you don't even serve.

What about default domains?

Domains that are not explicitly in the domains directory will not be served automatic certificates. You can check the Caddy documentation for adding domains explicitly to the Caddy configuration.

Push an Outline with Github Actions

I've never worked with Github Actions before, but when thinking about how to push an outline from Drummer to GitHub I thought I'd take a look.

Actions are in YAML files saved in a special directory .github/workflowsin your repository. They can run when something happens in the repository (like a push or a pull request) or can be triggered externally (with an API call). The action starts a virtual machine, runs commands, then shuts down.

Fetching an outline from Drummer and committing it to the repository was pretty easy...

name: fetch-opml
on: [workflow_dispatch]
jobs:
  fetch-opml:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v2
      - shell: bash
          run: |
            git config --global user.name "GitHub Action"
            git config --global user.email "papascott@gmail.com"
            curl http://drummer.scripting.com/ScottHansonDE/papascott-de.opml -o papascott-de.opml
            git add papascott-de.opml
            git commit -m "Fetched at `date`" --allow-empty
            git push origin main

NB: This post was written in Markdown, not Drummer, since I don't know yet how to render code blocks from OPML. Still diggin'!

Correction: Do NOT hide your secrets in the root outline

Correction 13 November: you shouldn't use this for real secrets, since the root outline is not really hidden or secure. But for global variables that you don't mind having exposed it should be OK. Caveat emptor!

My video demo yesterday revealed the URL of my Netlify build hook for all to see. It's now been changed, but I need not have revealed. Drummer has a root outline where global variables can be defined.

So in the root outIine I can create an env object, and define an entry for netlifyBuildHook for the URL. (You have to use proper JavaScript object syntax, with brackets, colons and quotes.)

The xhr.open line of my build script can then be
xhr.open("POST", root.env.netlifyBuildHook, true);
without revealing the actual URL.