2026-01-24 21:53:58 +01:00
2026-01-24 21:53:58 +01:00
2025-09-05 22:49:16 +02:00
2025-09-05 22:49:16 +02:00

Podman Role

Bootstrap containerized applications with Podman in minutes.

🚀 Quick Start

1. Basic Setup

- hosts: servers
  roles:
    - podman

2. Run Your First Container

- hosts: servers
  roles:
    - role: podman
      vars:
        podman_containers:
          - name: nginx
            image: nginx:latest
            ports:
              - "80:80"

3. Common Patterns

Web application with database:

podman_containers:
  - name: webapp
    image: myapp:latest
    ports:
      - "8080:8080"
    env:
      DATABASE_URL: "postgresql://postgres@db:5432/app"
    
  - name: postgres
    image: postgres:15
    volumes:
      - "db-data:/var/lib/postgresql/data"
    env:
      POSTGRES_DB: app
      POSTGRES_PASSWORD: secret

podman_volumes:
  - name: db-data

That's it! Podman will be installed, configured, and your containers will be running with systemd services automatically created.


📋 Requirements

  • Ansible: 2.11+
  • Target OS: Ubuntu 20.04+, Debian 11+
  • Collection: containers.podman (auto-installed)

🔧 Configuration Guide

Management Modes (Quadlet vs Systemd)

This role automatically selects the best management engine based on your operating system version:

  • Quadlet (Default for Debian 13+): Uses Podman's native systemd generator via .container files. This is the modern, preferred method.
  • Systemd (Default for Debian < 13): Uses legacy podman generate systemd to create service units.

The determination is controlled by the logic in defaults/main.yml:

# Auto-detected. True for Debian 13+, False otherwise.
podman_use_quadlet: "{{ ... }}"

# Sets default state to 'quadlet' or 'started'/'present' accordingly
podman_mode: ... 

Recommendation: Do not set state explicitly in your variables (e.g., podman_containers) unless you have a specific reason. The role's defaults will ensure the correct state is applied for your OS version.

Users can still manually control defaults if needed:

# Force Quadlet usage on older systems (if supported)
podman_use_quadlet: true

# Or customize default options
podman_container_defaults:
  quadlet_options:
    - "AutoUpdate=registry"
    - |
      [Install]
      WantedBy=default.target

If you prefer the standard imperative approach (similar to docker run) regardless of OS, you can override the defaults or set state: started on individual items.

Resource Definition

The variables podman_containers, podman_networks, podman_volumes, and podman_pods accept standard parameters from the containers.podman collection.

Containers

podman_containers:
  - name: nginx
    image: nginx:latest
    ports: ["80:80"]
    volumes:
      - "html_vol:/usr/share/nginx/html"
      - "./local_conf:/etc/nginx/conf.d:ro"
    env:
      NGINX_HOST: example.com
    # Quadlet-specific options can be added as a list
    quadlet_options:
      - "AutoUpdate=registry"

Networks

podman_networks:
  - name: app_net
    subnet: "10.0.0.0/24"
    gateway: "10.0.0.1"
    dns: ["8.8.8.8"]

Volumes

podman_volumes:
  - name: db_data
    # state defaults to 'quadlet'

Pods

podman_pods:
  - name: app_pod
    ports: ["8080:80"]
    share: "net,ipc"

Advanced Configuration

Registry & Security Policy

# Basic registry setup (development)
podman_policy_default_type: "insecureAcceptAnything"
podman_policy_reject_unknown_registries: false

# Production security (with signatures)
podman_policy_default_type: "reject"
podman_policy_reject_unknown_registries: true
podman_policy_trusted_registries:
  - registry: "docker.io"
    type: "insecureAcceptAnything"
    unqualified_search: true
    
  - registry: "internal.company.com"
    type: "signedBy"
    keyPath: "/etc/pki/containers/company.gpg"
    insecure: false
    mirror:
      - location: "backup.company.com"

# Additional registries (for special mirror/proxy configurations)
podman_registries_additional:
  - location: "internal-mirror.company.com"
    insecure: false
    blocked: false
    mirror:
      - location: "docker.io"
        insecure: false

Systemd Service Generation

