Linux Security·8 min read·

AppArmor vs SELinux: Mandatory Access Control Explained

Understand how AppArmor and SELinux confine processes under mandatory access control and choose the MAC layer that fits your distro and density.

NB

Netbay Cloud Team

Netbay Engineering

On this page

A firewall blocks packets at the network edge, but it cannot stop a compromised web worker from reading the private key file sitting next to your application. That is the job of mandatory access control, or MAC. On modern Linux that means AppArmor or SELinux — kernel mechanisms that confine what a process may access even if the process itself is malicious. This guide explains how each works, how they differ, and how to decide which one to rely on for your workload.

Two MAC engines, same kernel goal AppArmor path-based profiles per-executable policy Ubuntu/Debian default lower audit overhead easier to reason about SELinux label-based rules subject + object contexts RHEL family default finer-grained control heavier learning curve Both enforce policy at the kernel; they differ in how policy is attached to programs

The Case for MAC in the First Place

Everything up to now — file permissions, sudo, firewalls — is discretionary access control. If your nginx worker runs as www-data and owns its own files, nothing but convention stops a directory traversal from reading anything the worker user can read, which on a badly configured box is often far too much. MAC adds a mandatory layer: even the owner of a file cannot reach it if the kernel policy says the executing program is not allowed to. A compromised service is the common scenario, and MAC is the only local control that contains it consistently.

AppArmor: Confine by Program, by Path

AppArmor takes a pragmatic view: policy is attached to a program's path, and rules describe what files and capabilities that program may touch. Ubuntu ships with AppArmor enabled and a set of default profiles for common daemons, so you get baseline confinement out of the box. Administrators extend it by writing a profile that lists the executable path and the allowed read/write/file patterns.

bash
sudo aa-enabled
sudo aa-status --complaining
sudo apparmor_parser -r /etc/apparmor.d/usr.sbin.nginx

The strength of AppArmor is readability: a profile reads almost like a plain-English wish list, and the parser accepts new rules on the fly, which makes iterative hardening easy. Its model is coarse compared with SELinux — it names files and paths rather than labeling every process and object — but for a single-purpose web or database server that granularity is usually more than enough. It also has a permissive complaining mode that logs violations without enforcing, letting you build a profile from real traffic instead of guessing.

SELinux: Enforce by Label

SELinux inverts the model. It labels every process and every file with a security context — a user, role, type, and sensitivity — and decides access by comparing the type of the subject with the type of the object in a centralized policy. There are no path rules to eyeball; instead, a labeled nginx_t process is allowed exactly what the policy grants to nginx_t. Everything, including files, carries a label, and a file whose label is wrong is inaccessible even at the correct path.

bash
sudo getenforce
ls -Z /usr/sbin/sshd
sudo setenforce 0
sudo restorecon -Rv /etc/nginx
sudo sealert -l "*" | grep -i denied

SELinux ships enforcing on by default on RHEL-family systems, and its audit log is remarkably precise: a denial message names the denied operation, the offending type, and the suggested fix. The cost is that precise. Operators must learn the type model, and a mislabeled file during a deploy produces confusing "permission denied" errors that have nothing to do with Unix permissions. The sealert tool translates those opaque denials into human guidance, and restorecon repairs labels that a naive file copy wrecked.

Choosing for Your Distro and Workload

Your distro largely decides this for you: Ubuntu and Debian default to AppArmor, while Rocky, Alma, and Fedora default to SELinux. Fighting the default is possible but almost never worth it — the ecosystem, the packaging hooks, and the domain sockets of shared services are all wired for whichever engine your platform ships. If you are on a stock Ubuntu VPS, AppArmor protects you with almost no effort; if you are on Rocky, SELinux is doing the same job with more precision and more setup cost.

For container-heavy and multi-tenant hosts, the decision matters more. SELinux's label model scales cleanly to thousands of workloads because policy lives in a global type database rather than per-package paths. AppArmor's per-executable profiles are simpler for a handful of long-running daemons. Match the abstraction to your density: few, stable services favor AppArmor; many ephemeral workloads favor SELinux.

Work in Permissive or Complaining Mode Before Enforcing

The biggest practical failure with either system is flipping it from permissive to enforcing before real traffic has exercised the stack. AppArmor's complaining mode and SELinux's permissive mode log every would-be denial without stopping anything. Run your load test, watch the audit feed, correct your profiles or labels, and only then enforce.

bash
sudo aa-complain /etc/apparmor.d/usr.sbin.nginx   # AppArmor log-only
sudo setenforce 0                                  # SELinux log-only

Either way, the sequence is the same: measure what your software really does, encode that into policy, verify nothing legitimate is denied, then let the kernel enforce it. That loop is what separates a MAC setup that protects you from a flag you turned on and forgot.

Takeaway

AppArmor and SELinux differ in how they attach policy — per program path versus per label — but both deliver the same crucial property: a compromised process is confined to its intended footprint. Use the engine your distro ships, lean on the permissive modes to build accurate policy from real traffic, and enforce only when the audit is clean. Netbay's Ubuntu and Rocky VPS plans come from the Lucknow DC01 datacenter ready to have MAC confinement enabled from day one — netbayhosts.in.

Keep reading

Follow along on a real VPS

Deploy Linux in under 60 seconds

These guides are written against Ubuntu, Debian, and RHEL-family images — the same ones on NetBay.

Deploy an instance