Secure Podman containers with SELinux and AppArmor mandatory access controls

Intermediate 45 min Apr 01, 2026 402 views
Ubuntu 24.04 Debian 12 AlmaLinux 9 Rocky Linux 9

Implement mandatory access controls for Podman containers using SELinux on Red Hat-based systems and AppArmor on Debian-based systems. Learn to configure security policies, monitor violations, and harden container security with production-grade controls.

Prerequisites

  • Podman installed and configured
  • Root or sudo access
  • Basic understanding of Linux security concepts

What this solves

Container security relies on proper isolation between containers and the host system. While Podman provides better security defaults than Docker through rootless containers, mandatory access controls (MAC) like SELinux and AppArmor add critical defense-in-depth protection. These systems enforce fine-grained security policies that prevent containers from accessing unauthorized resources, even if an attacker compromises the container runtime.

Prerequisites

Before starting, ensure you have Podman installed and configured. If you need to install Podman, follow our Podman installation guide.

Step-by-step configuration

Update system packages

Start by updating your package manager to ensure you have the latest security updates.

sudo apt update && sudo apt upgrade -y
sudo dnf update -y

Install mandatory access control systems

Install SELinux on Red Hat-based systems or AppArmor on Debian-based systems along with required utilities.

sudo apt install -y apparmor apparmor-utils apparmor-profiles apparmor-profiles-extra
sudo dnf install -y selinux-policy-targeted policycoreutils-python-utils setroubleshoot-server

Verify mandatory access control status

Check that your mandatory access control system is active and enforcing policies.

sudo systemctl status apparmor
sudo aa-status
sestatus
getenforce

Configure SELinux for Podman containers (Red Hat-based systems)

Enable SELinux container separation and configure proper contexts for Podman containers.

sudo setsebool -P container_manage_cgroup true
sudo setsebool -P virt_use_nfs true
sudo setsebool -P virt_sandbox_use_all_caps true
Note: These SELinux booleans allow containers to manage cgroups, access NFS storage, and use necessary capabilities while maintaining security boundaries.

Create custom SELinux policy for containers

Create a custom SELinux policy module for enhanced container security controls.

policy_module(container_custom, 1.0)

require {
    type container_t;
    type user_home_t;
    type http_port_t;
    class tcp_socket name_bind;
    class dir { read getattr open search };
}

Allow containers to bind to HTTP ports

allow container_t http_port_t:tcp_socket name_bind;

Restrict access to user home directories

neverallow container_t user_home_t:dir { read getattr open search };
sudo mkdir -p /etc/selinux/local
sudo checkmodule -M -m -o /etc/selinux/local/container_custom.mod /etc/selinux/local/container_custom.te
sudo semodule_package -o /etc/selinux/local/container_custom.pp -m /etc/selinux/local/container_custom.mod
sudo semodule -i /etc/selinux/local/container_custom.pp

Create custom AppArmor profile for Podman containers (Debian-based systems)

Create a custom AppArmor profile that restricts container capabilities and file system access.

#include 

