Watching a single production box without a SIEM or a dedicated Security Team
Another weekend coding project, we were trying to work out whether a spike in attacker IPs in Nginx traffic was a typical harmless provider web crawler or something worse, swarm bots snooping.
We didn’t have an answer because no SIEM tools were installed on the server box that had been watching closely enough to know exactly what the traffic severity was. You can run standard IP traffic reports in the Ubuntu server and have Claude search who and where the IPs come from online, but this is a very manual, ad hoc process. Or go to Cloudflare reports, which can be limited depending on your plan type.
That gap is common for anyone running a VPS outside a big cloud provider’s managed security stack. You get Cloudflare reports, a firewall, maybe fail2ban if you set it up yourself, and then a lot of waiting, testing, and manual reporting.
Enterprise anomaly detection exists, but it assumes a fleet of machines, a SIEM ingesting logs centrally, and a security team’s budget. None of that fits a developer running a Linux server. Plus, there is a lot of telemetry and lock-in once you choose a system because the IP detection data lists are embedded into their services, as that is part of their secret sauce.
Or use Wazuh or Security Onion, which requires a manager server plus agents installed on each monitored host; a dedicated team of security helps as well. These are more geared towards end-to-end detection via GUI console, not a lightweight, compact first line of defense reporting tool built into the server.
So we built Vörwatch — Vör’s Watch, named for the Old Norse goddess of vigilant awareness, described in the Prose Edda as “wise and inquiring, so that nothing can be concealed from her.” All the good names are already taken by the big corpos so that's the best we can do on short notice, ok?
It’s a single bash script. No daemon, no database, no agent phoning home to a vendor’s cloud. It runs off cron, keeps its state in flat files, and does one job: notice when something on your server looks different than it did yesterday. This keeps with our privacy-enhanced technology ethos and is open source and free, just pure love, GitHub and minimal server storage space.
I like Linus Torvalds's approach: build it, put it on the net, and if people are interested, they will use it, improve it, and store it for you for future use.
Why we didn’t reach for an existing tool
Because where is the fun in a weekend DIY project in grabbing something off the shelf, we already run fail2ban and ufw on our own infrastructure, and they do a great job at the layer they’re built for: repeated failed logins, known bad ports. What they don’t do is tell you when a critical config file changes, when a new process starts talking outbound to an IP your server has never contacted before, or when nginx traffic quietly shifts from “normal load” into "someone's bots are scanning for exposed endpoints.”
That’s the layer between “firewall rules” and “full SIEM” that most single-server setups just leave empty. We looked at what was actually attacking our own VPS before deciding what Vörwatch needed to catch.
Combined fail2ban logs across our jails: over 1,600 unique IPs blocked and 40K worth of attempts logged in a two-month window, mostly malicious bot swarms. When we pulled the nginx access log through Vörwatch’s reputation scoring during testing, the top five source IPs by request volume looked like this:
115.186.231.43 35 requests [risk 1]
3.99.128.211 17 requests [risk 2]
216.73.217.6 8 requests [risk 5]
34.56.201.30 5 requests [risk 1]
40.223.148.196 4 requests [risk 1]
Notice that the risk ranking doesn’t track the request count. The IP with the fewest hits came back rated as most dangerous, because AbuseIPDB had real abuse reports against it that raw traffic volume alone would never have surfaced. That’s the exact blind spot a request-count-only monitor has, and it’s why we built the reputation layer as an optional add-on rather than skipping it.
What it actually checks
Vörwatch runs these detection passes on a cron schedule you set, defaulting to every 15 minutes:
File integrity monitoring. SHA-256 hashes of the files that matter most on any Linux box — sshd_config, passwd, shadow, crontab, nginx.conf, authorized_keys — checked against a baseline you capture. Any change gets flagged.
Listening port baselining. You capture what’s currently listening, and anything new that shows up later gets called out by name.
Outbound connection tracking. The first time your server talks to a new IP, that connection gets logged and checked against a public threat blocklist. Most servers have predictable outbound patterns. A new destination, especially one already flagged as bad, is worth a second look.
Process tree anomaly detection. This catches a specific and common attack signature: a web server or container process spawning a shell. If nginx suddenly has a bash child process, that's not a normal Tuesday, and it's exactly the kind of thing that's easy to miss scrolling through ps output by hand.
Nginx traffic analysis. High request volume from one source, or a burst of distinct 404s that looks like path scanning, both get flagged with the specific IP and count attached.
SSH cross-reference. Recent connection attempts get checked against the same blocklist used for outbound traffic, so a known-bad IP hitting your SSH port shows up in the same report as everything else.
Package vulnerability scanning. Every check cycle, Vörwatch can cross-reference your installed package list against OSV.dev’s free vulnerability database — one batched API call, not one per package, so it’s cheap even on a box with hundreds of packages.
The catch with a feed like this is volume: OSV.dev returns every historical CVE or USN ever filed against a package version, including old and already-patched-elsewhere entries, which on an older Ubuntu box can mean dozens of packages with hundreds of IDs apiece. The report caps what’s shown — top packages by CVE count, top IDs per package — so you get a readable summary instead of a wall of text, while the full uncapped list stays in a cache file if you need it.
Rootkit and backdoor scanning. If chkrootkit or rkhunter is already installed, Vörwatch shells out to it and folds the result into the same report — no new tool to learn, no separate log to check. Because a full filesystem scan is heavier than everything else Vörwatch does, it's rate-limited independently of the regular check cadence, running at most once a day by default regardless of how often check itself fires. Any hit is treated as urgent, the same tier as a blocklist match or a changed critical file.
CIS-style hardening spot-checks. Not a full CIS benchmark run — just the handful of settings that matter most and are easy to drift on without noticing: whether root login and password authentication are still enabled in sshd_config, and whether /etc/shadow and /etc/passwd still have sane permissions. These only re-alert when the finding set actually changes, so a known, unfixed issue shows up once, not every 15 minutes forever.
DNS query anomaly detection. Off by default, since not every box runs a local resolver that logs queries. If you point it at one — dnsmasq or systemd-resolved — Vörwatch tracks first-seen queried domains the same way it already tracks first-seen outbound IPs. A server suddenly resolving a domain it’s never asked for before is often the earliest visible sign of something new running, before it ever shows up as an outbound connection.
CISA KEV cross-reference — cross-checks OSV-found CVE IDs against CISA’s Known Exploited Vulnerabilities catalog (free, no key, actively maintained) so you can tell “OSV found something historical” apart from “this is confirmed being exploited right now” — a KEV match is treated as high-priority and emails immediately if configured
Two optional layers sit on top. A free AbuseIPDB key turns on the 1-to-5 reputation scoring shown above, scoped deliberately to just your nginx top-5 source IPs and cached for a week, so it never costs more than a handful of API calls per report.
A free Resend account turns on email notifications: urgent alerts (blocklist hits, file tampering, attack-pattern traffic) send immediately, everything else lands in a weekly digest instead of flooding your inbox every 15 minutes. You can change the send dates more or less depending on your needs.
The design decision we kept debating with
Vörwatch does not ban anything. It never runs ufw deny. It never calls fail2ban-client banip. It never touches iptables.
That’s deliberate, as we already have fail2ban. Automated banning based on heuristics carries a real false-positive cost on a single production box.
You don’t want a monitoring tool locking out a legitimate user, or worse, locking you out during a false alarm at 3am when nobody’s watching to notice the mistake. Every alert Vörwatch generates includes the exact command you’d run to act on it, but the decision stays with a human.
If you want full auto-remediation, something like CrowdSec exists for that and can run alongside Vörwatch. Vörwatch’s job is making sure the signal reaches you clearly, not deciding what to action automatically on your behalf.
Running the wizard
No runtime to install, no compiled binary to trust. It needs bash, the usual coreutils, iproute2, procps, and curl — things that are already sitting on almost every Linux box.
git clone https://github.com/Vektor-Memory/Vorwatch.git
cd Vorwatch
sudo bash install.sh
The installer wizard walks through an interactive setup: where to store state, how often to check, whether to add an AbuseIPDB key, whether to turn on email digests. Press Enter on any prompt to take the sensible default. sudo bash install.sh --defaults skips the wizard entirely and copies a template config you can edit by hand.
npm install -g @vektormemory/vorwatch
sudo vorwatch-install
It’s also on npm, under our org scope: https://www.npmjs.com/~vektormemory
Once it’s running:
vorwatch baseline # capture current state as "known good"
vorwatch check # run one detection pass
vorwatch install # wire up the cron job
vorwatch status # confirm everything's live
vorwatch report today # see what's happened
Why this exists
We didn’t want another dashboard to check. We wanted something that sits quietly in the background, runs its checks every 15 minutes, and only speaks up when something is actually worth attention. That’s the whole design philosophy in one line: recommend, don’t act, and don’t ask for more of a person’s time than the situation deserves.
It’s early days for the project, and there are almost certainly edge cases we haven’t hit yet. If you run a VPS and have ever wondered what’s happening on it between the moments you’re actually looking, we’d appreciate you trying it and telling us what feature additions it needs so we can improve it.
Top 5 IP risk list
The code is Apache 2.0 licensed and lives at github.com/Vektor-Memory/Vorwatch. Bring your own API keys, keep your own data, and never worry about a bash script phoning home with telemetry data it shouldn’t have.
VEKTOR Memory builds local-first, privacy-preserving persistent memory infrastructure for AI agents. Full technical documentation and changelog at vektormemory.com/docs.
Security
Information Security
Siem
Linux
Monitoring



Top comments (0)