PODMAN - Install Podman on Linux Redhat
Production-Ready Step-by-Step Guide Rootless Podman + Quadlet on Red Hat Enterprise Linux 10
This guide is designed for a production environment. It uses the modern Quadlet method (recommended) and follows Red Hat best practices for RHEL 10.
1. System Requirements (Production)
| Resource | Minimum | Recommended (Production) | Our Systems |
|---|---|---|---|
| CPU | 2 cores | 4+ cores | 8 cores |
| RAM | 4 GB | 8–16 GB+ | 32 GB |
| Disk | 40 GB free | 100 GB+ (SSD preferred) | 350 GB |
| cgroup | cgroup v2 | cgroup v2 (required) | |
| SELinux | Enforcing | Enforcing |
Check cgroup version:
Bash
podman info --format '{{.Host.CgroupVersion}}'
2. Prepare the System
2.1 Register and Update RHEL 10
Bash
sudo subscription-manager register
sudo subscription-manager attach --auto
sudo dnf update -y
sudo reboot
2.2 Install Container Tools
Bash
sudo dnf install -y container-tools
Optional (Docker CLI compatibility):
Bash
sudo dnf install -y podman-docker
Verify:
Bash
podman --version
podman info
3. Create a Dedicated Service User (Best Practice)
For production, avoid running services under a regular interactive user.
Bash
# Create a system user for containers
sudo useradd -r -m -d /home/podman -s /bin/bash podman
# Set a strong password or disable password login
sudo passwd podman # or lock the account later
Grant subordinate UIDs/GIDs (required for rootless):
Bash
sudo usermod --add-subuids 100000-165535 --add-subgids 100000-165535 podman
4. Enable Lingering (Critical for Production)
This allows the user services to run even when the user is not logged in.
Bash
sudo loginctl enable-linger podman
Verify:
Bash
loginctl show-user podman | grep Linger
# Linger=yes
5. Configure Rootless Environment
Switch to the service user:
Bash
sudo -u podman -i
Create required directories:
Bash
mkdir -p ~/.config/containers/systemd
mkdir -p ~/.config/containers
mkdir -p ~/.local/share/containers
Optional but Recommended: Storage Configuration
Bash
cat > ~/.config/containers/storage.conf << 'EOF'
[storage]
driver = "overlay"
runroot = "/run/user/$(id -u)/containers"
graphroot = "$HOME/.local/share/containers/storage"
[storage.options.overlay]
mount_program = "/usr/bin/fuse-overlayfs"
mountopt = "nodev,fsync=0"
EOF
Optional: Registries Configuration
Bash
cat > ~/.config/containers/registries.conf << 'EOF'
unqualified-search-registries = ["registry.access.redhat.com", "registry.redhat.io", "docker.io", "quay.io"]
[[registry]]
location = "docker.io"
insecure = false
EOF
6. Create Your First Production Quadlet
Example: Nginx reverse proxy / web service
Bash
cat > ~/.config/containers/systemd/nginx.container << 'EOF'
[Unit]
Description=Nginx Web Server (Production)
After=network-online.target
Wants=network-online.target
[Container]
Image=docker.io/library/nginx:alpine
ContainerName=nginx
PublishPort=8080:80
Volume=nginx-data.volume:/usr/share/nginx/html:Z
Volume=nginx-conf.volume:/etc/nginx/conf.d:Z
AutoUpdate=registry
Environment=TZ=America/New_York
PodmanArgs=--memory=512m --cpus=1.0 --memory-swap=512m
[Service]
Restart=always
TimeoutStartSec=300
[Install]
WantedBy=default.target
EOF
Create supporting volumes:
Bash
cat > ~/.config/containers/systemd/nginx-data.volume << 'EOF'
[Volume]
VolumeName=nginx-data
EOF
cat > ~/.config/containers/systemd/nginx-conf.volume << 'EOF'
[Volume]
VolumeName=nginx-conf
EOF
7. Activate the Service
Bash
# Reload systemd user units
systemctl --user daemon-reload
# Start and enable
systemctl --user enable --now nginx.service
# Check status
systemctl --user status nginx.service
podman ps
View logs:
Bash
journalctl --user -u nginx.service -f
8. Production Hardening Checklist
| Item | Command / Action | Status |
|---|---|---|
| SELinux | Keep enforcing | ☐ |
| Linger enabled | loginctl show-user podman | ☐ |
| Resource limits | Set in Quadlet (--memory, --cpus) | ☐ |
| Auto-update | AutoUpdate=registry in Quadlet | ☐ |
| Firewall | Open only required ports | ☐ |
| Log rotation | Configure journald or ship logs | ☐ |
| Image scanning | Use podman image scan or external scanner | ☐ |
| Backup volumes | Backup ~/.local/share/containers | ☐ |
| Non-interactive user | Disable password / use key-based access only | ☐ |
Firewall example:
Bash
sudo firewall-cmd --permanent --add-port=8080/tcp
sudo firewall-cmd --reload
9. Useful Management Commands
Bash
# List all user services
systemctl --user list-units --type=service
# Restart a service
systemctl --user restart nginx.service
# Stop a service
systemctl --user stop nginx.service
# View resource usage
podman stats
# Update all containers with AutoUpdate
podman auto-update
10. Optional: Auto-Update Timer
Enable Podman’s auto-update timer (as the podman user):
Bash
systemctl --user enable --now podman-auto-update.timer
Summary of Key Directories (Rootless)
| Purpose | Path |
|---|---|
| Quadlet files | ~/.config/containers/systemd/ |
| Container storage | ~/.local/share/containers/storage/ |
| User systemd units | ~/.config/systemd/user/ |
| Configuration | ~/.config/containers/ |