aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--README.md56
-rw-r--r--containers.yml148
-rw-r--r--docs/sample-environment/wordpress.yml15
-rw-r--r--docs/sample-environment/wordpress/quadlet/wordpress-app.container13
-rw-r--r--docs/sample-environment/wordpress/quadlet/wordpress-db.container13
-rw-r--r--docs/sample-environment/wordpress/quadlet/wordpress.pod11
-rw-r--r--host.yml118
-rw-r--r--roles/containers/defaults/main.yml11
-rw-r--r--roles/containers/tasks/main.yml17
-rw-r--r--roles/containers/tasks/quadlet_create.yml22
-rw-r--r--roles/containers/tasks/quadlet_remove.yml14
-rw-r--r--roles/containers/tasks/quadlet_start.yml27
-rw-r--r--roles/containers/tasks/quadlet_stop.yml8
-rw-r--r--roles/host/defaults/main.yml9
-rw-r--r--roles/host/files/check-network-online.service14
-rw-r--r--roles/host/tasks/cpanel-dnsonly.yml28
-rw-r--r--roles/host/tasks/linger.yml8
-rw-r--r--roles/host/tasks/main.yml19
-rw-r--r--roles/host/tasks/packages.yml6
-rw-r--r--roles/host/tasks/shell-helper.yml31
-rw-r--r--roles/host/tasks/systemd-user-network-check.yml20
-rw-r--r--roles/host/tasks/unprivileged-ports.yml17
-rw-r--r--roles/host/tasks/user.yml9
23 files changed, 330 insertions, 304 deletions
diff --git a/README.md b/README.md
index 6e803e0..05ad567 100644
--- a/README.md
+++ b/README.md
@@ -4,40 +4,42 @@ Ansible playbook for deploying and managing Podman containers.
![PodPlaybook](docs/images/logo.png)
-This playbook is for deploying and managing Podman containers in a reproducible way.
-By default it will create systemd service files and is compatible with or without the use of pods.
+This repo contains two roles, `host` and `containers`, that automate the deployment of Podman containers using quadlet.
+Quadlet files and some understanding of quadlet and/or systemd is required to use this tool.
## Usage
-- ```ansible-playbook host.yml```
-- ```machinectl shell containers@```
-- ```ansible-galaxy install -r collections/requirements.yml```
-- ```ansible-playbook containers.yml -e @docs/sample-environment/wordpress.yml```
+ ansible-playbook host.yml
+ sudo machinectl shell containers@
+ ansible-galaxy install -r collections/requirements.yml
+ ansible-playbook containers.yml
## Features
-- Declare container architecture using Ansible variables file
-- Rebuild, stop, start, enable systemd service, disable + remove systemd files
-- One command for re-build image, re-generate systemd unit files
-- Optionally, use tags for more precise control
- - ```container-start```, ```container-stop```, ```generate-systemd```, ```rebuild```, ```remove```, ```service-start```, ```service-stop```
-- Utilizes rootless Podman
+- Designed for rootless Podman
+- Easily deploy/remove quadlet files and stop/start quadlet services
+- Define your application's quadlet files so they are treated as one entity with Ansible
## Sample Environment
-A fully working pod with Wordpress and a MariaDB database are in the ```docs/sample-environment``` directory.
+A fully working pod with Wordpress and a MariaDB database are in the `docs/sample-environment` directory.
+The default variables in the `container` role will use this sample environment for deployment.
+Provide your own inventory and/or variables to override this.
## Requirements
- Ansible
-- Ansible collections
- - ```ansible-galaxy install -r collections/requirements.yml```
+- Ansible collections:
+ - ```ansible-galaxy install -r collections/requirements.yml```
- Podman
-- User with ```sudo``` rights
-
-## Assumptions
-- Rootless mode is being used, so tasks are written to use systemd user scope
- - Tasks would need to be tweaked for using the root user
-- ```containers``` user is automatically created during the ```host.yml``` play
-- The tasks were purposely kept simple, its expected that you use Podman runlabels for most options
-
-## Limitations
-- Tasks were written to be run as the unprivileged user - however this is tricky in Ansible
- - Because of this, I recommend using ```machinectl shell containers@``` to become user before running the ```containers.yml``` play
- - Your milage may vary if you use another method of changing users
+- User with `sudo` rights (to create unprivileged user)
+
+## Operation
+- `host.yml` - installs the needed packages and creates the `containers` unprivileged user - use with a privileged account
+- `containers.yml` - will copy the quadlet files and start the quadlet - use with the unprivileged account
+
+## Tags
+- `host.yml`:
+ - `unprivileged-ports` - configures host to allow port `80` and above to be used by unprivileged accounts
+ - `cpanel-dnsonly` - changes only needed when running on a dnsonly cPanel instance, check `roles/host/tasks/cpanel-dnsonly.yml` for details
+- `containers.yml`:
+ - `create` - create quadlet files
+ - `remove` - remove quadlet files
+ - `start` - start quadlet services
+ - `stop` - stop quadlet services
diff --git a/containers.yml b/containers.yml
index ab61772..59de80c 100644
--- a/containers.yml
+++ b/containers.yml
@@ -1,149 +1,5 @@
- hosts: localhost
tasks:
- - name: Rebuild images
- containers.podman.podman_image:
- name: "{{ item.name }}:{{ ansible_date_time.date }}-{{ ansible_date_time.hour }}{{ ansible_date_time.minute }}{{ ansible_date_time.second }}"
- path: "{{ item.path }}"
- build:
- file: "{{ item.file }}"
- cache: false
- tags: rebuild
- loop: "{{ containers }}"
-
- - name: Tag new images to latest
- containers.podman.podman_tag:
- image: "{{ item.name }}:{{ ansible_date_time.date }}-{{ ansible_date_time.hour }}{{ ansible_date_time.minute }}{{ ansible_date_time.second }}"
- target_names: "{{ item.name }}:latest"
- tags: rebuild
- loop: "{{ containers }}"
-
- - name: Stop systemd pod service
- ansible.builtin.systemd:
- name: "pod-{{ pod.name }}.service"
- state: stopped
- scope: user
- ignore_errors: true
- tags:
- - remove
- - service-stop
- when: pod is defined
-
- - name: Remove systemd pod service file
- ansible.builtin.file:
- path: "~/.config/systemd/user/pod-{{ pod.name }}.service"
- state: absent
- tags: remove
- when: pod is defined
-
- - name: Stop systemd container service
- ansible.builtin.systemd:
- name: "container-{{ item.name }}.service"
- state: stopped
- scope: user
- ignore_errors: true
- tags:
- - remove
- - service-stop
- loop: "{{ containers }}"
-
- - name: Remove systemd container service file
- ansible.builtin.file:
- path: "~/.config/systemd/user/container-{{ item.name }}.service"
- state: absent
- tags: remove
- loop: "{{ containers }}"
-
- - name: Remove pod
- containers.podman.podman_pod:
- name: "{{ pod.name }}"
- state: absent
- tags:
- - remove
- - container-stop
- when: pod is defined
-
- - name: Remove containers
- containers.podman.podman_container:
- name: "{{ item.name }}"
- state: absent
- tags:
- - remove
- - container-stop
- loop: "{{ containers }}"
-
- - name: Create pod
- containers.podman.podman_pod:
- name: "{{ pod.name }}"
- ports: "{{ pod.ports }}"
- network: "{{ pod.network | default(omit) }}"
- state: started
- tags: container-start
- when: pod is defined
-
- - name: Start containers
- ansible.builtin.shell: "podman container runlabel {{ item.runlabel }} {{ item.name}}:latest"
- tags: container-start
- loop: "{{ containers }}"
-
- - name: Generate systemd service file for pod
- containers.podman.podman_generate_systemd:
- name: "{{ pod.name }}"
- dest: "~/.config/systemd/user/"
- new: true
- tags: generate-systemd
- when: pod is defined
-
- - name: Generate systemd service file for container (when pod is not in use)
- containers.podman.podman_generate_systemd:
- name: "{{ item.name }}"
- dest: "~/.config/systemd/user/"
- new: true
- tags: generate-systemd
- loop: "{{ containers }}"
- when: pod is not defined
-
- - name: Reload systemd daemon
- ansible.builtin.systemd:
- daemon_reload: true
- scope: user
- tags:
- - remove
- - generate-systemd
-
- - name: Pause for container full startup
- ansible.builtin.pause:
- seconds: 30
-
- - name: Remove pod
- containers.podman.podman_pod:
- name: "{{ pod.name }}"
- state: absent
- when: pod is defined
-
- - name: Remove containers
- containers.podman.podman_container:
- name: "{{ item.name }}"
- state: absent
- loop: "{{ containers }}"
-
- - name: Start systemd pod service
- ansible.builtin.systemd:
- name: "pod-{{ pod.name}}.service"
- state: started
- enabled: true
- scope: user
- tags: service-start
- when: pod is defined
-
- - name: Start systemd container service
- ansible.builtin.systemd:
- name: "container-{{ item.name }}.service"
- state: started
- enabled: true
- scope: user
- tags: service-start
- loop: "{{ containers }}"
-
- - name: Prune old images
- ansible.builtin.shell: "podman image prune -f"
+ - ansible.builtin.import_role:
+ name: "containers"
diff --git a/docs/sample-environment/wordpress.yml b/docs/sample-environment/wordpress.yml
deleted file mode 100644
index 6f16f9d..0000000
--- a/docs/sample-environment/wordpress.yml
+++ /dev/null
@@ -1,15 +0,0 @@
-pod:
- name: wordpress
- ports:
- - "8080:80"
-# network:
-
-containers:
- - name: wordpress-db
- path: "docs/sample-environment/wordpress"
- file: "wordpress-db.containerfile"
- runlabel: "start"
- - name: wordpress-app
- path: "docs/sample-environment/wordpress"
- file: "wordpress-app.containerfile"
- runlabel: "start"
diff --git a/docs/sample-environment/wordpress/quadlet/wordpress-app.container b/docs/sample-environment/wordpress/quadlet/wordpress-app.container
new file mode 100644
index 0000000..20f9b69
--- /dev/null
+++ b/docs/sample-environment/wordpress/quadlet/wordpress-app.container
@@ -0,0 +1,13 @@
+[Unit]
+Wants=wordpress-pod.service
+After=wordpress-pod.service
+PartOf=wordpress-pod.service
+
+[Container]
+ContainerName=wordpress-app
+Environment=WORDPRESS_DB_HOST=127.0.0.1 WORDPRESS_DB_USER=root WORDPRESS_DB_PASSWORD=TESTTESTTEST WORDPRESS_DB_NAME=wordpress WORDPRESS_TABLE_PREFIX=wp_
+Image=docker.io/library/wordpress:latest
+PodmanArgs=--pod wordpress
+
+[Install]
+WantedBy=default.target
diff --git a/docs/sample-environment/wordpress/quadlet/wordpress-db.container b/docs/sample-environment/wordpress/quadlet/wordpress-db.container
new file mode 100644
index 0000000..8e6e0d6
--- /dev/null
+++ b/docs/sample-environment/wordpress/quadlet/wordpress-db.container
@@ -0,0 +1,13 @@
+[Unit]
+Wants=wordpress-pod.service
+After=wordpress-pod.service
+PartOf=wordpress-pod.service
+
+[Container]
+ContainerName=wordpress-db
+Environment=MARIADB_DATABASE=wordpress MARIADB_ROOT_PASSWORD=TESTTESTTEST
+Image=docker.io/mariadb:latest
+PodmanArgs=--pod wordpress
+
+[Install]
+WantedBy=default.target
diff --git a/docs/sample-environment/wordpress/quadlet/wordpress.pod b/docs/sample-environment/wordpress/quadlet/wordpress.pod
new file mode 100644
index 0000000..eea748a
--- /dev/null
+++ b/docs/sample-environment/wordpress/quadlet/wordpress.pod
@@ -0,0 +1,11 @@
+[Unit]
+Wants=check-network-online.service wordpress-app.service wordpress-db.service
+Before=wordpress-app.service wordpress-db.service
+After=check-network-online.service
+
+[Pod]
+PublishPort=8080:80
+PodName=wordpress
+
+[Install]
+WantedBy=default.target
diff --git a/host.yml b/host.yml
index a9b3d78..f2dea0a 100644
--- a/host.yml
+++ b/host.yml
@@ -1,120 +1,6 @@
- hosts: localhost
become: true
- vars:
- shell_service_status_helper: |
- echo "----systemd----"
- systemctl --user list-units 'pod-*' -q
- echo ""
- systemctl --user list-units 'container-*' -q
- echo ""
- echo "----podman----"
- podman pod list --sort status --format={{ '"{{.Status}} {{.Name}}"' }}
- echo ""
- podman container list --all --sort status --format={{ '"{{.State}} {{.Status}} {{.Names}}"' }}
- echo ""
tasks:
- - name: Create containers user
- ansible.builtin.user:
- name: "containers"
-
- - name: Add bashrc for container service status on login
- ansible.builtin.blockinfile:
- path: "/home/containers/.bashrc"
- owner: "containers"
- group: "containers"
- create: true
- block: "{{ shell_service_status_helper }}"
-
- - name: Check if fish shell is installed
- ansible.builtin.stat:
- path: "/usr/bin/fish"
- register: fish
-
- - name: Add fish config for container service status on login
- ansible.builtin.blockinfile:
- path: "/home/containers/.config/fish/conf.d/containers.fish"
- owner: "containers"
- group: "containers"
- create: true
- block: "{{ shell_service_status_helper }}"
- when: fish.stat.exists
-
- - name: Fix permissions on /home/containers
- ansible.builtin.file:
- path: "/home/containers"
- state: directory
- owner: "containers"
- group: "containers"
- recurse: true
-
- - name: Install systemd-container and podman
- ansible.builtin.package:
- name:
- - "systemd-container"
- - "podman"
- state: present
-
- - name: Confirm systemd-linger is set for containers user
- ansible.builtin.stat:
- path: "/var/lib/systemd/linger/containers"
- register: linger
-
- - name: Set systemd-linger for containers user (if necessary)
- ansible.builtin.shell: "loginctl enable-linger containers"
- when: not linger.stat.exists
-
- - name: Unprivileged port block
- block:
- - name: Confirm port 80 and above is allowed for unprivileged use
- ansible.builtin.shell: "sysctl net.ipv4.ip_unprivileged_port_start |grep 80"
-
- rescue:
- - name: Set sysctl parameter net.ipv4.ip_unprivileged_port_start=80
- ansible.builtin.lineinfile:
- path: "/etc/sysctl.conf"
- regexp: "^net.ipv4.ip_unprivileged_port_start=80"
- line: "net.ipv4.ip_unprivileged_port_start=80"
-
- - name: Reload sysctl
- ansible.builtin.shell: "sysctl -p /etc/sysctl.conf"
-
- - name: Confirm port 80 and above is allowed for unprivileged use
- ansible.builtin.shell: "sysctl net.ipv4.ip_unprivileged_port_start |grep 80"
- tags:
- - never
- - unprivileged-ports
-
- - name: cPanel DNS-only block
- block:
- - name: Confirm if cpsrvd is not listening on http ports
- ansible.builtin.shell: "whmapi1 get_tweaksetting key='disable_cphttpd' |grep 'value: 1' || /bin/true"
- register: cpsrv_listen
-
- - name: Turn off cpsrvd listening on http ports (if necessary)
- ansible.builtin.shell: "whmapi1 set_tweaksetting key='disable_cphttpd' value='1' ; /scripts/restartsrv_cpsrvd"
- when: cpsrv_listen.stdout | length == 0
-
- - name: Turn off firewalld
- ansible.builtin.service:
- name: "firewalld"
- state: stopped
- enabled: false
-
- - name: Create new tmp directory for podman
- ansible.builtin.file:
- path: "/var/containers/tmp"
- owner: containers
- group: containers
- state: directory
-
- - name: Configure podman to use new tmp directory
- ansible.builtin.blockinfile:
- path: "/etc/containers/containers.conf"
- create: true
- block: |
- [engine]
- env = ["TMPDIR=/var/containers/tmp"]
- tags:
- - never
- - cpanel-dnsonly
+ - ansible.builtin.import_role:
+ name: "host"
diff --git a/roles/containers/defaults/main.yml b/roles/containers/defaults/main.yml
new file mode 100644
index 0000000..ade45f3
--- /dev/null
+++ b/roles/containers/defaults/main.yml
@@ -0,0 +1,11 @@
+quadlet_path: "../../docs/sample-environment/wordpress/quadlet"
+
+quadlets:
+ - name: "wordpress-pod"
+ file: "wordpress.pod"
+
+ - name: "wordpress-app"
+ file: "wordpress-app.container"
+
+ - name: "wordpress-db"
+ file: "wordpress-db.container"
diff --git a/roles/containers/tasks/main.yml b/roles/containers/tasks/main.yml
new file mode 100644
index 0000000..02ee577
--- /dev/null
+++ b/roles/containers/tasks/main.yml
@@ -0,0 +1,17 @@
+- ansible.builtin.import_tasks: quadlet_create.yml
+ tags:
+ - create
+
+- ansible.builtin.import_tasks: quadlet_start.yml
+ tags:
+ - start
+
+- ansible.builtin.import_tasks: quadlet_stop.yml
+ tags:
+ - never
+ - stop
+
+- ansible.builtin.import_tasks: quadlet_remove.yml
+ tags:
+ - never
+ - remove
diff --git a/roles/containers/tasks/quadlet_create.yml b/roles/containers/tasks/quadlet_create.yml
new file mode 100644
index 0000000..ffbae8a
--- /dev/null
+++ b/roles/containers/tasks/quadlet_create.yml
@@ -0,0 +1,22 @@
+- name: Create quadlet directory
+ ansible.builtin.file:
+ path: "{{ lookup('env', 'HOME') }}/.config/containers/systemd"
+ state: "directory"
+
+- name: Copy quadlet files into quadlet directory
+ ansible.builtin.copy:
+ src: "{{ quadlet_path}}/{{ item.file }}"
+ dest: "{{ lookup('env', 'HOME') }}/.config/containers/systemd/{{ item.file }}"
+ loop_control:
+ label: "{{ item.name }} -> {{ item.file }}"
+ loop: "{{ quadlets }}"
+ register: quadlet_files
+
+- name: Reload systemd daemon
+ ansible.builtin.systemd:
+ daemon_reload: true
+ scope: "user"
+ when: quadlet_files.changed
+
+- name: Check quadlet status
+ ansible.builtin.shell: "/usr/lib/systemd/system-generators/podman-system-generator --user --dryrun"
diff --git a/roles/containers/tasks/quadlet_remove.yml b/roles/containers/tasks/quadlet_remove.yml
new file mode 100644
index 0000000..e6bc05b
--- /dev/null
+++ b/roles/containers/tasks/quadlet_remove.yml
@@ -0,0 +1,14 @@
+- name: Remove quadlet files from quadlet directory
+ ansible.builtin.file:
+ path: "{{ lookup('env', 'HOME') }}/.config/containers/systemd/{{ item.file }}"
+ state: "absent"
+ loop_control:
+ label: "{{ item.name }} -> {{ item.file }}"
+ loop: "{{ quadlets }}"
+ register: quadlet_files
+
+- name: Reload systemd daemon
+ ansible.builtin.systemd:
+ daemon_reload: true
+ scope: "user"
+ when: quadlet_files.changed
diff --git a/roles/containers/tasks/quadlet_start.yml b/roles/containers/tasks/quadlet_start.yml
new file mode 100644
index 0000000..5dcd39a
--- /dev/null
+++ b/roles/containers/tasks/quadlet_start.yml
@@ -0,0 +1,27 @@
+- name: Start quadlet
+ ansible.builtin.systemd_service:
+ name: "{{ item.name }}"
+ state: "started"
+ scope: "user"
+ loop_control:
+ label: "{{ item.name}}.service"
+ loop: "{{ quadlets }}"
+
+- name: Check for quadlet not in active or activating state
+ ansible.builtin.shell: "systemctl --user is-active {{ item.name }}.service"
+ loop_control:
+ label: "{{ item.name}}.service: {{ quadlet_status.stdout }}"
+ loop: "{{ quadlets }}"
+ register: quadlet_status
+ failed_when: quadlet_status.stdout not in ['active', 'activating']
+
+
+- name: Wait for quadlet state to go active
+ ansible.builtin.shell: "systemctl --user is-active {{ item.name }}.service"
+ loop_control:
+ label: "{{ item.name}}.service: {{ quadlet_status.stdout }}"
+ loop: "{{ quadlets }}"
+ register: quadlet_status
+ until: quadlet_status.stdout == 'active'
+ delay: 2
+ retries: 25
diff --git a/roles/containers/tasks/quadlet_stop.yml b/roles/containers/tasks/quadlet_stop.yml
new file mode 100644
index 0000000..b8a83f3
--- /dev/null
+++ b/roles/containers/tasks/quadlet_stop.yml
@@ -0,0 +1,8 @@
+- name: Stop quadlet
+ ansible.builtin.systemd_service:
+ name: "{{ item.name }}"
+ state: "stopped"
+ scope: "user"
+ loop_control:
+ label: "{{ item.name}}.service"
+ loop: "{{ quadlets }}"
diff --git a/roles/host/defaults/main.yml b/roles/host/defaults/main.yml
new file mode 100644
index 0000000..c393dc8
--- /dev/null
+++ b/roles/host/defaults/main.yml
@@ -0,0 +1,9 @@
+host_shell_login_helper: |
+ echo "----pods----"
+ podman pod list --sort status --format={{ '"{{.Status}} {{.Name}}"' }}
+ echo ""
+ echo "----containers----"
+ podman container list --all --sort status --format={{ '"{{.State}} {{.Status}} {{.Names}}"' }}
+ echo ""
+
+host_containers_user: "containers"
diff --git a/roles/host/files/check-network-online.service b/roles/host/files/check-network-online.service
new file mode 100644
index 0000000..afadbfe
--- /dev/null
+++ b/roles/host/files/check-network-online.service
@@ -0,0 +1,14 @@
+#This is needed because user units cannot check or interact with system units such as network-online.target
+#https://github.com/containers/podman/issues/22197
+#https://github.com/systemd/systemd/issues/3312
+
+[Unit]
+Description=Check for system level network-online.target (for users)
+
+[Service]
+Type=oneshot
+ExecStart=bash -c 'until systemctl is-active network-online.target; do sleep 1; done'
+RemainAfterExit=yes
+
+[Install]
+WantedBy=default.target
diff --git a/roles/host/tasks/cpanel-dnsonly.yml b/roles/host/tasks/cpanel-dnsonly.yml
new file mode 100644
index 0000000..dbb9062
--- /dev/null
+++ b/roles/host/tasks/cpanel-dnsonly.yml
@@ -0,0 +1,28 @@
+- name: Confirm if cpsrvd is not listening on http ports
+ ansible.builtin.shell: "whmapi1 get_tweaksetting key='disable_cphttpd' |grep 'value: 1' || /bin/true"
+ register: cpsrv_listen
+
+- name: Turn off cpsrvd listening on http ports (if necessary)
+ ansible.builtin.shell: "whmapi1 set_tweaksetting key='disable_cphttpd' value='1' ; /scripts/restartsrv_cpsrvd"
+ when: cpsrv_listen.stdout | length == 0
+
+- name: Turn off firewalld
+ ansible.builtin.service:
+ name: "firewalld"
+ state: stopped
+ enabled: false
+
+- name: Create new tmp directory for podman
+ ansible.builtin.file:
+ path: "/var/containers/tmp"
+ owner: "{{ host_containers_user }}"
+ group: "{{ host_containers_user }}"
+ state: directory
+
+- name: Configure podman to use new tmp directory
+ ansible.builtin.blockinfile:
+ path: "/etc/containers/containers.conf"
+ create: true
+ block: |
+ [engine]
+ env = ["TMPDIR=/var/containers/tmp"]
diff --git a/roles/host/tasks/linger.yml b/roles/host/tasks/linger.yml
new file mode 100644
index 0000000..dffc6a7
--- /dev/null
+++ b/roles/host/tasks/linger.yml
@@ -0,0 +1,8 @@
+- name: Confirm systemd-linger is set for containers user
+ ansible.builtin.stat:
+ path: "/var/lib/systemd/linger/{{ host_containers_user }}"
+ register: linger
+
+- name: Set systemd-linger for containers user (if necessary)
+ ansible.builtin.shell: "loginctl enable-linger {{ host_containers_user }}"
+ when: not linger.stat.exists
diff --git a/roles/host/tasks/main.yml b/roles/host/tasks/main.yml
new file mode 100644
index 0000000..5b9dd6b
--- /dev/null
+++ b/roles/host/tasks/main.yml
@@ -0,0 +1,19 @@
+- ansible.builtin.import_tasks: packages.yml
+
+- ansible.builtin.import_tasks: user.yml
+
+- ansible.builtin.import_tasks: linger.yml
+
+- ansible.builtin.import_tasks: shell-helper.yml
+
+- ansible.builtin.import_tasks: systemd-user-network-check.yml
+
+- ansible.builtin.import_tasks: unprivileged-ports.yml
+ tags:
+ - never
+ - unprivileged-ports
+
+- ansible.builtin.import_tasks: cpanel-dnsonly.yml
+ tags:
+ - never
+ - cpanel-dnsonly
diff --git a/roles/host/tasks/packages.yml b/roles/host/tasks/packages.yml
new file mode 100644
index 0000000..df78985
--- /dev/null
+++ b/roles/host/tasks/packages.yml
@@ -0,0 +1,6 @@
+- name: Install systemd-container and podman
+ ansible.builtin.package:
+ name:
+ - "systemd-container"
+ - "podman"
+ state: present
diff --git a/roles/host/tasks/shell-helper.yml b/roles/host/tasks/shell-helper.yml
new file mode 100644
index 0000000..e36784a
--- /dev/null
+++ b/roles/host/tasks/shell-helper.yml
@@ -0,0 +1,31 @@
+- name: Add bashrc for container service status on login
+ ansible.builtin.blockinfile:
+ path: "/home/{{ host_containers_user }}/.bashrc"
+ owner: "{{ host_containers_user }}"
+ group: "{{ host_containers_user }}"
+ create: true
+ block: "{{ host_shell_login_helper }}"
+
+- name: Check if fish shell is installed
+ ansible.builtin.stat:
+ path: "/usr/bin/fish"
+ register: fish
+
+- name: Block for fish
+ block:
+ - name: Create fish config directory
+ ansible.builtin.file:
+ path: "/home/{{ host_containers_user }}/.config/fish/conf.d"
+ state: directory
+ owner: "{{ host_containers_user }}"
+ group: "{{ host_containers_user }}"
+
+ - name: Add fish config for container service status on login
+ ansible.builtin.blockinfile:
+ path: "/home/{{ host_containers_user }}/.config/fish/conf.d/containers.fish"
+ owner: "{{ host_containers_user }}"
+ group: "{{ host_containers_user }}"
+ create: true
+ block: "{{ host_shell_login_helper }}"
+ when: fish.stat.exists
+ when: fish.stat.exists
diff --git a/roles/host/tasks/systemd-user-network-check.yml b/roles/host/tasks/systemd-user-network-check.yml
new file mode 100644
index 0000000..4c87f82
--- /dev/null
+++ b/roles/host/tasks/systemd-user-network-check.yml
@@ -0,0 +1,20 @@
+#This is a workaround so we can check for the network to come up before starting the quadlets
+#https://github.com/containers/podman/issues/22197
+#https://github.com/systemd/systemd/issues/3312
+
+- name: Copy check-network-online.service into systemd user service directory
+ ansible.builtin.copy:
+ src: "check-network-online.service"
+ dest: "/etc/systemd/user/check-network-online.service"
+ register: systemd
+
+- name: Reload systemd daemon
+ ansible.builtin.systemd_service:
+ daemon_reload: true
+ when: systemd.changed
+
+- name: Enable check-network-online.service for all users
+ ansible.builtin.systemd_service:
+ name: "check-network-online.service"
+ enabled: true
+ scope: "global"
diff --git a/roles/host/tasks/unprivileged-ports.yml b/roles/host/tasks/unprivileged-ports.yml
new file mode 100644
index 0000000..003646a
--- /dev/null
+++ b/roles/host/tasks/unprivileged-ports.yml
@@ -0,0 +1,17 @@
+- name: Unprivileged port block
+ block:
+ - name: Confirm port 80 and above is allowed for unprivileged use
+ ansible.builtin.shell: "sysctl net.ipv4.ip_unprivileged_port_start |grep 80"
+
+ rescue:
+ - name: Set sysctl parameter net.ipv4.ip_unprivileged_port_start=80
+ ansible.builtin.lineinfile:
+ path: "/etc/sysctl.conf"
+ regexp: "^net.ipv4.ip_unprivileged_port_start=80"
+ line: "net.ipv4.ip_unprivileged_port_start=80"
+
+ - name: Reload sysctl
+ ansible.builtin.shell: "sysctl -p /etc/sysctl.conf"
+
+ - name: Confirm port 80 and above is allowed for unprivileged use
+ ansible.builtin.shell: "sysctl net.ipv4.ip_unprivileged_port_start |grep 80"
diff --git a/roles/host/tasks/user.yml b/roles/host/tasks/user.yml
new file mode 100644
index 0000000..40e9f4c
--- /dev/null
+++ b/roles/host/tasks/user.yml
@@ -0,0 +1,9 @@
+- name: Create containers user
+ ansible.builtin.user:
+ name: "{{ host_containers_user }}"
+
+- name: Add containers user to systemd-journal group
+ ansible.builtin.user:
+ name: "{{ host_containers_user }}"
+ groups: "systemd-journal"
+ append: true