Server Monitoring System

Security is a process, not a state. This is my real-time, public notebook of turning four random machines into a hardened, monitored, and automated personal cloud.

Published
11 Dec 2025

TL;DR – Current State (11 Dec 2025)

  • Four machines (Lenovo laptop + home server + 2× Vultr) fully connected via Tailscale MagicDNS
  • Unified username username everywhere
  • Passwordless, key-only SSH (even on the weird one running SSH on 2222)
  • Ansible control plane working with zero warnings
  • Cloudflare proxy + DNS handling all public exposure
  • Next phase → passive breach detection & response (already half built)

GitHub repo (public, everything is in here):
https://github.com/mccrudd3n/server_security

Phase 1 – Complete (The Foundations)

ComponentStatusDetails
Zero-trust networkTailscale + MagicDNS (blackhole, cloud99, production, home)
Unified usernameusername on every box
Key-only SSHNo passwords anywhere
Ansible orchestrationSingle inventory.ini, works even on non-standard ports
Public exposureOnly Cloudflare Tunnel / Proxy → no open ports on any machine
FirewallingUFW only allows Tailscale subnet (100.64.0.0/10) + 80/443 where needed

Phase 2 – In Progress (Security Monitoring & Passive Prevention)

Security is a process → I want to learn how the second something weird happens, I am alerted.

Tools I’m looking to deploy (all free, all open-source)

ToolPurposeDeployment methodStatus
OSSEC (Atomic OSSEC)Host-based intrusion detection (file integrity, rootkits, log analysis)Ansible playbookRunning on all nodes
Wazuh (fork of OSSEC)Central manager + beautiful dashboard + active responseDocker on productionManager up, agents connected
Fail2BanBan IPs after repeated failed loginsAnsibleDone
CrowdSecCollaborative bouncer + modern fail2ban alternativeAnsible + central consoleTesting
UFW + nftables loggingLog dropped packetsAlready activeDone
Prometheus Node Exporter + AlertmanagerSystem metrics + alertingAnsibleNext

Current detection capabilities (already live)

  • Any change to /etc/passwd, /etc/ssh/sshd_config, or critical binaries → instant alert
  • New user created → alert
  • SSH brute-force attempts → auto-ban (Fail2Ban + CrowdSec)
  • Rootkit signatures → alert
  • Unexpected processes → alert
  • All logs shipped in real-time to central Wazuh dashboard at https://wazuh.production.mccrudd3n.com

Future additions (next 2 weeks)

FeatureToolingWhy it matters
Automated backups of OSSEC alertsRclone → encrypted off-siteEven if attacker wipes logs, I still have them
Honey potsCowrie SSH honeypot on a fake portEarly warning + attacker fingerprinting
Canary tokensThinkst Canary on fake filesInstant alert if someone reads them
Daily vulnerability scanningOpenVAS / Trivy (container)Know when I’m vulnerable
eBPF-based monitoringFalco or TraceeDetect weird syscalls in real time

My Current Ansible Playbooks (public)

# roles/common/tasks/main.yml
- name: Unified user exists
  user:
    name: username
    shell: /bin/bash
    groups: sudo,docker
    append: yes

- name: Deploy SSH key
  authorized_key:
    user: username
    key: "{{ lookup('file', '~/.ssh/id_ed25519.pub') }}"

- name: Harden SSH
  lineinfile:
    path: /etc/ssh/sshd_config
    regexp: '^PermitRootLogin'
    line: 'PermitRootLogin prohibit-password'

- name: Install and configure OSSEC agent
  include_role:
    name: ossec-agent

Everything is idempotent, version-controlled, and tested.

P.S. – If you’re a friendly hacker reading this…

Yes, I know this is public.
Yes, I want you to look.
If you spot a wee hole (misconfig, bad practice, exposed service, weak ACL, anything), please open an issue or DM me on [email protected]!
I learn fastest when someone actually breaks in (ethically) and tells me how.
I’ll credit you in the next blog post and buy you an ethernet coffee if our paths ever cross!

Security is a process.
This document will never be “finished” — it will only get longer and greener.

…Once the project is somewhat live, i will move this section into the blog or journal so that the projects section presents this project rather than my blabber!