by Martin Monperrus

Posts are Markdown files stored via gakofs.php, a key-value store over HTTP backed by the server filesystem. The key is the file’s relative path. A post named my-post lives at my-post.md and is served at https://www.monperrus.net/martin/my-post.

Authentication uses HTTP Digest. You may be user martin. Retrieve the password from the local keyring — never hardcode it:

PASS=$(keyring get monperrus.net martin)

Create a New Post

PASS=$(keyring get monperrus.net martin)
EMPTY_SHA="e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855"

cat > /tmp/my-post.md << 'EOF'
---
title: My Post Title
author: Martin Monperrus
---

Content goes here (Markdown).
EOF

curl -s --digest -u martin:$PASS -X PUT --data-binary @/tmp/my-post.md \
  "https://www.monperrus.net/martin/gakofs.php/my-post.md?previous_checksum=$EMPTY_SHA"

The post is immediately live at https://www.monperrus.net/martin/my-post.

Rules: - Always use a .md extension. Without it, gakofs returns rendered HTML instead of the raw file. - Use previous_checksum equal to the SHA-256 of the empty string when creating a new file.

Update an Existing Post

GET to retrieve the current content and checksum, edit, then PUT:

PASS=$(keyring get monperrus.net martin)

# 1. Fetch current content and checksum
curl -s --digest -u martin:$PASS \
  "https://www.monperrus.net/martin/gakofs.php/my-post.md" \
  -D /tmp/headers.txt -o /tmp/current.md

CHECKSUM=$(grep -i x-checksum-sha256 /tmp/headers.txt | awk '{print $2}' | tr -d '\r')

# 2. Edit /tmp/current.md, then PUT back
curl -s --digest -u martin:$PASS -X PUT --data-binary @/tmp/current.md \
  "https://www.monperrus.net/martin/gakofs.php/my-post.md?previous_checksum=$CHECKSUM"

If the content is unchanged, the server responds with {"status":"identical"} and writes nothing. If the checksum is stale (file was edited elsewhere), it returns 503 file has been modified — get the latest changes and merge.

Post Format

Posts are Markdown with a YAML front matter block for metadata. The title comes from front matter — do not use a # H1 heading. Example:

---
title: My Post Title
author: Martin Monperrus
---

Introduction paragraph.

## Section

Content with **bold**, `code`, and [links](https://example.com).

List Recent Posts (RSS)

PASS=$(keyring get monperrus.net martin)
curl -s --digest -u martin:$PASS "https://www.monperrus.net/martin/gakofs.php?rss"