21 October 2026 · Gilles Maury
Securing a server on no budget: green dashboards prove nothing
One evening in September 2026, on one of our servers, the intrusion detector raised 5,753 alerts in seven hours. Over the same window, the banning system made zero decisions.
Nothing was broken. The detector was running, the banner was running, the integrity checker was running, the monitoring was running. Every indicator was green. They just weren't talking to each other.
That isn't the kind of finding a dashboard surfaces. It only shows up when you go and compare two sources that ought to agree.
Why this concerns you
If you have an application hosted on a modest server — a VPS, a machine at a European provider, a box in the office — chances are your provider has listed the tools installed on it. Firewall, detection, banning, monitoring: the list is reassuring.
It proves nothing.
A tool that is installed and "green" proves it is switched on, not that it is protecting you. What protects you is the link between the tools — and regular proof that the link holds. In our case, malformed requests were rejected by the proxy before being written to its log. The banner only reads that log, so it never saw a thing. Each tool was doing its job correctly; the chain between them was severed.
That is exactly what surface-level audits don't look at.
The question to put to your infrastructure this week
It fits in one sentence, and the answer takes about ten minutes:
How many addresses did your network detector flag last month, and how many did your banning system actually block?
A large gap between the two is the precise signature of the hole we had. If the two numbers look alike, your chain holds. If one is in the thousands and the other is zero, you are monitoring noise, not threat.
The strategy in six principles
Here is what the incident made us write down. Nothing exotic, nothing paid for — but an order, and explicit links.
- Shrink the surface before monitoring it. Firewall closed by default, only the web ports public. Administrative access goes through a private tunnel and disappears from the internet. What isn't exposed doesn't need defending.
- One decision engine, several sensors. The proxy logs, the remote-access logs and the network detector's alerts all feed the same engine, which alone decides to ban. The detector detects; it does not block.
- Two blocking points, each at its own level. The firewall cuts banned addresses before they ever reach the applications; the proxy handles only what requires reading the HTTP request itself.
- Decide the failure behavior in advance. If the decision engine goes down, do you block everything or let everything through? Both are defensible. Finding out mid-incident is not.
- Monitor the chain, not the noise. An alert must call for an action. So you alert when a link breaks — blocker disconnected, log gone silent, address seen but never banned — not on every suspicious packet.
- Everything as code, identical everywhere. The configuration lives in a git repository, deploys through one script, and is verified by a second script that compares the real machine against the repository. Drift becomes visible.
Put end to end, it looks like this — and the useful part of the diagram is the arrows, not the boxes (labels in French; click to enlarge):
On the left, the traffic and the two points where you cut it. On the right, the loop that decides. It's the "bans" arrow, running right to left, that was missing on the night of the 5,753 alerts: everything else was already there.
Five traps, and the trick that goes with each
These are our own scars, published as they happened — with the countermeasure, because that's the actual deliverable:
- Banning only sees what gets logged. 5,753 alerts, zero decisions: the textbook case above. The trick: never judge a chain on a single source, cross-check two independent ones. The gap is the diagnosis.
- An application-level firewall doesn't protect containers. Docker inserts its own rules upstream of the ones you write. The trick: hook into the chain meant for that purpose, and verify it by attempting a connection from outside rather than by re-reading the config.
- Monitoring can die without warning. Prometheus stopped for eleven days, while the Alertmanager kept running and kept up appearances. The trick: a witness checked from outside the machine — something that watches the watcher, since it can't report its own absence.
- A permanently red alert is a switched-off alert. The integrity checker reported 166 legitimate changes every night; after a few weeks nobody read it. The trick: exclude the noise file by file, and date every exclusion — an undated exclusion becomes a permanent blind spot.
- A badly tuned blocker can block everything. The day the decision engine went down, every site answered 403. The trick: that's principle 4 — settle the failure behavior calmly in advance, and test it by deliberately killing the engine on a Sunday morning.
The thread running through all five: nothing was broken. Everything was badly connected.
What CyFun says about it — including what's wrong
CyFun (CyberFundamentals) is the framework of the Centre for Cybersecurity Belgium, used to implement NIS2. A small project is almost never required to comply with it; its most demanding level, Essential, is still the simplest grid for seeing what's missing. I explain elsewhere why I set that level as the target for the SaaS products I build.
Applied to an infrastructure built this way, the grid returns a two-sided verdict — and it's one most small setups share:
| Function | State | What's missing |
|---|---|---|
| Govern | Weak | Roles, written policy, review |
| Identify | Partial | Full inventory, risk analysis |
| Protect | Solid | Team access management, training |
| Detect | Solid | Centralized, retained logs |
| Respond | Weak | A written, tested incident plan |
| Recover | Partial | A restore tested from somewhere else |
In short: good at preventing and at seeing, insufficient at governing, reacting and getting back up.
Recovery deserves a pause, because it's the most common and most silent trap of all: having backups that work, and a restore that starts from the same data center. That's our case, and it's a lot of people's. An incident that takes out the data center then takes out plan B along with it. The trick: until a restore has actually been run from somewhere else, stopwatch in hand, it isn't a backup, it's an intention.
The next gain won't come from one more tool. It will come from one more document — a written incident plan — and from a restore exercise actually carried out.
What free doesn't cover
The tools are free and open source. The rest isn't, and it's better to know that upfront:
- Time. Connecting, triaging, reading, tuning exclusions one by one. That's the real price, and it recurs.
- Storage somewhere else. Off-site backup costs money, necessarily.
- People. Someone who knows what to do at 3 a.m. — and a second person able to take over. Protection that lives in one person's head doesn't hold.
- Certification, if you need it. The self-assessment grid itself is free.
What I do with all this
We apply this strategy to our own servers before proposing it to anyone. It isn't a ceiling to reach one day: it's the floor we no longer go below.
This article describes the target and the traps on the way to it: neither of those moves. Progress itself lives in the repository, which says step by step what is wired up and what isn't yet. That's deliberate, and it's the right division of labor: an article dates, a repository gets updated.
A provider who shows you nothing but green isn't showing you their infrastructure: they're showing you their dashboard.
Where to start
Run the gap test described above. If it reveals a hole, the order that follows is: wire the banning into the firewall, alert on the chain with an external witness, remove administrative access from the internet, make the network detector a source of decisions — in simulation first — then open the CyFun grid on Govern, Respond and Recover.
Everything is public: the full strategy, the step-by-step recipe with verification and rollback, and the scripts, MIT licensed (in French). No real scope exclusions are published there, deliberately — they would tell an attacker where not to look. The repository gives the method, not our blind spots.
If you'd rather we looked at your chain together than at your list of tools, let's talk.
