Ubuntu AppArmor: How to Inspect, Override, and Verify Mandatory Access Control for System Services
Ubuntu enables AppArmor by default. This guide explains how the kernel loads profiles at boot, how to add local overrides safely, and how to verify enforcement with aa-status and journalctl. Avoid common pitfalls and keep your system secure.
21 May 2026, 11:13 UTC

Why AppArmor Matters on Ubuntu
Ubuntu enables AppArmor by default. It is a kernel‑level mandatory access control (MAC) system that confines each process to a policy describing which files it may read, write, or execute, which network sockets it may open, and which capabilities it may use. Even if an attacker compromises a process, the policy limits the damage that can be done.
How Profiles Are Loaded at Boot
The apparmor.service unit runs apparmor_parser during system initialization. The parser reads all profiles from two locations:
/etc/apparmor.d– vendor‑provided profiles for packages installed viaapt./var/lib/snapd/apparmor– auto‑generated profiles for snaps.
The parser loads each profile into the kernel, setting it to either enforce or complain mode. Enforced profiles actively block unauthorized actions; complain profiles only log violations.
Inspecting Current Enforcement
Use aa-status to see which profiles are active and which processes they confine:
sudo aa-status
Typical output lists enforce profiles such as /usr.sbin.nginx and /usr.sbin.cupsd. If a profile is missing or in complain mode, you may need to re‑enable it or adjust your configuration.
Adding a Local Override Without Editing Vendor Profiles
Editing a profile in /etc/apparmor.d is discouraged because package upgrades overwrite your changes. Instead, create a file in /etc/apparmor.d/local that contains only the rules you want to add or modify.
Example: give nginx read access to a custom configuration directory /srv/custom/nginx.conf.
sudo nano /etc/apparmor.d/local/nginx
Add the following line:
/srv/custom/** r,
After saving, reload the profile:
sudo apparmor_parser -r /etc/apparmor.d/usr.sbin.nginx
The -r flag tells the parser to replace the existing profile with the updated one. Verify that the change is in effect by checking the audit log after triggering the access.
Verifying the Override
- Trigger the action that requires the new permission (e.g., restart
nginxafter adding a file to/srv/custom). - Check the kernel audit log for
DENIEDentries: - If you see no
DENIEDlines, the rule is active. If you see a denial, adjust the path or rule syntax.
journalctl -k | grep DENIED | grep nginx
Common Mistakes and How to Avoid Them
- Editing the vendor profile directly – upgrades overwrite changes. Use
/etc/apparmor.d/localinstead. - Forgetting to reload the profile – restarting the service does not reload AppArmor. Always run
apparmor_parser -rafter editing. - Setting the entire system to complain mode – this disables enforcement and defeats the purpose of MAC.
- Assuming path changes are harmless – AppArmor is path‑based. Moving a file into a new directory requires updating the profile.
- Editing snap profiles – snapd regenerates them on
snap refresh, so manual edits are lost.
Limitations of AppArmor on Ubuntu
- Path‑based matching can be fragile when using bind mounts or hard links.
- Snap profiles are regenerated on
snap refresh, so manual edits are lost. - Only processes that explicitly request a profile are confined; some legacy daemons may bypass AppArmor if not linked properly.
- Fine‑grained identity‑based controls (e.g., user‑specific policies) are not supported.
Practical Checklist Before Deploying a Custom Profile
- Confirm
apparmor.serviceis active:systemctl is‑active apparmor. - List current profiles:
sudo aa-status. - Add local overrides in
/etc/apparmor.d/local. - Reload the affected profile with
apparmor_parser -r. - Trigger the action and inspect
journalctl -kfor DENIED logs. - If no denials, run
sudo aa-complain /path/to/profileonly for testing, then revert to enforce. - Document the change in your configuration management system.
Conclusion
Ubuntu’s AppArmor provides robust, kernel‑level confinement for system services. By understanding how profiles are loaded, using local overrides, and verifying enforcement, you can extend security without compromising system stability. Avoid common pitfalls, respect the path‑based nature of policies, and keep your overrides version‑controlled for repeatable deployments.
0 replies
A thoughtful contribution can make all the difference. Be the first to share one.