# Backend - Media Library Viewer API FastAPI backend serving the REST API for Jellyfin media browsing, SSH file inspection, server monitoring, and JWT-protected access. ## 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 │ │ ├── files.py │ │ └── jobs.py │ ├── clients/ │ │ ├── jellyfin.py │ │ ├── jellyseerr.py │ │ ├── resources.py │ │ └── ssh.py │ ├── domain/ │ │ └── media.py │ └── services/ │ └── media_index.py └── tests/ ``` ## Setup ```bash cd backend python -m venv .venv source .venv/bin/activate pip install -e '.[dev]' ``` ## Configuration Create a `.env` file in the project root (or set environment variables): ```bash JELLYFIN_URL=https://jellyfin.example.com JELLYFIN_API_KEY=your-api-key JELLYFIN_USER_ID= # Optional Jellyseerr enrichment for the Users tab JELLYSEERR_URL=https://requests.example.com JELLYSEERR_API_KEY=your-jellyseerr-api-key # Optional backend logging level LOG_LEVEL=INFO # 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 SSH_HOST=media-server.example.com SSH_USERNAME=username SSH_PORT=22 # Host-side directory mounted into the backend container at /root/.ssh. SSH_KEY_HOST_DIR=/absolute/path/to/your/ssh-dir # Container-side path assembled by the app: SSH_KEY_DIRECTORY=/root/.ssh SSH_KEY_NAME=id_ed25519 SSH_PASSWORD= REMOTE_MEDIA_ROOT=/srv/media REMOTE_PATH_PREFIX= ``` ## 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. ## 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/status` — Collector status - `GET /api/monitoring/metrics` — Resource samples (last hour) - `GET /api/monitoring/disk` — Disk space - `POST /api/monitoring/start|stop|restart` — Collector controls - `GET /api/monitoring/diagnostics` — Collector debug info - `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