Your first hands-on practice with AppArmor: reading full status with aa-status and checking readiness with aa-enabled, understanding the list of active profiles, switching between enforce and complain modes, and loading and unloading profiles with apparmor_parser, including their persistence across reboots.

In episode 2 we built the foundation: the profile concept, enforce vs complain modes, and the kernel LSM architecture alongside the userspace. Now it's time for the first hands-on practice — touching AppArmor directly. In this episode we'll master three core abilities that gate every following episode: reading status, switching modes, and loading/unloading profiles.
Imagine you're a building's security operator. Before installing new rules, you need to know: how many occupants are already covered? Who is still left free? And how do you activate or revoke the rule for one occupant without disturbing the others? That's exactly the job we're learning now.
The first tool you must master is aa-status — your main window into AppArmor's runtime state. In episode 0 we saw its output briefly; now let's dissect every part:
sudo aa-statusapparmor module is loaded.
51 profiles are loaded.
49 profiles are in enforce mode.
2 profiles are in complain mode.
24 processes have profiles defined.
24 processes are in enforce mode.
0 profiles are in profile mode.
...
51 profiles are loaded:
/sbin/dhclient
/snap/snapd/current/usr/lib/snapd/snap-confine
/usr/bin/firefox
/usr/sbin/nginx
...Three key pieces of information from this output:
apparmor module is loaded — the kernel has loaded the AppArmor LSM. If this line is missing, AppArmor isn't active at all.On some systems, apparmor_status is an alias for aa-status — the two are identical. Use whichever is available on your system.
Before working, get into the habit of checking whether AppArmor is active in the kernel — especially after a reboot or when working on a system you don't know:
aa-enabledAn output of Yes means it's active; exit code 0 says the same — useful in scripts. If the output is No, check whether the kernel was booted with the apparmor=0 parameter or whether another LSM (e.g. SELinux) has taken over. This is the first troubleshooting step that often saves you.
From episode 2 you know the two profile working modes. Now let's learn to switch them directly. Two tools that work as a pair:
sudo aa-complain /usr/sbin/nginxsudo aa-enforce /usr/sbin/nginxBoth commands are really just wrappers that call apparmor_parser with the appropriate mode option. Notice the flow:
| Command | Parser option | Effect |
|---|---|---|
aa-complain <profile> | --complain | Denials are logged but not blocked |
aa-enforce <profile> | --enforce | Denials are logged and blocked |
A production example: you receive a new profile from a team. Run it in complain for a day or two, watch the logs, then promote it to enforce once you're confident. To see which profiles are in complain, aa-status lists them separately in the lower part of its output.
apparmor_parser is the most fundamental tool — every other command around it ultimately calls it. Its four core operations:
| Operation | Command | Meaning |
|---|---|---|
| Load (add) | apparmor_parser -a <file> | Load a new profile into the kernel |
| Reload | apparmor_parser -r <file> | Reload an existing profile |
| Remove (unload) | apparmor_parser -R <file> | Remove a profile from the kernel |
| Verify | apparmor_parser -Q <file> | Check profile validity without loading it |
A complete load workflow example:
sudo apparmor_parser -Q /etc/apparmor.d/nginx
sudo apparmor_parser -a /etc/apparmor.d/nginx
sudo aa-status | grep nginxThe first line validates the profile syntax without loading it — always do this before loading to avoid errors. The second line loads it into the kernel. The third confirms the nginx profile is registered. To unload a profile:
sudo apparmor_parser -R /etc/apparmor.d/nginxAfter -R, the profile disappears from the aa-status list and the nginx process is no longer confined. Unloading is often used while debugging: to confirm a denial comes from AppArmor, unload the profile and try again — if the application works normally, the profile is the problem, not the application.
It's important to understand the second layer of the profile file system: apparmor_parser -R only removes the profile from the kernel — it doesn't delete the profile file in /etc/apparmor.d/. As a result, the same profile will be loaded again at the next boot.
The boot flow looks like this:
systemd memulai service apparmor
│
▼
service memuat profil dari /etc/apparmor.d/
│
▼
apparmor_parser mengkompilasi dan memuat ke kernelThat means there are two different decisions you must understand:
apparmor_parser -a/-R directly./etc/apparmor.d/.Most production cases involve both: change the profile file, then reload with -r so the change takes effect without a reboot. You'll keep using this habit in episodes 4 and 5.
Important
Be careful with apparmor_parser -R on systems that depend on a profile. Removing the docker-default profile, for example, will make every running Docker container lose its AppArmor confinement. Always know which profile you're removing and what the impact is.
sudo. apparmor_parser, aa-status, and all modification tools need root privileges. Without sudo, the commands fail with permission denied.-R but thinking it's permanent. -R only removes from the kernel; the profile in /etc/apparmor.d/ will be loaded again at boot. For permanence, delete the profile file.-Q. Validate first with -Q to catch syntax typos — if the profile is broken, the load fails and the application runs unprotected.aa-status output. The "profiles in complain mode" list is a signal that some profiles aren't yet ready for enforce. Check routinely so no profile is silently only logging.In episode 3 we mastered three core abilities: reading status with aa-status and checking readiness with aa-enabled; switching profile modes with aa-complain and aa-enforce; and loading, unloading, and validating profiles with apparmor_parser, along with understanding persistence across reboots.
The core takeaways:
aa-status is your main window into AppArmor's runtime state; aa-enabled checks kernel readiness.aa-complain switches a profile to complain (logs without blocking); aa-enforce switches it back.apparmor_parser has four operations: -a load, -r reload, -R remove, -Q verify.-R only removes from the kernel; profiles in /etc/apparmor.d/ are reloaded at boot.-Q first, then load — validate before you execute.In episode 4, we enter the most creative part: writing basic profiles — learning the profile <name> { ... } syntax, the r w m k file rules, path globbing, deny rules, and the use of includes and abstractions. Keep your momentum, because starting with this episode you stop being a user and start being a policy author!