# Manage Backend API FastAPI backend serving the REST API for Jellyfin media browsing, SSH file inspection, server monitoring, and JWT-protected access for Manage. ## Project structure ``` backend/ ├── pyproject.toml ├── README.md ├── src/ │ └── media_library_viewer_api/ │ ├── __init__.py │ ├── main.py # FastAPI app entrypoint │ ├── config.py # pydantic-settings config │ ├── dependencies.py # Dependency injection │ ├── path_utils.py # Jellyfin→SSH path resolution │ ├── jobs.py # Job templates │ ├── utils.py # Formatting helpers │ ├── routers/ │ │ ├── dashboard.py │ │ ├── monitoring.py │ │ ├── media.py │ │ ├── users.py │ │ ├── settings.py │ │ ├── files.py │ │ └── jobs.py │ ├── clients/ │ │ ├── jellyfin.py │ │ ├── jellyseerr.py │ │ ├── local.py │ │ ├── resources.py │ │ └── ssh.py │ ├── domain/ │ │ └── media.py │ └── services/ │ ├── media_index.py │ └── settings_store.py └── tests/ ``` ## Setup ```bash cd backend python -m venv .venv source .venv/bin/activate pip install -e '.[dev]' ``` ## Configuration Set environment variables directly in your shell or a wrapper script before running the app or Compose. The Docker Compose files use interpolation and do not require an `env_file` entry. For local `.env` development, you can still create one if you prefer, but it is optional. ```bash # Optional backend logging level LOG_LEVEL=INFO # Optional SMTP settings for the Users -> message popup SMTP_HOST=smtp.example.com SMTP_PORT=587 SMTP_USERNAME=your-smtp-username SMTP_PASSWORD=your-smtp-password SMTP_FROM_ADDRESS=no-reply@example.com SMTP_FROM_NAME=Manage SMTP_USE_TLS=true SMTP_USE_SSL=false SMTP_TIMEOUT=30 # Jellyfin, Jellyseerr, and SSH targets are now configured per machine in the app's Settings tab. # The backend seeds a local machine automatically, so no global Jellyfin or SSH env vars are required. # Versioning # The backend tries to auto-detect its version from installed package metadata. # If needed, you can override the displayed version/build markers with APP_VERSION and APP_BUILD_INFO. APP_VERSION=0.1.0 APP_BUILD_INFO=dev # Authentik / OIDC AUTH_ENABLED=true OIDC_ISSUER_URL=https://authentik.example/application/o/media-library-viewer/ OIDC_AUDIENCE=media-library-viewer OIDC_JWKS_URL= OIDC_CLOCK_SKEW_SECONDS=30 ``` ## Running ```bash cd backend uvicorn media_library_viewer_api.main:app --reload --port 8000 ``` Or with PYTHONPATH if not installed: ```bash PYTHONPATH=src uvicorn media_library_viewer_api.main:app --reload --port 8000 ``` API docs available at: http://localhost:8000/docs ## Docker The repository root includes a production `docker-compose.yml` and a development `docker-compose.dev.yml`. The backend media index is stored in the `backend_cache` Docker volume so it survives container restarts and image rebuilds. The production compose file expects required environment variables to be supplied via interpolation (shell exports or inline `VAR=value docker compose ...`). ### Configuration workflow examples 1. Export your runtime variables before launching Compose: ```bash export BACKEND_APP_HOST=manage.example.com export FRONTEND_APP_HOST=manage.example.com export CERT_RESOLVER=letsencrypt export VITE_OIDC_ISSUER=https://authentik.example/application/o/manage/ export VITE_OIDC_CLIENT_ID=manage export VITE_OIDC_REDIRECT_URI=https://manage.example.com/ export VITE_OIDC_POST_LOGOUT_REDIRECT_URI=https://manage.example.com/ 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, 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. 3. Open **Monitoring** to see one section per configured machine. Each section uses its own collector state, disk path, metrics queries, and recent action history, which are populated automatically by the backend poller. For local development, `docker compose -f docker-compose.dev.yml up --build` does not require an SSH key unless you configure remote SSH machines in the Settings tab. ## API Endpoints - `GET /api/dashboard/counts` — Movie/series/episode totals - `GET /api/dashboard/libraries` — Per-library breakdown - `GET /api/dashboard/now-playing` — Active playback sessions - `GET /api/monitoring/machines` — Persistent monitoring machine definitions - `GET /api/monitoring/status?machine_id=` — Collector status for a machine - `GET /api/monitoring/metrics?machine_id=` — Resource samples (last hour) - `GET /api/monitoring/disk?machine_id=` — Disk space - `POST /api/monitoring/start|stop|restart?machine_id=` — Collector controls - `GET /api/monitoring/diagnostics?machine_id=` — Collector debug info - `GET /api/monitoring/poller` — Backend poller status and configuration - `GET /api/monitoring/machines/{machine_id}/actions` — Recent machine action history - `GET /api/dashboard/monitoring` — Dashboard-wide per-machine monitoring summary table with 10-minute averages and min/max subtext - `GET /api/settings/machines` — Manage machine definitions - `GET /api/media/status` — Index status - `POST /api/media/build` — Rebuild index - `GET /api/media/query` — Query with filters/sort/pagination - `GET /api/files/list?path=` — Directory listing - `GET /api/files/ffprobe?path=` — ffprobe JSON - `GET /api/files/stat?path=` — stat output - `GET /api/files/resolve-path?path=` — Path resolution - `GET /api/jobs/templates` — Available jobs - `POST /api/jobs/run` — Execute a job - `GET /api/users` — Jellyfin users with optional Jellyseerr enrichment - `GET /api/version` — Backend version/build metadata for the UI