mirror of
https://github.com/maziggy/bambuddy.git
synced 2026-10-18 11:56:01 +02:00
fix(spoolbuddy): sync SSH key over heartbeat to survive Bambuddy keypair rotation
Bambuddy's SSH keypair under <DATA_DIR>/spoolbuddy/ssh/ regenerates whenever
the data dir is recreated (volume remount, container recreate, fresh deploy).
The daemon previously only fetched the pubkey at registration, so any
rotation after a successful boot left ~/.ssh/authorized_keys pointing at
a stale public half — every Update click then failed with "Connection
closed by authenticating user spoolbuddy [preauth]" until the daemon was
restarted by hand. Each prior registration also appended a fresh entry
without pruning, accumulating stale Bambuddy-tagged keys indefinitely.
- HeartbeatResponse now carries ssh_public_key; the heartbeat route reads
it via the same try/except shape as the register route so a missing or
unreadable backend key doesn't break telemetry.
- _deploy_ssh_key() strips lines tagged bambuddy-spoolbuddy and writes
the current key once. No-op when already in sync (no mtime churn on
every heartbeat). User-managed entries are preserved.
- Daemon heartbeat handler calls _deploy_ssh_key when the response
carries a key, so rotations propagate within one heartbeat instead
of requiring a service restart.
Tests: 5 unit (creates-when-missing, replace-stale-pileup, preserve-user-keys,
idempotent, swallows-write-errors) + 2 backend integration (heartbeat carries
the key; backend key-read failure leaves ssh_public_key None but the
heartbeat still 200s).
This commit is contained in:
@@ -279,6 +279,17 @@ async def device_heartbeat(
|
||||
if was_offline:
|
||||
logger.info("SpoolBuddy device back online: %s", device.device_id)
|
||||
|
||||
# Include current SSH public key so the daemon can re-deploy it whenever
|
||||
# Bambuddy's keypair rotates (data dir wiped, container recreated, etc.) —
|
||||
# otherwise SSH updates fail until the daemon restarts.
|
||||
ssh_public_key: str | None = None
|
||||
try:
|
||||
from backend.app.services.spoolbuddy_ssh import get_public_key
|
||||
|
||||
ssh_public_key = await get_public_key()
|
||||
except Exception:
|
||||
pass
|
||||
|
||||
return HeartbeatResponse(
|
||||
pending_command=pending,
|
||||
pending_write_payload=pending_write,
|
||||
@@ -287,6 +298,7 @@ async def device_heartbeat(
|
||||
calibration_factor=device.calibration_factor,
|
||||
display_brightness=device.display_brightness,
|
||||
display_blank_timeout=device.display_blank_timeout,
|
||||
ssh_public_key=ssh_public_key,
|
||||
)
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user