Kyber Cypher Plain English edition
Text size Back to the full site
A hand about to flip a switch while hidden wires run away behind the wall, standing for proving nothing depends on something before switching it off.

Prove nothing is using it before you switch it off

What you will learn

  • Why the ten second version of this fix is the dangerous one
  • How to prove nothing is using something before you switch it off
  • How to stop things without losing anything they hold
What happened and why it matters

I found a couple of programs on my computers that were quietly accepting connections from anywhere on my network, when they only ever needed to talk to the machine they were already sitting on. That is a genuine thing worth fixing, and the fix is a single line of settings. It takes ten seconds.

Do not do it in ten seconds. Prove nobody is using it first.

The one piece of jargon, explained

A port is just a numbered doorway on a computer. Programs sit behind a doorway and wait for someone to knock. A doorway can be set to accept knocks from anywhere on your network, or only from programs already inside that same machine. The second one is almost always what you actually wanted.

Here is why the ten second version is a trap. A doorway open to the whole network is reachable by other machines. That is the security problem. But it might also be something that another machine is quietly relying on. Some job on a different computer connects to it at three in the morning, once a week, and has done for a year. Nobody wrote it down. The person who set it up was you, eighteen months ago.

Why tidying up breaks things in a particularly nasty way

A security cleanup usually breaks something that runs on a schedule. So the breakage does not show up when you make the change. It shows up days later, completely disconnected from what caused it, by which point you have changed twelve other things and the trail has gone cold.

So instead of ten seconds, I spent twenty minutes proving it. I looked at what was actually connected to those doorways, and I looked from both ends rather than only from the machine running the program. Nothing outside the machine was talking to them. Then, and only then, I changed the setting so they answer only to programs on their own computer, and I left everything else exactly as it was.

The same care covered the rest of the clear out. I found five programs that were running and doing nothing whatsoever, and two databases belonging to a project that was paused rather than abandoned.

Paused is not the same as finished

The paused project is the interesting one, because it is exactly where people reach for the wrong verb. The instinct when tidying is to remove things. But paused means somebody is coming back, and the thing they will need when they come back is the data.

So the correct move is to stop the thing and keep everything it owns. Nothing was deleted. The stored data stayed exactly where it was. All that changed is that those programs are no longer running and no longer using any memory.

That difference is worth saying out loud, because the tools blur it badly. Stopping something and destroying it are frequently one word apart on the same instruction, and the version that also destroys your data is very often the one suggested in the first answer you find online. Read the instruction you are about to run and specifically ask yourself what happens to the stored data.

The rule this leaves you with

Every cleanup step should be reversible, and you should know the exact way to reverse it before you run the thing that does it.

Switching a program off is reversible. Deleting its data is not. Closing a doorway is reversible. Destroying a database is not. When you have a reversible option and an irreversible one, and both achieve what you want today, the reversible one is not the timid choice. It is simply the correct one.

The honest catch

Proving something is unused is not the same as proving it will never be used. A quick look tells you about right now. A job that runs once a week will not appear in a five minute check, which is why how long you watch matters more than what you type.

Watch for a stretch of time long enough to contain the schedule you are worried about. If you genuinely cannot wait that long, make the change in a way you can undo in one step, and then pay attention to complaints.

The whole lesson fits in one sentence. Prove it is unused, make the change reversible, and never let a tidy up be the thing that destroys your data. This is the same idea as measure before you delete, pointed at your network instead of your hard drive.

Every cleanup step should be reversible, and you should know the exact way to reverse it before you run the thing that does it.

How to do it yourself

This half is for people who want to actually do it. Steps one to three only look at things and change nothing at all, so they are safe to run out of curiosity. If you would rather stop reading here, you have already got the useful part.

1. See which doorways are open, and how widely

What this does: lists every program on this machine that is waiting for connections, and shows which addresses each one will accept.

What to look at: the address, not the number. 127.0.0.1 means only this machine can reach it, which is the safe setting. 0.0.0.0 or :: means anything that can reach this computer can knock on that door. That difference is the entire subject of this guide.

ss -ltnp

