Two routes onto a Pi. The image for a blank card, the script for a board that already works, which is most of them. deploy/install.sh installs apt dependencies, clones to /opt/ashvale, builds a venv with --system-site-packages, enables I2C and installs a systemd unit. Tested end to end on the real Zero 2 W by installing a second instance on port 8099 alongside the live station: both served, and the live station was untouched throughout. That test earned its keep twice. The installer first declared success while the service was crash-looping on a port clash, because systemd reports active for the instant between exec and the first failed bind; it now polls the HTTP endpoint instead, which is the only check that means anything. And my first attempt to verify that fix was itself worthless, because curl on 127.0.0.1:8000 was answered by the live station rather than the instance under test. deploy/pi-image is a pi-gen stage on Raspberry Pi OS Lite, Trixie, arm64, which is exactly what the board runs. Built by .github/workflows/image.yml against a pinned pi-gen commit, so the artifact does not move when an upstream branch does, and published to Releases where the 2 GB asset limit comfortably fits a Lite image. The image ships no password, no WiFi and no SSH host keys. Baked host keys would give every person who flashed it the same identity and make them trivially impersonable on their own network. Coordinates default to Greenwich at 0 m, wrong for everybody on purpose, because a plausible wrong altitude quietly biases the sea-level reduction on every row. The source is copied through a .gitignore filter rather than a hand-written exclude list, and that is a security property rather than tidiness: the hand-written list I wrote first missed HANDOVER.md, which is gitignored precisely because it contains LAN addresses and SSH details. Verified: 69 files, no state, no local notes, all essentials present.
4.2 KiB
Getting Ashvale Station onto a Pi
Two routes. Pick the second one unless the card is empty.
| Use when | Cost | |
|---|---|---|
| Prebuilt image | A blank SD card, or you want a known-good starting point | ~500 MB download, reflashes the card |
| Install script | You already have a working Pi OS | ~2 minutes, keeps everything else |
Install script (recommended)
Works on any Raspberry Pi already running Raspberry Pi OS (Bookworm or Trixie).
curl -fsSL https://raw.githubusercontent.com/lynchaos/ashvale-station/main/deploy/install.sh | sudo bash
Installs the apt dependencies, clones into /opt/ashvale, builds a venv with
--system-site-packages, enables I2C, and installs and starts a systemd unit.
Then it polls the HTTP endpoint rather than trusting systemd, because a unit
that is crash-looping on a port clash reports active for the instant between
exec and its first failed bind.
Re-running it upgrades in place. It never touches data/ or config.yaml,
because those are your history and your coordinates and neither is recoverable.
Environment overrides, mostly useful for running a second instance beside a live one:
ASHVALE_DEST=/opt/ashvale-2 ASHVALE_SERVICE=ashvale-2 ASHVALE_PORT=8099 \
sudo -E bash deploy/install.sh
Reboot afterwards if it told you it enabled I2C: the Sense HAT is not detected until you do, and until then the station silently runs its simulator, which looks like it is working and is measuring nothing.
Prebuilt image
Download the .img.xz and its .sha256 from
Releases, verify, and
flash with Raspberry Pi Imager.
sha256sum -c ashvale-station-*.img.xz.sha256
Set your username, password and WiFi in Imager's customisation dialog. The image deliberately contains none of them. It also contains no SSH host keys: those are generated on first boot, because an image shipping real host keys would give every person who flashed it the same identity and make them trivially impersonable on their own network.
Boot it, wait a minute or two for the first-boot expansion, then open
http://<your-pi>:8000.
What is in it
Raspberry Pi OS Lite, Trixie, arm64, plus:
- the application in
/opt/ashvalewith its venv already built ashvale.service, enabled- I2C enabled in
config.txt, which the Sense HAT needs - a login banner with the address and the security caveat
/opt/ashvale/README.first-boot
Lite, not Desktop: the station is headless and a desktop would eat the 512 MB budget the whole project is designed around.
What is deliberately not in it
No password, no WiFi credentials, no SSH host keys, no database, no trained model state, and coordinates set to Greenwich at 0 m. That last one is wrong for everybody on purpose: altitude feeds the sea-level pressure reduction on every stored row, and pressure tendency is what drives the precipitation forecast, so a plausible-looking wrong altitude is worse than an obviously wrong one.
The build copies the working tree through a .gitignore filter rather than a
hand-written exclude list. That is a security property: a hand-written list
missed HANDOVER.md, which is gitignored precisely because it holds LAN
addresses and SSH details, and a local build would have baked one person's
network into an image other people flash.
Building the image yourself
CI does it on every tag via .github/workflows/image.yml, on a pinned pi-gen
commit so the output does not move when an upstream branch does. To build
locally you need a Linux host (or Docker) with qemu-user-static:
git clone --branch arm64 https://github.com/RPi-Distro/pi-gen
cp deploy/pi-image/config pi-gen/config
cp -r deploy/pi-image/stage-ashvale pi-gen/
touch pi-gen/stage3/SKIP pi-gen/stage4/SKIP pi-gen/stage5/SKIP
rm -f pi-gen/stage2/EXPORT_IMAGE
echo "ASHVALE_SRC=$PWD" >> pi-gen/config
cd pi-gen && sudo -E ./build.sh
Expect roughly an hour and about 10 GB of scratch space.
Licensing
Ashvale Station is Apache 2.0. The image also contains Raspberry Pi OS and Debian, which carry their own licences including some non-free firmware. It is an unofficial image and is not endorsed by or affiliated with Raspberry Pi Ltd or the Debian project.