# Importarr Importarr is an Arr-style service for importing manually categorized SABnzbd downloads after SAB reports final completion. It owns one SAB category, defaults to `manual`, and refuses to import transient Direct Unpack paths or jobs still in SAB queue/post-processing. ## New-machine install Importarr is intended to feel like a small Arr service: deploy the container or systemd service, edit one env file, point SABnzbd category `manual` at the same completed-download path, then open the web UI. ### Docker Compose, recommended ```sh mkdir -p /opt/importarr/config cd /opt/importarr curl -fsSLO https://gitea.delphas.dk/daniels/importarr/raw/branch/main/deploy/docker-compose.example.yml curl -fsSLo importarr.env https://gitea.delphas.dk/daniels/importarr/raw/branch/main/deploy/importarr.env.example ${EDITOR:-vi} importarr.env docker compose -f docker-compose.example.yml --env-file importarr.env up -d ``` Then open `http://host:8765/` or put it behind your reverse proxy. For a local build instead of a published image, run: ```sh docker build -t importarr:local . ``` ### systemd / pip install ```sh git clone https://gitea.delphas.dk/daniels/importarr.git cd importarr sudo sh deploy/systemd-install.sh sudo ${EDITOR:-vi} /etc/importarr/importarr.env sudo systemctl start importarr.service ``` The installer creates the `importarr` system user when needed, installs a virtualenv at `/opt/importarr/venv`, and installs the package in editable mode from the checked-out repository. The repository is therefore the source of truth: pull or edit the repo, reinstall/restart from the repo, and the service runs that code. For local upgrades from a checked-out repo on dgsserver1, use the repo workflow instead of editing live scripts: ```sh cd /srv/opencode-workspace/importarr .venv/bin/python -m pytest git status --short --branch sudo -n /opt/importarr/venv/bin/pip install --upgrade --editable /srv/opencode-workspace/importarr sudo -n systemctl restart importarr.service make verify-live ``` For a machine that should stay current with the repository, use the installed repo-upgrade helper: ```sh sudo -n sh /opt/importarr/repo-upgrade.sh ``` The helper refuses to run when the checkout has uncommitted changes, then performs `git pull --ff-only`, refreshes the editable install, restarts `importarr.service`, and prints service status. Use it after changes have been committed and pushed to `main`. Release-worthy changes should be committed, tagged with SemVer (`v0.1.1`, `v0.2.0`, ...), pushed with tags, then reinstalled from the tagged checkout or artifact. Do not hand-edit `/usr/local/sbin/importarr-status.py` or `/usr/local/sbin/manual-media-import.py` except for a documented emergency hotfix that is immediately backported here. ### Required setup 1. In SABnzbd, create or confirm category `manual`. 2. Set its completed folder to the same path mounted as `IMPORTARR_DOWNLOAD_ROOT`. 3. Set `IMPORTARR_SAB_URL` and `IMPORTARR_SAB_API_KEY_FILE` or `IMPORTARR_SAB_API_KEY`. 4. Mount/configure `IMPORTARR_MOVIES_ROOT` and `IMPORTARR_TV_ROOT` read/write. 5. Set `IMPORTARR_AUTH_TOKEN` unless write endpoints are protected by a reverse proxy. 6. Check `GET /health`, then inspect `/api/preview` before running imports. ## Safety model - SAB-managed imports must be in `IMPORTARR_SAB_CATEGORY` and present in SAB history as `Completed` with final `storage`. - Active queue/post-processing states such as `Queued`, `Repairing`, `Extracting`, and `Moving` are never ready. - `_UNPACK_`, `__UNPACK__`, `_FAILED_`, and `_ADMIN_` paths are skipped. - Manual batches are explicit one-time folders under `IMPORTARR_DOWNLOAD_ROOT`. ## API - `GET /health` - `GET /api/status` - `GET /api/jobs` - `GET /api/preview` - `GET /api/history` - `GET /api/manual-batches` - `POST /api/manual-batches` with `{ "path": "relative/or/absolute/path" }` - `DELETE /api/manual-batches/{id}` - `POST /api/import/run-now` Set `IMPORTARR_AUTH_TOKEN_FILE` or `IMPORTARR_AUTH_TOKEN` to require `Authorization: Bearer ` for write endpoints. ## Development ```sh python3.12 -m venv .venv . .venv/bin/activate pip install -e '.[test]' pytest uvicorn importarr.main:app --reload ``` ## Migration notes for dgsserver1 Export the existing script settings into `IMPORTARR_*` env vars, add historical folders as explicit manual batches, run a dry-run/inspection through `/api/preview`, then switch the systemd service or Compose route after the ready set matches expectations. On dgsserver1, the packaged service is the only intended active entrypoint after cutover. Keep `manual-media-import.timer` disabled unless a repo-managed worker/timer replaces it later. ## Repository-as-install workflow Importarr should not drift into host-local scripts. Treat the checked-out repository as the install source: 1. Make changes in `/srv/opencode-workspace/importarr`. 2. Run tests: `make test`. 3. Commit and push the repo change. 4. Install/restart from the same repo: `make upgrade-local` for local changes, or `make repo-upgrade` to pull the latest pushed `main` and restart. 5. Verify the live service: `make verify-live`. Do not edit `/usr/local/sbin/importarr-status.py`, `/usr/local/sbin/manual-media-import.py`, or files copied out of the repo as the normal workflow. If an emergency live hotfix is unavoidable, backport it to this repository immediately and run the repo install workflow again.