How to set up a gateway: from hardware to green

Wiki: Setup, edge and devices

Getting a gateway online for the first time? Start at Bring a gateway online, it sequences the on-site path (flash → claim → configure → verify) and links each step. This page is step 1 (flash) of that path.

When to use this

You have (or are about to order) a physical gateway and need to take it from an empty box to “online in Gateways, reading machines.” This is the hardware/OS half of onboarding. The in-app half (registering sources, tags, verifying live tags) picks up where this ends.

What you need

  • The gateway hardware, the Spall gateway: a palm-sized industrial computer (DIN-rail, dual-NIC, screw-terminal panel I/O). 2GB+ RAM, 16GB+ eMMC/SD.
  • A workstation with Raspberry Pi Imager and an SD/USB adapter (or rpiboot for boards where the eMMC has no card slot).
  • Network details for the plant: which drop/VLAN reaches the internet (the uplink role, wired, WiFi, or cellular) and which switch reaches the machines (the plant/OT role). The gateway only ever makes outbound connections, no inbound ports need opening. On a dual-NIC box the two roles are enforced by the gateway itself: the plant/OT port can never become the internet route, no matter what the machine network’s DHCP hands out (the classic “works for an hour then drops” hijack). If the site has a second uplink path (WiFi or a cellular modem) it fails over/back automatically by priority, see device offline or on cellular: reading the uplink status.
  • From the app: a one-time claim token, Gateways → Claim a device mints it (valid 60 minutes, mint it when you’re ready to boot, not the day before). If you’re claiming from the on-device console (Step 2’s “No file?” box below) you don’t need to pick a gateway id up front, the device supplies its own permanent id (its hardware serial) and only asks you for a friendly name.

The OS: you don’t install one

The gateway runs the Spall gateway image, a prebuilt image based on Raspberry Pi OS Lite (64-bit) that already contains the runtime, the edge agent, the hardware watchdog configuration, and the first-boot enrollment logic. You flash it. You don’t install or configure an OS by hand.

Step 1, Flash the image

  1. Get the current spall-gateway-<date>.img.xz (and its .sha256) from your Spall contact or your release channel, and verify the checksum.
  2. Open Raspberry Pi Imager → Choose OS → Use custom → select the .img.xz (Imager reads xz directly).
  3. Choose storage → the gateway’s eMMC/SD.
  4. Skip Imager’s OS customization (the gear/edit screen, hostname, SSH, user): the image already sets these. Customizing here fights the image’s own configuration.
  5. Write and verify.

Step 2, Drop the provisioning file

After flashing, the card’s small boot partition mounts on your workstation (it shows up as bootfs or boot). Create a file named spall-provision.json on it:

{
  "cloud_api": "https://app.spall.cc",
  "bootstrap_token": "claim_xxxxxxxxxxxxxxxxxxxxxxxx",
  "gateway_id": "gw-plant7-line1",
  "site_id": "plant7",
  "name": "Line 1 Edge Gateway"
}
  • bootstrap_token, the one-time token from Gateways → Claim a device.
  • gateway_id, pick a stable, meaningful id. This is how the device appears everywhere.
  • site_id / name, optional, can be set or changed later from Gateways.
  • On current images the file lands at /boot/firmware/ when the partition is mounted on the device, but from your workstation you just copy it to the root of the mounted boot partition. The first-boot script checks both historical locations, and if it finds no file it logs “no provisioning file found” and waits instead of failing.

Eject the card/eMMC, seat it in the carrier board.

