I manage infrastructure for clients across Pakistan. Last month, a freelancer friend got a $1,400 bill from CrowdStrike for 40 Linux servers. That's more than his monthly revenue.
Enterprise EDR is broken for the rest of the world. So I'm building an alternative.
SystemGuard is a lightweight, self-hosted HIDS I'm open-sourcing. It's not another wrapper around OSSEC — it's built from the kernel up with eBPF and Rust.
GitHub: https://github.com/systemguard-io/systemguard
The Problem Nobody Talks About
Western security tools assume:
- You can afford $35/host/month
- You want to send all your telemetry to US clouds
- You have a SOC team to tune 10,000 alerts
In Karachi, Lahore, and Islamabad, we run 5-100 servers on tight margins. We need:
- Real-time detection (<100ms)
- Self-hosted (data sovereignty)
- <2% CPU overhead
- Free
OSSEC hasn't had a meaningful commit since 2019. Wazuh is great but requires Elasticsearch cluster (overkill for 10 servers).
Why Rust, Not Go?
I prototyped in Go first. It worked — until I hit 15k syscalls/sec during a stress test. GC pause: 8ms. In that window, we lost 120 events. For a security tool, that's unacceptable.
I rewrote the agent in Rust with aya-rs. Same workload: 1.4% CPU, zero allocations in hot path, 5MB static binary.
The decision is documented here: ADR-001
Key trade-off: steeper learning curve, but memory safety is non-negotiable when your agent runs as root.
eBPF vs auditd: The Numbers
I benchmarked both on a t3.medium:
| Method | CPU | Events Lost |
|---|---|---|
| auditd | 22% | 4.2% |
| eBPF | 1.6% | 0% |
auditd copies every event to userspace. eBPF filters in-kernel. For monitoring openat() and execve(), eBPF is 14x more efficient.
Full analysis: ADR-002
Here's the actual probe (simplified):
c
SEC("tracepoint/syscalls/sys_enter_openat")
int trace_openat(void *ctx) {
struct event *e = bpf_ringbuf_reserve(&events, sizeof(*e), 0);
if (!e) return 0;
e->pid = bpf_get_current_pid_tgid() >> 32;
bpf_get_current_comm(&e->comm, 16);
// Filter in kernel: ignore /proc, /sys
bpf_ringbuf_submit(e, 0);
return 0;
}
Top comments (0)