# the same list, narrowed to only the ones open to the network
ss -ltnp | grep -E '0\.0\.0\.0|\[::\]'

2. Check whether anything is actually connected, from both ends

What this does: shows live connections to a doorway right now. Replace PORT with the number you saw in step one.

Why both ends: run the first one on the machine hosting the program, then go to the other machines and run the second. Something that connects on a schedule will show you absolutely nothing if you happen to look while it is idle.

# on the machine that hosts it: who is connected right now, and from where
ss -tnp state established "( sport = :PORT )"

# on another machine: is anything here reaching out to it
ss -tnp state established "( dport = :PORT )"

Do not skip the second one. The entire risk here is a dependency you have forgotten about, and forgotten dependencies live on other machines by definition.

3. Watch over a real stretch of time, not a single moment

What this does: counts the connections to that doorway once every minute and writes each count to a file, so you end up with a record instead of a memory of a screen.

Why bother: this is the step people skip, and it is the one that catches the weekly job. Leave it running for at least a full day, and longer if you are worried about something monthly.

What should happen: a file that slowly fills with lines. Press Ctrl and C together to stop it when you have watched long enough.

# log the number of connections, once a minute
while true; do
  printf '%s %s\n' "$(date -Is)" \
    "$(ss -tn state established "( sport = :PORT )" | tail -n +2 | wc -l)"
  sleep 60
done >> /tmp/port-watch.log

What this does: sorts that record by the count and shows the five busiest lines.

What to look for: if the highest number is zero, nothing used it for the whole time you were watching. That is your evidence.

sort -k2 -n /tmp/port-watch.log | tail -5

4. Change the setting so it only listens to itself

What this does: these are settings lines, not commands to run. Each one goes in that program's own settings file and tells it to accept connections only from its own machine.

Why do it here rather than with a firewall: a firewall rule is a second thing that has to keep being true. Setting it correctly here means the doorway was never open in the first place.

# PostgreSQL, in the file postgresql.conf
listen_addresses = 'localhost'

# Redis, in the file redis.conf
bind 127.0.0.1

# Docker, in the compose file: publish to this machine only
ports:
  - "127.0.0.1:5432:5432"      # not "5432:5432"

Then run the command from step one again to confirm the address changed, and check that the program on this machine which legitimately uses it still works. If other machines genuinely do need to reach it, the right answer is to put those machines on a private network together rather than opening the door to everything, which is what reach your own computers from anywhere without opening your front door is about.

5. Stop things without losing what they hold

What this does: switches a program off and stops it starting again next time the machine boots. The data it holds is untouched.

How to undo it: the same command with enable instead of disable, which is written in the comment so you do not have to remember it.

# reversible, and the data is not touched
sudo systemctl disable --now some-service
# to bring it back: sudo systemctl enable --now some-service

What this does: stops a group of containerised programs while keeping both the containers and their stored data.

The dangerous neighbour: the commented out line below is one word longer and it destroys the stored data. It is shown here only so you recognise it when you meet it in a forum answer. Do not run it.

# stops them, keeps the containers AND the stored data
docker compose stop

# DANGER: this one deletes the stored data. one word longer.
# docker compose down -v

One more trap worth knowing. If several unrelated things are grouped into the same project, shutting the whole project down can take an innocent neighbour with it. Stop things by name rather than taking down a whole group, unless you have checked what else is in there.

6. Write down how to undo it, before you do it

What this does: nothing technical at all. It is a plain text file, kept next to whatever you changed, recording the date, the change, and the exact way back.

Why it is the most valuable step here: if you cannot write down how to undo something, that is the signal to stop and think. It is not a reason to press on and hope.

# rollback.md, kept beside whatever you changed
# 2026-08-14 set the database to listen only to its own machine
#   undo: set listen_addresses='*' in postgresql.conf, restart it
# 2026-08-14 stopped the paused project
#   undo: docker compose start   (the data was never removed)

Related reading: measure before you delete is this same rule aimed at disk space, and give every job its own key is the same instinct aimed at passwords.

This page in the original Kyber Cypher voice: Prove nothing's using it before you shut it off