diff --git a/backend/README.md b/backend/README.md index 3f9f8bf..ed7c63a 100644 --- a/backend/README.md +++ b/backend/README.md @@ -126,8 +126,9 @@ docker compose up --build 2. After the API is running, open the app, go to **Settings**, and add machine entries: - **Local**: monitors the API host itself without SSH. - **SSH**: monitors another machine using a host, username, and a private key pasted directly into the machine settings, with an optional passphrase. - - The machine editor groups Connection, Monitoring / Files, Jellyfin, and Jellyseerr settings under separate headings so each service area is easier to scan. - - Saving an SSH machine now validates the banner/auth flow and records the first trusted host key into the backend-managed `known_hosts` file, surfacing any errors if the host cannot be reached or authenticated. + - The machine editor groups Connection, Monitoring / Files, Jellyfin, Jellyseerr, and Notes under separate headings so each service area is easier to scan. + - Saving a monitoring machine now validates the banner/auth flow, records the first trusted host key into the backend-managed `known_hosts` file, and starts the collector so charts populate without a separate manual step. + - If the host cannot be reached or authenticated, the save flow surfaces the SSH error directly in the dialog. - Use **Validate SSH + trust host** in the machine editor before saving if you want to test the banner/auth flow explicitly. - The first successful SSH connection uses trust-on-first-use: the backend records that machine's host key into its managed `known_hosts` file automatically, then continues verifying it strictly on later connects. diff --git a/backend/src/media_library_viewer_api/routers/settings.py b/backend/src/media_library_viewer_api/routers/settings.py index bfac4d6..d6c25cf 100644 --- a/backend/src/media_library_viewer_api/routers/settings.py +++ b/backend/src/media_library_viewer_api/routers/settings.py @@ -12,6 +12,7 @@ from pydantic import BaseModel, Field from media_library_viewer_api.clients.ssh import RemoteSSHClient from media_library_viewer_api.config import get_settings from media_library_viewer_api.dependencies import get_monitoring_poller, get_settings_store +from media_library_viewer_api.services.monitoring_actions import start_collector from media_library_viewer_api.services.db_maintenance import remove_sqlite_database from media_library_viewer_api.services.known_hosts import has_known_host from media_library_viewer_api.services.media_index import MediaIndex @@ -124,6 +125,12 @@ def _validate_saved_machine_ssh(machine: MonitoringMachineInput, store: Settings client.close() +def _start_machine_collector(machine: MonitoringMachineInput, store: SettingsStore) -> None: + if "monitoring" not in {str(service).strip().lower() for service in machine.services}: + return + start_collector(machine.model_dump(exclude_none=True), store) + + @router.post("/machines/test-ssh") def test_machine_ssh( machine: MonitoringMachineInput, @@ -183,7 +190,9 @@ def post_machine( saved = store.upsert_machine(machine.model_dump(exclude_none=True), machine.id) poller = get_monitoring_poller() try: - _validate_saved_machine_ssh(MonitoringMachineInput.model_validate(saved), store) + saved_machine = MonitoringMachineInput.model_validate(saved) + _validate_saved_machine_ssh(saved_machine, store) + _start_machine_collector(saved_machine, store) finally: poller.start() poller.kick() @@ -201,7 +210,9 @@ def put_machine( saved = store.upsert_machine(machine.model_dump(exclude_none=True), machine_id) poller = get_monitoring_poller() try: - _validate_saved_machine_ssh(MonitoringMachineInput.model_validate(saved), store) + saved_machine = MonitoringMachineInput.model_validate(saved) + _validate_saved_machine_ssh(saved_machine, store) + _start_machine_collector(saved_machine, store) finally: poller.start() poller.kick() diff --git a/docs/REQUIREMENTS.md b/docs/REQUIREMENTS.md index c70b284..bf521d6 100644 --- a/docs/REQUIREMENTS.md +++ b/docs/REQUIREMENTS.md @@ -277,5 +277,5 @@ Phase 1: Jellyfin media index, SSH-based remote filesystem inspection, server mo - 2026-05-07: The shell should display both frontend and backend version labels so deployed builds are easy to identify without opening a separate diagnostics screen. - 2026-05-07: SSH host verification should use trust-on-first-use for new machines by recording the first observed host key into the backend-managed known_hosts file, while still rejecting later key mismatches. - 2026-05-07: The SSH machine editor should expose a validation button that tests banner/auth flow and records the host key before save so users get clear feedback when a host is unreachable. -- 2026-05-07: Saving an SSH machine should also validate the banner/auth flow and update the backend-managed known_hosts entry for the current host, surfacing any save-time SSH errors to the user. +- 2026-05-07: Saving a monitoring-capable machine should validate the banner/auth flow, update the backend-managed known_hosts entry for the current host, and start the remote resource collector so charts populate without a separate manual step. - 2026-05-07: Machine settings should visually separate Connection, Monitoring / Files, Jellyfin, Jellyseerr, and Notes into clearly labeled sections. diff --git a/frontend/src/pages/Settings.tsx b/frontend/src/pages/Settings.tsx index ce0c8f0..aaf71c3 100644 --- a/frontend/src/pages/Settings.tsx +++ b/frontend/src/pages/Settings.tsx @@ -336,7 +336,8 @@ function MachineEditor({ Monitoring / Files - Media root and path mapping used by monitoring and browsing. + Media root and path mapping used by monitoring and browsing. Saving a + monitoring machine also starts its collector automatically.