- name: Install Podman with Docker CLI tools ansible.builtin.apt: name: ["podman", "docker-cli", "docker-compose"] state: present - name: Allow rootless containers to use capabilities in their user namespace ansible.posix.seboolean: name: container_use_userns_all_caps state: true persistent: true when: selinux is defined and selinux is not false - name: Create SELinux policy build directory ansible.builtin.file: path: "{{ podman_selinux_dir }}" state: directory owner: root group: root mode: "0755" when: selinux is defined and selinux is not false - name: Install container log SELinux policy source ansible.builtin.copy: src: oci_log.te dest: "{{ podman_selinux_dir }}/oci_log.te" owner: root group: root mode: "0644" register: podman_selinux_src when: selinux is defined and selinux is not false - name: Clear stale container log SELinux artifacts ansible.builtin.file: path: "{{ podman_selinux_dir }}/oci_log.{{ item }}" state: absent loop: [mod, pp] when: - selinux is defined and selinux is not false - podman_selinux_src is changed - name: Compile container log SELinux policy module ansible.builtin.command: cmd: >- checkmodule -M -m -o {{ podman_selinux_dir }}/oci_log.mod {{ podman_selinux_dir }}/oci_log.te creates: "{{ podman_selinux_dir }}/oci_log.mod" when: selinux is defined and selinux is not false - name: Package container log SELinux policy module ansible.builtin.command: cmd: >- semodule_package -o {{ podman_selinux_dir }}/oci_log.pp -m {{ podman_selinux_dir }}/oci_log.mod creates: "{{ podman_selinux_dir }}/oci_log.pp" when: selinux is defined and selinux is not false - name: List loaded SELinux policy modules ansible.builtin.command: cmd: semodule -l register: podman_semodule_list changed_when: false when: selinux is defined and selinux is not false - name: Load container log SELinux policy module ansible.builtin.command: cmd: semodule -i {{ podman_selinux_dir }}/oci_log.pp register: podman_semodule changed_when: podman_semodule.rc == 0 when: - selinux is defined and selinux is not false - podman_selinux_src is changed or "oci_log" not in podman_semodule_list.stdout_lines - name: Set SELinux context on container log directory community.general.sefcontext: target: "{{ podman_log_root }}(/.*)?" setype: oci_log_t state: present when: selinux is defined and selinux is not false - name: Create container log directory ansible.builtin.file: path: "{{ podman_log_root }}" state: directory owner: root group: root mode: "0755" setype: >- {{ (selinux is defined and selinux is not false) | ternary('oci_log_t', omit) }} - name: Install GnuPG tools and trusted CA bundle ansible.builtin.apt: name: ["gnupg", "ca-certificates"] state: present when: podman_compose is defined - name: Get podman user info for user namespace configuration ansible.builtin.getent: database: passwd key: "{{ item }}" loop: "{{ podman_compose.keys() | list }}" register: user_info loop_control: label: "{{ item }}" when: podman_compose is defined - name: Set subuid base facts for podman users ansible.builtin.set_fact: podman_subuid_base: "{{ podman_subuid_base | default({}) | combine({ item.item: 100000 + ((item.ansible_facts.getent_passwd[item.item][1] | int - 1000) * 65536) }) }}" loop: "{{ user_info.results }}" loop_control: label: "{{ item.item }}" - name: Configure /etc/subuid for rootless users ansible.builtin.lineinfile: path: "/etc/subuid" line: "{{ item.item }}:{{ podman_subuid_base[item.item] }}:65536" regexp: "^{{ item.item }}:" create: true backup: true mode: "0644" loop: "{{ user_info.results }}" loop_control: label: "{{ item.item }}" - name: Configure /etc/subgid for rootless users ansible.builtin.lineinfile: path: "/etc/subgid" line: "{{ item.item }}:{{ podman_subuid_base[item.item] }}:65536" regexp: "^{{ item.item }}:" create: true backup: true mode: "0644" loop: "{{ user_info.results }}" loop_control: label: "{{ item.item }}" - name: Ensure systemd linger directory exists ansible.builtin.file: path: /var/lib/systemd/linger state: directory owner: root group: root mode: "0755" - name: Enable lingering for podman compose users ansible.builtin.file: path: "/var/lib/systemd/linger/{{ item.item }}" state: touch owner: root group: root mode: "0644" access_time: preserve modification_time: preserve loop: "{{ user_info.results }}" loop_control: label: "{{ item.item }}" - name: Start user manager for podman compose users ansible.builtin.systemd_service: name: "user@{{ item.ansible_facts.getent_passwd[item.item][1] }}.service" state: started loop: "{{ user_info.results }}" loop_control: label: "{{ item.item }}" - name: Wait for user runtime directory ansible.builtin.wait_for: path: "/run/user/{{ item.ansible_facts.getent_passwd[item.item][1] }}/bus" timeout: 30 loop: "{{ user_info.results }}" loop_control: label: "{{ item.item }}" - name: Start and enable the Podman socket ansible.builtin.systemd: name: podman.socket state: started enabled: true scope: user vars: uid: "{{ item.ansible_facts.getent_passwd[item.item][1] }}" environment: XDG_RUNTIME_DIR: "/run/user/{{ uid }}" DBUS_SESSION_BUS_ADDRESS: "unix:path=/run/user/{{ uid }}/bus" become: true become_user: "{{ item.item }}" loop: "{{ user_info.results }}" loop_control: label: "{{ item.item }}" - name: Create global containers config directory ansible.builtin.file: path: /etc/containers state: directory mode: "0755" - name: Configure global containers.conf for rootless ansible.builtin.copy: content: | [engine] cgroup_manager = "cgroupfs" events_logger = "journald" runtime = "crun" dest: /etc/containers/containers.conf backup: true mode: "0644" - name: Configure Docker CLI to use rootless Podman socket ansible.builtin.copy: src: files/docker-host.sh dest: /etc/profile.d/docker-host.sh owner: root group: root mode: "0755" - name: Install git for repository cloning ansible.builtin.apt: name: git state: present when: podman_compose is defined - name: Login to private Podman registries with Docker CLI for each user ansible.builtin.include_tasks: login.yml loop: "{{ podman_login | dict2items }}" loop_control: loop_var: podman_user when: podman_login is defined - name: Stat rootless Podman directory ansible.builtin.stat: path: "/home/{{ compose_user.key }}/.local/share/containers" loop: "{{ podman_compose | dict2items }}" loop_control: loop_var: compose_user label: "{{ compose_user.key }}" register: podman_user_containers_stat when: - podman_compose is defined - selinux is defined - selinux is not false - name: Create rootless Podman directory ansible.builtin.file: path: "/home/{{ item.compose_user.key }}/.local/share/containers" state: directory owner: "{{ item.compose_user.key }}" group: "{{ item.compose_user.key }}" mode: "700" loop: "{{ podman_user_containers_stat.results }}" loop_control: label: "{{ item.compose_user.key }}" when: - podman_compose is defined - selinux is defined - selinux is not false - not item.stat.exists - name: Label rootless Podman directory ansible.builtin.command: >- restorecon -Rv /home/{{ item.compose_user.key }}/.local/share/containers loop: "{{ podman_user_containers_stat.results }}" loop_control: label: "/home/{{ item.compose_user.key }}/.local/share/containers" changed_when: true when: - podman_compose is defined - selinux is defined - selinux is not false - not item.stat.exists - name: Stat Podman label directories ansible.builtin.stat: path: "{{ item.path }}" loop: "{{ podman_label }}" register: podman_label_stat loop_control: label: "{{ item.path }}" when: - podman_label is defined - selinux is defined - selinux is not false - name: Create Podman label directories ansible.builtin.file: path: "{{ item.item.path }}" owner: "{{ item.item.owner | default(omit) }}" group: "{{ item.item.group | default(omit) }}" mode: "{{ item.item.mode | default('700') }}" state: directory loop: "{{ podman_label_stat.results }}" loop_control: label: "{{ item.item.path }}" when: - podman_label is defined - selinux is defined - selinux is not false - not item.stat.exists - name: Set labels on Podman label directories ansible.builtin.command: "chcon {{ item.item.label }} {{ item.item.path }}" loop: "{{ podman_label_stat.results }}" changed_when: true loop_control: label: "{{ item.item.path }} => {{ item.item.label }}" when: - podman_label is defined - selinux is defined - selinux is not false - not item.stat.exists - name: Deploy Podman compose projects for each user ansible.builtin.include_tasks: deploy.yml vars: podman_user: "{{ compose_user.key }}" podman_compose_config: "{{ compose_user.value }}" loop: "{{ podman_compose | dict2items }}" loop_control: loop_var: compose_user when: podman_compose is defined tags: podman_compose