This guide walks through setting up a brand new Raspberry Pi to run TrailCurrent. These steps are performed once per device. After this, all future updates are handled by the deployment package (deploy.sh).
Download and install Raspberry Pi Imager v2.0.6 or newer. Older versions (1.9.x and below) will silently fail to apply OS customisation settings on Trixie-based images.
Important: As of early 2026, neither apt (ships 1.8.5) nor snap (ships 1.9.6) provide a new enough version. Download v2.0.6+ directly from the GitHub releases page:
- Windows —
imager-v2.0.6.exe- macOS —
rpi-imager-v2.0.6.dmg- Linux (deb) —
rpi-imager_2.0.6_amd64.deb, then install withsudo apt install ./rpi-imager_2.0.6_amd64.deb(usingaptinstead ofdpkgensures dependencies are resolved automatically; if the download fails with adpkg-deberror, re-download the file — it was likely truncated)- Linux (AppImage) —
Raspberry_Pi_Imager-v2.0.6-desktop-x86_64.AppImage, thenchmod +xand run directly
Insert the SD card into your development machine and launch the Imager. Pi Imager v2.0.6 uses a step-by-step wizard — each screen is accessed via the sidebar on the left.
1. Device — Select your Raspberry Pi model (Pi 4 or Pi 5).
2. OS — Select Raspberry Pi OS (other) to see additional options.
Then select Raspberry Pi OS Lite (64-bit). This is the headless version (no desktop environment) based on Debian Trixie.
3. Storage — Select your SD card.
4. Customisation — After selecting storage, the wizard moves into the customisation steps. Do not click SKIP CUSTOMISATION — these settings are required for SSH access on first boot.
Hostname — Enter a hostname for the Pi. This name identifies the device on the network (reachable via <hostname>.local once Avahi is installed).
Localisation — Select your capital city to set the WiFi regulatory domain, then adjust the Time zone and Keyboard layout dropdowns as needed. For US users, select Washington, D.C. (United States) as the capital city — this defaults to Eastern time. Change the Time zone dropdown to your local zone (e.g. America/Chicago for Central).
Tip: The capital city dropdown contains several hundred entries. Type the first letter of the city name to jump to that section, or use arrow keys to scroll.
User — Create a username and password. You will use these credentials to SSH into the Pi. The username must be lowercase.
Wi-Fi — If the Pi will use a wired Ethernet connection, clear the SSID field (delete any text) so Pi Imager skips WiFi configuration. If you need WiFi, enter your network SSID and password.
Remote access — Enable SSH and select Use password authentication.
Raspberry Pi Connect — Leave this disabled. It is not needed for TrailCurrent.
5. Write — Review the summary to verify your selections, then click WRITE.
Confirm by clicking I UNDERSTAND, ERASE AND WRITE to begin flashing.
- Raspberry Pi 4 or 5 (8GB RAM recommended)
- TrailCurrent Pi Hat (plugs directly onto the GPIO header)
- microSD card (32GB+) or NVME Drive via NVME Base
Insert the flashed SD card into the Pi's microSD slot.
With the Pi powered off, install the TrailCurrent CAN Hat onto the Pi 5 GPIO header.
Connect the JST XH 4-pin cable (JST S4B-XH-SM4-TB) to the hat. The pinout from left to right is:
WARNING: There is no reverse polarity protection on this circuit. Incorrect wiring will damage the Pi. Double-check the pinout before applying power.
Plug the Pi into an available LAN port on your WiFi router using an Ethernet cable.
Connect power to the Pi so that it boots.
On your development machine connected to the same network as the Pi, open a terminal and navigate to the directory where you cloned this repository. Then transfer the setup script to the Pi:
cd <path-to-your-clone>/TrailCurrentInVehicleCompute
scp rpi_one_time/setup-pi.sh <username>@<pi-ip-address>:~/SSH into the Pi and run it:
ssh <username>@<pi-ip-address>
chmod +x ~/setup-pi.sh
sudo ~/setup-pi.shThe script installs and configures everything automatically:
| Step | What it does |
|---|---|
| 1 | Updates system packages (apt-get update && upgrade) |
| 2 | Installs dependencies: jq, openssl, python3, python3-venv, can-utils, avahi, curl, unzip |
| 3 | Installs Docker and Docker Compose plugin, enables on boot |
| 4 | Enables SPI interface via raspi-config |
| 5 | Adds MCP2515 CAN bus overlay to boot config (12MHz oscillator, GPIO25 interrupt) |
| 6 | Installs can0.service systemd unit to auto-start CAN interface at 500kbps |
| 7 | Adds your user to the docker group |
| 8 | Configures auto-boot on power — Pi 5 only (no power button needed in vehicle) |
| 9 | Creates Python virtual environment at ~/local_code/cantomqtt |
| 10 | Installs and enables the cantomqtt systemd service |
| 11 | Creates the deployment directory structure at ~/ |
| 12 | Generates TLS/SSL certificates using the Pi's hostname (10-year validity) |
A reboot is required for SPI and the CAN overlay to take effect:
sudo rebootAfter the Pi comes back up, SSH in and verify:
# Should list /dev/spidev0.1 (spidev0.0 is claimed by the MCP2515 CAN overlay)
ls /dev/spidev0.*
# Should show the can0 interface — confirms the SPI overlay and MCP2515 driver are loaded
ip link show can0
# Should print a version string (e.g. "Docker version 27.x.x")
docker --version
# Should print a version string (e.g. "Docker Compose version v2.x.x")
docker compose versionNote: After setup and reboot,
can0should showstate UPwithqdisc pfifo_fast. If it showsstate DOWNwithqdisc noop, thecan0.servicedid not start — check withsystemctl status can0.service.
If can0 does not appear at all, the CAN hat overlay or wiring may be incorrect. If any command is not found, re-run the setup script.
WARNING — "MCP251x didn't enter in config mode"
If
can0remainsstate DOWNanddmesg | grep -i mcpshows:mcp251x spi0.0 can0: MCP2515 successfully initialized. mcp251x spi0.0: MCP251x didn't enter in config modeThis indicates a hardware problem with the CAN hat. The MCP2515 chip is detected over SPI but cannot be configured. Attempting to manually bring up the interface (
ip link set can0 up) may hang the system and require a power cycle. Do not proceed with deployment — the hat likely has a defective solder joint or damaged component and must be replaced.
The map tiles file must be in place before running deploy.sh. If it is missing, Docker will create a root-owned directory at the mount point, which breaks the tileserver and requires manual cleanup (sudo rm -rf ~/data/tileserver/map.mbtiles then re-create as a file).
From your development machine:
scp map.mbtiles <username>@<hostname>.local:~/data/tileserver/map.mbtilesThe ~/data/tileserver/ directory was already created by the setup script. See UpdatingMapTiles.md for how to obtain or generate this file.
Your Pi is now ready for application deployment:
-
Create a deployment package on your development machine (see PI_DEPLOYMENT.md):
# cd to root of cloned directory before executing ./create-deployment-package.sh --version=1.0.0 -
Transfer the zip to the Pi:
scp trailcurrent-deployment-1.0.0.zip <username>@<hostname>.local:~
-
SSH into the Pi:
ssh <username>@<hostname>.local
-
Extract and deploy:
unzip trailcurrent-deployment-1.0.0.zip chmod +x deploy.sh ./deploy.sh
-
Set NodeRed MQTT Password Navigtate to
https://<yourhostname>.local:8443 -
Login with credentials Using the credentials you set in your .env file login to the server.
-
Set MQTT Password Click on any of the mqtt nodes and edit the broker by going the the security tab and entering the username and password from your .env file. Then publish from node-red. All nodes use the same connnection so you only need to edit one. Afer publishing you should be able to see CAN data and control devices.
On first run, deploy.sh will prompt you to configure .env with your credentials. TLS certificates were already generated during setup using the Pi's hostname. See PI_DEPLOYMENT.md for the full deployment walkthrough.
| Document | Purpose |
|---|---|
| PI_DEPLOYMENT.md | Deploying and updating the application |
| UpdatingMapTiles.md | Generating and updating map tile data |














