No description
  • Go 96.2%
  • Nix 3.8%
Find a file
Repository files (latest commit first)
Filename Latest commit message Latest commit date
2026-07-15 21:33:13 -04:00
cmd/qbit-bridge app: composition root in internal/app.Run; main.go delegates 2026-04-19 12:13:20 -04:00
docs module: add services.qbit-bridge.logLevel option 2026-04-19 20:30:23 -04:00
internal session: handle qBittorrent 5.x QBT_SID_<port> cookie name 2026-07-15 21:33:13 -04:00
nix module: add services.qbit-bridge.logLevel option 2026-04-19 20:30:23 -04:00
.envrc nix: consolidate module under nix/ (module/ → nix/module.nix) 2026-04-19 14:08:47 -04:00
.gitignore gitignore: add /.worktrees for isolated dev workspaces 2026-04-19 11:31:38 -04:00
flake.lock remove claude flake input 2026-07-01 20:09:03 -04:00
flake.nix remove claude flake input 2026-07-01 20:09:03 -04:00
go.mod integration: scaffold tagged end-to-end test + test SSH key 2026-04-19 12:18:00 -04:00
go.sum integration: scaffold tagged end-to-end test + test SSH key 2026-04-19 12:18:00 -04:00
HANDOVER.md format: run treefmt (prettier on docs, gofmt on nix-adjacent files); commit flake.lock 2026-04-19 12:25:27 -04:00
README.md docs: configuration + deployment guide 2026-04-19 14:31:09 -04:00
renovate.json nix: consolidate module under nix/ (module/ → nix/module.nix) 2026-04-19 14:08:47 -04:00

qbit-bridge

A qBittorrent Web API shim that sits between *arr apps (Sonarr, Radarr, …) and a qBittorrent running on a remote seedbox. It proxies the API calls *arr makes, pulls completed torrents to the local host over SFTP (replacing sshfs / syncthing / rclone-mount), and rewrites /torrents/info so *arr sees one honest progress bar covering both the seedbox download and the seedbox→local transfer. No more "100% on seedbox, missing locally" gap.

Single-operator, single-seedbox tool. No web UI, no multi-user support.

Quick start

Add this flake as an input in your NixOS config:

# flake.nix of your system config
{
  inputs.qbit-bridge.url = "git+https://git.matt.you/matt/qbit-bridge";
  inputs.qbit-bridge.inputs.nixpkgs.follows = "nixpkgs";
  # ...
}

Enable the service on the host that will run the shim:

# host module
{
  imports = [ inputs.qbit-bridge.nixosModules.default ];

  services.qbit-bridge = {
    enable = true;

    upstreamUrl = "https://seedbox.example.com/qbittorrent";

    seedbox = {
      host = "seedbox.example.com";
      user = "matt";
      identityFile = "/run/secrets/qbit-bridge-ssh-key"; # sops-nix / whatever
    };

    outputDir = "/mnt/media/downloads";
  };
}

Point *arr at http://127.0.0.1:46881 instead of the seedbox directly. Enter any username/password — the shim accepts anything and forwards to upstream using upstreamUrl. See docs/configuration.md for the full option reference, *arr-side setup, and troubleshooting.

Outputs

  • packages.${system}.default — the shim binary.
  • nixosModules.default — the NixOS module. Auto-wires the package; just set services.qbit-bridge.enable = true.
  • checks.${system}.tests — runs the Go unit suite under nix flake check.

Local dev

nix develop
go test -race ./...

Integration test (requires Docker or Podman):

# with podman:
export DOCKER_HOST=unix:///run/user/$(id -u)/podman/podman.sock
export TESTCONTAINERS_RYUK_DISABLED=true
go test -tags=integration -race ./internal/integration/...

Design