Deployment: Raspberry Pi archive-only node (pattern C)
This guide runs kiwix-serve on a Raspberry Pi without
Ollama or any AI components. Use this pattern when:
- You want a dedicated, low-power archive node on the LAN.
- Another machine (laptop or Pi with the text-only stack) provides the AI layer.
- You are running a split deployment (see
docs/deployment/split.md).
Time estimate: one to two hours, mostly downloading ZIM files.
Hardware requirements
| Component | Minimum | Notes |
|---|---|---|
| Board | Raspberry Pi 4 (1 GB RAM) | kiwix-serve is very lean |
| Storage | USB SSD, 8 GB free | Size depends on bundle; see below |
| Power | Official 5 V / 3 A adapter | |
| Network | Ethernet recommended | Stable LAN connection for split use |
No Ollama means RAM requirements are minimal—even a 1 GB Pi 4 or a Pi
Zero 2 W can run kiwix-serve comfortably. A Pi 5 has no
advantage here.
Do not use SD card storage for ZIM files. Even reads of large ZIM files cause significant SD wear. A USB SSD is required.
Bundle size guide
| Bundle | Approx. ZIM size | Recommended SSD |
|---|---|---|
minimal |
~3.5 GB | 16 GB |
balanced |
~30 GB | 64 GB |
comprehensive |
~130 GB+ | 256 GB+ |
Step 1: Image the OS
Download Raspberry Pi OS Lite (64-bit) — the "Lite" variant, no desktop. Bookworm (Debian 12) or later.
Flash with Raspberry Pi Imager. Before writing, configure:
- Hostname:
allarkive-archive(or similar) - SSH enabled
- Username and password
- Wi-Fi if needed (Ethernet preferred for a server)
Boot, confirm SSH:
ssh pi@allarkive-archive.localUpdate:
sudo apt update && sudo apt full-upgrade -y
sudo rebootStep 2: Mount the USB SSD
lsblkFormat if needed (new SSD):
sudo fdisk /dev/sda # new GPT partition table, one partition
sudo mkfs.ext4 /dev/sda1Mount:
sudo mkdir -p /mnt/ssd
sudo mount /dev/sda1 /mnt/ssdPersist across reboots—add to /etc/fstab (get UUID via
sudo blkid /dev/sda1):
UUID=YOUR-UUID /mnt/ssd ext4 defaults,noatime 0 2
sudo mount -a
df -h /mnt/ssdStep 3: Install Docker
curl -fsSL https://get.docker.com | sh
sudo usermod -aG docker "$USER"
newgrp docker
docker compose versionStep 4: Clone the repository
sudo mkdir -p /mnt/ssd/allarkive-repo
sudo chown "$USER" /mnt/ssd/allarkive-repo
git clone https://github.com/allarkive/allarkive /mnt/ssd/allarkive-repo
cd /mnt/ssd/allarkive-repoStep 5: Create data directory
mkdir -p /mnt/ssd/allarkive/zimStep 6: Download a bundle
Run fetch-bundle.sh from the Pi (it resumes partial
downloads):
ALLARKIVE_DATA_DIR=/mnt/ssd/allarkive \
scripts/fetch-bundle.sh minimal --dest /mnt/ssd/allarkive/zimReplace minimal with balanced or
comprehensive if you have the storage.
Verify:
ls -lh /mnt/ssd/allarkive/zim/*.zimStep 7: Configure kiwix
Copy the environment template:
cp compose/.env.example compose/.envEdit compose/.env—only a few fields are relevant for
archive-only:
ALLARKIVE_DATA_DIR=/mnt/ssd/allarkive
# Port binding for kiwix-serve.
# Default (127.0.0.1) means LAN access is not possible.
# For split deployment, change KIWIX_BIND to 0.0.0.0 and
# secure with a firewall. See docs/deployment/split.md.
KIWIX_BIND=127.0.0.1
KIWIX_PORT=8081
WEBUI_SECRET_KEY is not used by the archive-only stack;
leave it blank.
Step 8: Start kiwix-serve
cd /mnt/ssd/allarkive-repo
docker compose -f compose/docker-compose.pi-archive.yml --env-file compose/.env up -dStep 9: Smoke test
curl -sf http://127.0.0.1:8081/ > /dev/null && echo "kiwix OK"Open a browser on the Pi (or over SSH port-forward):
ssh -L 8081:127.0.0.1:8081 pi@allarkive-archive.localThen open http://127.0.0.1:8081. You should see the
kiwix-serve article browser with the downloaded archive listed.
Enabling LAN access (required for split deployment)
By default, kiwix is bound to 127.0.0.1 and is not
reachable from other machines. For a split deployment, the archive node
must be reachable from the AI node.
Edit compose/.env:
KIWIX_BIND=0.0.0.0
Restart:
docker compose -f compose/docker-compose.pi-archive.yml --env-file compose/.env up -dVerify kiwix is now listening on all interfaces:
ss -tlnp | grep 8081Expected: 0.0.0.0:8081 instead of
127.0.0.1:8081.
Firewall recommendation: if the Pi is on a home LAN,
restrict access to known IPs using ufw:
sudo apt install -y ufw
sudo ufw default deny incoming
sudo ufw allow ssh
# Allow kiwix from the AI node's IP only
sudo ufw allow from <AI-NODE-IP> to any port 8081
sudo ufw enableFor a full reverse-proxy setup with auth, see
docs/deployment/lan-access.md.
Port summary
| Service | Port | Bound to (default) |
|---|---|---|
| kiwix-serve | 8081 | 127.0.0.1 |
Troubleshooting
kiwix exits immediately
Check logs:
docker compose -f compose/docker-compose.pi-archive.yml logs kiwixCommon causes:
- No ZIM files in
/mnt/ssd/allarkive/zim/— fetch a bundle first. - The
ALLARKIVE_DATA_DIRin.envdoes not match the actual mount path.
Download stalls mid-bundle
fetch-bundle.sh uses wget --continue.
Re-run it; it resumes. If the connection is consistently dropping,
try:
scripts/fetch-bundle.sh minimal --dest /mnt/ssd/allarkive/zimSSD not mounting after reboot
Check /etc/fstab entries and that the UUID matches:
sudo blkid /dev/sda1
grep ssd /etc/fstabIf the UUID has changed (replaced SSD), update
/etc/fstab.
ZIM file corrupted
Re-run fetch-bundle.sh. It verifies checksums and will
re-download any file that fails verification.
Updating ZIM files
Kiwix releases updated ZIM snapshots periodically. To update:
- Update the bundle manifest in
bundles/<name>/manifest.jsonwith new URLs and checksums. - Run
fetch-bundle.sh— it replaces old files and verifies the new ones. - Restart kiwix-serve:
docker compose -f compose/docker-compose.pi-archive.yml restart kiwixWhat is next
- To add the AI layer to this Pi, see
docs/deployment/pi-text-only.md. - To connect an AI node to this archive node over the LAN, see
docs/deployment/split.md.