Your Proxmox host runs a dozen Docker containers, a handful of LXCs, and has SSH exposed to the local network. You trust your users, but you have no record of who ran docker exec --privileged into that production container or when someone edited /etc/pve/user.cfg.
This is the security blind spot in most homelabs: the kernel can log everything, but nobody enables it.
Linux auditd is the built-in kernel-level auditing framework that captures syscalls, file access, process execution, and configuration changes. It costs no additional software, minimal CPU overhead, and produces structured logs you can query with familiar tools. This guide walks through a complete auditd deployment for a Docker and Proxmox homelab — from basic install to daily alert queries.
What Is auditd? The Kernel Audit Framework
auditd is not a userland add-on. It sits at the kernel level, intercepting system calls through the Linux Audit subsystem and forwarding events to userspace via a netlink socket. The architecture has three layers:
- Kernel — captures syscalls and file watches via the audit framework compiled into the kernel
- auditd daemon — receives events from the kernel, writes them to disk, and optionally forwards them to remote log servers
- ausearch / aureport — command-line tools for searching and summarizing audit logs
The systemd integration is minimal: audit.socket activates the daemon on demand, and auditd.service manages the full lifecycle. You explicitly enable it — it stays off by default on most distributions.
Installing and Enabling auditd
Installation is a single package on Debian-based systems:
|
|
Verify the kernel audit subsystem is active:
|
|
Expected output shows enabled 1 and a valid pid for the daemon.
The main configuration lives at /etc/audit/auditd.conf. Defaults are conservative for general-purpose systems, but for a homelab bump these values:
max_log_file = 128
max_log_file_action = rotate
space_left_action = email
admin_space_left_action = suspend
disk_full_action = suspend
max_log_file_action = rotate prevents the daemon from stopping when the log reaches the size limit. Set space_left_action to email if you have local mail configured, otherwise use syslog to forward to journald.
Essential Audit Rules for Homelab Security
Rules are added with auditctl at runtime and persist through rule files. These three categories cover the critical homelab attack surface.
Monitor Docker Daemon and Container Execution
The Docker binary and its data directory are the primary targets:
|
|
The first rule watches for any execution of docker — every docker run, docker exec, docker ps that hits disk triggers an event. The -k flag assigns a key for easy filtering with ausearch. The -p x flag watches execute permission; -p wa watches write and attribute changes for configuration and data paths.
Monitor Proxmox Host Operations
Proxmox management tools — qm for VMs, pct for containers — are CLI binaries that should only run during planned maintenance:
|
|
The /etc/pve directory is a PMXA filesystem (FUSE) shared across cluster nodes. Watching it captures changes to VM configs, storage definitions, and user permissions through the Proxmox web interface or CLI. The /var/log/pve watch catches task log writes — who started, stopped, or migrated a VM.
Monitor Critical System Paths
User database, SSH configuration, and cron are common privilege escalation vectors:
|
|
Monitor Sensitive System Calls
File-watch rules only cover specific paths. Syscall rules catch actions anywhere in the filesystem and on kernel objects:
|
|
The execve syscall rule generates an event for every binary execution on the system — including scripts launched by interpreters like Python and Bash. This is your catch-all for discovering unauthorized processes. Combine it with the docker-execution rules to correlate: was this docker exec an authorized deployment or a compromise?
Making Audit Rules Persistent
Runtime rules with auditctl do not survive a reboot. For persistence, write rule files to /etc/audit/rules.d/ and load them with augenrules:
|
|
Repeat for Proxmox, system paths, and syscall rules:
|
|
|
|
|
|
Load and verify:
|
|
Querying Audit Logs with ausearch and aureport
Once rules are active and events are flowing, the real value comes from querying the log. These commands are your daily audit interface.
Search by Rule Key
|
|
Generate Summary Reports
|
|
Watch Live Events
|
|
JSON Output for Log Aggregation
|
|
This is directly ingestible by Loki, Elasticsearch, or any JSON log pipeline. If you run the Grafana Loki stack in your homelab, pipe auditd events there for dashboards.
Integrating auditd with systemd-journald
auditd events appear in systemd-journald via the audispd syslog plugin. Enable it:
|
|
View audit events in journald:
|
|
For structured log aggregation, set up the audisp-remote plugin to forward to a central syslog server or use the built-in syslog forwarding in /etc/audit/audisp-remote.conf:
remote_server = 10.0.20.50
port = 601
transport = tcp
Docker-Specific Auditing: Containers and the Docker Socket
auditd complements Docker’s built-in event system. Docker events tell you containers started and stopped; auditd tells you who executed the docker command and which user on the host triggered it.
Watch the Docker socket for API access:
|
|
This catches any process reading from or writing to the Docker socket — useful for detecting unauthorized containers or tooling that accesses Docker without going through the CLI.
To catch docker exec and docker attach sessions, the execve syscall rule combined with the docker binary watch gives you the full picture: which user ran docker exec -it nginx sh and at what time.
|
|
Preventing Audit Log Tampering
Audit logs are only useful if they survive an attack. Once all rules are loaded, lock the audit configuration so that no one — including root — can disable or modify rules without a reboot:
|
|
Set this as the last rule in one of your rule files to apply it automatically:
|
|
After this, auditctl -e 0 returns permission denied. Only a reboot clears it, and during boot the rules reload before network services start.
For additional protection, forward logs off-host. The audisp-remote plugin sends events to a central syslog or a dedicated logging VM. Set it up:
|
|
On the remote server, run a syslog listener:
|
|
Storage Management and Log Rotation
auditd logs to /var/log/audit/audit.log by default. With active rules on a busy homelab host, expect 10-50 MB per day depending on workload. Set adequate limits:
# /etc/audit/auditd.conf
max_log_file = 128
max_log_file_action = rotate
num_logs = 5
This keeps 5 rotated files of 128 MB each — roughly 640 MB of history. Adjust based on your storage budget. If you forward to remote logging, you can reduce it further.
The system logrotate configuration at /etc/logrotate.d/auditd handles rotation via signal. Verify it exists and reload if needed:
|
|
Verification and Testing
After deploying, run a quick smoke test:
|
|
Expected output from auditctl -s shows enabled 1, pid of the running daemon, rate_limit (default 0 = unlimited), and backlog_limit (default 64).
Conclusion
auditd is one of the most underused security tools in homelabs. It ships with every Linux kernel, costs almost nothing in overhead, and produces forensic-grade logs of everything happening on your host. With the rules in this guide, you cover Docker execution, Proxmox VM management, critical file changes, and system-call-level process monitoring — all with a one-time setup.
Once auditd is running, it works silently in the background. The logs accumulate in /var/log/audit/audit.log, ready to answer the question no homelab owner wants to face: What happened, when, and who did it?
Deploy auditd alongside CrowdSec or Fail2ban for a complete host security posture. Set up remote log forwarding if you have a second host. Configure it once, and forget about it — until the day you need it.