Files
importarr/README.md
T

6.2 KiB

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.

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:

docker build -t importarr:local .

systemd / pip install

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 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 the package built from that code.

For local upgrades from a checked-out repo on dgsserver1, use the repo workflow instead of editing live scripts:

cd /srv/opencode-workspace/importarr
.venv/bin/python -m pytest
git status --short --branch
sudo -n /opt/importarr/venv/bin/pip install --upgrade /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:

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, reinstalls the package from the repo, 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 <token> for write endpoints.

Development

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.

Local install lessons learned

  • The live systemd service runs as the unprivileged importarr user.
  • Do not install the system service with pip install --editable /srv/opencode-workspace/importarr; that can fail at startup if the service user cannot read the workspace checkout.
  • The supported local service install is a normal package install from the repo into /opt/importarr/venv:
sudo -n /opt/importarr/venv/bin/pip install --upgrade /srv/opencode-workspace/importarr
sudo -n systemctl restart importarr.service
  • deploy/systemd-install.sh, make upgrade-local, and /opt/importarr/repo-upgrade.sh already use this supported model.
  • After every implementation task that should affect the live local service, run:
make upgrade-local
make verify-live
  • If make verify-live fails, check:
sudo -n systemctl --no-pager --full status importarr.service
sudo -n journalctl -u importarr.service -n 120 --no-pager