Offline Server-in-a-Box
Rugged Pi/mini-PC that serves maps (OSM), a wiki/manuals library, a bulletin board, and a LAN file share—even with zero internet.
What it does
- Maps (offline): TileServer-GL + OpenMapTiles MBTiles.
- Wiki/manuals: Kiwix-serve ZIM library.
- Bulletin board: Etherpad real-time notes.
- File share: Samba (guest-friendly).
- Captive portal: Router splash (openNDS) → your homepage.
Power & Box
| Input | 12 V / 24 V DC |
|---|---|
| Compute | Raspberry Pi 5 or mini-PC |
| Storage | NVMe or USB-SSD (≥256 GB) |
| Wi-Fi | OpenWrt router (captive portal) |
| Power to Pi | 5 V buck (≥5 A) or PoE+ |
Bill of Materials
Core
| Compute | Raspberry Pi 5 + heatsink/fan |
|---|---|
| Storage | NVMe via Pi M.2 HAT or USB-3 SSD |
| Router | OpenWrt/GL.iNet travel router |
| Case | Pelican 1300/1400 (or similar) |
Power & I/O
| DC in | 12/24 V source + inline fuse |
|---|---|
| Pi power | 5 V buck (≥5 A) or PoE+ HAT (Pi 4) |
| Cabling | Short Ethernet, ferrules, labels |
| Cooling | 40 mm fan + mesh vents |
Pi 5 needs 5 V/5 A headroom (official PSU shown in docs). PoE+ HAT powers Pi 4 via 802.3at. Power table • PoE+ HAT
Wiring & Network Layout
12/24V DC → Fuse → 5V Buck → Pi (or PoE+ Injector → Pi PoE+ HAT) Pi (eth0) → Router LAN (OpenWrt + openNDS captive portal) Clients → Wi-Fi SSID (portal) → redirect to http://srv/ (Homepage) Ports: /maps (8080), /wiki (8090), /bulletin (9001) proxied behind :80
openNDS = maintained captive portal for OpenWrt; configure splash + redirect URL. OpenWrt wiki
Step-by-Step (Do these in order)
- Flash OS: Raspberry Pi OS (64-bit Lite); enable SSH; hostname srv. Optional: enable USB/NVMe boot. Pi docs
- Install Docker Engine (Debian/ARM64): follow official instructions (Docker apt repo). Docker on Debian
- Create folders: /srv/maps /srv/kiwix /srv/board /srv/proxy
- Offline content: Place my-region.mbtiles into /srv/maps. Put ZIM files into /srv/kiwix/zim. OpenMapTiles • Kiwix-serve
- Compose services: Use the docker-compose file below; bring up with docker compose up -d. TileServer-GL config (MBTiles) included. TileServer-GL docs
- SMB share: Install Samba on host; add a public share to /srv/share. Samba guide
- Router portal: On OpenWrt, install openNDS; set splash and redirect URL to http://srv/. openNDS docs
- Attribution: Show “© OpenStreetMap contributors” near the map and link ODbL. OSMF attribution
Docker Compose (paste into /srv/docker-compose.yml)
services:
tiles:
image: maptiler/tileserver-gl
command: ["--port","8080","--config","/data/config.json"]
volumes: [ "./maps:/data" ]
ports: ["8080:8080"]
restart: unless-stopped
kiwix:
image: ghcr.io/kiwix/kiwix-serve:3.7.0
command: ["/usr/bin/kiwix-serve","--port=8090","--library","/data/library.xml","/data"]
volumes: [ "./kiwix:/data" ]
ports: ["8090:8090"]
restart: unless-stopped
etherpad:
image: etherpad/etherpad:latest
environment:
- TITLE=GamerzCrave Bulletin
- DEFAULT_PAD_TEXT=Welcome to the offline bulletin.
volumes: [ "./board:/opt/etherpad-lite/var" ]
ports: ["9001:9001"]
restart: unless-stopped
nginx:
image: nginx:alpine
volumes:
- ./proxy/nginx.conf:/etc/nginx/nginx.conf:ro
- ./proxy/www:/usr/share/nginx/html:ro
ports: ["80:80"]
depends_on: [ tiles, kiwix, etherpad ]
restart: unless-stopped
TileServer-GL Config (/srv/maps/config.json)
{
"options": { "paths": { "root": "/data", "mbtiles": "/data" } },
"styles": { "bright": { "style": "bright.json" } },
"data": { "planet": { "mbtiles": "my-region.mbtiles" } }
}
TileServer-GL can point directly at local MBTiles. Config docs
Nginx Reverse Proxy & Homepage
# /srv/proxy/nginx.conf
events {}
http {
server {
listen 80;
location = / { root /usr/share/nginx/html; try_files /index.html =404; }
location /maps/ { proxy_pass http://tiles:8080/; }
location /wiki/ { proxy_pass http://kiwix:8090/; }
location /bulletin/ { proxy_pass http://etherpad:9001/; }
add_header Cache-Control "no-store";
}
}
Offline Hub Offline Server-in-a-Box
- Maps (OSM © contributors)
- Wiki & Manuals
- Bulletin Board
- File Share
Samba Share (host)
# Create and expose a guest-friendly share sudo apt -y install samba sudo mkdir -p /srv/share sudo chown -R nobody:nogroup /srv/share printf "\n[public]\npath=/srv/share\nbrowseable=yes\nread only=no\nguest ok=yes\nforce user=nobody\n" | sudo tee -a /etc/samba/smb.conf sudo systemctl restart smbd
Full parameter reference in Samba’s smb.conf docs.
Quick-Start (printable)
- Power up router & Pi (12/24 V fused). Wait 60 s.
- Connect to Wi-Fi SSID → Captive portal → Accept.
- Homepage opens: Maps / Wiki / Bulletin / Files.
- Admin: ssh pi@srv • docker compose ps
- Shut down: sudo shutdown -h now → kill DC → close case.
Maintenance & Safety
- Keep vents clear; verify buck holds 5.1 V under load.
- Show OSM attribution near maps + link the copyright page.
- Portal splash: terms + privacy note; don’t MITM traffic.
Sources
- Kiwix-serve (ZIM over HTTP): docs.
- OpenMapTiles + TileServer-GL (Docker + MBTiles): OpenMapTiles • TileServer-GL • MBTiles config.
- openNDS captive portal on OpenWrt: OpenWrt wiki • docs.
- Samba standalone server & smb.conf: guide • manpage.
- Docker Engine on Debian (ARM64 ok): docs.
- Pi power & PoE+: power table • PoE+ HAT.
- OSM license & attribution: copyright • attribution guidelines.