Skip to main content

fleet_man

A lightweight Python library for running and monitoring scripts on Raspberry Pis from a browser. Each Pi hosts its own control panel with live log streaming. An optional fleet coordinator aggregates all Pis into a single dashboard.

Built on FastAPI + WebSockets. No external message broker. No database. Each Pi is fully autonomous.


install

pip install 'uvicorn[standard]' fastapi httpx

quick start — single Pi

# app.py
import sys
import uvicorn
from pathlib import Path
from process_manager import ProcessManager, ScriptSpec

PY = sys.executable

scripts = {
    "CAN-M":  ScriptSpec("CAN Manager",  [PY, "gc_monitor/run.py"]),
    "backup": ScriptSpec("backup",        ["bash", "jobs/backup.sh"]),
    "server": ScriptSpec("api server",    [PY, "jobs/server.py"]),
}

mgr = ProcessManager(
    name="pi-kitchen",
    scripts=scripts,
    log_dir=Path("/var/log/jobs"),
    port=5001,
)

app = mgr.create_app()

if __name__ == "__main__":
    uvicorn.run(app, host="0.0.0.0", port=5001)

Open http://<pi-ip>:5001 in your browser.


ProcessManager

ProcessManager(
    scripts,                          # dict[str, ScriptSpec]  — required
    name="pi",                        # node name shown in UI
    log_dir=Path("/tmp/pm_logs"),     # where .log files are written
    coordinator_url=None,             # optional fleet coordinator URL
    host=None,                        # LAN IP advertised to coordinator (auto-detected)
    port=8000,                        # port this Pi listens on
)

ScriptSpec

ScriptSpec(label, cmd)
arg type description
label str display name shown in the UI
cmd list[str] or callable command to run

cmd can be a callable — it is invoked at start time, so it can pull config from disk or environment dynamically:

def build_cmd():
    config = load_config()
    return ["python", "worker.py", "--env", config["env"]]

ScriptSpec("worker", build_cmd)

fleet coordinator

The coordinator runs on any central machine (laptop, NAS, another Pi). It polls each registered Pi, tracks online/offline status, and serves a unified fleet dashboard where you can start and stop scripts across all nodes.

# coordinator.py
import uvicorn
from coordinator import create_coordinator_app

app = create_coordinator_app(fleet_name="home-lab")

if __name__ == "__main__":
    uvicorn.run(app, host="0.0.0.0", port=9000)

Open http://<coordinator-ip>:9000.

auto-registration

Pass coordinator_url to ProcessManager and each Pi registers itself on startup and re-registers every 30 seconds — no manual steps needed. Boot order doesn't matter; Pis retry until the coordinator is reachable.

mgr = ProcessManager(
    name="pi-kitchen",
    scripts=scripts,
    coordinator_url="http://192.168.1.10:9000",
    port=5001,
)

You'll see confirmation in the Pi's console:

[pm] registered with coordinator at http://192.168.1.10:9000

If the coordinator is down at boot:

[pm] coordinator unreachable at http://192.168.1.10:9000 — will retry

Either way the Pi starts normally. The coordinator is purely additive — removing it changes nothing about how the Pi operates.

manual registration (curl)

If you're not using coordinator_url, you can register a node manually:

curl -X POST http://192.168.1.10:9000/register \
     -H "Content-Type: application/json" \
     -d '{"name":"pi-kitchen","host":"192.168.1.42","port":5001}'

log files

Each script writes stdout and stderr to a .log file in log_dir. For a script with key CAN-M the log is written to <log_dir>/CAN-M.log. Logs persist across restarts and are also tailable directly:

tail -f /var/log/jobs/CAN-M.log

The last 500 lines are buffered in memory and replayed instantly when you open the log panel in the browser. New lines stream in live via WebSocket.


API reference

Each Pi exposes the following endpoints:

method path description
GET / local dashboard UI
GET /api/status JSON status of all scripts
POST /api/start/<key> start a script
POST /api/stop/<key> stop a script
GET /api/log/<key> last 500 lines of log (plain text)
WS /ws status push every 2s + start/stop commands
WS /ws/<key> live log stream for one script

The coordinator exposes:

method path description
GET / fleet dashboard UI
POST /register register or re-register a node
GET /api/fleet full fleet status JSON
GET /api/nodes all node info
POST /api/<node>/start/<key> start a script on a specific node
POST /api/<node>/stop/<key> stop a script on a specific node
WS /ws live fleet status push + forwarded commands

architecture

[ browser ]
    │
    │  WebSocket  (live status + logs)
    │
    ├─────────────────────────┐
    │                         │
[ coordinator :9000 ]   [ Pi dashboard :5001 ]
    │                         │
    │  HTTP poll /api/status   │  asyncio subprocess
    │  every 3s                │  stdout/stderr → WS
    │                         │
    └──────── Pi nodes ────────┘
         pi-kitchen  :5001
         pi-garage   :5001
         pi-shed     :5001

Each Pi is standalone. The coordinator is optional. If the coordinator restarts, Pis re-register automatically within 30 seconds.


notes

  • Scripts must run in the foreground. Processes that daemonize (fork and detach) will not be tracked correctly.
  • State is in-memory. If the Pi's process_manager process restarts, running scripts become orphans. Use systemd to keep process_manager itself alive if uptime matters.
  • sys.executable is recommended over "python" or "python3" to ensure the correct interpreter is used, especially inside a virtualenv.

Release files for fleet-man 0.0.4

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for fleet-man 0.0.4
File Size Uploaded
fleet_man-0.0.4.tar.gz 18.4 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for fleet-man 0.0.4
File Interpreter ABI Platform
fleet_man-0.0.4-py3-none-any.whl Python 3 none any Details

Total release size: 37.2 kB

Release files / fleet_man-0.0.4.tar.gz

Download URL fleet_man-0.0.4.tar.gz
Size 18.4 kB
Tags Source
SHA-256 checksum
How to use checksums
916ca2cf1d198fac861e6048764d39a116c499b1517cd8a3fda835b6adb3e019
BLAKE2b-256 checksum
How to use checksums
702fff8bd85011fcb8ba27b3cc115696bb569b916831e5737cad5a5692ba4219
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/6.2.0 CPython/3.13.5

Release files / fleet_man-0.0.4-py3-none-any.whl

Download URL fleet_man-0.0.4-py3-none-any.whl
Size 18.8 kB
Tags Python 3
SHA-256 checksum
How to use checksums
d9fef5927bf570cb4ae2e041704eb8156faff2dab6de321bdf2128bb810131b5
BLAKE2b-256 checksum
How to use checksums
cda836fa91572ff0f03dacffee8c124dba7a7c98e951dc994310f60165215dc5
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/6.2.0 CPython/3.13.5

Release history Release notifications | RSS feed

This release

0.0.4 This release

2 release files

0.0.3

2 release files

0.0.2

2 release files

0.0.1

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page