bambuddy/slicer-api/docker-compose.yml
maziggy a849759469 Explain an oversized model instead of reporting a slicer crash (#2802)
The sidecar caps model uploads and reports a rejection as a bare
HTTP 500 "File too large" -- multer's MulterError is not the sidecar's
AppError, so its handler falls through to the default status. A 500
reads as a crash inside the slicer, and the one message Bambuddy had
about request size was written for the 413 a reverse proxy sends, so
it never appeared. The reporter tried MAX_FILE_SIZE, BODY_PARSER_LIMIT
and EXPRESS_PAYLOAD_LIMIT, stopped nginx, and moved from Windows to
Docker -- none of which the sidecar reads.

Match the rejection by what it says rather than by its status, so an
installation still on an older sidecar image gets the same explanation.
The 500 match is strict -- the body must be only multer's message --
because a genuine CLI failure is also a 500 and has to keep reaching
the embedded-settings fallback. Old images are told to update, since
they have no setting to change; current ones are told which one to set.

Raising SlicerInputError rather than SlicerApiServerError is also what
skips the fallback retry, which had been re-uploading the identical
oversized file after a second 25-second 3MF conversion.

Log the model size on every slice. Nothing recorded it, so a support
package from a slice that died on an upload cap looked exactly like one
that died on a bad profile, and this had to be sized by hand.

Fall back to the exception class name when a transport error stringifies
empty -- three lines of the reporter's log read "Slicer sidecar
unreachable: " and stopped there.

Needs a sidecar image update to take full effect; MAX_MODEL_UPLOAD_MB is
documented in slicer-api/.env.example.
2026-08-10 12:18:29 +02:00

69 lines
2.3 KiB
YAML

# Optional slicer-API sidecar stack for Bambuddy.
#
# Both services are HTTP wrappers around a slicer CLI: the same Node code
# (`maziggy/orca-slicer-api`, `bambuddy/profile-resolver` branch) bundled
# with a different binary in each image. Bambuddy talks to them via the
# URLs configured in Settings -> Slicer.
#
# bambu-studio-api → host port 3001 (BambuStudio CLI)
# orca-slicer-api → host port 3003 (OrcaSlicer CLI)
#
# Bambuddy's virtual-printer feature reserves host ports 3000 and 3002,
# which is why the OrcaSlicer sidecar sits on 3003. Override either port
# in `.env` (see `.env.example`) if you don't run Bambuddy on this host.
#
# Usage:
# cd slicer-api/
# docker compose up -d # starts OrcaSlicer only
# docker compose --profile bambu up -d # starts both
#
# First start pulls pre-built images from GHCR (~110 MB OrcaSlicer,
# ~220 MB BambuStudio). No local build, no git in the BuildKit worker,
# works on QNAP / Synology / Container Station out of the box.
#
# Both images are linux/amd64 only. OrcaSlicer's ARM64 path is on hold
# pending an upstream extraction fix; BambuStudio doesn't publish ARM64
# at all.
services:
orca-slicer-api:
image: ghcr.io/maziggy/orca-slicer-api:${SIDECAR_TAG:-latest}
container_name: orca-slicer-api
restart: unless-stopped
ports:
- "${ORCA_API_PORT:-3003}:3000"
volumes:
- ./data/orca:/app/data
environment:
NODE_ENV: production
PORT: "3000"
# Largest model accepted for a slice, in MB. See .env.example.
MAX_MODEL_UPLOAD_MB: "${MAX_MODEL_UPLOAD_MB:-512}"
healthcheck:
test: ["CMD", "curl", "-f", "http://localhost:3000/health"]
interval: 30s
timeout: 5s
start_period: 10s
retries: 3
bambu-studio-api:
image: ghcr.io/maziggy/bambu-studio-api:${SIDECAR_TAG:-latest}
container_name: bambu-studio-api
restart: unless-stopped
ports:
- "${BAMBU_API_PORT:-3001}:3000"
volumes:
- ./data/bambu:/app/data
environment:
NODE_ENV: production
PORT: "3000"
# Largest model accepted for a slice, in MB. See .env.example.
MAX_MODEL_UPLOAD_MB: "${MAX_MODEL_UPLOAD_MB:-512}"
healthcheck:
test: ["CMD", "curl", "-f", "http://localhost:3000/health"]
interval: 30s
timeout: 5s
start_period: 10s
retries: 3
profiles:
- bambu