My Server Has No SSH Port
A small decision about a one-box setup — and the access-control idea underneath it, which scales much further than the box does.
I was standing up a small personal server on AWS — nothing exotic, just a single instance to host a few projects. The launch wizard reached the firewall step and offered the usual default: allow SSH, source 0.0.0.0/0. Anywhere.
By default, the launch wizard offered me SSH open to the entire internet.
I work in application security, so I know exactly what that warning means. The textbook fix is to restrict SSH to your own IP. Except I was on a home connection with a dynamic address that changes whenever the router feels like it. Pinning the rule to my IP would mean re-editing the security group every few days — and the first time I got lazy, I'd widen it back to anywhere, "just for now." That "just for now" is how a depressing number of incidents begin.
So I had the standard dilemma: a management port that has to be reachable, and no clean, stable way to scope who can reach it.
Then I stopped and asked a different question.
The question I almost skipped
Not how do I lock down port 22, but why is port 22 open at all?
I closed it. Not narrowed — closed, to the entire internet. The instance has no inbound SSH rule. No port 22, no bastion, no VPN.
I reach it through a session broker instead (AWS Systems Manager, in my case): an agent on the box makes an outbound connection to a managed endpoint, and I open a session through that. There is no listening port for anyone to find, scan, or brute-force. And because I still wanted rsync, scp, and remote editing from my IDE, I tunnel ordinary SSH through that session — full developer ergonomics, zero exposed surface. From my terminal, it's still ssh myserver. From the internet, there is simply nothing to connect to.
The dynamic-IP problem didn't get solved. It got deleted, along with the port that created it.

The same shell, reached through an identity-brokered session — no listening port involved.
This was never about SSH
Here's the part that outlives my little server, and the reason I'm writing it down.
The reflex I almost followed — an exposure exists, so harden it — is the default mode of most security work. Allowlist the source. Rotate the keys. Stand up a bastion. Put a WAF in front. All of that is real, necessary work, and all of it quietly assumes the exposure is a given and that your job is to make it safer.
But some exposures aren't givens. They're choices you inherited from a default. And the strongest version of a control is often its own absence: the only attack surface you never have to defend is the one that isn't there.
At the scale of one hobby box, deleting SSH is a convenience. At the scale of a real organisation, the same move is the difference between two very different operating models. The harden it path leads to a fleet of bastion hosts and VPN concentrators — machines you provision, patch, and monitor, which hold standing credentials and are themselves a prize (jump boxes are a favourite pivot for precisely that reason). The delete it path — brokered, identity-based access, whether that's SSM, an identity-aware proxy, or something like Teleport — removes the network exposure and the fleet you built to guard it. You stop running the very thing you'd otherwise have to defend forever.
The mental move that transfers is small, and worth making a habit: when you find yourself configuring how to safely expose something, pause and ask whether it needs to be exposed at all. Access is an identity question far more often than it is a network one.
Two operating models for the same need: guard the door, or remove it.
What you gain by removing it, not securing it
Reframing access from "who can reach this port" to "which identity is allowed to do this, right now" pays off in ways that matter far more at ten thousand servers than at one:
- Every session is attributable. Access is authenticated and authorised against an identity rather than a network location — and logged. On my box, that's an audit trail nobody will ever read. In a regulated environment, "every privileged access is tied to a person and recorded" is the exact line an auditor is looking for — and here you get it as a property of the design, not a bolted-on logging project.
- The credential you removed is the one you never manage. No standing SSH keys scattered across laptops and CI to leak, rotate, and chase; access is brokered through short-lived, identity-based credentials. As someone who spends real time scanning repositories for leaked secrets, I'll take removing the secret over guarding it every time.
- Least privilege gets easier, not harder. Access becomes per-identity, time-bound, and centrally revocable — rather than "whoever holds the key, forever."
The audit trail you get for free: each session authenticated, attributed, and logged.
None of this is novel; it's the whole premise behind zero trust and identity-aware access. What the one-box exercise made concrete for me is that the principle shows up at every scale, and that the right moment to apply it is the instant you're tempted to harden an exposure instead of removing it.
The habit worth keeping
My server has no SSH port. Not because I locked it down well, but because I asked whether it needed one — and the answer was no.
That's the whole idea, and it generalises cleanly: before you reach for the allowlist, the bastion, or the key-rotation policy, check whether the thing needs a door at all. The most defensible exposure is the one you deleted — and the habit of going looking for those is a good part of what separates hardening a system from architecting one.