164 lines
5.9 KiB
Markdown
164 lines
5.9 KiB
Markdown
# 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
|
|
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.
|
|
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 JELLYFIN_URL=https://jellyfin.example.com
|
|
export JELLYFIN_API_KEY=your-api-key
|
|
export SSH_HOST=media-server.example.com
|
|
export SSH_USERNAME=username
|
|
export SSH_KEY_HOST_DIR=$HOME/.ssh
|
|
export SSH_KEY_NAME=id_ed25519
|
|
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, key directory, and key name.
|
|
|
|
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.
|
|
|
|
## 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
|