How to Configure AppArmor on Ubuntu
AppArmor is a mandatory access control framework for Linux that restricts programs to a limited set of resources. On Ubuntu-based Breeze instances, AppArmor comes pre-installed and provides application-level security confinement using profiles that define exactly what each program can access.
Checking AppArmor Status
Verify that AppArmor is running on your Breeze instance:
sudo aa-status
sudo systemctl status apparmor
The output shows profiles in enforce mode (blocking violations), complain mode (logging only), and unconfined processes.
Understanding Profile Modes
- Enforce — violations are blocked and logged; the application cannot exceed its allowed permissions
- Complain — violations are logged but not blocked; useful for developing and testing profiles
- Disabled — the profile is not loaded at all
# Set a profile to complain mode
sudo aa-complain /etc/apparmor.d/usr.sbin.nginx
# Set a profile to enforce mode
sudo aa-enforce /etc/apparmor.d/usr.sbin.nginx
# Disable a profile
sudo ln -s /etc/apparmor.d/usr.sbin.nginx /etc/apparmor.d/disable/
sudo apparmor_parser -R /etc/apparmor.d/usr.sbin.nginx
Installing Profile Utilities
sudo apt install -y apparmor-utils apparmor-profiles apparmor-profiles-extra
The apparmor-profiles-extra package provides additional pre-built profiles for common applications.
Creating a Custom Profile
Use aa-genprof to generate a profile interactively. For example, creating a profile for a custom application:
sudo aa-genprof /usr/local/bin/myapp
In another terminal, exercise the application through its normal operations. Then return to the profiling terminal and press S to scan for events, choosing allow or deny for each access request.
Profile Syntax
Profiles are stored in /etc/apparmor.d/. A basic profile looks like:
# /etc/apparmor.d/usr.local.bin.myapp
/usr/local/bin/myapp {
# Include base abstractions
#include <abstractions/base>
#include <abstractions/nameservice>
# Allow reading configuration
/etc/myapp/** r,
/etc/myapp/config.yml r,
# Allow writing logs
/var/log/myapp/ rw,
/var/log/myapp/** rw,
# Allow reading shared libraries
/usr/lib/** mr,
# Network access
network inet stream,
network inet dgram,
# Deny everything else by default
deny /etc/shadow r,
deny /etc/passwd w,
}
Reloading Profiles
After modifying a profile, reload it:
sudo apparmor_parser -r /etc/apparmor.d/usr.local.bin.myapp
To reload all profiles:
sudo systemctl reload apparmor
Troubleshooting Denials
When AppArmor blocks an operation, it logs the denial:
# View AppArmor denials
sudo dmesg | grep "apparmor=\"DENIED\""
# Or use the journal
sudo journalctl -k | grep "apparmor"
# Use aa-logprof to update the profile based on logged denials
sudo aa-logprof
Confining Common Services
Key services to confine on your Breeze instance:
- Nginx/Apache — restrict web server file access to document roots only
- MySQL/MariaDB — limit database access to data directories and sockets
- PHP-FPM — confine PHP processes to prevent arbitrary file access
- Postfix/Sendmail — restrict mail services to mail-related files
Best Practices
- Start in complain mode — develop profiles by logging violations before enforcing
- Use abstractions — leverage built-in abstraction files for common access patterns
- Test thoroughly — exercise all application functionality while profiling
- Keep profiles minimal — grant only the permissions each application truly needs
- Version control profiles — track profile changes in git for auditability
AppArmor is a powerful tool for limiting the blast radius of a compromised application on your Breeze instance, ensuring that even exploited services cannot access unauthorized resources.