
apparmor traps a compromised app inside its own permissions
aa-status
aa-enforce /etc/apparmor.d/usr.sbin.nginxthe problem with "one exploit, whole box"
here's the uncomfortable truth about running any internet-facing service: nginx, apache, your homelab's plex server, whatever. if there's a bug in it, and someone finds it, the default assumption on most linux boxes is that the attacker now has whatever permissions that process had. and by default, that's usually way more than it needs. it can read your ssh keys, poke around in /etc, write to places it has no business writing to. one vulnerable app becomes a fully compromised server.
apparmor exists to make that assumption wrong.
what apparmor actually does
apparmor is a linux kernel security module that puts a program in a box. not a metaphorical box, an actual enforced set of rules that says "this binary can read these files, write to these directories, and use these capabilities, and nothing else." if the program tries to step outside that box, the kernel says no, regardless of what the process itself thinks it's allowed to do.
the key idea is this: apparmor doesn't trust the application. it doesn't care if the app got exploited, tricked, or is running malicious injected code. the confinement is enforced at the kernel level, so even a fully hijacked process is still stuck inside its profile.
checking what's actually confined on your system
start here:
aa-status
this command shows you every apparmor profile currently loaded, and whether it's in enforce mode (actively blocking violations) or complain mode (just logging them, not blocking). a lot of default installs ship with useful profiles sitting in complain mode, which is basically a security camera with no lock on the door. it's watching, but it's not stopping anything.
run aa-status right now on your own server. you might be surprised how many profiles are loaded but not actually enforcing anything.
turning on real enforcement
once you know a profile exists for something you're running, like nginx, you flip it into enforce mode with:
aa-enforce /etc/apparmor.d/usr.sbin.nginx
breaking that down: aa-enforce is the tool that switches a profile's mode, and the path after it points to the actual profile file, which lives in /etc/apparmor.d/ and is named after the binary it confines. from this point forward, nginx can only do what that profile explicitly allows. no reading /root/.ssh, no writing to /usr/bin, no wandering into parts of the filesystem it has no legitimate reason to touch.
if nginx gets popped through some remote code execution bug, the attacker isn't suddenly "on your server." they're stuck inside nginx's tiny permission bubble. they can't pivot to your ssh keys, your other services, or your system binaries, because the kernel itself is refusing those requests on nginx's behalf, exploit or not.
why this matters more than patching alone
patching is reactive. you find out about a vulnerability, you update, you hope you were fast enough. apparmor is proactive, it assumes something will eventually go wrong with one of your services and limits the blast radius before that ever happens. this is the same logic behind not giving every employee admin access "just in case." least privilege isn't about distrust, it's about damage control.
a lot of distros already ship apparmor profiles for common services like nginx, ssh, and docker, they're just sitting unused or in complain mode. checking and enforcing them takes minutes and costs you nothing in normal operation, since a properly working service never needed those extra permissions anyway.
the takeaway
run aa-status on every box you manage today and see what's actually enforcing versus just watching. for anything internet-facing, especially web servers, ssh daemons, and containers, get their profiles into enforce mode with aa-enforce. it won't stop someone from finding a bug in your software, but it turns "they own your server" into "they're stuck in a room with no doors." that difference is the entire point of defense in depth, and it costs you a command, not a rewrite.