Usenet

type: nzb

Usenet is a provider type but not a debrid service. There is no API token and no remote library. You drop .nzb files into a watch directory and zurg turns each one into a release. Articles are fetched from your news server and decoded at the moment a player asks for those bytes.

This page is the provider entry and the Docker specifics only. Everything else about running Usenet on zurg lives in Usenet with zurg. That is the full walkthrough with news accounts and NZBs and the mount and Plex. It is the page to read second.

Configure it

There is no token. An nntp block with a host is what makes the entry valid.

zurg: v1
providers:
  - type: nzb
    nntp:
      host: news.example.com
      port: 563
      tls: true
      username: YOUR_USENET_USERNAME
      password: YOUR_USENET_PASSWORD
      connections: 8
      cache_size_mb: 512
mount_path: "/zurg_mnt/zurg"

Set connections to what your plan actually allows. zurg reads at that number because one connection carries a fraction of a plan's throughput. Streaming saturates the allowance rather than fetching one article at a time. Going over what the plan permits gets connections refused.

On a fresh container install setup will prompt for all of it.

cd ~/zurg
docker compose run --rm zurg setup \
  --no-service --skip-downloads --mount-path /zurg_mnt/zurg \
  --provider nzb

For an unattended install the password comes from a file and everything else comes from flags.

docker compose run --rm zurg setup --non-interactive \
  --no-service --skip-downloads --mount-path /zurg_mnt/zurg \
  --provider nzb \
  --nntp-host news.example.com \
  --nntp-username YOUR_USENET_USERNAME \
  --nntp-password-file /config/secrets/nntp \
  --nntp-connections 8

--nntp-tls defaults to true and --nntp-port defaults to 563 with TLS or 119 without.

On an install that already has a config.yml use Add provider in the Dashboard at http://localhost:9999/config/ or edit the file. Restart either way.

docker compose restart zurg

Where the NZBs go in a container

The watch directory is nzbs/ beside the config. That means ~/zurg/nzbs/ on the host and /config/nzbs/ inside the container. It is the same directory. Put files in from the host.

mkdir -p ~/zurg/nzbs
cp /path/to/some.nzb ~/zurg/nzbs/
ls /zurg_mnt/zurg/__nzb__/

The watch directory is picked up every 15 seconds or so. Because it lives inside the ./:/config bind it survives a docker compose pull and a container recreate like everything else.

Rules specific to this type

  • Only one enabled nzb entry. Two would scan the same directory and duplicate every release. More news servers belong under that one entry's nntp.servers. There they serve the same library rather than a second copy of it.

  • watchlist: true is refused. A news server is never handed a torrent.

  • add_torrents is ignored and startup warns about it for the same reason.

  • download_tokens and strm_link_token do nothing. There is no credential to rotate.

  • The directory is __nzb__ because the name defaults to the type. Set name: usenet on the entry if you would rather browse __usenet__.

A second news server is worth more than it looks

Retention is per provider. An article one server has aged out is very often still on another. Without a second account the only way to recover a dead article is PAR2 and that costs a read of the entire release. So a second server is the difference between fetching one article and re-reading everything.

Extra accounts go under this entry's nntp.servers rather than into a second nzb entry. priority and backup and backbone decide who is asked and in what order. Reads are driven at the combined allowance of the accounts that are not marked backup. The worked config and what each key buys are in Usenet with zurg.

Check it worked

curl -fsS -X POST http://localhost:9999/api/providers/nzb/test
docker compose logs --tail=100 zurg
ls /zurg_mnt/zurg/__nzb__/

The probe here authenticates against the news server using at most one connection from the existing pool. There is no account API to ask.

When it goes wrong

Two symptoms belong to the provider entry itself rather than to the library.

Reads tear and zurg drops to one article at a time. pipeline_depth is higher than the server tolerates. zurg reduces it by itself and warns. Set it to 1 explicitly for a server that cannot handle several commands in flight.

Throughput is poor on a high latency link. Leave socket_receive_buffer_kb unset. A pinned buffer is one the kernel stops tuning. On Linux that holds the receive window near 64 KiB and costs most of the account's throughput.

Everything else has a row in the troubleshooting table on Usenet with zurg. Refused connections and slow streaming and a provider that never gets asked and a Dashboard edit that dropped nntp.servers are all there.