AppArmor vs SELinux: Which One Should Actually Be Running on Your Machine
Two security systems, one job. Here's which one your distro already picked for you — and what to do if it picked neither.
Every Linux distro you’ve ever installed has been quietly running a security system in the background that you’ve probably never touched. On Ubuntu, it’s AppArmor. On Fedora, it’s SELinux. Most people never think about either one until something gets denied and a service mysteriously refuses to start.
That’s usually the first time anyone learns these tools exist. This post covers what they actually do, how they’re different, what happens on distros that ship with neither, and whether you should bother installing one yourself.
The Problem They’re Both Solving
Regular Linux permissions — the rwx bits you already know — are Discretionary Access Control (DAC). “Discretionary” because the owner of a file decides who can touch it. If your user account owns a file, you can chmod it wide open, and nothing stops you.
The problem is that any process running as you inherits your discretion. If a compromised PDF viewer is running under your user account, it can read your SSH keys, your browser cookies, your entire home directory — because DAC has no concept of “this program should only ever touch PDF files.”
That’s the gap AppArmor and SELinux both fill. They’re Mandatory Access Control (MAC) systems: a policy defined outside the app decides what each program is allowed to do, regardless of what the user running it is otherwise permitted to do. Even if an attacker gets code execution inside your PDF viewer, a MAC policy can say “this process may never open a network socket or read outside ~/Documents” — full stop, no discretion involved.
Both are implemented as Linux Security Modules (LSM), a kernel framework that lets a security system hook into every file open, socket creation, and process action. Only one LSM can be the primary enforcement engine at a time, which is why AppArmor and SELinux are mutually exclusive on a running system — you don’t run both.
💡 Why This Matters: Without a MAC layer, “compromise one app, own the whole user account” is the default outcome of most exploits. MAC is what turns a single-app compromise into a contained incident instead of a full account takeover.
AppArmor: Path-Based and Application-Centric
AppArmor profiles describe a program in terms of file paths and capabilities: “the executable at /usr/sbin/nginx may read /etc/nginx/, may write to /var/log/nginx/, may bind to network sockets, and nothing else.” Profiles live as plain text files in /etc/apparmor.d/, named after the binary path they confine, which makes them genuinely readable without training.
It’s an application-centric model — you write policy from the perspective of “what does this one program need,” not the perspective of the whole system’s object graph. That’s what makes it approachable: you can look at a profile and immediately understand what it constrains.
AppArmor ships enabled by default on Ubuntu, Debian, and openSUSE. Managing it day-to-day looks like this:
# Check overall status and which profiles are loaded
sudo aa-status
# Put a profile in "complain" mode — logs violations but doesn't block them,
# useful while you're tuning a new profile
sudo aa-complain /usr/sbin/nginx
# Switch it back to full enforcement
sudo aa-enforce /usr/sbin/nginx💡 Quick Check: After
sudo aa-status, look at the counts under “profiles are in enforce mode” vs “complain mode.” If everything you care about (browser, SSH, common daemons) shows up in enforce mode, AppArmor is actively protecting you, not just logging.
SELinux: Label-Based and System-Centric
SELinux takes a fundamentally different approach. Instead of tracking file paths, it attaches a security context (a label, like httpd_sys_content_t) to every file, process, port, and object on the system, stored as an extended attribute. Policy is then written in terms of which labels are allowed to interact with which other labels — “processes labeled httpd_t may read files labeled httpd_sys_content_t” — independent of where those files physically live.
This is the source of both its power and its reputation. Because policy is decoupled from paths, SELinux can enforce constraints across the entire system consistently, including edge cases path-based systems miss — SELinux currently implements roughly 217 LSM hooks versus AppArmor’s 80, giving it more complete coverage of kernel-level mediation. It’s also why SELinux is the stronger choice for multi-tenant and container isolation: SELinux separates containers from each other and from the host filesystem by default, something AppArmor’s default policy doesn’t provide since it lacks the multi-category security (MCS) labeling SELinux relies on for that separation.
The tradeoff is real complexity. Because labels are metadata attached to the filesystem itself (via extended attributes), moving or creating files in unexpected ways can leave them mislabeled — the single most common cause of “SELinux broke my app” reports.
SELinux ships enabled by default on Fedora, RHEL, CentOS Stream, Rocky, and AlmaLinux. The core commands:
# Current enforcement mode: Enforcing, Permissive, or Disabled
getenforce
# Full status including the loaded policy type
sestatus
# Temporarily relax to Permissive (logs, doesn't block) without a reboot
sudo setenforce 0
# Restore a file's expected label after moving/creating it out of place
sudo restorecon -Rv /path/to/file⚠️ Important Exception:
setenforce 0only survives until reboot and only affects runtime enforcement — it doesn’t touch the persistent setting in/etc/selinux/config. If you’re debugging a denial, that’s fine. If you actually want SELinux off long-term, you need to edit the config file and expect a relabel on next boot, which is slow on large filesystems.
Head-to-Head Comparison
| AppArmor | SELinux | |
|---|---|---|
| Model | Path-based, application-centric | Label-based, system-centric |
| Policy syntax | Plain-text profiles, one per app | Type Enforcement + labels, more abstract |
| Learning curve | Shallow — readable without training | Steep — requires understanding contexts/labels |
| Default on | Ubuntu, Debian, openSUSE, SUSE | Fedora, RHEL, CentOS Stream, Rocky, AlmaLinux |
| Kernel mediation coverage | ~80 LSM hooks (Linux v6.19) | ~217 LSM hooks (Linux v6.19) |
| Container/multi-tenant isolation | Weaker — no built-in separation between containers | Stronger — separates containers from each other and the host by default |
| Common failure mode | Missing a path in a profile | Mislabeled files after moves/creates |
| Best fit | Desktops, single-purpose servers, fast setup | Enterprise, multi-tenant hosts, compliance-driven environments |
💡 Why This Works: The path-vs-label distinction explains almost every practical difference in the table above. A path-based system has to know where things are; a label-based one only has to know what things are. That’s why SELinux survives file moves and renames gracefully where a naive AppArmor profile might not, and it’s also why SELinux needs the extra bookkeeping (labels, relabeling) that makes it harder to manage.
What If Your Distro Ships With Neither?
This is where it gets less talked about. Plenty of distributions — Arch Linux chief among them — don’t enable, or even ship, either system by default. Arch’s philosophy leans toward “give the user full control and don’t decide for them,” so a fresh Arch install runs on DAC alone unless you deliberately add a MAC layer.
The good news: you’re not stuck. Both are available, though not equally supported.
AppArmor on Arch is fully supported in the official kernel and just needs to be turned on:
# Install the userspace tools
sudo pacman -S apparmor
# Enable the systemd service so profiles load at boot
sudo systemctl enable --now apparmor
# Tell the kernel to actually use it — edit your bootloader config
# (e.g. /etc/default/grub) and add to GRUB_CMDLINE_LINUX_DEFAULT:
# lsm=lockdown,yama,apparmor,bpf
sudo grub-mkconfig -o /boot/grub/grub.cfgThe lsm= kernel parameter controls the initialization order of security modules, and AppArmor needs to appear as the first “major” module in that list for it to actually enforce anything — installing the package alone isn’t enough; the kernel parameter is what flips it on.
SELinux on Arch is a much rougher path. It isn’t officially supported by the Arch project, and installing it means pulling packages from an unofficial community repository, some of which aren’t cryptographically signed. Realistically, if you want SELinux, running Fedora or a RHEL-family distro where it’s a first-class citizen is a far better use of your time than fighting it onto Arch.
Distros like Alpine, Void, and Gentoo are similar cases: the kernel typically supports both LSMs, but neither is preconfigured, and the amount of manual setup varies. Gentoo actually documents both paths well since its whole model is “you configure everything anyway.”
⚠️ Important Exception: on distros with neither MAC system enabled, checking
sudo aa-statusorgetenforcewon’t give you a helpful error — the commands may not exist at all, or will report the module isn’t loaded. Don’t assume “no output” means “it’s off but available.” Check withcat /sys/kernel/security/lsmfirst to see what your kernel actually has compiled in and active.
Should You Bother Installing One?
If your distro already ships with AppArmor or SELinux enabled — leave it on. Every credible guide agrees on this: for the vast majority of Ubuntu users, sticking with the AppArmor that’s already there and well-documented is the right call, since it’s well-integrated and provides substantial security improvement over running with no MAC system at all. The same logic holds in reverse for Fedora/RHEL users and SELinux — don’t disable it “because it’s annoying” without understanding what you’re giving up.
If you’re on a distro like Arch that ships with neither, whether it’s worth installing one depends on what the machine actually does:
- A personal desktop or laptop, mostly browsing and local apps — AppArmor is worth the modest setup cost. It’s low overhead, and profiles for common browsers and daemons are often available in your distro’s repos already.
- A server exposed to the internet (web app, SSH-reachable box, anything multi-user) — this is where a MAC layer earns its keep the most, since it’s specifically designed to contain what a compromised network-facing service can do. If you’re running a server and need serious security, SELinux is worth the extra complexity; for desktops and workstations, AppArmor is the more practical choice.
- A single-user throwaway VM or sandbox — honestly, may not be worth the setup time. MAC systems shine when there’s something worth protecting from a compromised process; a disposable environment has less at stake.
💡 Why This Matters: The core argument for installing one isn’t “SELinux/AppArmor stops attackers from getting in” — it doesn’t, that’s not its job. It’s damage containment. Every serious security model assumes something, somewhere, eventually gets compromised. MAC is what decides whether that compromise stays inside one sandboxed process or spreads to your entire user account.
The Bottom Line
Don’t switch away from whatever your distro already gives you — that’s the version with the best tooling, documentation, and community support for your setup. If you’re on something minimal like Arch, AppArmor is the pragmatic default: officially supported, genuinely simple to reason about, and enough to meaningfully raise the bar for a desktop or lightweight server. Reach for SELinux specifically when you need multi-tenant isolation or compliance requirements — and at that point, you’re usually better off just running it on a distro built around it rather than bolting it onto one that isn’t.