XDR Podman Quadlets for User Session: Enhanced Container Security
This guide demonstrates how to deploy XDR (Extended Detection and Response) agents as Podman Quadlets in user sessions, providing rootless container-based security monitoring with seamless systemd integration. This approach enhances security by running XDR agents without root privileges while maintaining full monitoring capabilities.
Overview
Podman Quadlets represent a modern approach to container management, combining the security benefits of rootless containers with the reliability of systemd service management. When applied to XDR deployment, this creates a robust security monitoring solution that:
- Runs without root privileges (enhanced security)
 - Integrates with systemd for automatic startup and management
 - Provides isolated execution environments
 - Enables easy updates and maintenance
 - Scales across multiple user sessions
 
Prerequisites
System Requirements
- Operating System: Linux with systemd 250+ (RHEL 9, Ubuntu 22.04, Fedora 36+)
 - Podman: Version 4.4+ with quadlet support
 - User Account: Regular user account (non-root)
 - XDR Agent: Container image for your XDR solution
 
Initial Setup
# Verify Podman versionpodman --version
# Check systemd user instancesystemctl --user status
# Enable lingering for user (allows services to run without login)sudo loginctl enable-linger $USER
# Create quadlet directory structuremkdir -p ~/.config/containers/systemd/Understanding Quadlets
Quadlets are systemd unit files that define how Podman containers should run. They’re automatically converted to proper systemd services by the podman-systemd-generator.
Key Benefits
- Declarative Configuration: Define containers as systemd units
 - Automatic Management: Systemd handles lifecycle, restarts, and dependencies
 - User Session Support: Run containers in user context without root
 - Native Integration: Leverage systemd features like timers and dependencies
 
