leaving nekoweb

2026-03-25T20:39:03-0400 | 859 words

Besides The Beguinage, I have two professional websites respectively hosted on Codeberg Pages and Github Pages with domains I own. This is very silly and stretches me across three hosts where the differences in deployment and service are real fiction. My three big gripes:

  1. The two Git hosts have sorts of CI/CD. I deploy my Codeberg site with a post-receive Git hook in lieu of Woodpecker CI or Forgejo Actions, and my GitHub site still uses Eleventy whose subject matter isn't tech at All with GitHub Actions. I don't love Nekoweb enough to be a Patreon supporter (sorry) and think even then its FTP and Git offerings are a little simple for my needs.
  2. MIME types, which are only a problem for this website. Most web servers, including Cloudflare (which Nekoweb uses), assign application/octet-stream to anything that isn't HTML, CSS, JavaScript, or an image, which is why browsers prompt you whether you want to download SVGs and non-web text file formats instead of just displaying them. This is an annoyance for me because The Beguinage has Python and shell scripts and stray CSV's hanging around, and I like naming text files with pseudo extensions like ssh.keys.

And with an eye toward the future, I'm a little interested in dynamic hosting. Not sure yet since I dislike JavaScript so much, but if this is how I use Flask, sure.

The stack is:

My workflow is:

  1. Edit a local git repo on my laptop or desktop.
  2. Push changes to my personal git server on a clamshelled MacBook Air 2017 (current uptime: 31 weeks), which has a post-receive hook that mirrors the repo to yet another bare repo on my VPS.
  3. My VPS copy has another Git hook that copies the built website to /var/www/, which Caddy exposes to my domain.

Storing websites at /var/www seems to be an established convention with no real logic on a single-user server. I could very well have put them anywhere in my user directory, but here's my /etc/caddy/Caddyfile:

www.beguine.net, beguine.net {
    root * /var/www/beguine.net
    try_files {path}.html {path}
    encode gzip zstd
    file_server {
        index index.html
        }
    handle_errors {
        rewrite * /{err.status_code}.html
        file_server
    }
    @textpls {
        path *.sh
        path *.py
        path *.keys
        path *.csv
    }
    header @textpls Content-Type "text/plain; charset=utf-8"
}

I went with Caddy over nginx on pure vibes, man. As you can see, the config is only a few lines. You just start it as a system service and restart it to load changes.

The post-receive Git hook on my VPS for actual deployment:

#!/usr/bin/env bash
GIT_DIR=$(pwd)
UV_BIN="/home/user/.local/bin/uv"
TEMP_WORK_TREE=$(mktemp -d)
TARGET="/var/www/beguine.net"
BRANCH="main"

while read oldrev newrev ref
do
    if [[ "$ref" == "refs/heads/$BRANCH" ]]; then
        echo "Building..."
        git --work-tree="$TEMP_WORK_TREE" checkout -f "$BRANCH"
        cd "$TEMP_WORK_TREE" || exit
        $UV_BIN run kamote build

        if [ -d "_build" ]; then
            echo "Syncing _build to $TARGET..."
            rsync -avq --delete _build/ "$TARGET/"
            echo "Deployment successful!"
        else
            echo "Error: _build directory not found after run."
            exit 1
        fi

        rm -rf "$TEMP_WORK_TREE"
    fi
done

Nekoweb has been fun and this website has been on it longer than it was on Neocities, but in the end I feel a little older than the userbase and more focused on backend and systems programming than in web dev. But generally, I'd like the indie web to be as indie as possible, which includes self-hosting and not being too closely tied to any one community's norms.

This also lets me get rid of making both an RSS and Atom feed for the sake of Nekoweb's global feed. I don't know why it only accepts RSS. If web development education is a goal of this platform, I would think migrating users toward Atom is a good move.

My other big goal in moving is to self-host stagit at git.beguine.net in lieu of the mess that is src. At least the Python projects that I want to distribute as something other than tarballs. The whole MIME type circus was in pursuit of keeping my shell scripts as they are.