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 version
podman --version
# Check systemd user instance
systemctl --user status
# Enable lingering for user (allows services to run without login)
sudo loginctl enable-linger $USER
# Create quadlet directory structure
mkdir -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 Agent
Documentation=https://docs.example.com/xdr-agent
Wants=network-online.target
After=network-online.target
StartLimitIntervalSec=60
StartLimitBurst=3
[Container]
# Container image
Image=registry.example.com/security/xdr-agent:latest
ContainerName=xdr-agent
# Security options
SecurityLabelDisable=false
ReadOnly=true
NoNewPrivileges=true
# Resource limits
CpuLimit=2
MemoryLimit=2G
MemoryReservation=1G
# Environment variables
Environment="XDR_SERVER=xdr.example.com"
Environment="XDR_PORT=8443"
Environment="LOG_LEVEL=info"
EnvironmentFile=/home/%u/.config/xdr/agent.env
# Volume mounts
Volume=/home/%u/.config/xdr/certs:/etc/xdr/certs:ro,Z
Volume=/var/log/journal:/var/log/journal:ro
Volume=/proc:/host/proc:ro
Volume=/sys:/host/sys:ro
Volume=/etc/os-release:/host/etc/os-release:ro
# Tmpfs for temporary data
Tmpfs=/tmp:size=512M,mode=1777
Tmpfs=/var/tmp:size=512M,mode=1777
# Network configuration
Network=host
Hostname=xdr-%H
# Health check
HealthCmd="/usr/bin/xdr-agent healthcheck"
HealthInterval=30s
HealthRetries=3
HealthTimeout=10s
HealthStartPeriod=60s
# Labels for management
Label="io.containers.autoupdate=registry"
Label="com.example.component=security"
Label="com.example.managed-by=quadlet"
[Service]
# Restart policy
Restart=always
RestartSec=30
# Systemd integration
Type=notify
NotifyAccess=all
# Security hardening
PrivateTmp=yes
ProtectSystem=strict
ProtectHome=read-only
ProtectKernelTunables=yes
ProtectKernelModules=yes
ProtectControlGroups=yes
RestrictRealtime=yes
RestrictSUIDSGID=yes
LockPersonality=yes
# Timeouts
TimeoutStartSec=120
TimeoutStopSec=30
[Install]
WantedBy=default.target
Advanced XDR Configuration with Secrets
Create ~/.config/containers/systemd/xdr-agent-advanced.container
:
[Unit]
Description=Advanced XDR Security Agent with Secret Management
Documentation=https://docs.example.com/xdr-agent
Requires=podman-secret-xdr-token.service
After=podman-secret-xdr-token.service
[Container]
Image=registry.example.com/security/xdr-agent:latest
ContainerName=xdr-agent-advanced
# Pull policy
Pull=newer
PullRetryCount=3
PullRetryDelay=10s
# User and group mapping
UserNS=keep-id
User=1000
Group=1000
# Capabilities (minimal required set)
DropCapability=all
AddCapability=CAP_SYS_PTRACE,CAP_DAC_READ_SEARCH,CAP_NET_RAW
# Secret management
Secret=xdr-token,type=env,target=XDR_AUTH_TOKEN
Secret=xdr-cert,type=mount,target=/etc/xdr/cert.pem
Secret=xdr-key,type=mount,target=/etc/xdr/key.pem,mode=0600
# Advanced volumes with specific options
Volume=/home/%u/.config/xdr/config.yaml:/etc/xdr/config.yaml:ro,Z
Volume=xdr-data:/var/lib/xdr:Z
Volume=/run/user/%U/podman/podman.sock:/var/run/docker.sock:ro
# Environment with interpolation
Environment="HOSTNAME=%H"
Environment="XDR_NODE_ID=%H-%u"
Environment="XDR_CLUSTER_NAME=production"
# Entrypoint override
Entrypoint=/usr/bin/xdr-agent
Cmd="--config=/etc/xdr/config.yaml" "--node-id=$XDR_NODE_ID"
# Logging configuration
LogDriver=journald
LogOpt="tag=xdr-agent"
LogOpt="labels=com.example.component"
[Service]
Type=notify
Restart=on-failure
RestartSec=30
RestartPreventExitStatus=0 2
# Dependency ordering
RequiresMountsFor=/home/%u/.config/xdr
# Resource accounting
CPUAccounting=yes
MemoryAccounting=yes
TasksAccounting=yes
IOAccounting=yes
# Watchdog
WatchdogSec=60
[Install]
WantedBy=default.target
Supporting Services
Secret Creation Service
Create ~/.config/containers/systemd/podman-secret-xdr-token.service
:
[Unit]
Description=Create Podman Secret for XDR Token
ConditionPathExists=!/run/user/%U/containers/secrets/xdr-token
Before=xdr-agent-advanced.service
[Service]
Type=oneshot
RemainAfterExit=yes
ExecStart=/bin/bash -c 'podman secret create xdr-token /home/%u/.config/xdr/token'
ExecStop=podman secret rm xdr-token
[Install]
WantedBy=default.target
Auto-Update Timer
Create ~/.config/containers/systemd/podman-auto-update-xdr.timer
:
[Unit]
Description=Auto-update XDR containers
Documentation=man:podman-auto-update(1)
[Timer]
OnCalendar=daily
RandomizedDelaySec=900
Persistent=true
[Install]
WantedBy=timers.target
Create ~/.config/containers/systemd/podman-auto-update-xdr.service
:
[Unit]
Description=Auto-update XDR containers
Documentation=man:podman-auto-update(1)
Wants=network-online.target
After=network-online.target
[Service]
Type=oneshot
ExecStart=/usr/bin/podman auto-update --label "io.containers.autoupdate=registry"
ExecStartPost=/usr/bin/systemctl --user try-restart xdr-agent.service
[Install]
WantedBy=default.target
Configuration Files
XDR Agent Configuration
Create ~/.config/xdr/config.yaml
:
# XDR Agent Configuration
version: 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: 5000
Environment File
Create ~/.config/xdr/agent.env
:
# XDR Agent Environment Variables
# This file should be protected with appropriate permissions
# Server Configuration
XDR_SERVER=xdr.example.com
XDR_PORT=8443
# Agent Settings
XDR_DEPLOYMENT_TYPE=production
XDR_REGION=us-east-1
XDR_TENANT_ID=tenant-123
# Features
XDR_FEATURE_EDR=true
XDR_FEATURE_DLP=false
XDR_FEATURE_COMPLIANCE=true
# Performance Tuning
XDR_WORKER_THREADS=4
XDR_BUFFER_SIZE=65536
XDR_BATCH_SIZE=100
# Logging
LOG_LEVEL=info
LOG_FORMAT=json
Deployment 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 directories
echo "Creating configuration directories..."
mkdir -p "${XDR_CONFIG}/certs"
mkdir -p "${XDR_HOME}/.config/containers/systemd"
# Set permissions
chmod 700 "${XDR_CONFIG}"
chmod 700 "${XDR_CONFIG}/certs"
# Generate or copy certificates
echo "Setting up certificates..."
# Copy your certificates to ${XDR_CONFIG}/certs/
# Ensure proper permissions (600 for keys, 644 for certs)
# Create secrets
echo "Creating secrets..."
if [ -f "${XDR_CONFIG}/token" ]; then
podman secret create xdr-token "${XDR_CONFIG}/token" || true
fi
# Reload systemd
echo "Reloading systemd configuration..."
systemctl --user daemon-reload
# Enable and start services
echo "Enabling XDR services..."
systemctl --user enable --now podman-secret-xdr-token.service
systemctl --user enable --now xdr-agent.service
systemctl --user enable --now podman-auto-update-xdr.timer
# Verify deployment
echo "Verifying deployment..."
systemctl --user status xdr-agent.service --no-pager
podman 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 output
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
NC='\033[0m' # No Color
echo "XDR Agent Health Check"
echo "====================="
# Check service status
echo -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 1
fi
# Check container status
echo -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 1
fi
# Check container health
echo -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 usage
echo -e "\nResource Usage:"
podman stats --no-stream --format "table {{.Container}}\t{{.CPUPerc}}\t{{.MemUsage}}" xdr-agent
# Check recent logs for errors
echo -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 status
echo -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 status
systemctl --user status xdr-agent.service
# View detailed logs
journalctl --user -u xdr-agent.service -f
# Check quadlet generation
/usr/lib/systemd/system-generators/podman-system-generator --user --dryrun
# Verify quadlet syntax
systemd-analyze --user verify xdr-agent.service
Permission Issues
# Fix SELinux contexts
restorecon -Rv ~/.config/xdr/
# Check volume permissions
podman unshare ls -la /var/lib/containers/storage/volumes/xdr-data/_data
# Reset user namespace
podman system migrate
Network Connectivity
# Test from container
podman run --rm -it --network host \
registry.example.com/security/xdr-agent:latest \
curl -v https://xdr.example.com:8443/health
# Check firewall rules
firewall-cmd --list-all
Debug Mode
Create ~/.config/containers/systemd/xdr-agent-debug.container
for debugging:
[Unit]
Description=XDR Agent Debug Mode
Conflicts=xdr-agent.service
[Container]
Image=registry.example.com/security/xdr-agent:latest
ContainerName=xdr-agent-debug
# Debug settings
Environment="LOG_LEVEL=debug"
Environment="XDR_DEBUG=true"
# Interactive mode
Interactive=true
TTY=true
# Override entrypoint for debugging
Entrypoint=/bin/bash
# Mount source code for debugging (if available)
Volume=/home/%u/src/xdr-agent:/src:ro,Z
# Same mounts as production
Volume=/home/%u/.config/xdr/certs:/etc/xdr/certs:ro,Z
Volume=/var/log/journal:/var/log/journal:ro
[Service]
Type=simple
Restart=no
[Install]
WantedBy=default.target
Performance Optimization
Resource Tuning
Create ~/.config/containers/systemd/xdr-agent.resource
:
[Unit]
Description=Resource limits for XDR Agent
[Slice]
# CPU allocation
CPUWeight=50
CPUQuota=200%
# Memory limits
MemoryMax=2G
MemoryHigh=1500M
# IO limits
IOWeight=50
IOReadBandwidthMax=/var/lib/containers 50M
IOWriteBandwidthMax=/var/lib/containers 20M
# Task limits
TasksMax=100
Monitoring Dashboard
Create a monitoring script ~/.local/bin/xdr-monitor.sh
:
#!/bin/bash
# Real-time XDR monitoring dashboard
watch -n 5 '
echo "=== XDR Agent Monitor ==="
echo
echo "Service Status:"
systemctl --user is-active xdr-agent.service
echo
echo "Container Stats:"
podman stats --no-stream xdr-agent
echo
echo "Recent Logs:"
journalctl --user -u xdr-agent.service -n 5 --no-pager
echo
echo "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-linger
for persistent monitoring - Avoid privileged containers unless absolutely necessary
2. Secret Management
# Use Podman secrets for sensitive data
podman secret create xdr-api-key api-key.txt
rm api-key.txt
# Rotate secrets regularly
podman secret rm xdr-api-key
podman secret create xdr-api-key new-api-key.txt
3. Network Isolation
# For enhanced security, use custom networks
[Container]
Network=xdr-network
IP=10.88.0.10
4. Audit Logging
# Enable audit logging for XDR activities
auditctl -w /home/$USER/.config/xdr/ -p wa -k xdr_config_change
auditctl -w /var/lib/containers/storage/volumes/xdr-data/ -p wa -k xdr_data_access
Integration with XDR Platforms
Wazuh Integration
# Add to config.yaml for Wazuh XDR
integrations:
wazuh:
enabled: true
manager: wazuh.example.com
port: 1514
protocol: tcp
agent_name: ${HOSTNAME}-podman
groups:
- linux
- containers
- xdr
Elastic Security Integration
# Add to config.yaml for Elastic
integrations:
elastic:
enabled: true
hosts:
- https://elastic1.example.com:9200
- https://elastic2.example.com:9200
username: xdr_agent
api_key: ${ELASTIC_API_KEY}
index: xdr-events
Conclusion
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.