A polished pocket control center for Raspberry Pi, Docker, personal servers, alerts, and nearby ESP32 devices.
PocketDeck turns an M5StickC Plus2 into a tiny, responsive interface for a Raspberry Pi 5 and owner-operated infrastructure. The handheld stays focused on rendering, navigation, radio, and power management. A lightweight Python agent performs system inspection, Docker control, health checks, GitHub requests, safe server actions, and alert normalization.
The result is closer to a small commercial handheld than an Arduino debug screen: restrained dark visuals, clear hierarchy, compact charts, semantic status colors, confirmation flows, cached offline states, and no full-screen bitmap dependency.
| App | Capability |
|---|---|
| Home | Pi availability, CPU, RAM, temperature, Docker health, latency, time, Wi-Fi, and battery |
| Pi Monitor | Hostname, uptime, load, memory, swap, disk, network totals, processes, and rolling charts |
| Docker | Explicitly allowlisted containers with state, health, CPU, RAM, uptime, restarts, and confirmed restart |
| Servers | Pi-side HTTP health checks with latency, status code, and last success |
| GitHub | Repository, branch, latest commit, CI, issues, pull requests, and deployment summary |
| Messages | ESP-NOW peer pairing and configurable quick-message transport |
| Commands | Exact server-side argv allowlist—never arbitrary remote shell |
| Alerts | Deduplicated server, disk, temperature, Docker-health, and failed-action notifications |
| Network | SSID, RSSI, IP, gateway, DNS, Wi-Fi channel, and Pi latency |
| Diagnostics | Free/min heap, PSRAM, largest block, peers, radio state, uptime, and build information |
| LoRa | Optional transport abstraction with a safe disabled state until hardware is selected |
┌ POCKETDECK ───────── 21:43 ┐ ┌ DOCKER ────────────────┐
│ ┌ PI 5 ───┐ ┌ CPU 34% ─┐ │ │ ● api 3% 12% │
│ │ ONLINE │ │ ━━━━━━━── │ │ │ ● postgres 1% 18% │
│ │ 47°C │ └───────────┘ │ │ ● redis 2% 8% │
│ └──────────┘ ┌ RAM 27% ─┐ │ │ ○ worker stopped │
│ 7/7 containers · 18 ms │ │ A restart · B select │
└─────────────────────────────┘ └─────────────────────────┘
- A — open, select, or confirm.
- B — move to the next app, row, page, peer, or quick message.
- Hold B — return Home.
- Power — board-managed power action and wake interaction.
Control actions always pass through a confirmation overlay. The display uses a small header canvas and direct RGB565 primitives rather than a retained full-screen framebuffer.
- PlatformIO + Arduino ESP32
- M5Unified / M5GFX
- One bounded FreeRTOS network worker; the UI loop never performs HTTP
- Fixed-size models for containers, services, alerts, peers, messages, and history
- 8 KiB maximum accepted HTTP payload
- Exponential Wi-Fi reconnect and clear stale/offline state
- Active, dim, and display-sleep policies with reduced background polling
- ESP-NOW packet codec with CRC16, message IDs, acknowledgements, pairing window, and NVS peer persistence
- FastAPI + uvicorn
- psutil system metrics
- Docker SDK normalization and explicit container allowlist
- Concurrent HTTP uptime checks
- Fine-grained GitHub read integration
- Exact argv action runner with
shell=False, timeouts, bounded output, and a clean PATH - Bounded alert queue with cooldown deduplication
- systemd hardening and a dedicated
pocketdeckuser
PocketDeck is designed for an owner's trusted devices and networks.
- Read endpoints require a bearer token.
- Mutations additionally require an HMAC-SHA256 signature, timestamp, and one-time nonce.
- Sensitive requests are rate-limited and rejected outside a 60-second clock window.
- GitHub credentials stay on the Pi.
- Wi-Fi and agent credentials stay in ESP32 NVS.
- Docker and command targets are explicit allowlists.
- There is no arbitrary shell endpoint and subprocesses never use
shell=True. - Dangerous actions require device-side confirmation.
Use a validating TLS reverse proxy before exposing the agent outside a trusted network. Do not forward port 8787 directly to the public internet.
sudo apt update
sudo apt install -y git python3 python3-venv python3-pip curl ca-certificates rsync
git clone https://github.com/rezvvent/PocketDeck.git
cd PocketDeck
sudo ./scripts/setup-pi.sh
sudo nano /etc/pocketdeck/config.yml
sudo systemctl restart pocketdeck-agent
sudo systemctl status pocketdeck-agent --no-pagerbrew install git python pipx
pipx ensurepath
pipx install platformio
git clone https://github.com/rezvvent/PocketDeck.git
cd PocketDeck
pio run -d firmware -e m5stickc-plus2
./scripts/flash.sh /dev/cu.usbserial-YOUR_PORTOn first boot, join PocketDeck-AB12, open http://192.168.4.1, and provide the 2.4 GHz Wi-Fi credentials, Pi Agent URL, and generated shared token.
The complete beginner walkthrough is in INSTALL.md.
PocketDeck ships with safe examples, not guessed access to the host. Configure only what the handheld should see or control:
docker:
enabled: true
allowed:
api:
container: production-api
label: API
destructive: false
services:
- id: website
name: Website
url: https://example.com/health
timeout_seconds: 5
expected_status: [200, 204]
actions:
restart_nginx:
label: Restart Nginx
command: [/usr/bin/sudo, /usr/bin/systemctl, restart, nginx.service]
dangerous: true
timeout_seconds: 30See CONFIGURATION.md for Docker permissions, narrow sudoers rules, GitHub setup, writable-path hardening, and the request-signing scheme.
# Mock Pi agent
./scripts/dev.sh
# Backend tests
cd pi-agent
.venv/bin/pytest -q
# Pure packet-codec tests
pio test -d firmware -e native
# Target firmware build
pio run -d firmware -e m5stickc-plus2Verified build baseline:
Pi agent tests 10 passed
Packet codec tests 2 passed
Firmware target SUCCESS
Static RAM 56,120 / 327,680 bytes (17.1%)
Firmware image 1,216,069 / 3,342,336 bytes (36.4%)
Runtime free heap and PSRAM depend on the physical board. Firmware prints a bounded memory report every 30 seconds and exposes the same values in Diagnostics.
The V1 core builds and runs on M5StickC Plus2 with the Raspberry Pi agent. System monitoring, first-boot setup, authenticated API access, Docker allowlisting, server checks, safe commands, alerts, power policy, mock mode, and the UI shell are present.
ESP-NOW requires a second compatible device for end-to-end testing. LoRa intentionally remains a hardware-specific adapter boundary until an exact module, legal frequency, and pinout are selected.
- Installation from zero
- Configuration and safe actions
- Architecture and memory strategy
- ESP-NOW pairing
- Optional LoRa upgrade
- Troubleshooting
- Validation and memory report
MIT © 2026 PocketDeck contributors.