A self-hosted web app for managing a multi-brand 3D printer farm. Replaces manual USB job distribution with centralized status monitoring and automated job dispatch — built to run 24/7 on a dedicated machine on your local network.
No cloud. No subscriptions. No vendor lock-in.
Security note: This app has no built-in authentication. It is designed to run on a trusted local network only. Do not expose port 3000 (or 5173 in dev) to the internet — your printer API keys are served to any client that can reach the server. Run it behind your router's firewall or a local VPN.
- Live fleet view — see every printer's status, progress, and time remaining at a glance, auto-refreshing every 15 seconds
- Automated job dispatch — define projects and parts, upload G-code, and let the scheduler assign jobs to idle printers automatically
- Operator confirmation flow — every finished print requires a human sign-off before the next job dispatches, preventing runaway failures
- Multi-brand support — Prusa, Elegoo, Bambu, and Klipper printers in the same fleet, managed from one interface
- CSV fleet import — add 50 printers at once from a spreadsheet
- TV dashboard mode — a heads-up fleet summary designed for a monitor on the shop wall
- Farm backup and restore — export your entire farm config and job history as a single JSON file
| Brand | Protocol | Models |
|---|---|---|
| Prusa | PrusaLink REST API | MK4S, XL, and other PrusaLink-compatible models |
| Elegoo | SDCP WebSocket (Centauri Carbon) · MQTT (Centauri Carbon 2) | Centauri Carbon, Centauri Carbon 2 |
| Bambu Lab | MQTT + FTPS | X1C, P1S, and other Bambu models (with AMS slot selection) |
| Klipper | Moonraker REST API | Voron and any Klipper-firmware printer |
| OctoPrint | OctoPrint REST API | Any printer running OctoPrint / OctoPi |
| Package | Role |
|---|---|
| Node.js + Express | HTTP API server |
| better-sqlite3 | Embedded SQLite database — synchronous, zero configuration |
| axios | HTTP communication with Prusa, Klipper, and OctoPrint printers |
| mqtt | MQTT over TLS for Bambu printer communication |
| basic-ftp | FTPS file transfer to Bambu printers |
| sdcp | WebSocket protocol driver for Elegoo SDCP printers |
| multer | G-code file upload handling |
| papaparse | CSV fleet import |
| form-data | Multipart upload for Klipper/Moonraker |
| PM2 | Process manager — auto-start on boot, crash recovery |
| Package | Role |
|---|---|
| React 18 | UI framework |
| React Router v6 | Client-side routing |
| Vite | Build tool and dev server |
| Technology | Role |
|---|---|
| SQLite (via better-sqlite3) | Single-file embedded database — no database server required |
Requires Node.js 22 LTS — Node 24+ has known issues compiling the native SQLite dependency on Windows (see the Installation Guide for details).
git clone https://github.com/joeltelling/print-farm-manager.git
cd print-farm-manager
npm install
cd client && npm install && cd ..
npm run dev- API server:
http://localhost:3000 - Web UI (hot reload):
http://localhost:5173
Requires Docker (and Compose, bundled with Docker Desktop and modern Docker Engine installs). This runs the same production build described in Option B, packaged into a container — no local Node.js install needed on the host.
git clone https://github.com/joeltelling/print-farm-manager.git
cd print-farm-manager
docker compose up -d --buildThis builds the image (compiling better-sqlite3 and building the React client inside the container) and starts it in the background, restarting automatically on crash or host reboot. The SQLite database, hourly backups, and uploaded G-code files are stored in the named Docker volumes farm-data and farm-gcode, so they survive container rebuilds and updates.
Open http://localhost:3000 in a browser, or replace localhost with the machine's LAN IP to access it from any device on the network.
Updating to a new version:
git pull
docker compose up -d --buildUseful commands:
| Command | What it does |
|---|---|
docker compose logs -f |
Follow server logs |
docker compose stop |
Stop the container (data is preserved) |
docker compose up -d |
Start it again |
docker compose down |
Stop and remove the container (volumes are preserved) |
Without Compose, the equivalent docker run is:
docker build -t print-farm-manager .
docker run -d --name print-farm-manager --restart unless-stopped \
-p 3000:3000 \
-v farm-data:/app/server/data \
-v farm-gcode:/app/server/gcode \
print-farm-managerSame security note as above applies inside Docker: only publish port 3000 to interfaces on your trusted LAN, not
0.0.0.0on an internet-facing host.
For a full walkthrough covering prerequisites, network setup, auto-start with PM2, backup, updating, and troubleshooting on both Windows and macOS, see the Installation Guide.
The short version:
npm install
cd client && npm install && cd ..
npm run build
npm startOpen http://localhost:3000 in a browser, or replace localhost with the machine's LAN IP to access it from any device on the network.
The fastest way to add a large fleet is via CSV import on the Settings page.
| Column | Required | Example |
|---|---|---|
name |
Yes | MK4S_01 |
ip |
Yes | 192.168.1.100 |
type |
Yes | prusa / elegoo-centauri / elegoo-centauri2 / bambu / klipper / octoprint |
api_key |
Prusa and OctoPrint (API key), Bambu and Centauri Carbon 2 (LAN access code) | aK3jR7xQ2pLm9vN |
serial_number |
Bambu and Centauri Carbon 2 | 01S00C123456789 |
group |
No | MK4S Farm |
model |
No | mk4s |
If the model column is omitted, the model is inferred automatically from the printer name where possible; unrecognised models prompt for manual selection after import.
print-farm-manager/
├── server/
│ ├── index.js # Express entry point
│ ├── db.js # SQLite schema + migrations
│ ├── poller.js # 15-second printer poll loop
│ ├── scheduler.js # Job dispatch engine
│ └── drivers/ # Per-brand printer drivers
│ ├── prusa.js # PrusaLink REST
│ ├── elegoo-centauri.js # SDCP WebSocket (Centauri Carbon)
│ ├── elegoo-centauri2.js # MQTT + chunked HTTP PUT (Centauri Carbon 2)
│ ├── bambu.js # MQTT + FTPS
│ ├── klipper.js # Moonraker REST
│ └── octoprint.js # OctoPrint REST
├── client/ # React + Vite frontend
├── docs/ # Full documentation
├── Dockerfile # Multi-stage production image (build client + server, run on Node 22)
└── docker-compose.yml # Production container with persistent data/gcode volumes
MIT

