diff --git a/dev/host_vars/podman.yml b/dev/host_vars/podman.yml index e9a8ba2..0a438c7 100644 --- a/dev/host_vars/podman.yml +++ b/dev/host_vars/podman.yml @@ -1,4 +1,7 @@ -# base +############## +#### base #### +############## + allow_reboot: false manage_network: false @@ -7,8 +10,37 @@ users: uid: 1001 gid: 1001 home: true + ansible_temp: true + +################ +#### podman #### +################ -# podman user_namespaces: - kris +podman_compose_deploy: + kris: + root: /home/kris/podman_root + trusted_keys: + - id: FBF673CEEC030F8AECA814E73EDA9C3441EDA925 + keyserver: keyserver.ubuntu.com + compose: + - name: traefik + url: https://github.com/krislamo/traefik + version: d62bd06b37ecf0993962b0449a9d708373f9e381 + enabled: true + accept_newhostkey: true # Consider verifying manually instead + env: + DASHBOARD: true + +################### +#### Bitwarden #### +################### + +# Get Installation ID & Key at https://bitwarden.com/host/ +bitwarden_domain: vault.local.krislamo.org +bitwarden_dbpass: password +bitwarden_install_id: 4ea840a3-532e-4cb6-a472-abd900728b23 +bitwarden_install_key: 1yB3Z2gRI0KnnH90C6p +#bitwarden_prodution: true diff --git a/dev/podman.yml b/dev/podman.yml index 21ea295..a5cda6f 100644 --- a/dev/podman.yml +++ b/dev/podman.yml @@ -6,3 +6,4 @@ roles: - base - podman + - bitwarden diff --git a/roles/base/tasks/system.yml b/roles/base/tasks/system.yml index 852585c..8c7bf92 100644 --- a/roles/base/tasks/system.yml +++ b/roles/base/tasks/system.yml @@ -90,6 +90,20 @@ label: "{{ item.key }}" when: users is defined +- name: Create Ansible's temporary remote directory for users + ansible.builtin.file: + path: "{{ item.value.homedir | default('/home/' + item.key) }}/.ansible/tmp" + state: directory + mode: "700" + owner: "{{ item.key }}" + group: "{{ item.value.gid }}" + loop: "{{ users | dict2items }}" + loop_control: + label: "{{ item.key }}" + when: + - users is defined + - item.value.ansible_temp | default(false) + - name: Set authorized_keys for system users ansible.posix.authorized_key: user: "{{ item.key }}" diff --git a/roles/podman/defaults/main.yml b/roles/podman/defaults/main.yml new file mode 100644 index 0000000..8639764 --- /dev/null +++ b/roles/podman/defaults/main.yml @@ -0,0 +1,4 @@ +# Default configuration for podman role +podman_repos_keytype: ed25519 +podman_ssh_key_path: "{{ ansible_user_dir }}/.ssh" +podman_nodocker: false diff --git a/roles/podman/handlers/main.yml b/roles/podman/handlers/main.yml new file mode 100644 index 0000000..3094352 --- /dev/null +++ b/roles/podman/handlers/main.yml @@ -0,0 +1,54 @@ +- name: Reload systemd manager configuration + ansible.builtin.systemd: + daemon_reload: true + scope: user + become: true + become_user: "{{ podman_user }}" + listen: podman_compose_systemd + +- name: Find which services had a podman-compose.yml updated + ansible.builtin.set_fact: + podman_compose_restart_list: + "{{ (podman_compose_restart_list | default([])) + [{'user': podman_user, + 'service': item.item.name}] }}" + loop: "{{ podman_compose_update.results }}" + loop_control: + label: "{{ podman_user }}/{{ item.item.name }}" + when: item.changed + listen: podman_compose_restart + +- name: Find which services had their .env updated + ansible.builtin.set_fact: + podman_compose_restart_list: + "{{ (podman_compose_restart_list | default([])) + [{'user': podman_user, + 'service': item.item.name}] }}" + loop: "{{ podman_compose_env_update.results }}" + loop_control: + label: "{{ podman_user }}/{{ item.item.name }}" + when: item.changed + listen: podman_compose_restart + +- name: Restart podman-compose services + ansible.builtin.systemd: + state: restarted + name: "podman-compose@{{ item.service }}" + scope: user + become: true + become_user: "{{ item.user }}" + loop: "{{ podman_compose_restart_list | default([]) | unique }}" + when: podman_compose_restart_list is defined + listen: podman_compose_restart + +- name: Start podman-compose services and enable on boot + ansible.builtin.systemd: + name: "podman-compose@{{ item.name }}" + state: started + enabled: true + scope: user + become: true + become_user: "{{ podman_user }}" + loop: "{{ podman_compose }}" + loop_control: + label: "{{ podman_user }}/{{ item.name }}" + when: item.enabled is defined and item.enabled is true + listen: podman_compose_enable diff --git a/roles/podman/tasks/deploy.yml b/roles/podman/tasks/deploy.yml new file mode 100644 index 0000000..c344f04 --- /dev/null +++ b/roles/podman/tasks/deploy.yml @@ -0,0 +1,182 @@ +- name: Get user info for podman compose user + ansible.builtin.getent: + database: passwd + key: "{{ podman_user }}" + register: podman_user_info + +- name: Set user-specific variables + ansible.builtin.set_fact: + podman_rootdir: "{{ podman_compose_config.root }}" + podman_userid: "{{ podman_user_info.ansible_facts.getent_passwd[podman_user][1] }}" + podman_compose: "{{ podman_compose_config.compose }}" + podman_repos: "{{ podman_compose_config.root }}/.compose_repos" + +- name: Create podman-compose root directory for user + ansible.builtin.file: + path: "{{ podman_rootdir }}" + state: directory + owner: "{{ podman_user }}" + group: "{{ podman_user }}" + mode: "0700" + +- name: Create user systemd directory + ansible.builtin.file: + path: "/home/{{ podman_user }}/.config/systemd/user" + state: directory + owner: "{{ podman_user }}" + group: "{{ podman_user }}" + mode: "0755" + +- name: Install podman-compose systemd service for user + ansible.builtin.template: + src: podman-compose.service.j2 + dest: "/home/{{ podman_user }}/.config/systemd/user/podman-compose@.service" + owner: "{{ podman_user }}" + group: "{{ podman_user }}" + mode: "0644" + notify: podman_compose_systemd + +- name: Create directories for cloning podman-compose repositories + ansible.builtin.file: + path: "{{ repo_dir }}" + state: directory + owner: "{{ podman_user }}" + group: "{{ podman_user }}" + mode: "0700" + loop: + - "{{ podman_repos }}" + loop_control: + loop_var: repo_dir + when: + - podman_compose is defined + - podman_compose | length > 0 + +- name: Create .ssh directory for podman compose user + ansible.builtin.file: + path: "{{ podman_ssh_key_path }}" + state: directory + owner: "{{ podman_user }}" + group: "{{ podman_user }}" + mode: "0700" + when: + - podman_compose is defined + - podman_compose | length > 0 + +- name: Generate OpenSSH deploy keys for podman-compose clones + community.crypto.openssh_keypair: + path: "{{ podman_ssh_key_path }}/podman-id_{{ podman_repos_keytype }}" + type: "{{ podman_repos_keytype }}" + comment: "{{ ansible_hostname }}-{{ podman_user }}-deploy-key" + owner: "{{ podman_user }}" + group: "{{ podman_user }}" + mode: "0600" + state: present + when: podman_compose is defined + +- name: Import trusted GPG keys for podman-compose projects + ansible.builtin.command: + cmd: "gpg --keyserver {{ key.keyserver | default('keys.openpgp.org') }} --recv-key {{ key.id }}" + become: true + become_user: "{{ podman_user }}" + loop: "{{ podman_compose_config.trusted_keys }}" + loop_control: + loop_var: key + label: "{{ key.id }}" + changed_when: false + when: podman_compose_config.trusted_keys is defined + +- name: Clone external podman-compose projects + ansible.builtin.git: + repo: "{{ project.url }}" + dest: "{{ podman_repos }}/{{ project.name }}" + version: "{{ project.version }}" + accept_newhostkey: "{{ project.accept_newhostkey | default(false) }}" + gpg_whitelist: "{{ (project.trusted_keys | default(podman_compose_config.trusted_keys | default([]))) | map(attribute='id') | list }}" + verify_commit: >- + {{ true if (project.trusted_keys is defined and project.trusted_keys) or + (podman_compose_config.trusted_keys is defined and podman_compose_config.trusted_keys) + else false }} + key_file: "{{ podman_ssh_key_path }}/podman-id_{{ podman_repos_keytype }}" + become: true + become_user: "{{ podman_user }}" + loop: "{{ podman_compose }}" + loop_control: + loop_var: project + label: "{{ project.url }}" + when: + - podman_compose is defined + - podman_compose | length > 0 + +- name: Create directories for podman-compose projects + ansible.builtin.file: + path: "{{ podman_rootdir }}/{{ project.name }}" + state: directory + owner: "{{ podman_user }}" + group: "{{ podman_user }}" + mode: "0700" + loop: "{{ podman_compose }}" + loop_control: + loop_var: project + label: "{{ project.name }}" + when: + - podman_compose is defined + - podman_compose | length > 0 + +- name: Synchronize podman-compose.yml (or docker-compose.yml) + ansible.posix.synchronize: + src: "{{ podman_repos }}/{{ project.name }}/{{ project.path | default('docker-compose.yml') }}" + dest: "{{ podman_rootdir }}/{{ project.name }}/docker-compose.yml" + owner: false + group: false + delegate_to: "{{ inventory_hostname }}" + register: podman_compose_update + notify: + - podman_compose_restart + - podman_compose_enable + loop: "{{ podman_compose | default([]) }}" + loop_control: + loop_var: project + label: "{{ project.name }}" + when: + - podman_compose is defined + - podman_compose | length > 0 + +- name: Fix ownership of synchronized compose files + ansible.builtin.file: + path: "{{ podman_rootdir }}/{{ project.name }}/docker-compose.yml" + owner: "{{ podman_user }}" + group: "{{ podman_user }}" + mode: "0600" + loop: "{{ podman_compose | default([]) }}" + loop_control: + loop_var: project + label: "{{ project.name }}" + when: + - podman_compose is defined + - podman_compose | length > 0 + +- name: Set environment variables for podman-compose projects + ansible.builtin.template: + src: podman-compose-env.j2 + dest: "{{ podman_rootdir }}/{{ project.name }}/.env" + owner: "{{ podman_user }}" + group: "{{ podman_user }}" + mode: "0600" + register: podman_compose_env_update + notify: + - podman_compose_restart + - podman_compose_enable + no_log: true + loop: "{{ podman_compose }}" + loop_control: + loop_var: project + label: "{{ project.name }}" + when: podman_compose is defined and project.env is defined + +- name: Enable lingering for podman compose user + ansible.builtin.command: + cmd: "loginctl enable-linger {{ podman_user }}" + changed_when: false + when: + - podman_compose is defined + - podman_compose | length > 0 diff --git a/roles/podman/tasks/main.yml b/roles/podman/tasks/main.yml index fac30bc..9c7fb4d 100644 --- a/roles/podman/tasks/main.yml +++ b/roles/podman/tasks/main.yml @@ -43,6 +43,7 @@ owner: root group: root mode: "0644" + when: podman_nodocker | bool - name: Create global containers config directory ansible.builtin.file: @@ -60,3 +61,17 @@ dest: /etc/containers/containers.conf mode: "0644" backup: true + +- name: Install git for repository cloning + ansible.builtin.apt: + name: git + state: present + when: podman_compose_deploy is defined + +- name: Deploy Podman compose projects for each user + ansible.builtin.include_tasks: deploy.yml + vars: + podman_user: "{{ item.key }}" + podman_compose_config: "{{ item.value }}" + loop: "{{ podman_compose_deploy | dict2items }}" + when: podman_compose_deploy is defined diff --git a/roles/podman/templates/podman-compose-env.j2 b/roles/podman/templates/podman-compose-env.j2 new file mode 100644 index 0000000..8e31e49 --- /dev/null +++ b/roles/podman/templates/podman-compose-env.j2 @@ -0,0 +1,10 @@ +# {{ ansible_managed }} +{% if item.env is defined %} +{% for key, value in item.env.items() %} +{% if value is boolean %} +{{ key }}={{ value | lower }} +{% else %} +{{ key }}={{ value }} +{% endif %} +{% endfor %} +{% endif %} \ No newline at end of file diff --git a/roles/podman/templates/podman-compose.service.j2 b/roles/podman/templates/podman-compose.service.j2 new file mode 100644 index 0000000..770da40 --- /dev/null +++ b/roles/podman/templates/podman-compose.service.j2 @@ -0,0 +1,17 @@ +[Unit] +Description=%i podman-compose service for {{ podman_user }} +After=network-online.target +Wants=network-online.target + +[Service] +Type=oneshot +RemainAfterExit=true +WorkingDirectory={{ podman_rootdir }}/%i +ExecStart=/usr/bin/podman-compose up -d --remove-orphans +ExecStop=/usr/bin/podman-compose down +Environment="PODMAN_USERNS=keep-id" +Environment="PODMAN_SOCKET_PATH=/run/user/{{ podman_userid }}/podman/podman.sock" +TimeoutStartSec=0 + +[Install] +WantedBy=default.target \ No newline at end of file