mirror of
https://github.com/maziggy/bambuddy.git
synced 2026-09-30 03:01:21 +02:00
fix(install): use ProtectHome=read-only for /home-rooted installs (#1685)
bambuddy.service shipped with ProtectHome=true, which makes /home/* invisible to the service namespace. Installing into /home/bambuddy/ (instead of the default /opt/bambuddy/) made ExecStart=/home/bambuddy/venv/bin/uvicorn fail with status=203/EXEC because systemd couldn't resolve the binary path. ReadWritePaths=$INSTALL_PATH does not reliably re-expose /home/* subpaths for exec resolution. install/install.sh now detects /home/* INSTALL_PATH and emits ProtectHome=read-only; default /opt/bambuddy installs keep ProtectHome=true. The manual deploy template defaults to read-only with a comment on when to tighten it. read-only keeps /home immutable to the service - no security regression, since ReadWritePaths still gates writes to the install/data/log dirs only.
This commit is contained in:
@@ -10,6 +10,8 @@ All notable changes to Bambuddy will be documented in this file.
|
||||
- **Queue items + Print modal now show the build plate type, per-plate accurate (#1281, reported by @CMW-ISS)** — Reporter on a multi-printer farm with 40+-plate runs needed to walk to the printer with the right physical plate; the archive card had recently grown a bed-type badge, but the queue and the scheduling modal didn't. They were having to open the source 3MF in the slicer to look up which plate each queued / scheduled job needs. **Backend**: new `extract_bed_type_from_3mf(file_path, plate_id)` helper in `utils/threemf_tools.py`, alongside the existing `extract_filament_usage_from_3mf` shape — reads `Metadata/slice_info.config`, finds the `<plate>` with the matching `index`, returns its `curr_bed_type`. When `plate_id` is None it returns the first plate's value (matches the archive-level capture convention). `PrintQueueItemResponse` gains a `bed_type: str | None` field; `_enrich_response` populates it from `archive.bed_type` / `library_file.file_metadata["bed_type"]` as the file-level default, then overrides per-plate via the new helper when `item.plate_id` is set. This matters because `archive.bed_type` is captured at ingest as the FIRST plate's value only (see `services/archive.py:235`) — a 40-plate 3MF mixing PEI + Engineering returns "PEI" for every plate at the archive level, even though the user's plate 17 actually needs Engineering. The per-plate override re-reads the 3MF and returns the truth. **`/archives/{id}/plates`** (and the library-file equivalent) now include `bed_type` in each plate object so the PrintModal's plate selector can render the badge inline. **Frontend**: queue card meta row gains a bed badge after filament weight — uses the existing `getBedTypeInfo(bed_type)` helper from `utils/bedType.ts` (the same one the archive card uses, so all 11 canonical bed labels + icons are covered including the BambuStudio / OrcaSlicer spelling drift). PrintModal's per-plate `PlateSelector` shows the bed badge under each plate's filament line; the modal header carries a bed badge for the selected (or sole) plate, surfaced before the user hits Schedule. `PlateInfo` + `PlateMetadata` types both get an optional `bed_type` field. No new i18n keys needed — `getBedTypeInfo` returns the canonical English plate name as the human label, matching the archive card's existing convention. **Tests**: 8 new unit cases in `test_threemf_tools.py::TestExtractBedTypeFrom3mf` pin the helper (single-plate, multi-plate per-plate, no-plate-id defaults to first, unknown-plate-id → None, plate-without-bed-type → None (no fall-through to another plate's value), missing slice_info, invalid file, whitespace trim). Full backend suite green (3848/3848); frontend build clean; ESLint clean; vitest on touched pages 81/81; i18n parity 5092 leaves × 11 locales green.
|
||||
|
||||
### Fixed
|
||||
- **Native systemd install no longer fails when INSTALL_PATH is under /home (#1685, reported by @Geoff-S)** — `bambuddy.service` shipped with `ProtectHome=true`, which makes `/home/*` invisible to the service namespace. When the user installed into `/home/bambuddy/` (instead of the default `/opt/bambuddy/`), the `ExecStart=/home/bambuddy/venv/bin/uvicorn` path couldn't be resolved at exec time and the unit failed with `status=203/EXEC: Unable to locate executable`. The `ReadWritePaths=$INSTALL_PATH` directive doesn't reliably re-expose `/home/*` subpaths for executable resolution. **Fix:** `install/install.sh` now detects `INSTALL_PATH == /home/*` and emits `ProtectHome=read-only` for that case; the default `/opt/bambuddy/` install keeps the stricter `ProtectHome=true`. The manual `deploy/bambuddy.service` template defaults to `ProtectHome=read-only` with a comment explaining when to tighten it to `true`. `read-only` keeps `/home` immutable to the service (no security regression — the service can read its venv but not write anywhere outside the `ReadWritePaths` allowlist).
|
||||
|
||||
- **VP settings card now shows the target printer's serial in proxy mode** — On a proxy-mode VP, the runtime services (SSDP advertisement, MQTT bind identity, certificate subject) all use the target printer's actual serial via `target_printer_serial or self.serial` (`manager.py:235, 941, 957`), but the `/api/v1/virtual-printers` response — which feeds the VP settings card — always returned the self-generated suffix-based serial from `_get_serial_for_model(model_code, vp.serial_suffix)`. The card therefore displayed a serial that didn't match what the bridge actually advertises and what the slicer sees, breaking the visual "one identity per VP" mental model. **Fix:** `_vp_to_dict` (`api/routes/virtual_printers.py:77`) is now async and accepts `db`; when `vp.mode == VP_MODE_PROXY and vp.target_printer_id`, it issues a single `SELECT serial_number FROM printers WHERE id = vp.target_printer_id` and substitutes the result into the response `serial` field. Archive / queue / review modes keep the self-generated serial — those modes synthesise their own identity and never speak the target's. **Defensive fallback** when the target row is missing (printer deleted mid-config, manual SQL tweak, race between delete-printer and read-VP): the response falls back to the self-generated serial so the card still renders and the user can fix the target, rather than the API 500-ing. All 4 `_vp_to_dict` call sites (list, create, get, update) updated to `await` with `db`. **Tests:** 3 new in `TestVirtualPrinterSerialSurface` — proxy VP returns target serial across all three response paths (create / get / list), non-proxy VP with a target still uses the self-generated serial, orphaned proxy VP falls back to self-generated. Full VP API suite stays green (34/34); VP unit suite stays green (126/126); ruff clean.
|
||||
|
||||
### Added
|
||||
|
||||
@@ -54,7 +54,10 @@ SyslogIdentifier=bambuddy
|
||||
NoNewPrivileges=true
|
||||
PrivateTmp=true
|
||||
ProtectSystem=strict
|
||||
ProtectHome=true
|
||||
# ProtectHome=true hides /home/* and breaks ExecStart when INSTALL_PATH is
|
||||
# under /home (issue #1685). Default is the safer read-only; flip to true if
|
||||
# your INSTALL_PATH is outside /home (e.g. /opt/bambuddy).
|
||||
ProtectHome=read-only
|
||||
ReadWritePaths=DATA_DIR LOG_DIR INSTALL_PATH
|
||||
|
||||
[Install]
|
||||
|
||||
+10
-1
@@ -519,6 +519,15 @@ create_systemd_service() {
|
||||
|
||||
log_info "Creating systemd service..."
|
||||
|
||||
# ProtectHome=true hides /home/* from the service, which breaks ExecStart
|
||||
# when INSTALL_PATH lives under /home (issue #1685). Loosen to read-only in
|
||||
# that case so the venv binary is still resolvable; ReadWritePaths below
|
||||
# re-grants writes for the install/data/log dirs.
|
||||
local protect_home="true"
|
||||
if [[ "$INSTALL_PATH" == /home/* ]]; then
|
||||
protect_home="read-only"
|
||||
fi
|
||||
|
||||
cat > /tmp/bambuddy.service << EOF
|
||||
[Unit]
|
||||
Description=BamBuddy - Bambu Lab Print Management
|
||||
@@ -552,7 +561,7 @@ AmbientCapabilities=CAP_NET_BIND_SERVICE
|
||||
NoNewPrivileges=true
|
||||
PrivateTmp=true
|
||||
ProtectSystem=strict
|
||||
ProtectHome=true
|
||||
ProtectHome=$protect_home
|
||||
ReadWritePaths=$DATA_DIR $LOG_DIR $INSTALL_PATH
|
||||
|
||||
[Install]
|
||||
|
||||
Reference in New Issue
Block a user