No file? Use the on-device console instead, it’s a complete claim path on its own, no JSON needed. If you skip the provisioning file, the gateway boots unclaimed and serves a small setup page at http://<gateway-ip>:8080 on its local network. Open it from a laptop or phone on the same network and you’ll see the device’s own hardware serial displayed read-only (you never type one). Fill in:

  • Cloud API URL (e.g. https://app.spall.cc), pre-filled if the image already has one baked in, editable otherwise. Submitting the form saves it on the device so you never need to touch a shell.
  • Name (optional), a friendly label like “Line 1 gateway”, renameable later from Gateways.
  • The claim token.
  • Advanced (optional, usually leave alone), a broker URL override for non-standard setups, only relevant on a bench/lab network with no TLS broker.

Click Enroll and the page goes live, it shows CLAIMED, then CONNECTED once the broker link is up, right on the device’s own screen.

Step 3, Wire and power on

  • Uplink NIC (role: uplink) → the drop/VLAN with internet access.
  • Plant/OT NIC (role: plant) → the machine-side switch (PLCs, CNCs, meters). This port is locked out of ever carrying the internet route, safe to hand it to whatever the machine network’s DHCP wants to do.
  • Power (DIN-rail supply per your carrier board’s spec) → on.

First boot takes a few minutes: the device starts the edge agent, reads the provisioning file, enrolls itself against the cloud with the claim token, and pulls its MQTT credentials. You do not need a keyboard, monitor, or laptop on the floor.

Step 4, Verify green

  1. In the app, open Gateways: the device should appear and move from claimed to configured, with a recent heartbeat and its agent version reported.
  2. Add its machines: use the Connect a Machine wizard, or the gateway’s own Sources & tags tab, see manage gateways: the gateway home, then push the configuration from there.
  3. Prove every tag is real on the gateway’s own Status tab, each configured tag must show a live value before you sign off.

How the box behaves (what to expect from a settings standpoint)

  • SSH is off by default. Day-to-day management (config, upgrades, health) happens from the cloud. Debugging a dead box is via physical console (HDMI/serial on the carrier board). This keeps the plant network free of a standing remote-login surface.
  • Outbound-only networking. Telemetry goes out over MQTT (TLS, port 8883). Nothing listens for inbound connections from the plant or the internet.
  • A hardware watchdog is enabled, if the device wedges, it power-cycles itself instead of sitting dead until someone walks over.
  • Data survives internet outages. The agent buffers readings locally when the uplink drops and backfills the cloud when it returns. Gateways shows buffer depth so you can see it catching up.
  • No remote-login surface, period. The gateway never runs a remote-shell or remote-login service, not even one you’d have to turn on. Support can pull diagnostics remotely with your consent. If hands-on help is ever needed, support sends a small plug-in access device that only works while it’s physically connected to your gateway.
  • Updates are over-the-air (OTA). Software/Releases pushes signed agent updates. You approve a target version, devices converge to it. No truck rolls for software.

Alternative: manual install on your own OS

If you’re evaluating without Spall hardware (or re-using an existing Pi), you can run the agent on a stock Raspberry Pi OS Lite (64-bit): flash it with Imager as usual, get the device on the network, then ask your Spall contact for the manual provisioning script (run as root), it installs Docker and brings up the agent. You’ll then enroll it with a claim token the same way. The golden image is the supported path for real deployments (watchdog, hardening, and first-boot enrollment are only guaranteed there). The manual path is best kept to bench evaluation.

Troubleshooting

  • Never appears in Gateways, check the uplink cable/VLAN first, then the provisioning file name and location (root of the boot partition, exact name spall-provision.json), then whether the claim token expired (mint a fresh one and re-drop the file, it’s read on boot).
  • Token expired, tokens live 60 minutes. Mint another in Gateways → Claim a device, update bootstrap_token in the file, power-cycle.
  • Appears but no machine data, that’s the next stage: sources/tags aren’t configured yet, or the OT NIC isn’t cabled to the machine switch. Run the Connect a Machine wizard and the connection test.
  • Need console access, HDMI + USB keyboard (or the carrier’s serial header). Logs: journalctl -u spall-firstboot for enrollment, docker logs for the agent.
  • “What’s this gateway’s IP?” / “is it actually on wired or did it fall back to cellular?”, read the gateway’s own Status tab instead of ARP-scanning the switch or SSHing in. It self-reports on every heartbeat: eth0 · 10.0.0.225 · default for a wired uplink, or LTE ATT ▂▄▆ −71 dBm plus an amber “fallback path” badge when the default route has fallen onto wifi/cellular. If the line is missing, either the device hasn’t heartbeated recently, or it’s on an older agent build that doesn’t report it yet, check “seen Xm ago” next to it before assuming something’s broken. The Network tab shows the same information as a fuller table (every reported interface, the cellular modem’s carrier/technology/signal, and data usage), if you want more than the one-line summary.
  • Red/amber data-usage badge on a cellular box, the Network tab’s Data usage card tells you it’s near or over its configured budget_mb_day, not a connectivity fault. Go to the Status tab and click Budget: … (edit) to raise the limit if the usage is expected.
  • Gateway dropped to WiFi/cellular, or went offline, and you’re not sure why, see device offline or on cellular: reading the uplink status for how to read the failover reason instead of guessing.