A lightweight, local-first collaboration box for small groups using small, cheap Debian-family hardware.
This repository currently implements milestone 1:
- Flash a Raspberry Pi with Raspberry Pi OS Lite
- Boot it
- Log into Cockpit with the machine's normal system account
- Use a preinstalled collaborative app
For milestone 1, the preinstalled app is Etherpad.
This repository deliberately stays thin:
- docs/: design and ADRs
- bootstrap/: first-boot and host install scripts
- apps/: curated app recipes
- config/: upstream tool configuration
- scripts/: development helpers
- test/: smoke tests
- web/: static landing page
- image/: Raspberry Pi provisioning examples
There is no custom admin backend, custom auth system, or custom orchestration layer.
- Flash Raspberry Pi OS Lite onto storage
- If Raspberry Pi Imager asks for a username, use
localbox - Use the same password in Raspberry Pi Imager and in the setup helper below
- Mount the boot partition on your workstation
- Prepare the boot partition:
just setup-pi-boot /path/to/boot-partitionFor example, on macOS this might be:
just setup-pi-boot /Volumes/bootfsThen:
- Eject the storage safely
- Insert it into the Pi
- Boot the Pi on a network with internet access for the initial package install and container image pull
- Wait for first-boot provisioning to finish
- Visit:
https://<pi-ip>:9090/for Cockpithttp://<pi-ip>/for the landing pagehttp://<pi-ip>/etherpad/for Etherpad
First boot can take several minutes. During provisioning, Caddy may briefly show
its default welcome page before localbox replaces the configuration. Wait for
provisioning to finish, then use doctor.sh as the success check.
After first-boot provisioning, the Milestone 1 flow works on the local network without requiring continued internet access.
Pre-provisioned public-trusted HTTPS has been proven for the milestone 1 stack.
Validated paths:
- host-level secure Pi boot staging via
just check - ARM64 VM runtime HTTPS smoke via
just vm-smoke-https - Raspberry Pi hardware serving a public certificate on the LAN
- Chromium and Firefox loading the DNS name without a certificate warning
Firefox on macOS may need Local Network permission before it can reach a LAN
localbox. For the hardware/browser checklist, see
docs/testing/preprovisioned-https.md.
- Debian-family host
- Raspberry Pi OS Lite is the primary first target
- Podman Quadlet is the installed runtime for supported apps
- Compose remains the source format for app recipes
This repository supports a leaner development loop before testing on hardware.
just checkThis runs:
- shell syntax checks
- shellcheck if installed
- config rendering checks
- secure Pi boot staging checks
just setup-pi-boot /path/to/boot-partitionjust stage-pi-boot out/pi-boot '$6$example...'
just validate-boot-tree out/pi-bootThe first HTTPS prototype uses a real DNS name and pre-provisioned certificate files. This is intended to prove warning-free browser access before automating certificate issuance or local DNS.
Prepare the boot partition with a real DNS name and certificate/key pair:
just setup-secure-pi-boot \
/path/to/boot-partition \
localbox.example.org \
/path/to/fullchain.pem \
/path/to/privkey.pemIf the helper is run with sudo, it restores ownership of the repo-local ignored profile and secrets/tls/ copy to the invoking user where possible.
After provisioning, arrange local DNS or a temporary hosts-file entry so the DNS name resolves to the Pi's LAN address.
For example:
192.168.8.199 localbox.example.org
The helper writes an ignored local profile at
bootstrap/profiles/pi-https-preprovisioned.local.env and copies certificate
material into the ignored secrets/tls/ directory before staging the boot tree.
The HTTPS runtime path can be tested in the ARM64 VM before trying real Raspberry Pi hardware:
just vm-smoke-httpsThis uses a throwaway self-signed certificate, so it tests the localbox HTTPS plumbing rather than public browser trust.
For the real hardware/browser proof, see docs/testing/preprovisioned-https.md.
If the Pi appears on the network but the landing page is not available, SSH in:
ssh localbox@<pi-ip>Then inspect first-boot provisioning:
cloud-init status --long
sudo journalctl -u localbox-bootstrap.service --no-pager -n 120If package installation failed because APT indexes or mirrors were stale, refresh APT and rerun the localbox installer:
sudo apt-get clean
sudo rm -rf /var/lib/apt/lists/*
sudo apt-get update
sudo /boot/firmware/localbox/bootstrap/install.sh /boot/firmware/localbox/bootstrap/profiles/pi-milestone1.env
sudo /boot/firmware/localbox/bootstrap/doctor.shOn some images the boot path may be /boot rather than /boot/firmware:
sudo /boot/localbox/bootstrap/install.sh /boot/localbox/bootstrap/profiles/pi-milestone1.env
sudo /boot/localbox/bootstrap/doctor.shcloud-init status tells you whether cloud-init handed first boot to systemd.
doctor.sh tells you whether localbox is currently healthy.
Milestone 1 serves the landing page and Etherpad over HTTP on the local network. Cockpit uses HTTPS on port 9090 and may show a browser certificate warning.
sudo ./bootstrap/install.sh
sudo ./bootstrap/doctor.shapps/
etherpad/
bootstrap/
install.sh
doctor.sh
profiles/
config/
caddy/
scripts/
test/
docs/
arm64-vm.md
adrs/
design-spec.md
development.md
image/
pi/
web/
- build a custom Pi image in CI
- provide click-to-install apps yet
- provide a custom dashboard backend
- require OpenWrt
- solve local naming/discovery beyond direct IP access
Design the local name-resolution and certificate lifecycle story for the public-trusted HTTPS mode.
See docs/adrs/006-local-https-trust-modes.md.