# Global systemd settings
podman_generate_systemd: true
podman_systemd_options:
  restart_policy: always
  stop_timeout: 120
  after: ["network.target"]
  wants: ["network-online.target"]
  container_prefix: "container-"
  pod_prefix: "pod-"

Container Defaults

# Auto-remove containers when they exit (applies to all containers unless overridden)
podman_auto_remove: true

Resource Cleanup

# Auto-cleanup unused resources
podman_prune_enabled: true
podman_prune_options:
  container: true    # Remove stopped containers
  image: true        # Remove unused images
  network: true      # Remove unused networks
  volume: true       # Remove unused volumes
  system: true       # Full system cleanup

Storage Configuration

podman_configure_storage: true
podman_storage_driver: overlay
podman_storage_graphroot: /var/lib/containers/storage
podman_storage_runroot: /run/containers/storage

API & Socket Services

podman_enable_socket: true      # Enable Podman socket
podman_enable_api_service: true # Enable REST API
podman_enable_auto_update: true # Enable automatic container updates

Note: When using podman_enable_auto_update, containers must use fully qualified image names including the registry (e.g., docker.io/postgres:15 instead of postgres:15) and should have AutoUpdate=registry in their quadlet_options or be configured with Quadlet state.


🏷️ Available Tags

Run specific parts of the role:

# Install only
ansible-playbook -t podman-install playbook.yml

# Configure only  
ansible-playbook -t podman-configure playbook.yml

# Manage containers only
ansible-playbook -t podman-containers playbook.yml

# Manage networks only
ansible-playbook -t podman-networks playbook.yml

Available tags:

  • podman - Run everything
  • podman-install - Package installation
  • podman-configure - Configuration files
  • podman-services - System services
  • podman-networks - Network management
  • podman-volumes - Volume management
  • podman-pods - Pod management
  • podman-containers - Container management
  • podman-systemd - Systemd service generation
  • podman-prune - Resource cleanup

📚 Example Playbooks

Development Environment

- hosts: dev-servers
  roles:
    - role: podman
      vars:
        # Permissive for development
        podman_policy_default_type: "insecureAcceptAnything"
        podman_enable_socket: true
        
        podman_containers:
          - name: dev-web
            image: nginx:latest
            ports:
              - "8080:80"
            volumes:
              - "./web:/usr/share/nginx/html"

Production Environment

- hosts: prod-servers
  roles:
    - role: podman
      vars:
        # Strict security for production
        podman_policy_default_type: "reject"
        podman_policy_reject_unknown_registries: true
        podman_policy_trusted_registries:
          - registry: "registry.company.com"
            type: "signedBy"
            keyPath: "/etc/pki/containers/prod.gpg"
            
        podman_containers:
          - name: prod-app
            image: registry.company.com/app:v1.2.3
            restart_policy: always
            memory: "2g"
            cpu_shares: 2048
            healthcheck:
              test: ["CMD", "curl", "-f", "http://localhost/health"]
              interval: 30s
              timeout: 10s
              retries: 3

Multi-Service Application

- hosts: app-servers
  roles:
    - role: podman
      vars:
        podman_networks:
          - name: app-network
            subnet: "172.20.0.0/16"
            
        podman_volumes:
          - name: postgres-data
          - name: redis-data
          - name: app-uploads
            
        podman_containers:
          # Database
          - name: postgres
            image: postgres:15
            networks:
              - app-network
            volumes:
              - "postgres-data:/var/lib/postgresql/data"
            env:
              POSTGRES_DB: myapp
              POSTGRES_PASSWORD: "{{ vault_db_password }}"
              
          # Cache
          - name: redis
            image: redis:7-alpine
            networks:
              - app-network
            volumes:
              - "redis-data:/data"
              
          # Application
          - name: app
            image: myapp:latest
            networks:
              - app-network
            ports:
              - "80:8080"
            volumes:
              - "app-uploads:/app/uploads"
            env:
              DATABASE_URL: "postgresql://postgres:{{ vault_db_password }}@postgres:5432/myapp"
              REDIS_URL: "redis://redis:6379"

📄 License

MIT

👤 Author

Daniel Akulenok podman@valid.dk

Description
No description provided
Readme 85 KiB
Languages
Jinja 100%