Sign inSign up

quireink/quireink

By quireink

•Updated about 18 hours ago

A blog you host yourself, small enough for a NAS. An AI agent can write and publish to it.

Image
Content management system
0

5.9K

quireink/quireink repository overview

⁠Quire Ink

A blog you host yourself, and an AI agent can write and publish to. One process, two SQLite files, no cloud account anywhere in the path. No algorithm deciding who sees your writing, no ads across it, and no company that can change the rules.


⁠Start it

docker run -d --name quire \
  -p 127.0.0.1:3000:3000 \
  -e SITE_URL=https://example.com \
  -v quire-data:/var/lib/quire/data \
  -v quire-uploads:/var/lib/quire/uploads \
  quireink/quireink:latest

Then read the log. A blog nobody owns yet prints the link that claims it, every time it starts:

docker logs quire
  ┌─────────────────────────────────────────────────────────────────────────┐
  │  This blog has no owner yet. Open the link below to claim it.           │
  └─────────────────────────────────────────────────────────────────────────┘

  https://example.com/setup?token=…

Open it and the rest is a browser: username, email, password, two-factor, then four short questions about the site. No docker exec and no interactive terminal, because a NAS log panel is enough on its own. The token lives in memory, so a restart mints a new one, and /setup answers 404 the moment an account exists. Anyone who would rather use the shell still can: docker exec -it quire docker-entrypoint.sh bun run user create --username you --email [email protected].

Put a reverse proxy in front of it for TLS. The port is bound to 127.0.0.1 on purpose, and the setup guide⁠ has an nginx block you can copy.

⁠On a NAS — Synology, QNAP, Unraid

Their container UIs mount real folders rather than named volumes, because that is what their own backup jobs can see. Point both mounts at a folder you created and set PUID / PGID to whoever owns it. The container adopts the folders on first boot and never runs the app as root:

services:
  quire:
    image: quireink/quireink:latest
    restart: unless-stopped
    ports:
      - "127.0.0.1:3000:3000"
    environment:
      SITE_URL: https://example.com
      PUID: 1026     # Synology: Control Panel → User & Group
      PGID: 100
    volumes:
      - /volume1/docker/quireink/data:/var/lib/quire/data
      - /volume1/docker/quireink/uploads:/var/lib/quire/uploads

⁠Tags

TagWhat it means
latestThe newest release. The one to install, because the newest release is the one carrying the fixes.
2.2Fixes within the 2.2 line, no feature surprises. For anyone who would rather step up a major version by hand.
2.2.19One exact release. Nothing moves, ever.

linux/amd64 and linux/arm64, each built on its own native runner. The same image is on GHCR as ghcr.io/joiha-steven/quireink, pushed by the same run with the same digest.

⁠Configuration

Almost nothing lives here. SMTP, the site's name and language, colours, fonts, the newsletter and the analytics settings are all entered in the admin and stored in the database.

VariableDefaultWhat it does
SITE_URL—Your public URL, no trailing slash. Feeds, share images and preview links are built from it.
PUID / PGID1000Who owns the data. Only matters with bind mounts — see the NAS section.
PORT3000Inside the container.
DATA_DIR/var/lib/quire/dataBoth SQLite files. Mount it or lose your blog.
STORAGE_LOCAL_DIR/var/lib/quire/uploadsImages and files. Mount it too.
CRON_SECRET—Unlocks /api/cron for an external scheduler; the route is closed without it. The built-in clock needs neither.
ANALYTICS_TZUTCThe site's default timezone, until one is picked in Settings → Blog.

The environment table⁠ has the rest.

⁠What is in it

A real editor over Markdown, with tables, footnotes, callouts, mathematics and video, that saves as you type and can hold a post until Tuesday. Six palettes in light and dark, four reading fonts, a book mode set in two columns like paper, and a five-ink highlighter whose strokes are grown rather than drawn, so no two on a page share a shape. Search that answers as you type, comments, a newsletter, analytics without cookies, and sign-in with a passkey beside the password and the code. An article page costs about 120 KB.

An AI agent can write and publish for you over MCP, through exactly the rules the admin follows, and you can take its access away at any moment.

Three more doors, the first two switched off until you turn them on: the blog can be followed from Mastodon and anywhere else that speaks ActivityPub, read by a program over a read-only JSON API, and downloaded as Markdown in a ZIP that another blog engine can import. Nothing here holds your writing hostage.

⁠Upgrading

docker compose pull && docker compose up -d

Or docker pull quireink/quireink:latest and start the container again. The schema is applied at boot, inside a transaction, so there is no migration command to run. Take a backup first.

⁠Backups

There is a button in the admin that hands you the whole blog as one archive: both databases and every upload. Scheduled snapshots are on by default but stay on the same disk, so getting a copy off the machine is your job.

⁠Licence

PolyForm Noncommercial⁠, plus one additional permission⁠ that lets you run this published image commercially, paid hosting included. Only a modified version used commercially needs to ask first.

Tag summary

Content type

Image

Digest

sha256:331062973…

Size

88.6 MB

Last updated

about 18 hours ago

docker pull quireink/quireink