8.3 KiB
Magent
Magent is a friendly, AI-assisted request tracker for Seerr + Arr services. It shows a clear timeline of where a request is stuck, explains what is happening in plain English, and offers safe actions to help fix issues.
How it works
- Requests are pulled from Seerr and stored locally.
- Magent joins that request to Sonarr/Radarr, Prowlarr, qBittorrent, and Jellyfin using TMDB/TVDB IDs and download hashes.
- A state engine normalizes noisy service statuses into a simple, user-friendly state.
- The UI renders a timeline and a central status box for each request.
- Optional AI triage summarizes the likely cause and safest next steps.
Core features
- Request search by title/year or request ID.
- Recent requests list with posters and status.
- Timeline view across Seerr, Arr, Prowlarr, qBittorrent, Jellyfin.
- Central status box with clear reason + next steps.
- Safe action buttons (search, resume, re-add, etc.).
- Admin settings for service URLs, API keys, profiles, and root folders.
- Health status for each service in the pipeline.
- Cache and sync controls (full sync, delta sync, scheduled syncs).
- Local database for speed and audit history.
- Users and access control (admin vs user, block access).
- Local account password changes via "My profile".
- Personal viewing stats from Jellystat: minutes, movies, episodes, streaks, and recent plays alongside requests. See Jellystat setup.
- Admin review and confirmation of account IDs across Jellyfin, Seerr, Jellystat and Magent. See user identities.
- Docker-first deployment for easy hosting.
Quick start (Docker - primary)
Docker is the recommended way to run Magent. It includes the backend and frontend with sane defaults.
docker compose up --build
Then open:
- Frontend: http://localhost:3000
- Backend: http://localhost:8000
Docker setup steps
- Create
.envwith your service URLs and API keys. - Run
docker compose up --build. - Log in at http://localhost:3000.
- Visit Settings to confirm service health.
Docker environment variables (sample)
JELLYSEERR_URL="http://localhost:5055"
JELLYSEERR_API_KEY="..."
SONARR_URL="http://localhost:8989"
SONARR_API_KEY="..."
SONARR_QUALITY_PROFILE_ID="1"
SONARR_ROOT_FOLDER="/tv"
RADARR_URL="http://localhost:7878"
RADARR_API_KEY="..."
RADARR_QUALITY_PROFILE_ID="1"
RADARR_ROOT_FOLDER="/movies"
PROWLARR_URL="http://localhost:9696"
PROWLARR_API_KEY="..."
QBIT_URL="http://localhost:8080"
QBIT_USERNAME="..."
QBIT_PASSWORD="..."
SQLITE_PATH="data/magent.db"
JWT_SECRET="replace-with-at-least-32-random-characters"
SETTINGS_ENCRYPTION_KEY="replace-with-a-fernet-key"
JWT_EXP_MINUTES="120"
ADMIN_USERNAME="set-a-real-admin-username"
ADMIN_PASSWORD="set-a-long-unique-admin-password"
Screenshots
Add screenshots here once available:
docs/screenshots/home.pngdocs/screenshots/request-timeline.pngdocs/screenshots/settings.pngdocs/screenshots/profile.png
Local development (secondary)
Use this only when you need to modify code locally.
Backend (FastAPI)
cd backend
python -m venv .venv
.\.venv\Scripts\Activate.ps1
pip install -r requirements.txt
uvicorn app.main:app --reload --port 8000
Environment variables (sample):
$env:JELLYSEERR_URL="http://localhost:5055"
$env:JELLYSEERR_API_KEY="..."
$env:SONARR_URL="http://localhost:8989"
$env:SONARR_API_KEY="..."
$env:SONARR_QUALITY_PROFILE_ID="1"
$env:SONARR_ROOT_FOLDER="/tv"
$env:RADARR_URL="http://localhost:7878"
$env:RADARR_API_KEY="..."
$env:RADARR_QUALITY_PROFILE_ID="1"
$env:RADARR_ROOT_FOLDER="/movies"
$env:PROWLARR_URL="http://localhost:9696"
$env:PROWLARR_API_KEY="..."
$env:QBIT_URL="http://localhost:8080"
$env:QBIT_USERNAME="..."
$env:QBIT_PASSWORD="..."
$env:SQLITE_PATH="data/magent.db"
$env:JWT_SECRET="replace-with-at-least-32-random-characters"
$env:SETTINGS_ENCRYPTION_KEY="replace-with-a-fernet-key"
$env:JWT_EXP_MINUTES="120"
$env:ADMIN_USERNAME="set-a-real-admin-username"
$env:ADMIN_PASSWORD="set-a-long-unique-admin-password"
Frontend (Next.js)
cd frontend
npm install
npm run dev
Admin panel: http://localhost:3000/admin
Login uses the admin credentials above (or any other local user you create in SQLite).
Local quality checks
bash scripts/ci_backend_quality_gate.sh
cd frontend
npm ci
npm run lint
npm run format:check
npm run typecheck
npm test
npm run build
Public Hosting Notes
The frontend proxies /api/* to the backend container. Set:
NEXT_PUBLIC_API_BASE=/api(browser uses same-origin)BACKEND_INTERNAL_URL=http://backend:8000(container-to-container)
If you prefer the browser to call the backend directly, set NEXT_PUBLIC_API_BASE to your public backend URL and ensure CORS is configured.
Gitea CI/CD
This repo now includes a Gitea Actions workflow at .gitea/workflows/ci-cd.yml.
- Push to
beta: runs the complete quality gate and deploys the isolated beta environment toAMS-DEV01. - Push to
mainorprod: runs the same verification without automatically changing production. - Production releases are tagged from
mainand deployed toGRZ-DKR01using the checklist inPRODUCTION.md.
The beta deploy step ships tracked repository files over SSH, preserves beta's own .env and data/, rebuilds with docker compose up -d --build, and smoke-tests:
http://127.0.0.1:8000/healthhttp://127.0.0.1:3000/login
Configure these Gitea Actions secrets before enabling the deploy job:
The existing PROD_* names are retained for compatibility, but this workflow uses them only for the isolated beta host deployment.
PROD_SSH_PRIVATE_KEY: private key for the deployment account.PROD_SSH_HOST: target host, for exampleAMS-DEV01.PROD_SSH_USER: target user, for examplezak.PROD_SSH_KNOWN_HOSTS: required pinnedknown_hostsentry. Deployments reject unknown or changed hosts.
Beta always deploys to the isolated /home/<deployment-user>/magent-beta directory; the production path secret is intentionally ignored.
Security and data handling
Generate independent signing and settings-encryption secrets before first startup:
python -c "import secrets; print(secrets.token_urlsafe(48))"
python -c "from cryptography.fernet import Fernet; print(Fernet.generate_key().decode())"
JWT_SECRETmust contain at least 32 characters. Access sessions expire after 120 minutes by default and are revoked after logout, password, role, or blocked-state changes.SETTINGS_ENCRYPTION_KEYprotects service API keys, SMTP credentials, webhooks, and private keys stored in SQLite. Keep it in.env, outside the database and its backups. If omitted, Magent derives a migration-compatible key fromJWT_SECRET; a dedicated key is recommended.- Invite secrets are stored as one-way hashes. Existing invite links continue to work after migration, but the admin UI cannot reveal an old link. Copy a link when it is created, or generate a replacement link later; replacement immediately invalidates the prior link.
- Magent encrypts sensitive settings, not the entire SQLite database. Request metadata, account records, logs, the
data/volume, and backups should live on encrypted host storage with access restricted to the deployment account. REQUESTS_CLEANUP_DAYScontrols routine request-history retention (90 days by default). Account deletion removes authentication and subscription records and anonymizes retained request and portal history.- Production and beta cookies require HTTPS and use
SameSite=Strict. Keep the backend port bound to loopback and publish the frontend only through the intended reverse proxy.
History endpoints
GET /requests/{id}/history?limit=10recent snapshotsGET /requests/{id}/actions?limit=10recent action logs
Troubleshooting
Login fails
- Make sure
ADMIN_USERNAMEandADMIN_PASSWORDare set in.env. - Confirm the backend is reachable:
http://localhost:8000/health(or see container logs).
Services show as down
- Check the URLs and API keys in Settings.
- Verify containers can reach each service (network/DNS).
No recent requests
- Confirm Seerr credentials in Settings.
- Run a full sync from Settings -> Requests.
Docker images not updating
- Run
docker compose up --buildagain. - If needed, run
docker compose downfirst, then rebuild.