Saltar al contenido principal

Print Bridge on Raspberry Pi Zero W

This document covers deploying the apps/print-bridge app natively on a Raspberry Pi Zero W and connecting it to the FlowPOS staging or production backend.


Architecture overview

FlowPOS Backend (Cloud Run)
└── Socket.IO /restaurant namespace
└── Print Bridge (Raspberry Pi Zero W)
└── Thermal Printer (TCP or USB)

The print-bridge is a Node.js Express server that:

  • Serves a React configuration UI on port 3456
  • Connects to the FlowPOS backend via Socket.IO (WebSocket)
  • Receives kitchen print jobs in real-time
  • Renders ESC/POS receipts and sends them to the printer

Why not Docker on Pi Zero W

The Pi Zero W uses an ARMv6 CPU. Docker's binaries (written in Go) require ARMv7 instructions — running Docker results in:

Illegal instruction

The solution is to run Node.js natively using the unofficial armv6l builds maintained specifically for the Pi Zero.


Prerequisites

Hardware and software from Raspberry Pi Zero W Setup Guide:

  • Pi Zero W with Raspberry Pi OS Lite (32-bit) installed
  • SSH access via ssh luis@flowpi.local
  • Wi-Fi connected (2.4 GHz)

Step 1 — Install Node.js 20 LTS (ARMv6)

The official Node.js builds do not include ARMv6. Use the unofficial armv6l builds:

NODE_VER=v20.18.0
curl -fsSL "https://unofficial-builds.nodejs.org/download/release/${NODE_VER}/node-${NODE_VER}-linux-armv6l.tar.gz" \
| sudo tar -xz -C /usr/local --strip-components=1

node --version
npm --version

Install pnpm and native build tools:

sudo npm install -g pnpm
sudo apt-get install -y python3 make g++ libvips-dev

libvips-dev allows sharp to use the system library for image processing instead of compiling it from scratch.


Step 2 — Build on your Mac

From the workspace root on your Mac:

pnpm --filter @flowpos-workspace/print-bridge run build

This compiles:

  • apps/print-bridge/dist/agent/ — Node.js CommonJS agent
  • apps/print-bridge/dist/ui/ — Vite React SPA

Why build on Mac and not on the Pi

The Vite UI build uses @swc/core which has no pre-built binary for ARMv6. Building must happen on an x86/ARM64 machine.


Step 3 — Copy to the Pi

From the workspace root on your Mac:

rsync -avzR --exclude='node_modules' --exclude='.git' \
./pnpm-workspace.yaml \
./package.json \
./pnpm-lock.yaml \
./apps/print-bridge \
./packages/global \
./packages/receipt-layout \
./packages/receipt-escpos \
luis@flowpi.local:~/print-bridge/

The -R flag preserves the full relative path so the workspace structure is correct on the Pi.


Step 4 — Install production dependencies on the Pi

ssh luis@flowpi.local
cd ~/print-bridge

Remove the husky prepare script (it is a dev dependency and will cause install to fail):

python3 -c "
import json
with open('package.json') as f:
p = json.load(f)
p.setdefault('scripts', {}).pop('prepare', None)
with open('package.json', 'w') as f:
json.dump(p, f, indent=2)
print('prepare script removed')
"

Approve native build scripts (required in pnpm v10+):

pnpm approve-builds

Select bcrypt and sharp when prompted (skip protobufjs — it is optional for Firebase).

Install:

pnpm install --filter @flowpos-workspace/print-bridge... --prod --frozen-lockfile

This compiles bcrypt natively for ARMv6. Expect 5–15 minutes.


Step 5 — Generate a permanent secret

The BRIDGE_SECRET encrypts the config file on disk. It must stay the same across restarts or the config will be unreadable.

openssl rand -hex 32

Save the output in a password manager or Doppler before continuing.


Step 6 — Systemd service

Staging

sudo tee /etc/systemd/system/print-bridge.service > /dev/null << 'EOF'
[Unit]
Description=FlowPOS Print Bridge
After=network-online.target
Wants=network-online.target

[Service]
User=luis
WorkingDirectory=/home/luis/print-bridge/apps/print-bridge
ExecStart=/usr/local/bin/node dist/agent/index.js
Restart=always
RestartSec=5
Environment=FLOWPOS_API_URL=https://api.staging.flowandgrow.tech
Environment=BRIDGE_SECRET=REPLACE_WITH_YOUR_SECRET
Environment=BRIDGE_DATA_DIR=/home/luis/print-bridge-data

[Install]
WantedBy=multi-user.target
EOF

Production

Same as above but set:

Environment=FLOWPOS_API_URL=https://api.flowandgrow.tech

Enable and start:

mkdir -p ~/print-bridge-data
sudo systemctl enable print-bridge
sudo systemctl start print-bridge
sudo systemctl status print-bridge

Step 7 — Access the UI

Open in your browser:

http://flowpi.local:3456

Step 8 — Pair with FlowPOS

  1. In the FlowPOS admin panel, navigate to Kitchen Stations or Printers.
  2. Generate a new pairing code.
  3. Paste the code immediately into the bridge UI at http://flowpi.local:3456/config.

The pairing code is stored in Redis with a short TTL (~5 minutes). Generate and use it without delay.

Verify the configured API URL

cat ~/print-bridge-data/config.json

The apiUrl field must match the environment where you generated the pairing code:

EnvironmentapiUrl
Staginghttps://api.staging.flowandgrow.tech
Productionhttps://api.flowandgrow.tech

A staging pairing code will not validate against the production backend.


Useful commands

View live logs

journalctl -u print-bridge -f

Check service status

sudo systemctl status print-bridge

Stop the service

sudo systemctl stop print-bridge

Verify it stopped:

sudo systemctl status print-bridge

Restart after a config change

sudo systemctl restart print-bridge

Test backend connectivity from the Pi

curl -s https://api.staging.flowandgrow.tech/health
curl -s https://api.flowandgrow.tech/health

Updating the app

After a new build on your Mac and rsync:

sudo systemctl stop print-bridge
cd ~/print-bridge
pnpm install --filter @flowpos-workspace/print-bridge... --prod --frozen-lockfile
sudo systemctl start print-bridge
journalctl -u print-bridge -f

Troubleshooting

"Illegal instruction" on any binary

The binary was compiled for ARMv7 or ARM64 and will not run on the Pi Zero W's ARMv6 CPU. Ensure you are using the armv6l Node.js build from unofficial-builds.nodejs.org.

"Pairing failed"

  • The pairing code expired — generate a new one and use it within 5 minutes.
  • The pairing code is from staging but the bridge points to production (or vice versa). Check config.json.
  • bcrypt native module was not compiled — run pnpm approve-builds and reinstall.

"Cannot find module" on startup

The dist/agent/ directory is missing. Run the build on your Mac first:

pnpm --filter @flowpos-workspace/print-bridge run build

Then rsync and reinstall.

UI not loading at http://flowpi.local:3456

Check that the service is running and the port is open:

sudo systemctl status print-bridge
curl http://localhost:3456

pnpm install fails with "husky not found"

Remove the prepare script from the root package.json using the Python snippet in Step 4.

sharp or bcrypt errors at runtime

Run pnpm approve-builds, select both packages, then reinstall and restart the service.


Notes

  • The Pi Zero W has 512MB RAM. The print-bridge uses ~80–120MB at idle.
  • No swap file is needed when running natively (unlike Docker, which adds significant overhead).
  • The BRIDGE_DATA_DIR volume holds config.json (encrypted), dedup.json (prevents duplicate prints), and .secret (fallback key). Back up this directory if you reconfigure the Pi.