XDR Agent Quadlet Configuration
Basic XDR Container Quadlet
Create ~/.config/containers/systemd/xdr-agent.container:
[Unit]Description=XDR Security AgentDocumentation=https://docs.example.com/xdr-agentWants=network-online.targetAfter=network-online.targetStartLimitIntervalSec=60StartLimitBurst=3
[Container]# Container imageImage=registry.example.com/security/xdr-agent:latestContainerName=xdr-agent
# Security optionsSecurityLabelDisable=falseReadOnly=trueNoNewPrivileges=true
# Resource limitsCpuLimit=2MemoryLimit=2GMemoryReservation=1G
# Environment variablesEnvironment="XDR_SERVER=xdr.example.com"Environment="XDR_PORT=8443"Environment="LOG_LEVEL=info"EnvironmentFile=/home/%u/.config/xdr/agent.env
# Volume mountsVolume=/home/%u/.config/xdr/certs:/etc/xdr/certs:ro,ZVolume=/var/log/journal:/var/log/journal:roVolume=/proc:/host/proc:roVolume=/sys:/host/sys:roVolume=/etc/os-release:/host/etc/os-release:ro
# Tmpfs for temporary dataTmpfs=/tmp:size=512M,mode=1777Tmpfs=/var/tmp:size=512M,mode=1777
# Network configurationNetwork=hostHostname=xdr-%H
# Health checkHealthCmd="/usr/bin/xdr-agent healthcheck"HealthInterval=30sHealthRetries=3HealthTimeout=10sHealthStartPeriod=60s
# Labels for managementLabel="io.containers.autoupdate=registry"Label="com.example.component=security"Label="com.example.managed-by=quadlet"
[Service]# Restart policyRestart=alwaysRestartSec=30
# Systemd integrationType=notifyNotifyAccess=all
# Security hardeningPrivateTmp=yesProtectSystem=strictProtectHome=read-onlyProtectKernelTunables=yesProtectKernelModules=yesProtectControlGroups=yesRestrictRealtime=yesRestrictSUIDSGID=yesLockPersonality=yes
# TimeoutsTimeoutStartSec=120TimeoutStopSec=30
[Install]WantedBy=default.targetAdvanced XDR Configuration with Secrets
Create ~/.config/containers/systemd/xdr-agent-advanced.container:
[Unit]Description=Advanced XDR Security Agent with Secret ManagementDocumentation=https://docs.example.com/xdr-agentRequires=podman-secret-xdr-token.serviceAfter=podman-secret-xdr-token.service
[Container]Image=registry.example.com/security/xdr-agent:latestContainerName=xdr-agent-advanced
# Pull policyPull=newerPullRetryCount=3PullRetryDelay=10s
# User and group mappingUserNS=keep-idUser=1000Group=1000
# Capabilities (minimal required set)DropCapability=allAddCapability=CAP_SYS_PTRACE,CAP_DAC_READ_SEARCH,CAP_NET_RAW
# Secret managementSecret=xdr-token,type=env,target=XDR_AUTH_TOKENSecret=xdr-cert,type=mount,target=/etc/xdr/cert.pemSecret=xdr-key,type=mount,target=/etc/xdr/key.pem,mode=0600
# Advanced volumes with specific optionsVolume=/home/%u/.config/xdr/config.yaml:/etc/xdr/config.yaml:ro,ZVolume=xdr-data:/var/lib/xdr:ZVolume=/run/user/%U/podman/podman.sock:/var/run/docker.sock:ro
# Environment with interpolationEnvironment="HOSTNAME=%H"Environment="XDR_NODE_ID=%H-%u"Environment="XDR_CLUSTER_NAME=production"
# Entrypoint overrideEntrypoint=/usr/bin/xdr-agentCmd="--config=/etc/xdr/config.yaml" "--node-id=$XDR_NODE_ID"
# Logging configurationLogDriver=journaldLogOpt="tag=xdr-agent"LogOpt="labels=com.example.component"
[Service]Type=notifyRestart=on-failureRestartSec=30RestartPreventExitStatus=0 2
# Dependency orderingRequiresMountsFor=/home/%u/.config/xdr
# Resource accountingCPUAccounting=yesMemoryAccounting=yesTasksAccounting=yesIOAccounting=yes
# WatchdogWatchdogSec=60
[Install]WantedBy=default.targetSupporting Services
Secret Creation Service
Create ~/.config/containers/systemd/podman-secret-xdr-token.service:
[Unit]Description=Create Podman Secret for XDR TokenConditionPathExists=!/run/user/%U/containers/secrets/xdr-tokenBefore=xdr-agent-advanced.service
[Service]Type=oneshotRemainAfterExit=yesExecStart=/bin/bash -c 'podman secret create xdr-token /home/%u/.config/xdr/token'ExecStop=podman secret rm xdr-token
[Install]WantedBy=default.targetAuto-Update Timer
Create ~/.config/containers/systemd/podman-auto-update-xdr.timer:
[Unit]Description=Auto-update XDR containersDocumentation=man:podman-auto-update(1)
[Timer]OnCalendar=dailyRandomizedDelaySec=900Persistent=true
[Install]WantedBy=timers.targetCreate ~/.config/containers/systemd/podman-auto-update-xdr.service:
[Unit]Description=Auto-update XDR containersDocumentation=man:podman-auto-update(1)Wants=network-online.targetAfter=network-online.target
[Service]Type=oneshotExecStart=/usr/bin/podman auto-update --label "io.containers.autoupdate=registry"ExecStartPost=/usr/bin/systemctl --user try-restart xdr-agent.service
[Install]WantedBy=default.targetConfiguration Files
XDR Agent Configuration
Create ~/.config/xdr/config.yaml:
# XDR Agent Configurationversion: 2
agent:  id: ${XDR_NODE_ID}  name: ${HOSTNAME}-xdr  type: endpoint
server:  url: https://${XDR_SERVER}:${XDR_PORT}  tls:    cert: /etc/xdr/cert.pem    key: /etc/xdr/key.pem    ca: /etc/xdr/ca.pem    verify: true
collectors:  system:    enabled: true    interval: 60s    metrics:      - cpu      - memory      - disk      - network
  process:    enabled: true    interval: 30s    include_cmdline: true
  file_integrity:    enabled: true    paths:      - /etc      - /usr/bin      - /usr/sbin      - /home/%u/.ssh    exclude:      - "*.log"      - "*.tmp"
  network:    enabled: true    capture_packets: false    connection_tracking: true
  container:    enabled: true    runtime: podman    socket: /var/run/docker.sock
