Kiwix#

Kiwix serves offline copies of online content — Wikipedia, Stack Exchange, DevDocs, and more — packaged as ZIM files, so they’re readable with no internet connection. It runs on voile (the Synology NAS) and is reachable on the LAN and over Tailscale at https://voile.armadillo-banfish.ts.net:8092.

Available content#

The current library (query live via /catalog/v2/entries):

ZIM Topic
wikibooks_en_all Wikibooks (open textbooks)
dsp.stackexchange.com_en_all Signal Processing Q&A
webmasters.stackexchange.com_en_all Webmasters Q&A
politics.stackexchange.com_en_all Politics Q&A
devdocs_en_zig DevDocs — Zig language docs
libretexts.org_en_math LibreTexts mathematics
wikitech_en_all Wikitech (Wikimedia infra docs)
survivorlibrary.com_en_all Survivor Library
www.ready.gov_en Ready.gov emergency prep
wikiquote_ja_all Japanese Wikiquote

Book slugs carry dates

The servable slug includes a volatile date suffix (e.g. wikibooks_en_all_maxi_2021-03) that changes when a ZIM is updated. Resolve it from /catalog/v2/entries rather than hardcoding it. Full-text search is per-book: /search?books.name=<slug>&pattern=<query>.

As an AI knowledge base#

Kiwix is the offline grounding source for the local llm CLI. The kiwix-ask tool searches these ZIMs, pulls the top articles, and feeds them to the model on mokou as context — so during a cloud-AI outage the assistant can cite real references (Wikipedia, DevDocs, Stack Exchange) instead of guessing:

kiwix-ask -b stackexchange "what is a windowing function in an FFT?"
kiwix-ask -b devdocs "zig comptime"

See the llm CLI page for flags and how slug resolution works.

It’s also linked from the Homer dashboard.

Managing the library from the dev shell#

kiwix-zim (in the default nix develop shell, also nix run .#kiwix-zim) manages voile’s library. ZIMs live at /volume2/Kiwix on voile; kiwix-serve runs there via docker compose.

kiwix-zim list                       # ZIMs currently served on voile (slug includes the date)
kiwix-zim outdated                   # compare each against library.kiwix.org; list newer versions
kiwix-zim get cooking.stackexchange.com_en_all   # download the latest from upstream
kiwix-zim get https://…/some.zim     # …or a direct URL
kiwix-zim push some_2026-02.zim      # rsync to voile:/volume2/Kiwix, then print the restart command
kiwix-zim crawl https://example.org example   # crawl a site into example.zim with zimit (podman/docker)

After push, kiwix-serve must be restarted to pick up new ZIMs — push prints the exact command (sudo docker compose restart needs an interactive password, so it’s not run for you):

ssh -p 22 voile 'cd /volume2/Kiwix && sudo docker compose restart'

get and update won’t pull a ZIM larger than KIWIX_MAX_GB (default 2 GB) over HTTP — instead they print its .torrent link and instructions, so multi-hundred-GB archives (Wikipedia, Project Gutenberg, …) are fetched via a torrent client and then kiwix-zim pushed. Raise the limit with KIWIX_MAX_GB=<n> to force an HTTP download.

Overridable via env: KIWIX_HOST, KIWIX_SSH (default voile), KIWIX_SSH_PORT (22), KIWIX_ZIM_DIR (/volume2/Kiwix), KIWIX_LIBRARY (https://library.kiwix.org), KIWIX_DOWNLOAD_DIR, KIWIX_MAX_GB.

Creating ZIMs#

  • From a local site / HTML directoryzimwriterfs (in the zim-tools package, also in the dev shell): zimwriterfs --welcome=index.html --illustration=favicon.png --language=eng --title="My Site" --name=mysite ./html_dir mysite.zim. Validate with zimcheck mysite.zim; inspect with zimdump. This is how falseblue.com.zim is built.
  • By crawling a live websitekiwix-zim crawl <url> <name> wraps zimit (a browsertrix crawler), which runs as a container, so it needs podman or docker available.

Then kiwix-zim push <file>.zim and run the printed restart command.