[BUG] RPC readiness probe hardcodes localhost, so a non-loopback rpc-bind-address leaves container init incomplete and every stop is a SIGKILL
Nobody has claimed this yet.
Assessment
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Newbie friendliness
- 56/100
- Issue type
- Bug
- Clarity
- Mostly clear
- Activity status
- Active
- Tech stack
- docker, shell
- Domain
- devops, infrastructure
Research direction
Start with svc-transmission/run and svc-transmission/finish, focusing on how each script reads rpc-port and targets the RPC service. Reproduce the non-loopback setup from the issue, then verify wildcard and specific bind addresses both complete init and that docker stop exits cleanly without SIGKILL or premature finish-script termination.
Written by the indexing model from the issue text.
Description
Is there an existing issue for this?
- I have searched the existing issues
I checked #80, #279, #261, #285, #306 and #324. #80 is the closest — it identified that transmission-remote --exit failed when USER/PASS were set, and was fixed by passing credentials — but it never identified the bind-address dependency described below. #324 is a different bug (the [::] default failing to bind on some Synology/QNAP kernels), though the workaround being given there — hand-editing rpc-bind-address — is exactly how a user can walk into this one.
Current Behavior
svc-transmission/run gates service readiness on a hardcoded loopback probe:
PORT=$(jq '.["rpc-port"]' /config/settings.json)
s6-notifyoncheck -d -n 300 -w 1000 -c "nc -z localhost ${PORT:-9091}" \
s6-setuidgid abc /usr/bin/transmission-daemon \
-g /config -f
It reads rpc-port from settings.json but ignores rpc-bind-address, always probing localhost.
With the default rpc-bind-address ([::], or 0.0.0.0) this is invisible, because localhost resolves to an address the wildcard socket accepts. But if rpc-bind-address is set to a specific non-loopback address, nc -z localhost can never succeed, and the container never finishes starting:
s6-notifyonchecknever signals readinesss6-svlisten1 -U -- /run/s6-rc/servicedirs/svc-transmissionblocks forever waiting for "up"rc.init top/s6-rc -v1 -u -t 0 -- change topnever complete — container init stays permanently in progress- because init never finished, s6's shutdown path never delivers SIGTERM to
transmission-daemon - every
docker stoptherefore ends in SIGKILL
The damage is that the daemon is hard-killed on every single stop/restart: resume data is not flushed and no "stopped" announce is sent to trackers. Nothing in the logs indicates a problem — the daemon itself is completely healthy and serving RPC the whole time.
There is a second, independent loopback hardcode in the same service's finish script, so even once readiness is fixed the graceful exit still cannot land off-localhost:
/usr/bin/transmission-remote 127.0.0.1:${PORT:-9091} -n "$USER":"$PASS" --exit
Related: there is no timeout-finish file in the servicedir, so s6 SIGKILLs the finish script at its 5000 ms default. On a large library the daemon legitimately needs longer than that to exit (measured ~8–9 s for ~1300 torrents on my host), so tail --pid=${pid} is killed before the daemon is actually gone.
Expected Behavior
The readiness probe and the shutdown request should target the address Transmission is actually bound to, derived from rpc-bind-address. Wildcard binds (0.0.0.0, ::, [::]) should keep probing loopback as they do today.
Container init should complete, and docker stop should result in a graceful shutdown (exit 0) regardless of which address RPC is bound to.
Steps To Reproduce
- Create a user-defined network so the container has a predictable non-loopback address:
docker network create --subnet 172.30.0.0/16 tmnet - Seed
/config/settings.jsonwith"rpc-bind-address": "172.30.0.5" - Start the container on that network with
--ip 172.30.0.5(command below) - Observe the daemon is healthy and listening on
172.30.0.5:9091, but[ls.io-init] done.is never printed and the init processes are still alive:
$ docker top tm-base # columns abridged for readability
1201 root {rc.init} /bin/sh -e /run/s6/basedir/scripts/rc.init top
1228 root s6-rc -v1 -u -t 0 -- change top
1344 root s6-svlisten1 -U -- /run/s6-rc/servicedirs/svc-transmission ... s6-svc -u -- /run/s6-rc/servicedirs/svc-transmission
1361 root s6-notifyoncheck -d -n 300 -w 1000 -c nc -z localhost 9091 s6-setuidgid abc /usr/bin/transmission-daemon -g /config -f
$ docker exec tm-base netstat -tln | grep 9091
tcp 0 0 172.30.0.5:9091 0.0.0.0:* LISTEN
- Stop it and observe the SIGKILL:
$ S=$(date +%s); docker stop -t 30 tm-base; E=$(date +%s); echo "elapsed: $((E-S))s"
elapsed: 31s
$ docker inspect -f '{{.State.ExitCode}}' tm-base
137
The full 30 s grace period elapses with no shutdown log lines at all — the daemon never received a signal.
For contrast, the identical container with the stock [::] default completes init in ~2 s and stops cleanly with exit 0 in ~4 s.
Environment
- OS: originally observed on Ubuntu 24.04 LTS; the isolated reproduction above was run on OrbStack (macOS) with the same image and is reproducible on both
- How docker service was installed: distro's package manager (Ubuntu) / OrbStack (macOS)
CPU architecture
x86-64
Docker creation
docker network create --subnet 172.30.0.0/16 tmnet
mkdir -p ./cfg && cat > ./cfg/settings.json <<'EOF'
{
"rpc-bind-address": "172.30.0.5",
"rpc-port": 9091,
"rpc-url": "/transmission/"
}
EOF
docker run -d --name tm-base \
--network tmnet --ip 172.30.0.5 \
-e PUID=1000 -e PGID=1000 \
-e USER=tu -e PASS=tp \
-v "$PWD/cfg:/config" \
ghcr.io/linuxserver/transmission:4.1.3@sha256:6b78970a0cb00709d3817fcb47b7cf74da56a43384bbd50d03955ca87e38c5f0
Image: 4.1.3-r0-ls356, built 2026-07-28.
Container logs
[migrations] started
[migrations] no migrations found
───────────────────────────────────────
██╗ ███████╗██╗ ██████╗
██║ ██╔════╝██║██╔═══██╗
██║ ███████╗██║██║ ██║
██║ ╚════██║██║██║ ██║
███████╗███████║██║╚██████╔╝
╚══════╝╚══════╝╚═╝ ╚═════╝
Brought to you by linuxserver.io
───────────────────────────────────────
To support LSIO projects visit:
https://www.linuxserver.io/donate/
───────────────────────────────────────
GID/UID
───────────────────────────────────────
User UID: 1000
User GID: 1000
───────────────────────────────────────
Linuxserver.io version: 4.1.3-r0-ls356
Build-date: 2026-07-28T12:17:56+00:00
───────────────────────────────────────
[custom-init] No custom files found, skipping...
[2026-08-01T19:04:58.423+0000] inf ip-cache.cc:385 Cached IPv4 source address 172.30.0.5 (ip-cache.cc:385)
...
[2026-08-01T19:04:58.423+0000] inf session.cc:424 Listening to incoming peer connections on 0.0.0.0:51413 (session.cc:424)
[2026-08-01T19:04:58.423+0000] inf session.cc:424 Listening to incoming peer connections on [::]:51413 (session.cc:424)
[2026-08-01T19:04:58.423+0000] inf port-forwarding.cc:221 State changed from 'Not forwarded' to 'Starting' (port-forwarding.cc:221)
[2026-08-01T19:04:58.423+0000] inf tr-udp.cc:207 Bound UDP IPv4 address 0.0.0.0:51413 (tr-udp.cc:207)
[2026-08-01T19:04:58.423+0000] inf tr-udp.cc:254 Bound UDP IPv6 address [::]:51413 (tr-udp.cc:254)
[2026-08-01T19:04:58.423+0000] WRN tr-lpd.cc:288 Couldn't initialize IPv6 LPD: No such device (19) (tr-lpd.cc:288)
[2026-08-01T19:04:58.468+0000] inf rpc-server.cc:878 Added '127.0.0.1' to host whitelist (rpc-server.cc:878)
[2026-08-01T19:04:58.468+0000] inf rpc-server.cc:878 Added '::1' to host whitelist (rpc-server.cc:878)
[2026-08-01T19:04:58.468+0000] inf rpc-server.cc:1013 Serving RPC and Web requests on 172.30.0.5:9091/transmission/ (rpc-server.cc:1013)
[2026-08-01T19:04:58.468+0000] inf rpc-server.cc:825 Listening for RPC and Web requests on '172.30.0.5:9091' (rpc-server.cc:825)
[ls.io-init] done. never appears. On docker stop the log simply ends — there is no
"shutting down" and no "Closing transmission session" line, because the daemon is never
signalled.
- Dominant language
- Dockerfile
- Stars
- 739
- Forks
- 205
- PR merge metrics
- No merged PRs in 30d
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
More from linuxserver/docker-transmission
-
invalid no-issue-activity
Difficulty 4/5 3-5 days Newbie friendliness 25/100
linuxserver/docker-transmission#325 · 3 comments · 1 reaction ·
-
Difficulty 4/5 3-5 days Newbie friendliness 35/100
linuxserver/docker-transmission#324 · 12 comments ·
All issues in linuxserver/docker-transmission
Similar issues
-
Difficulty 2/5 1-3 hours Newbie friendliness 84/100
copse-dev/agent-pane#2953 ·
-
Difficulty 2/5 1-3 hours Newbie friendliness 90/100
simonw/sqlite-utils#872 ·
-
Difficulty 1/5 Under an hour Newbie friendliness 84/100
-
Difficulty 2/5 1-3 hours Newbie friendliness 84/100
danielmiessler/LifeOS#2215 ·
-
Difficulty 2/5 1-3 hours Newbie friendliness 78/100
sympozium-ai/sympozium#627 ·