Publishing a website on Fastmail - Part III
After many failed deploys and at least two existential crises, I went back to first principles: simplify.
No modules. No rclone. No trying to obscure passwords mid-script.
Just a GitHub Actions workflow that:
- Checks out the repo
- Installs Hugo
- Downloads the Ananke theme manually
- Builds the site
- Uses curl and MKCOL to recursively ensure folders exist
- Uploads files one-by-one to Fastmail via WebDAV
You’ll need an app-specific password from Fastmail to then add that to the secrets of your repo, but that is the only semi-complicated part of this process.
The Final Working Workflow
name: Build and Upload Hugo Site to Fastmail
on:
push:
branches:
- main
jobs:
deploy:
runs-on: ubuntu-latest
env:
FASTMAIL_USERNAME: ${{ secrets.FASTMAIL_USERNAME }}
FASTMAIL_PASSWORD: ${{ secrets.FASTMAIL_PASSWORD }}
REMOTE_DIR: "Sites/blog"
LOCAL_DIR: "public"
steps:
- name: Checkout repository (with submodules)
uses: actions/checkout@v3
with:
submodules: true
- name: Set up Hugo
uses: peaceiris/actions-hugo@v2
with:
hugo-version: 'latest'
extended: true
- name: Download Ananke theme
run: |
mkdir -p themes
git clone --depth=1 https://github.com/theNewDynamic/gohugo-theme-ananke.git themes/ananke
- name: Build Hugo site
run: hugo --minify
- name: Upload Hugo site to Fastmail (via curl + WebDAV)
run: |
set -euo pipefail
BASE_URL="https://webdav.fastmail.com"
TARGET_URL="${BASE_URL}/${REMOTE_DIR}"
echo "Uploading from local: $LOCAL_DIR"
echo "To Fastmail folder: $REMOTE_DIR"
find "$LOCAL_DIR" -type f | while read -r FILE; do
REL_PATH="${FILE#$LOCAL_DIR/}"
DEST_URL="${TARGET_URL}/${REL_PATH}"
# Ensure directories exist on the server
IFS='/' read -ra PARTS <<< "$(dirname "$REL_PATH")"
CURRENT_URL="$TARGET_URL"
for PART in "${PARTS[@]}"; do
[[ -z "$PART" ]] && continue
CURRENT_URL="$CURRENT_URL/$PART"
curl -s -o /dev/null -u "$FASTMAIL_USERNAME:$FASTMAIL_PASSWORD" -X MKCOL "$CURRENT_URL" || true
done
# Upload the file
curl -T "$FILE" -u "$FASTMAIL_USERNAME:$FASTMAIL_PASSWORD" "$DEST_URL"
echo "Uploaded: $REL_PATH"
done
The Result
Every time I commit, GitHub Actions builds the site, and Fastmail hosts it. Static, fast, and mercifully free of anything that needs maintenance.
My blog now lives at:
It took too long. It broke in more ways than I can count. But it works. And I never had to install Hugo locally.
That’s good enough for me.
Up next: How to point a telescope at a sandwich.