Hoardarr is a self-hosted movie automation workflow built on Swamp. It discovers digital releases, selects torrents with deterministic rules, downloads through NordVPN, and transfers verified media to a Mac running iCloud Drive.
This guide takes you from a clone to a safe dry run. Live downloads, network changes, file transfers, cleanup, and scheduling are separate opt-in steps.
Warning
Use Hoardarr only for content you are authorized to download. A live run disables Tailscale while Torlink is active. Keep local or LAN access to the Linux host before commissioning the network transition.
Hoardarr is currently a reference deployment, not a portable installer. The checked-in configuration assumes:
- A Linux host with user-scoped systemd services.
- Swamp installed at
/home/saiguy/.local/bin/swamp. - Node.js 26.7.0 installed through mise.
- NordVPN and Tailscale installed on the Linux host.
- A Mac reachable over Tailscale and OpenSSH.
- iCloud Drive configured on the Mac with the destination stored locally.
- The repositories cloned under
/home/saiguy/Projects. - A TMDB API key.
You also need git, npm, jq, ssh, rsync, sha256sum, ip, systemctl,
and systemd-analyze on the Linux host. The Linux user must belong to the
nordvpn group and have systemd user lingering enabled.
If your host differs, adapt the deployment before running the bootstrap:
| Setting | Files to update |
|---|---|
| Linux user, home, binaries, and repository paths | extensions/models/host_bootstrap.ts, extensions/models/media_files.ts, assets/systemd/*.service, models/@funsaized/torlink/torlink.yaml, models/@swamp/ssh/mac.yaml, models/@whyvez/disk-usage/staging-disk.yaml, vaults/local_encryption/*.yaml, workflows/workflow-movies.yaml |
| Mac user, host, SSH key, and iCloud path | models/@swamp/ssh/mac.yaml, extensions/models/network_session.ts, workflows/workflow-hoardarr-bootstrap.yaml, workflows/workflow-movies.yaml |
| NordVPN country and city | extensions/models/network_session.ts |
| Reconciliation schedule | workflows/workflow-movies.yaml |
Preserve existing model and workflow IDs. Run the tests and workflow validation after changing any deployment value.
Install Swamp using its official installer, then authenticate:
curl -fsSL https://swamp-club.com/install.sh | sh
export PATH="$HOME/.local/bin:$PATH"
swamp auth login
swamp auth whoami --jsonThe checked-in systemd unit expects the Swamp binary at
/home/saiguy/.local/bin/swamp. Update the deployment files listed above if
your path differs.
Hoardarr currently loads @funsaized/torlink from a sibling source checkout.
Clone all three repositories at the paths used by your deployment:
mkdir -p "$HOME/Projects"
git clone https://github.com/baairon/torlink.git "$HOME/Projects/torlink"
git clone https://github.com/funsaized/swamp-torlink.git "$HOME/Projects/swamp-torlink"
git clone https://github.com/funsaized/hoardarr.git "$HOME/Projects/hoardarr"Build Torlink and verify its headless search command:
cd "$HOME/Projects/torlink"
npm ci
npm run build
node dist/cli.cjs search "ubuntu" --category moviesThe command must print one JSON document. Hoardarr requires a Torlink build with
headless search and the pinned @funsaized/torlink type version
2026.08.28.2.
From the Hoardarr repository, register the local Torlink extension and pull the remaining dependencies:
cd "$HOME/Projects/hoardarr"
swamp extension source add "$HOME/Projects/swamp-torlink" --only models --json
swamp extension pull @keeb/mms --yes --json
swamp extension pull @swamp/ssh --yes --json
swamp extension pull @aaronge/systemd-panel --yes --json
swamp extension pull @whyvez/disk-usage --yes --jsonDo not pull the older @funsaized/torlink registry beta. Confirm that Swamp
loaded the local source and the expected type:
swamp extension source list --json
swamp doctor extensions --json
swamp model type describe @funsaized/torlink --compact --jsonThe extension doctor must pass. The Torlink type must be version
2026.08.28.2.
Before bootstrap, confirm these host requirements:
- NordVPN is logged in with
nordvpn login. - The Linux user belongs to the
nordvpngroup. - Tailscale is online and operated by the Linux user.
- The Mac has Remote Login enabled.
- Key-based SSH to the configured Mac host works without a password.
- The configured iCloud Movies directory exists and is writable.
- The Mac has enough local disk space and iCloud storage.
- The iCloud destination is configured to remain downloaded locally.
Check group membership and user lingering on the Linux host:
groups
loginctl show-user "$USER" -p LingerIf either requirement is missing, add it and then sign out and back in:
sudo usermod -aG nordvpn "$USER"
sudo loginctl enable-linger "$USER"The bootstrap verifies NordVPN authentication and the Tailscale operator. It does not add groups or enable lingering.
Hoardarr treats the checksum-verified Mac copy as transfer completion. iCloud upload happens asynchronously after that point.
The checked-in hoardarr vault definition stores secret material outside Git.
Store the TMDB key through Swamp's hidden interactive prompt:
cd "$HOME/Projects/hoardarr"
swamp vault put hoardarr TMDB_API_KEY
swamp vault list-keys hoardarr --jsonThe key list should contain TMDB_API_KEY. Never place the key in a model,
workflow, command argument, issue, or commit.
Validate both workflows before execution:
swamp workflow validate hoardarr-bootstrap --json
swamp workflow validate movies --jsonRun the bootstrap workflow:
swamp workflow run hoardarr-bootstrap
swamp model method run host-bootstrap inspect
swamp data get host-bootstrap bootstrap-current --jsonThe final bootstrap data should report ok: true. Bootstrap creates the local
staging and state directories, installs the two user service files, applies the
Mac definition, and verifies the Mac connection and host key. It does not enable
or start either service.
If bootstrap fails, inspect its report before changing configuration:
swamp report get @swamp/workflow-summary --workflow hoardarr-bootstrap --jsonA dry run inspects the host and plans existing catalog work. It does not perform discovery, network transitions, downloads, transfers, or cleanup.
swamp workflow validate movies --json
swamp workflow run movies --input dryRun=true
swamp report get hoardarr/movie-run-summary --workflow movies --markdown
swamp data get movie-catalog plan-current --jsonDo not continue until the run succeeds and the report matches your expected catalog state.
This step changes the host's active networking. Keep a local console or LAN
connection available because enter-download intentionally takes Tailscale
down.
Inspect the baseline first:
swamp model get network-session --json
swamp model method run network-session inspectThen test entry and recovery without starting Torlink:
swamp model method run network-session enter-download
swamp model method run network-session restoreExpected download state:
- Torlink remains inactive.
- Tailscale is offline.
- The NordVPN kill switch is enabled.
- NordVPN is connected to the configured country and city.
- Public traffic uses a changed VPN egress.
Expected restored state:
- Torlink is inactive.
- NordVPN is disconnected.
- The kill switch is disabled.
- Tailscale is online.
restore returns the local network baseline but does not ping the Mac. The live
workflow's enter-transfer method verifies Mac reachability before transfer.
If either method fails, read the method summary before retrying:
swamp report get @swamp/method-summary --model network-session --jsonReview workflows/workflow-movies.yaml before the first live run. It can change
network state, download torrents, write to the Mac, and delete a verified local
payload after transfer.
swamp run history --active --json
swamp workflow validate movies --json
swamp workflow run movies --input dryRun=false
swamp report get hoardarr/movie-run-summary --workflow movies --markdownDo not start a manual run while another movies run is active. Start with content you are authorized to download. Watch the first run from a local or LAN session, not through Tailscale alone.
The checked-in schedule runs at 02:00, 08:00, 14:00, and 22:00 according
to the Swamp server's cron interpretation. Change and revalidate the workflow if
you want another schedule.
Enable scheduling only after a live run and recovery have succeeded. Starting
the Swamp service activates the checked-in dryRun: false trigger, so scheduled
runs can change networking, download, transfer, and clean files without another
prompt.
swamp model get hoardarr-swamp-unit --json
swamp model method run hoardarr-swamp-unit enableUser
swamp model method run hoardarr-swamp-unit startUser
swamp model method run hoardarr-swamp-unit syncUserDo not enable torlink.service. The movies workflow starts and stops Torlink
inside the verified VPN window.
Inspect active and recent runs:
swamp run history --active --json
swamp workflow history search --workflow movies --json
swamp workflow history logs movies --jsonInspect reports and current state:
swamp report get hoardarr/movie-run-summary --workflow movies --markdown
swamp report get @swamp/workflow-summary --workflow movies --json
swamp data get movie-catalog plan-current --json
swamp data get torlink snapshot-current --json
swamp model method run network-session inspectStop scheduled execution:
swamp model get hoardarr-swamp-unit --json
swamp model method run hoardarr-swamp-unit stopUser
swamp model method run hoardarr-swamp-unit disableUserRestore the safe network baseline after a failed or interrupted live run:
swamp model get torlink-unit --json
swamp model method run torlink-unit stopUser
swamp model get network-session --json
swamp model method run network-session restoreThe restore method refuses to disconnect NordVPN while Torlink may still be active. Inspect the relevant method summary if stopping Torlink fails.
- Run
swamp help <command>before assuming CLI syntax from an older guide. - Validate the workflow before every manual execution.
- Inspect generated reports before retrying a failed method or workflow.
- Confirm
@funsaized/torlinkcame from the local source when its type is missing or has the wrong version. - Keep Torlink disabled at baseline. An active Torlink process blocks network restoration by design.
- Treat
cleanup-pendingas a cleanup retry, not a reason to redownload. - Plan
downloading,seeding, andseedStoppedbuckets exist so in-flight torrents and pending metadata cleanup survive across runs. The download job waits on items already in flight; do not delete their catalog rows manually. swamp workflow run moviesblocks through downloading and the five-minute seed window. Let the command finish; terminating the client cancels the run and invokes download recovery.- Movie rsync and remote checksum verification use one-hour operation timeouts.
A failed or interrupted copy remains
transfer-ready; local cleanup is not authorized until remote verification and catalog transition both succeed.
Use the Deno bundled with Swamp to run the extension tests:
DENO="$(swamp doctor extensions --json | jq -r .denoPath)"
"$DENO" test --allow-all extensions
swamp workflow validate hoardarr-bootstrap --json
swamp workflow validate movies --jsonContributions are welcome. Open an issue before changing network or deletion
safety rules, keep secrets and .swamp/ runtime data out of commits, and submit
the smallest change that solves the problem.
- How Hoardarr works explains the architecture, safety model, state transitions, and tradeoffs.
Hoardarr is available under the MIT License.