From 2c8f49191c91cc06ffd11f91d8e45f2ab10514f8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cl=C3=A9ment=20D=C3=A9siles?= <1536672+cdesiles@users.noreply.github.com> Date: Mon, 10 Nov 2025 18:23:44 +0100 Subject: [PATCH] feat: enhance podman configuration with advances networking --- roles/podman/README.md | 186 ++++++++++++++++++++++ roles/podman/defaults/main.yml | 23 +++ roles/podman/tasks/main.yml | 30 +++- roles/podman/templates/registries.conf.j2 | 14 ++ 4 files changed, 246 insertions(+), 7 deletions(-) create mode 100644 roles/podman/README.md create mode 100644 roles/podman/templates/registries.conf.j2 diff --git a/roles/podman/README.md b/roles/podman/README.md new file mode 100644 index 0000000..065851d --- /dev/null +++ b/roles/podman/README.md @@ -0,0 +1,186 @@ +# Podman Role + +This Ansible role installs and configures Podman for container management on NAS/homelab systems. + +## Features + +- Installs Podman and podman-compose +- Configures container registry search paths +- Creates shared projects directory for compose files +- Enables short image name resolution (e.g., `redis:alpine` → `docker.io/library/redis:alpine`) + +## Requirements + +- systemd-based Linux distribution +- Root/sudo access + +## Role Variables + +Available variables with defaults (see `defaults/main.yml`): + +```yaml +# Base directory for docker-compose projects +podman_projects_dir: /opt/podman + +# Unqualified search registries (for short image names) +podman_unqualified_search_registries: + - docker.io + - quay.io + - ghcr.io + +# Podman bridge network (leave empty for default dynamic assignment) +podman_subnet: "" + +# Podman bridge gateway IP (used by services binding to bridge) +podman_subnet_gateway: "" + +# Podman bridge interface name (if using custom network) +podman_subnet_iface: podman1 +``` + +### Unqualified Search Registries + +When you use short image names (without registry prefix), Podman searches these registries in order: + +```bash +# Short name +podman pull redis:alpine + +# Resolves to +docker.io/library/redis:alpine +``` + +**Default search order:** +1. `docker.io` - Docker Hub +2. `quay.io` - Red Hat Quay +3. `ghcr.io` - GitHub Container Registry + +You can customize this list via the `podman_unqualified_search_registries` variable. + +### Podman Bridge Network + +By default, Podman dynamically assigns network subnets to bridge interfaces. You can document your network configuration using these variables: + +**Default behavior (empty `podman_subnet`):** +- Podman manages networks automatically +- No manual configuration needed + +**Explicit network documentation:** + +```yaml +podman_subnet: "10.89.0.0/24" +podman_subnet_gateway: "10.89.0.1" +podman_subnet_iface: podman1 +``` + +Use this to: +- Document your infrastructure topology +- Allow services to bind to the bridge gateway (e.g., PostgreSQL, Valkey) +- Reference in other roles that need bridge network information +- Maintain consistent network configuration across deployments + +**Finding your Podman network:** + +```bash +# List Podman networks +podman network ls + +# Show bridge interfaces +ip addr show | grep podman + +# Get specific interface IP +ip -4 addr show podman1 +``` + +## Dependencies + +None. + +## Example Playbook + +```yaml +--- +- hosts: servers + become: true + roles: + - role: podman +``` + +### Custom Configuration + +```yaml +--- +- hosts: servers + become: true + roles: + - role: podman + vars: + podman_projects_dir: /mnt/storage/containers + podman_unqualified_search_registries: + - docker.io + - ghcr.io + - registry.gitlab.com +``` + +## Files Deployed + +- `/etc/containers/registries.conf` - Registry configuration +- `{{ podman_projects_dir }}` - Projects directory (default: `/opt/podman`) + +## Usage + +### Running Containers + +```bash +# Using short names (works after role deployment) +podman run -d redis:alpine + +# Using fully qualified names (always works) +podman run -d docker.io/library/redis:alpine +``` + +### Docker Compose + +Services using `podman-compose` should store their compose files in subdirectories: + +``` +/opt/podman/ +├── immich/ +│ └── docker-compose.yml +├── nextcloud/ +│ └── docker-compose.yml +└── gitea/ + └── docker-compose.yml +``` + +## Troubleshooting + +### Short names not resolving + +Check the registries configuration: +```bash +cat /etc/containers/registries.conf +``` + +Test search order: +```bash +podman search redis --limit 3 +``` + +### Permission denied + +Ensure the user is in the appropriate groups (handled by Podman package): +```bash +# Check groups +groups $USER + +# May need to log out and back in after installation +``` + +## License + +MIT + +## Author Information + +Created for managing containerized services in NAS/homelab environments. diff --git a/roles/podman/defaults/main.yml b/roles/podman/defaults/main.yml index aa5ccbb..89ba48c 100644 --- a/roles/podman/defaults/main.yml +++ b/roles/podman/defaults/main.yml @@ -1 +1,24 @@ +--- podman_projects_dir: /opt/podman + +# Unqualified search registries (for short image names like "redis:alpine") +podman_unqualified_search_registries: + - docker.io + - quay.io + - ghcr.io + +# Podman bridge network configuration +# Define the network where containers will operate +# Leave empty to use Podman's default dynamic network assignment +# Example: "10.89.0.0/24" if you want to explicitly set it +podman_subnet: "" + +# Podman bridge gateway IP (typically .1 of the bridge network) +# Used by services that need to bind to the bridge interface +# Example: "10.89.0.1" for the 10.89.0.0/24 network +podman_subnet_gateway: "" + +# Podman bridge interface name (corresponds to the network above) +# Common values: podman0, podman1, etc. +# Only relevant if podman_subnet is set +podman_subnet_iface: podman1 diff --git a/roles/podman/tasks/main.yml b/roles/podman/tasks/main.yml index 345d07e..c5a43aa 100644 --- a/roles/podman/tasks/main.yml +++ b/roles/podman/tasks/main.yml @@ -1,20 +1,36 @@ -- name: install podman - package: - name: podman +--- +- name: Install podman packages + ansible.builtin.package: + name: + - podman + - podman-compose + state: present -- command: +- name: Get main user + ansible.builtin.command: cmd: whoami no_log: true become: false register: main_user + changed_when: false -- set_fact: +- name: Set main user variable + ansible.builtin.set_fact: main_user: "{{ main_user.stdout }}" no_log: true -- name: create projects directory - file: +- name: Create projects directory + ansible.builtin.file: path: "{{ podman_projects_dir }}" state: directory owner: "{{ main_user }}" group: "{{ main_user }}" + mode: "0755" + +- name: Deploy registries configuration + ansible.builtin.template: + src: registries.conf.j2 + dest: /etc/containers/registries.conf + owner: root + group: root + mode: "0644" diff --git a/roles/podman/templates/registries.conf.j2 b/roles/podman/templates/registries.conf.j2 new file mode 100644 index 0000000..bc04c3a --- /dev/null +++ b/roles/podman/templates/registries.conf.j2 @@ -0,0 +1,14 @@ +# Podman registries configuration managed by Ansible + +# Unqualified search registries +# These registries will be searched when using short image names (e.g., "redis:alpine") +unqualified-search-registries = [ +{% for registry in podman_unqualified_search_registries %} + "{{ registry }}"{{ "," if not loop.last else "" }} +{% endfor %} +] + +# Registry configuration +# docker.io +[[registry]] +location = "docker.io"