logging:  level: ${LOG_LEVEL}  format: json  outputs:    - type: file      path: /var/lib/xdr/agent.log      rotate:        max_size: 100M        max_age: 7d        max_backups: 5    - type: syslog      facility: local0      tag: xdr-agent
response:  enabled: true  actions:    - quarantine    - kill_process    - block_network  require_approval: true
performance:  max_cpu_percent: 20  max_memory_mb: 2048  rate_limit:    events_per_second: 1000    burst: 5000Environment File
Create ~/.config/xdr/agent.env:
# XDR Agent Environment Variables# This file should be protected with appropriate permissions
# Server ConfigurationXDR_SERVER=xdr.example.comXDR_PORT=8443
# Agent SettingsXDR_DEPLOYMENT_TYPE=productionXDR_REGION=us-east-1XDR_TENANT_ID=tenant-123
# FeaturesXDR_FEATURE_EDR=trueXDR_FEATURE_DLP=falseXDR_FEATURE_COMPLIANCE=true
# Performance TuningXDR_WORKER_THREADS=4XDR_BUFFER_SIZE=65536XDR_BATCH_SIZE=100
# LoggingLOG_LEVEL=infoLOG_FORMAT=jsonDeployment Process
Initial Deployment
#!/bin/bash# deploy-xdr.sh - XDR Deployment Script
set -euo pipefail
XDR_USER="${USER}"XDR_HOME="/home/${XDR_USER}"XDR_CONFIG="${XDR_HOME}/.config/xdr"
echo "Deploying XDR Agent for user: ${XDR_USER}"
# Create directoriesecho "Creating configuration directories..."mkdir -p "${XDR_CONFIG}/certs"mkdir -p "${XDR_HOME}/.config/containers/systemd"
# Set permissionschmod 700 "${XDR_CONFIG}"chmod 700 "${XDR_CONFIG}/certs"
# Generate or copy certificatesecho "Setting up certificates..."# Copy your certificates to ${XDR_CONFIG}/certs/# Ensure proper permissions (600 for keys, 644 for certs)
# Create secretsecho "Creating secrets..."if [ -f "${XDR_CONFIG}/token" ]; then    podman secret create xdr-token "${XDR_CONFIG}/token" || truefi
# Reload systemdecho "Reloading systemd configuration..."systemctl --user daemon-reload
# Enable and start servicesecho "Enabling XDR services..."systemctl --user enable --now podman-secret-xdr-token.servicesystemctl --user enable --now xdr-agent.servicesystemctl --user enable --now podman-auto-update-xdr.timer
# Verify deploymentecho "Verifying deployment..."systemctl --user status xdr-agent.service --no-pagerpodman ps --filter "name=xdr-agent"
echo "XDR Agent deployment complete!"Health Monitoring Script
Create ~/.local/bin/xdr-health-check.sh:
#!/bin/bash# XDR Health Monitoring Script
set -euo pipefail
# Colors for outputRED='\033[0;31m'GREEN='\033[0;32m'YELLOW='\033[1;33m'NC='\033[0m' # No Color
echo "XDR Agent Health Check"echo "====================="
# Check service statusecho -n "Service Status: "if systemctl --user is-active --quiet xdr-agent.service; then    echo -e "${GREEN}ACTIVE${NC}"else    echo -e "${RED}INACTIVE${NC}"    exit 1fi
# Check container statusecho -n "Container Status: "if podman ps --format "{{.Names}}" | grep -q "xdr-agent"; then    echo -e "${GREEN}RUNNING${NC}"else    echo -e "${RED}NOT RUNNING${NC}"    exit 1fi
# Check container healthecho -n "Container Health: "HEALTH=$(podman inspect xdr-agent --format '{{.State.Health.Status}}' 2>/dev/null || echo "unknown")case $HEALTH in    healthy)        echo -e "${GREEN}HEALTHY${NC}"        ;;    starting)        echo -e "${YELLOW}STARTING${NC}"        ;;    unhealthy)        echo -e "${RED}UNHEALTHY${NC}"        exit 1        ;;    *)        echo -e "${YELLOW}UNKNOWN${NC}"        ;;esac
# Check resource usageecho -e "\nResource Usage:"podman stats --no-stream --format "table {{.Container}}\t{{.CPUPerc}}\t{{.MemUsage}}" xdr-agent
# Check recent logs for errorsecho -e "\nRecent Errors (last 10 minutes):"journalctl --user -u xdr-agent.service --since "10 minutes ago" -p err --no-pager || echo "No errors found"
# Check auto-update statusecho -e "\nAuto-Update Status:"systemctl --user status podman-auto-update-xdr.timer --no-pager | grep -E "Loaded:|Active:|Trigger:"
echo -e "\nHealth check complete!"Troubleshooting
Common Issues and Solutions
Service Won’t Start
# Check service statussystemctl --user status xdr-agent.service
# View detailed logsjournalctl --user -u xdr-agent.service -f
# Check quadlet generation/usr/lib/systemd/system-generators/podman-system-generator --user --dryrun
# Verify quadlet syntaxsystemd-analyze --user verify xdr-agent.servicePermission Issues
# Fix SELinux contextsrestorecon -Rv ~/.config/xdr/
# Check volume permissionspodman unshare ls -la /var/lib/containers/storage/volumes/xdr-data/_data
# Reset user namespacepodman system migrateNetwork Connectivity
# Test from containerpodman run --rm -it --network host \    registry.example.com/security/xdr-agent:latest \    curl -v https://xdr.example.com:8443/health
# Check firewall rulesfirewall-cmd --list-allDebug Mode
Create ~/.config/containers/systemd/xdr-agent-debug.container for debugging:
[Unit]Description=XDR Agent Debug ModeConflicts=xdr-agent.service
[Container]Image=registry.example.com/security/xdr-agent:latestContainerName=xdr-agent-debug
# Debug settingsEnvironment="LOG_LEVEL=debug"Environment="XDR_DEBUG=true"
# Interactive modeInteractive=trueTTY=true
# Override entrypoint for debuggingEntrypoint=/bin/bash
# Mount source code for debugging (if available)Volume=/home/%u/src/xdr-agent:/src:ro,Z
# Same mounts as productionVolume=/home/%u/.config/xdr/certs:/etc/xdr/certs:ro,ZVolume=/var/log/journal:/var/log/journal:ro
[Service]Type=simpleRestart=no
[Install]WantedBy=default.targetPerformance Optimization
Resource Tuning
Create ~/.config/containers/systemd/xdr-agent.resource:
[Unit]Description=Resource limits for XDR Agent
[Slice]# CPU allocationCPUWeight=50CPUQuota=200%
# Memory limitsMemoryMax=2GMemoryHigh=1500M
# IO limitsIOWeight=50IOReadBandwidthMax=/var/lib/containers 50MIOWriteBandwidthMax=/var/lib/containers 20M
# Task limitsTasksMax=100Monitoring Dashboard
Create a monitoring script ~/.local/bin/xdr-monitor.sh:
#!/bin/bash# Real-time XDR monitoring dashboard
watch -n 5 'echo "=== XDR Agent Monitor ==="echoecho "Service Status:"systemctl --user is-active xdr-agent.serviceechoecho "Container Stats:"podman stats --no-stream xdr-agentechoecho "Recent Logs:"journalctl --user -u xdr-agent.service -n 5 --no-pagerechoecho "Network Connections:"podman exec xdr-agent ss -tunap 2>/dev/null | head -10'Security Best Practices
1. Rootless Operation
- Always run XDR agents in user sessions when possible
 - Use 
