Set Up AppArmor Application Security on VPS

Set Up AppArmor Application Security on VPS

June 2026 · 7 min read

AppArmor (Application Armor) is a Linux Security Module enabled by default on Ubuntu that restricts what each program can access — files, network resources, and system capabilities. If Nginx or PHP-FPM is exploited, AppArmor confines the attacker to a defined sandbox, preventing lateral movement and significantly reducing damage.

Check Current AppArmor Status

# Check if AppArmor is enabled
sudo systemctl status apparmor

# View all active profiles
sudo apparmor_status

# View profile mode (enforce/complain)
sudo aa-status | grep -E "(enforce|complain)"

Install AppArmor Tools

sudo apt update
sudo apt install apparmor apparmor-utils apparmor-profiles apparmor-profiles-extra -y

# Enable AppArmor
sudo systemctl enable --now apparmor

Review Existing Profiles

# List all profiles in the system
ls /etc/apparmor.d/

# Key profiles Ubuntu ships with:
# usr.sbin.nginx - Nginx web server
# usr.bin.man - man page viewer
# usr.lib.snapd.snap-confine - Snap packages

# View profile details
cat /etc/apparmor.d/usr.sbin.nginx

Enable Existing Profiles

# Set profile to enforce mode
sudo aa-enforce /etc/apparmor.d/usr.sbin.nginx

# Enable multiple profiles at once
sudo aa-enforce /etc/apparmor.d/usr.sbin.*

# Enable complain mode (logs but doesn't block) for testing first
sudo aa-complain /etc/apparmor.d/usr.sbin.nginx

Create a New Profile for an Application

# Use aa-genprof to auto-generate a profile
sudo aa-genprof /usr/bin/myapp
# Run the application during this time, then press S to scan events

# Or create manually
sudo nano /etc/apparmor.d/usr.bin.myapp
#include <tunables/global>

/usr/bin/myapp {
    #include <abstractions/base>
    #include <abstractions/nameservice>

    # Read-only
    /etc/myapp/config.conf r,
    /var/log/myapp/ r,

    # Read-write
    /var/log/myapp/*.log rw,
    /tmp/myapp/ rw,

    # Network
    network inet tcp,
    network inet udp,

    # Deny access to sensitive files
    deny /etc/shadow r,
    deny /root/** rw,
}
sudo apparmor_parser -r /etc/apparmor.d/usr.bin.myapp
sudo aa-enforce /etc/apparmor.d/usr.bin.myapp
Tip: Always start in complain mode first. Run your application for 1-2 days, then check /var/log/syslog for any legitimate AppArmor denials before switching to enforce mode.

Verify AppArmor is Working Correctly

# View status of all profiles
sudo apparmor_status

# View AppArmor denials in syslog
sudo grep "apparmor" /var/log/syslog | tail -20

# Check audit log
sudo ausearch -m avc | tail -20

# Check which profiles are in enforce mode
sudo aa-status | grep "profiles are in enforce mode"
Tip: If you see apparmor="DENIED" in syslog, AppArmor blocked an operation. When an application malfunctions after enabling enforce mode, always check this log first.

Common Issues & Troubleshooting

Application stops working after enabling AppArmor enforce

AppArmor is blocking an operation the application requires. Switch to complain mode first, then review logs:

sudo aa-complain /etc/apparmor.d/usr.sbin.nginx
sudo systemctl restart nginx
sudo grep "apparmor.*ALLOWED" /var/log/syslog | grep nginx
# Add the missing rules to the profile, then switch back to enforce

Profile fails to load (syntax error)

Check syntax using apparmor_parser:

sudo apparmor_parser -p /etc/apparmor.d/usr.bin.myapp
# Will display error and line number
# Fix and reload
sudo apparmor_parser -r /etc/apparmor.d/usr.bin.myapp

AppArmor doesn't block even though profile is in enforce mode

Verify the profile is actually loaded:

sudo aa-status | grep myapp
# Should show myapp under "profiles are in enforce mode"
# If not visible, reload:
sudo systemctl reload apparmor

Docker container won't run with AppArmor

Docker uses a default profile called docker-default. For containers requiring special capabilities:

# Run container with custom profile
docker run --security-opt apparmor=docker-default myapp
# Or disable AppArmor for this container (not recommended)
docker run --security-opt apparmor=unconfined myapp

Frequently Asked Questions

How does AppArmor differ from SELinux?

AppArmor uses path-based policies and is easier to configure than SELinux, which uses label-based policies. AppArmor is the default on Ubuntu/Debian, while SELinux is standard on RHEL/CentOS. Both provide Mandatory Access Control (MAC) but AppArmor is better suited for VPS administrators who want security without learning complex labeling systems.

Does AppArmor impact performance?

Impact is minimal, typically 2-3% overhead, because the kernel checks cached policies in memory rather than reading from disk each time. I/O-heavy applications like databases may see slightly higher overhead, but it remains at acceptable levels.

Does Ubuntu automatically install AppArmor profiles?

Ubuntu ships with profiles for some software by default, including Nginx, cups, man, and snap packages. For everything else, you must create profiles manually or install them from the apparmor-profiles-extra package.