profile podman-custom flags=(attach_disconnected,mediate_deleted) {
  #include 
  
  # Network access
  network inet tcp,
  network inet udp,
  network inet6 tcp,
  network inet6 udp,
  network netlink raw,
  
  # File system access (restricted)
  /usr/bin/** rix,
  /bin/** rix,
  /sbin/** rix,
  /lib/** rm,
  /lib64/** rm,
  
  # Container-specific paths
  /var/lib/containers/** rw,
  /tmp/** rw,
  /dev/null rw,
  /dev/zero rw,
  /dev/random r,
  /dev/urandom r,
  
  # Deny access to sensitive system areas
  deny /etc/shadow r,
  deny /etc/passwd w,
  deny /boot/** rwklx,
  deny /sys/kernel/security/** rwklx,
  
  # Capabilities (minimal set)
  capability net_bind_service,
  capability setuid,
  capability setgid,
  capability dac_override,
}
sudo apparmor_parser -r /etc/apparmor.d/podman-custom
sudo systemctl reload apparmor

Configure Podman to use security profiles

Create a Podman configuration that automatically applies security profiles to containers.

[containers]
seccomp_profile = "/usr/share/containers/seccomp.json"
apparmor_profile = "podman-custom"
selinux = true
label = true

[engine]
runtime = "runc"
events_logger = "journald"
namespace = "containers"

[machine]
cpus = 2
memory = 2048
mkdir -p ~/.config/containers

Test container security with a sample application

Deploy a test container to verify that security policies are properly applied and enforced.

podman run -d --name security-test \
  --security-opt label=type:container_t \
  --read-only \
  --tmpfs /tmp \
  -p 8080:80 \
  docker.io/nginx:alpine

Create container security monitoring script

Create a monitoring script to track security violations and policy enforcement.

#!/bin/bash

Container Security Monitoring Script

Monitors SELinux/AppArmor violations for containers

LOG_FILE="/var/log/container-security.log" DATE=$(date '+%Y-%m-%d %H:%M:%S') log_message() { echo "[$DATE] $1" >> "$LOG_FILE" echo "[$DATE] $1" }

Check for SELinux violations (Red Hat-based systems)

if command -v ausearch &> /dev/null; then log_message "Checking SELinux violations..." VIOLATIONS=$(ausearch -m AVC -ts recent 2>/dev/null | grep container | wc -l) if [ "$VIOLATIONS" -gt 0 ]; then log_message "WARNING: Found $VIOLATIONS SELinux violations for containers" ausearch -m AVC -ts recent 2>/dev/null | grep container >> "$LOG_FILE" else log_message "No SELinux violations detected" fi fi

Check for AppArmor violations (Debian-based systems)

if command -v aa-status &> /dev/null; then log_message "Checking AppArmor violations..." VIOLATIONS=$(dmesg | grep -i apparmor | grep -i denied | grep podman | wc -l) if [ "$VIOLATIONS" -gt 0 ]; then log_message "WARNING: Found $VIOLATIONS AppArmor violations for containers" dmesg | grep -i apparmor | grep -i denied | grep podman >> "$LOG_FILE" else log_message "No AppArmor violations detected" fi fi

Check running containers security context

log_message "Checking container security contexts..." podman ps --format "table {{.Names}}\t{{.Status}}\t{{.SecurityOpt}}" >> "$LOG_FILE" log_message "Security monitoring complete"
sudo chmod 755 /usr/local/bin/monitor-container-security.sh
Never use chmod 777. It gives every user on the system full access to your files. Script files only need execute permissions for the owner and group.

Set up automated security monitoring

Create a systemd timer to run security monitoring every hour and log violations.

[Unit]
Description=Container Security Monitor
After=network.target

[Service]
Type=oneshot
User=root
ExecStart=/usr/local/bin/monitor-container-security.sh
StandardOutput=journal
StandardError=journal
[Unit]
Description=Run container security monitoring hourly
Requires=container-security-monitor.service

[Timer]
OnCalendar=hourly
Persistent=true

[Install]
WantedBy=timers.target
sudo systemctl daemon-reload
sudo systemctl enable --now container-security-monitor.timer
sudo systemctl status container-security-monitor.timer

Verify your setup

Test that your mandatory access controls are properly protecting containers.

# Check container is running with security context
podman ps --format "table {{.Names}}\t{{.Status}}\t{{.SecurityOpt}}"

Test security policy enforcement

podman exec security-test ls /etc/shadow 2>&1 || echo "Access denied - security working"

Check security monitoring

sudo /usr/local/bin/monitor-container-security.sh cat /var/log/container-security.log

Verify MAC system status

sudo systemctl status container-security-monitor.timer
# Check AppArmor profile status
sudo aa-status | grep podman
dmesg | grep -i apparmor | tail -5
# Check SELinux context and policies
ps auxZ | grep container
sudo semodule -l | grep container

Advanced security hardening

Configure resource limits and capabilities

Add additional security controls through resource limits and capability restrictions.

[containers]
default_capabilities = [
  "CHOWN",
  "DAC_OVERRIDE", 
  "FOWNER",
  "FSETID",
  "KILL",
  "SETGID",
  "SETUID",
  "SETPCAP",
  "NET_BIND_SERVICE"
]

default_ulimits = [
  "nofile=65536:65536",
  "nproc=4096:4096"
]

Enable user namespace for additional isolation

userns_size = 65536

Create secure container startup template

Create a script template for launching containers with enhanced security settings.

#!/bin/bash

Secure Podman Container Launcher

Usage: secure-podman-run.sh [port]

CONTAINER_NAME="$1" IMAGE="$2" PORT="${3:-8080}" if [ -z "$CONTAINER_NAME" ] || [ -z "$IMAGE" ]; then echo "Usage: $0 [port]" exit 1 fi echo "Launching secure container: $CONTAINER_NAME" podman run -d \ --name "$CONTAINER_NAME" \ --security-opt no-new-privileges:true \ --security-opt label=type:container_t \ --cap-drop ALL \ --cap-add NET_BIND_SERVICE \ --cap-add SETUID \ --cap-add SETGID \ --read-only \ --tmpfs /tmp:rw,noexec,nosuid,size=100m \ --tmpfs /var/run:rw,noexec,nosuid,size=100m \ --pids-limit 1000 \ --memory 512m \ --cpus 1.0 \ --user 1001:1001 \ -p "$PORT:8080" \ "$IMAGE" echo "Container $CONTAINER_NAME started with enhanced security" podman ps --filter name="$CONTAINER_NAME"
sudo chmod 755 /usr/local/bin/secure-podman-run.sh

Monitor and troubleshoot security violations

Set up centralized logging for security events

Configure centralized logging to capture and analyze security violations across containers.

# Container security logging
:msg, contains, "apparmor" /var/log/container-security.log
:msg, contains, "selinux" /var/log/container-security.log
:msg, contains, "container" /var/log/container-security.log
& stop
sudo systemctl restart rsyslog

Common issues

SymptomCauseFix
Container fails to start with permission deniedSELinux/AppArmor blocking container accessCheck ausearch -m AVC or dmesg | grep apparmor for denials
Container cannot bind to privileged portsMissing NET_BIND_SERVICE capabilityAdd --cap-add NET_BIND_SERVICE to podman run
File access denied inside containerIncorrect SELinux context on host filesRun sudo chcon -Rt container_file_t /path/to/files
AppArmor profile not loadingSyntax error in profileRun sudo apparmor_parser -Q /etc/apparmor.d/profile to check
High security violation countOverly restrictive policiesReview logs and adjust policies incrementally
Container performance issuesExcessive security checksMonitor with our performance monitoring guide

Production considerations

For production deployments, integrate container security monitoring with your existing observability stack. Consider implementing Cilium Tetragon runtime security for advanced eBPF-based monitoring and threat detection.

Set up automated alerting when security violations exceed acceptable thresholds. Create separate security profiles for different container workload types (web servers, databases, batch jobs) to balance security with functionality.

Regularly audit your security policies and update them as application requirements change. Keep SELinux and AppArmor policies in version control and test changes in staging environments before production deployment.

Next steps

Automated install script

Run this to automate the entire setup

Need help?

Don't want to manage this yourself?

We handle infrastructure security hardening for businesses that depend on uptime. From initial setup to ongoing operations.