loginctl enable-lingerfor persistent monitoring - Avoid privileged containers unless absolutely necessary
 
2. Secret Management
# Use Podman secrets for sensitive datapodman secret create xdr-api-key api-key.txtrm api-key.txt
# Rotate secrets regularlypodman secret rm xdr-api-keypodman secret create xdr-api-key new-api-key.txt3. Network Isolation
# For enhanced security, use custom networks[Container]Network=xdr-networkIP=10.88.0.104. Audit Logging
# Enable audit logging for XDR activitiesauditctl -w /home/$USER/.config/xdr/ -p wa -k xdr_config_changeauditctl -w /var/lib/containers/storage/volumes/xdr-data/ -p wa -k xdr_data_accessIntegration with XDR Platforms
Wazuh Integration
# Add to config.yaml for Wazuh XDRintegrations:  wazuh:    enabled: true    manager: wazuh.example.com    port: 1514    protocol: tcp    agent_name: ${HOSTNAME}-podman    groups:      - linux      - containers      - xdrElastic Security Integration
# Add to config.yaml for Elasticintegrations:  elastic:    enabled: true    hosts:      - https://elastic1.example.com:9200      - https://elastic2.example.com:9200    username: xdr_agent    api_key: ${ELASTIC_API_KEY}    index: xdr-eventsConclusion
Deploying XDR agents as Podman Quadlets in user sessions provides a secure, maintainable, and scalable approach to endpoint security monitoring. This configuration offers:
- Enhanced Security: Rootless containers with minimal privileges
 - Operational Excellence: Systemd integration for reliability
 - Easy Management: Declarative configuration and automatic updates
 - Flexible Deployment: Adaptable to various XDR platforms
 
By following this guide, organizations can implement enterprise-grade security monitoring while adhering to the principle of least privilege and modern container best practices.