I Deleted My Entire Security Stack. My Apps Got Safer.
fail2ban, the ufw ruleset, the WAF, the log-watchers - all purged in a month, and my apps got safer, because every one of them was a compensating control for a single inherited default: a public IP. The purge checklist, the before/after, and what I kept. Uninstalling fail2ban felt like removing a smoke detector. My finger hovered for a genuine minute. Then I pressed enter, and over the next month almost everything went: the ufw ruleset I'd maintained for years, the WAF config, auditd's screaming cron, the nightly "security" scripts whose output I'd stopped reading in 2024. My apps got safer. That sentence is the opposite of what it sounds like, so let me show the work. The compensating question Before the purge I asked what each tool was actually compensating for: - fail2ban → SSH reachable from the entire internet - ufw ruleset → a public address with ports that must be filtered - WAF → the app directly reachable by anything that finds its IP - log-watchers → the noise generated by all of the above Different tools, one root cause: the machine has a public address - a decision I never made, just inherited, because "server comes with an IP" is how servers work. I wasn't running a security stack. I was running a payment plan on a bad default. Changing the default The workloads moved to Cubes on Krova Cloud - Firecracker microVMs, own kernel each, and the part that retired the stack: no public IP. Private NAT'd network, traffic through managed TLS ingress, default-deny inbound, only explicitly opened ports reachable. I open none. Before/after, same eyes: # BEFORE - old VPS, the street: $ ss -tlnp LISTEN 0.0.0.0:22 # the brute-force magnet LISTEN 0.0.0.0:80 LISTEN 0.0.0.0:443 # AFTER - Cube, from inside: $ krova ssh app-1 -- ip -brief addr eth0 UP 10.0.x.x/24 # private. that's the whole list. $ krova ssh app-1 -- ss -tlnp LISTEN 127.0.0.1:8080 # the app, listening to itself $ krova tcp list app-1 # empty. no port forwards, nothing to filter, nothing to ban. With no address there's nothing to brute-force, so fail2ban has no job. With default-deny and no surface, the ruleset has no job. One migration weekend retired four tools and ~1,000 lines of compensating config. The purge checklist (and why it's safe) apt purge fail2ban # no public SSH → nothing to ban ufw disable # retired, NOT "off and exposed" - # safe only because the platform default # is private + default-deny inbound # WAF config → archived; app-level validation stays in the app crontab -e # delete auditd + nightly scanner lines Read that ufw disable line carefully. It is safe because the exposure left first. On a box with a public IP, the same command is a breach with extra steps. Order matters: default first, meds second. What I did NOT delete - Secrets hygiene - scoped, short-lived, injected at runtime. - Backups + restore drills - off-host copies, scheduled restores into a fresh Cube. - Patching & dependency cadence - the boring rhythm continues. - Application security - authn/authz, input validation, tenant checks. The purge hit tools defending the door; the app's own locks were never the target. The honest part - Keep your tools if your symptom is mandatory. Gameservers, UDP media, weird protocols - real public-address workloads exist. This isn't "firewalls are a scam"; it's "ask whether the symptom is optional." For a shocking number of web workloads, it is. - Architecture isn't a sedative. No public IP shrinks the surface; it doesn't review your PRs. The threat model got smaller, not zero. - Ops stay yours. Isolation is the platform's job; patching, backups, drills remain the owner's, same as any self-hosted box. I didn't remove the locks. I removed the street. Most of my "security" was pain management for a street I never needed. When the street went away, the pharmacy closed. Ask your stack the compensating question tonight. You might find a default you inherited, a wound you've been medicating for years - and a weekend where the meds go away. Top comments (0)
Comments
No comments yet. Start the discussion.