mirror of
https://github.com/maziggy/bambuddy.git
synced 2026-09-29 18:51:43 +02:00
BambuStudio reads its FTP upload destination out of net.info[].ip in the MQTT status, and the bridge fills that field from the VP's bind address. On Docker bridge networking the two are different machines' worth of address: slicers reach Bambuddy on the host's LAN IP, the container binds something like 172.24.0.2, and that private address is what the slicer was handed -- so it opened an FTP connection to an address that does not exist on its network and the send stalled around 10%. VIRTUAL_PRINTER_ADVERTISE_ADDRESS supplies the address slicers actually use, taking precedence over the bind address and over the same-subnet host interface the bridge falls back to. The armed log line names its source, so (VIRTUAL_PRINTER_ADVERTISE_ADDRESS) against (bind_address) tells an operator whether the variable reached the container at all, and the not-armed diagnostic now names it as the remedy -- a bridge-network install that has not set it is exactly the one that cannot auto-resolve either, and until now saw only that nothing worked. An environment variable rather than a change to how the advertised address is resolved, which is the decision worth recording. The VP already has a "Network Interface Override" field, and reading it here is the smaller patch, but it feeds SSDP and the certificate SANs only: honouring it would silently move the upload destination on every install that has one set -- the multi-NIC, VLAN and Tailscale setups, which are the ones most likely to have been arrived at by hand and least likely to survive being second-guessed. Unset, this changes nothing, and a test pins that. A value that is not a dotted-quad IPv4 is refused with one warning naming it and the previous address is used instead. That direction is deliberate: declining to rewrite would put the real printer's IP back in front of the slicer, which is the leak the rewrite exists to close, so a typo must not be able to reopen it. 0.0.0.0 counts as unset and whitespace is stripped, for values pasted into a compose file. Host and macvlan networking need none of this and stay what Virtual Printer is developed against. The variable removes one blocker; it does not make bridge mode equivalent. The wiki said in three places that the host address could not be discovered at all, which is no longer true, so those now describe the variable and keep the recommendation.
192 lines
10 KiB
YAML
192 lines
10 KiB
YAML
services:
|
||
bambuddy:
|
||
image: ghcr.io/maziggy/bambuddy:latest
|
||
build: .
|
||
# Usage:
|
||
# docker compose up -d → pulls pre-built image from ghcr.io
|
||
# docker compose up -d --build → builds locally from source
|
||
container_name: bambuddy
|
||
# File ownership inside the data and logs volumes is normalised by the
|
||
# entrypoint at startup (chowns to PUID:PGID and drops privileges via
|
||
# gosu before running the app). Override PUID / PGID below to match
|
||
# your host user if needed — defaults to 1000:1000 to match the
|
||
# historical compose `user:` directive.
|
||
#
|
||
# Allow binding to privileged ports (322, 990) as non-root user — required
|
||
# for FTPS in every VP mode and for the RTSPS camera proxy in proxy mode +
|
||
# non-proxy modes that have a target printer configured. Without this, the
|
||
# FTP and RTSP listeners silently fail.
|
||
cap_add:
|
||
- NET_BIND_SERVICE
|
||
#
|
||
# LINUX: Use host mode for printer discovery and camera streaming
|
||
network_mode: host
|
||
#
|
||
# macOS/WINDOWS: Docker Desktop doesn't support host mode.
|
||
# Comment out "network_mode: host" above and uncomment "ports:" below.
|
||
# Note: Printer discovery won't work - add printers manually by IP.
|
||
#ports:
|
||
# - "${PORT:-8000}:8000"
|
||
# - "3000:3000" # Virtual printer bind/detect
|
||
# - "3002:3002" # Virtual printer bind/detect
|
||
# - "8883:8883" # Virtual printer MQTT
|
||
# - "990:990" # Virtual printer FTP control
|
||
# - "6000:6000" # Virtual printer file transfer tunnel
|
||
# - "322:322" # Virtual printer RTSP camera (X1/H2/P2; proxy mode + non-proxy modes with a target printer)
|
||
# - "2024-2026:2024-2026" # Virtual printer proprietary ports (A1/P1S)
|
||
# - "50000-50029:50000-50029" # Virtual printer FTP passive data (3 VPs × 10-port slice)
|
||
#
|
||
# FTP passive-mode port slicing (#1646): non-proxy VPs (Archive / Review /
|
||
# Queue modes) get a 10-port slice each, allocated by VP id — VP 1 →
|
||
# 50000-50009, VP 2 → 50010-50019, VP 3 → 50020-50029, etc. The default
|
||
# exposure above covers 3 VPs; widen the range to cover more
|
||
# (`50000-500N9` where N = vp_count - 1). Proxy-mode VPs forward the
|
||
# real printer's full 50000-50100 range — if you use proxy mode, expose
|
||
# `50000-50100:50000-50100` instead.
|
||
#
|
||
# Why narrow this matters on bridge mode: with Docker's default
|
||
# userland-proxy (true), every exposed port spawns one docker-proxy host
|
||
# process per address family (IPv4 + IPv6). The original 1001-port range
|
||
# spawned ~2000 such processes, pinning ~3.5 GB of host RAM that doesn't
|
||
# appear in `docker stats` (host-level, not container-level). 30 ports
|
||
# → ~60 processes → ~210 MB instead.
|
||
#
|
||
# Bridge mode is the normal setup for any Linux host that runs
|
||
# Bambuddy alongside other services (NAS, multi-tenant Docker VM,
|
||
# Synology DSM, Unraid) — `network_mode: host` would conflict with
|
||
# ports those other services already bind. Bambuddy uses host mode by
|
||
# default because SSDP printer discovery needs L2 multicast, but it's
|
||
# a deliberate trade-off, not a security-blind default; setups that
|
||
# forgo discovery (add printers by IP) can stay on bridge with the
|
||
# narrowed range above.
|
||
volumes:
|
||
- bambuddy_data:/app/data
|
||
- bambuddy_logs:/app/logs
|
||
#
|
||
# OPTIONAL — only needed if you ALSO run a native install of Bambuddy
|
||
# on the same host and want both installs to share the same Virtual
|
||
# Printer CA certificate (so the slicer only has to trust one CA).
|
||
# Most Docker-only users should leave this commented out — the
|
||
# entrypoint will keep the VP data inside the named volume above.
|
||
# If uncommented, the entrypoint chowns the host directory to
|
||
# PUID:PGID on first start so the container user can write to it.
|
||
#- ./virtual_printer:/app/data/virtual_printer
|
||
#
|
||
# Mount scheduled backup output to NAS or external storage
|
||
# Backups default to DATA_DIR/backups/ inside the data volume.
|
||
# Uncomment to store them externally (e.g. on a NAS share).
|
||
#- /path/to/nas/bambuddy-backups:/app/data/backups
|
||
#
|
||
# Tailscale integration (optional): mount the host's tailscaled socket
|
||
# so Bambuddy can request Let's Encrypt certs for virtual printers via
|
||
# your tailnet's MagicDNS name. Requires:
|
||
# 1. Tailscale installed + `tailscale up` completed on the host
|
||
# 2. `sudo tailscale set --operator=<container-user>` on the host so
|
||
# the user running the container can call `tailscale cert`
|
||
# Without this mount, the Tailscale toggle in the UI is harmless —
|
||
# Bambuddy falls back to self-signed certs.
|
||
#- /var/run/tailscale/tailscaled.sock:/var/run/tailscale/tailscaled.sock
|
||
#
|
||
# Using a self signed certificate for Home Assistant
|
||
# Add your certificate to certs directory and mount it to the container.
|
||
# The certificate will be added to the system trust store on container startup.
|
||
# Enable the system trust store with the USE_SYSTEM_TRUST_STORE env var to
|
||
# have Bambuddy trust the certificate.
|
||
# - /path/to/certs:/usr/local/share/ca-certificates
|
||
#
|
||
# External library folders. Mount the host paths the operator wants
|
||
# users to be able to register as external folders. The in-container
|
||
# paths chosen here MUST appear in BAMBUDDY_EXTERNAL_ROOTS below.
|
||
# Read-only (:ro) is recommended unless you want users uploading
|
||
# files back to the host share.
|
||
#- /mnt/nas/3d-prints:/external/nas:ro
|
||
#- /srv/library:/external/projects:ro
|
||
environment:
|
||
- TZ=${TZ:-Europe/Berlin}
|
||
# User/group the container drops to after the entrypoint normalises
|
||
# ownership on /app/data and /app/logs. Match your host user (run
|
||
# `id -u` / `id -g`) if you want files written by the container to
|
||
# show up as your user on the host. Defaults to 1000:1000.
|
||
- PUID=${PUID:-1000}
|
||
- PGID=${PGID:-1000}
|
||
# Port BamBuddy runs on (default: 8000)
|
||
# Usage: PORT=8080 docker compose up -d
|
||
- PORT=${PORT:-8000}
|
||
# Directory this compose file lives in, so Settings → Updates can print
|
||
# an update command you can paste from anywhere instead of one that only
|
||
# works if you are already in the right directory (#2664). Uncomment to
|
||
# have Compose fill it in from the shell you run `docker compose` in; the
|
||
# field is also editable in Settings if you would rather set it there or
|
||
# if you drive Compose with `-f` from elsewhere.
|
||
#- BAMBUDDY_COMPOSE_DIR=${PWD}
|
||
# Virtual printer: Set to the Docker host's IP when using bridge mode (ports:).
|
||
# Required for FTP passive mode to work behind NAT.
|
||
# Example: VIRTUAL_PRINTER_PASV_ADDRESS=192.168.1.100
|
||
#- VIRTUAL_PRINTER_PASV_ADDRESS=
|
||
# Virtual printer: the address slicers use to reach Bambuddy, written into
|
||
# the MQTT status the slicer reads its upload destination from. Only needed
|
||
# in bridge mode, where that address belongs to the host and the container
|
||
# cannot see it — without this the slicer is told the container IP (e.g.
|
||
# 172.17.0.2) and the upload has nowhere to go. Leave unset on host or
|
||
# macvlan networking, which remain the recommended modes.
|
||
# Example: VIRTUAL_PRINTER_ADVERTISE_ADDRESS=192.168.1.100
|
||
#- VIRTUAL_PRINTER_ADVERTISE_ADDRESS=
|
||
#
|
||
# External PostgreSQL (optional — uses SQLite by default)
|
||
# Example: DATABASE_URL=postgresql+asyncpg://bambuddy:password@db-host:5432/bambuddy
|
||
#- DATABASE_URL=
|
||
#
|
||
# Slicer API sidecar (optional — Settings → "Use Slicer API" toggles this on).
|
||
# Default points at the OrcaSlicer sidecar on the docker host; change if you
|
||
# run the sidecar on a different host/port. The matching docker-compose.yml
|
||
# for the sidecars lives in the orca-slicer-api fork
|
||
# (https://github.com/maziggy/orca-slicer-api).
|
||
#- SLICER_API_URL=http://localhost:3003
|
||
#
|
||
# MFA at-rest encryption key (#1219). Auto-generated to
|
||
# DATA_DIR/.mfa_encryption_key on first startup if unset. Override here
|
||
# to manage the key out-of-band (e.g. via a secret manager).
|
||
#- MFA_ENCRYPTION_KEY=
|
||
#
|
||
# External library folders (GHSA-r2qv follow-up). Empty default
|
||
# disables the "Add external folder" feature; set to one or more
|
||
# colon-separated absolute paths INSIDE THE CONTAINER to opt in.
|
||
# The paths must also be bind-mounted from the host — uncomment
|
||
# the matching volume snippet below.
|
||
# Example for a single NAS mount:
|
||
#- BAMBUDDY_EXTERNAL_ROOTS=/external/nas
|
||
# Example for two roots:
|
||
#- BAMBUDDY_EXTERNAL_ROOTS=/external/nas:/external/projects
|
||
#
|
||
# Enable System Trust Store for certificate validation (e.g. for local Home Assistant)
|
||
# You also need to mount your certificates to the container (see volumes section above).
|
||
# - USE_SYSTEM_TRUST_STORE=true
|
||
restart: unless-stopped
|
||
# Docker's default is 10s, after which it SIGKILLs. Bambuddy shuts down in
|
||
# well under that (uvicorn caps its wait on in-flight requests at 5s, then
|
||
# the app checkpoints the SQLite WAL, disconnects MQTT and stops the virtual
|
||
# printers), but a Pi with several virtual printers and a slow SD card can be
|
||
# nearer the limit than is comfortable. The headroom costs nothing — the
|
||
# container exits as soon as it is done, not when the timer expires.
|
||
stop_grace_period: 30s
|
||
|
||
# Optional: External PostgreSQL database
|
||
# Uncomment to run Postgres alongside Bambuddy (or use an external Postgres host)
|
||
#postgres:
|
||
# image: postgres:16-alpine
|
||
# container_name: bambuddy-db
|
||
# restart: unless-stopped
|
||
# environment:
|
||
# POSTGRES_USER: bambuddy
|
||
# POSTGRES_PASSWORD: changeme
|
||
# POSTGRES_DB: bambuddy
|
||
# volumes:
|
||
# - bambuddy_pgdata:/var/lib/postgresql/data
|
||
# ports:
|
||
# - "5432:5432"
|
||
|
||
volumes:
|
||
bambuddy_data:
|
||
bambuddy_logs:
|
||
#bambuddy_pgdata:
|