BamBuddy¶
Bambu Lab printer management app for monitoring print jobs, filament inventory, and remote slicing. Runs in the home namespace with two slicer API sidecars built by a weekly Jenkins pipeline.
- Source —
ghcr.io/maziggy/bambuddy· wiki - URL — bambuddy.hdhomelab.com
- Namespace —
home - Database — PostgreSQL
192.168.68.7:5432/bambuddy - Flux manifests —
flux/apps/noah/home/bambuddy/ - Auth — Authentik OIDC (slug:
bambuddy)
Architecture¶
graph TB
subgraph pod["bambuddy pod (home namespace)"]
BB[bambuddy\nghcr.io/maziggy/bambuddy\n:8000]
ORC[orca-slicer-api\ncicd/orca-slicer-api\n:3003]
BST[bambu-studio-api\ncicd/bambu-studio-api\n:3001]
end
subgraph storage["Storage"]
PG[(PostgreSQL\n192.168.68.7\nbambuddy DB)]
NFS[NFS PVC\nbambuddy-data\nslicer/orca · slicer/bambu]
end
subgraph infra["Infrastructure"]
SP[Spoolman\nhttp://spoolman.home.svc\n:8000]
JK[Jenkins\nbambuddy-slicer-build\nweekly]
GIT[Gitea\ncicd/orca-slicer-api\ncicd/bambu-studio-api]
end
BB -->|DATABASE_URL| PG
BB -->|SLICER_API_URL| ORC
BB -->|BAMBU_STUDIO_API_URL| BST
BB -->|spoolman integration| SP
ORC --> NFS
BST --> NFS
JK -->|builds & pushes| GIT
GIT -->|Flux image policy| ORC
GIT -->|Flux image policy| BST
Pod layout¶
| Container | Image | Port | Purpose |
|---|---|---|---|
bambuddy |
ghcr.io/maziggy/bambuddy |
8000 | Main app |
orca-slicer-api |
gitea.hdhomelab.com/cicd/orca-slicer-api |
3003 | OrcaSlicer wrapper |
bambu-studio-api |
gitea.hdhomelab.com/cicd/bambu-studio-api |
3001 | BambuStudio wrapper |
Both slicer containers run as root (required by the slicer binaries) and mount the bambuddy-data NFS PVC at subpaths slicer/orca and slicer/bambu for profile storage.
Slicer images¶
The slicer images are not pre-built by the upstream project. They are built from the bambuddy/profile-resolver branch, which patches profile resolution for Bambu-authored .3mf files.
A Jenkins pipeline (bambuddy-slicer-build) builds and pushes both images to the internal Gitea registry on a weekly cron (H 6 * * 1). Builds are skipped if the tag already exists.
| Image | Registry path | Tag format | Example |
|---|---|---|---|
| OrcaSlicer | cicd/orca-slicer-api |
orca<version> |
orca2.3.2 |
| BambuStudio | cicd/bambu-studio-api |
bambu<version> |
bambu02.06.00.51 |
Storage¶
| Resource | Type | Purpose |
|---|---|---|
PostgreSQL bambuddy DB |
192.168.68.7:5432 |
App data (printers, filaments, jobs) |
bambuddy-data PVC |
syno-nfs-retain 5Gi |
Slicer profiles for both sidecars |
SQLite on NFS
Bambuddy defaults to SQLite. Running SQLite on an NFS-backed PVC causes database corruption — see SQLite on Local Path. PostgreSQL is used instead via the DATABASE_URL env var.
Database¶
Role and database are provisioned by OpenTofu (tofu/tf-deploy/psql/locals.tf). Credentials are pulled from Vault at psql/bambuddy and injected via an ExternalSecret:
OIDC¶
Authentik provider BamBuddy (slug: bambuddy). Credentials stored in Vault at apps/bambuddy/oidc.
| Field | Value |
|---|---|
| Discovery URL | https://auth.hdhomelab.com/application/o/bambuddy/ |
| Callback URL | https://bambuddy.hdhomelab.com/api/v1/auth/oidc/callback |
Configure in Bambuddy → Settings → Authentication → OIDC.
Slicer API¶
Slicer URLs are injected via env vars — no manual UI configuration needed:
| Env var | Value |
|---|---|
SLICER_API_URL |
http://localhost:3003 |
BAMBU_STUDIO_API_URL |
http://localhost:3001 |
Spoolman integration¶
Spoolman runs as a separate deployment in the same namespace. Connect in Bambuddy → Settings → Spoolman:
Bambuddy has a native Spoolman UI — no iframe — providing precise per-print filament consumption from layer-by-layer G-code analysis.
Image automation¶
Flux ImagePolicy tracks updates for all three images automatically:
| Image | Policy | Pattern |
|---|---|---|
bambuddy |
alphabetical asc | ^v?(\d+\.\d+\.\d+\.\d+)$ |
orca-slicer-api |
semver | ^orca(\d+\.\d+\.\d+)$ |
bambu-studio-api |
alphabetical asc | ^bambu(\d+\.\d+\.\d+\.\d+)$ |
Alphabetical policy for bambu-studio-api
BambuStudio uses leading-zero version strings (e.g. 02.06.00.51). Flux's semver and numerical policies can't parse these, so alphabetical ascending is used — this works correctly because all components are zero-padded to equal width.