The 60-second triage lives on mrsaynothing.dev; the war stories live here.
Every connection-refused hunt I've been part of — mine, and the ones documented in public issues — ended in one of two embarrassments. Either the thing that should have been listening was never started (the systemd service nobody enabled after the reboot), or the caller was talking to itself: 127.0.0.1 inside a container, pointing at nothing.
Today's post on the site breaks the six causes down for Ollama specifically, ranked by how often each one turns out to be the answer. The caller table is the part worth taping next to the monitor: container → host.docker.internal or the service name, never localhost.
So, the question:
What was actually broken the last time you saw connection refused?
The service that wasn't enabled? The port you changed in one config file and not the other? The container that called itself for an hour before anyone checked? Old wrong answers welcome — the dumber the cause, the better the story.
Top comments (2)
Your two cover the caller and the process. The third one, and in Docker the most common, is on the listener side: the process is up, the port is right, and it bound to 127.0.0.1 instead of 0.0.0.0, so it refuses everything from outside its own namespace. Same error string, and it survives every check that asks "is the service running", because it is.
The diagnostic worth adding to your table is the difference between refused and timed out, because it splits the causes before anyone starts guessing. Connection refused means a RST came back: routing worked, you reached the right network namespace, and nothing was listening on that port there. A hang or a timeout means you never arrived — wrong host, firewall, wrong network. People treat the two as one symptom and they rule out opposite halves of the list.
Then
ss -ltnprun inside the namespace you are actually calling into finishes it in one line. Nothing listening is your first embarrassment. Listening on 127.0.0.1 is the third. Listening on 0.0.0.0 while the call is still refused means you are in the wrong namespace, which is your second.@mickyarun This is the cause the triage skips — everything checks out on the caller side because the process genuinely is fine. The tell is in ss -tlnp: 127.0.0.1:11434 where the caller needs 0.0.0.0. Inside a container that loopback is unreachable by design, so the fix is the listen address, not the network path. Banked for the follow-up post — credited.