diff options
| author | Jan Tuomi <jan@jantuomi.fi> | 2026-05-16 19:19:07 +0300 |
|---|---|---|
| committer | Jan Tuomi <jan@jantuomi.fi> | 2026-05-16 19:19:07 +0300 |
| commit | 75732c1a9aa1fed11794f509d33bdea5171d41c0 (patch) | |
| tree | 057717d5e3010b77f15b9fd36806e691fbfc0853 | |
| parent | b97ed17f3747345ccf83ddd7c2b4349f43c73e98 (diff) | |
Set up redis jail, improve role setup
| -rw-r--r-- | roles/jail/tasks/jail_launch.yml | 8 | ||||
| -rw-r--r-- | roles/jail/tasks/jail_setup.yml | 166 | ||||
| -rw-r--r-- | roles/jail/tasks/main.yml | 174 | ||||
| -rw-r--r-- | roles/jails/01_ingress/tasks/main.yml | 5 | ||||
| -rw-r--r-- | roles/jails/02_postgres/defaults/main.yml | 3 | ||||
| -rw-r--r-- | roles/jails/02_postgres/tasks/main.yml | 14 | ||||
| -rw-r--r-- | roles/jails/09_redis/defaults/main.yml | 6 | ||||
| -rw-r--r-- | roles/jails/09_redis/handlers/main.yml | 4 | ||||
| -rw-r--r-- | roles/jails/09_redis/tasks/main.yml | 26 |
9 files changed, 225 insertions, 181 deletions
diff --git a/roles/jail/tasks/jail_launch.yml b/roles/jail/tasks/jail_launch.yml new file mode 100644 index 0000000..52cc1c1 --- /dev/null +++ b/roles/jail/tasks/jail_launch.yml @@ -0,0 +1,8 @@ +- name: Flush handlers + meta: flush_handlers + +- name: Start services + service: + name: "{{ item }}" + state: started + loop: "{{ services | default([]) }}" diff --git a/roles/jail/tasks/jail_setup.yml b/roles/jail/tasks/jail_setup.yml new file mode 100644 index 0000000..9122b79 --- /dev/null +++ b/roles/jail/tasks/jail_setup.yml @@ -0,0 +1,166 @@ +# Host-side setup (runs on the jail host via SSH) +- name: "Check if {{ jail_name }} container exists" + shell: "zfs list -o name | grep -Fxq 'zroot/jails/containers/{{ jail_name }}'" + failed_when: false + changed_when: false + register: jail_exists + delegate_to: "{{ jail_delegate_host }}" + +- name: "Check {{ jail_name }} userland version" + shell: "zfs get -H -o value origin zroot/jails/containers/{{ jail_name }}" + register: jail_origin + changed_when: false + when: jail_exists.rc == 0 + delegate_to: "{{ jail_delegate_host }}" + +- name: "*** MIGRATION REQUIRED: {{ jail_name }} ***" + pause: + prompt: | + + ════════════════════════════════════════════════════════════════ + JAIL USERLAND MIGRATION: {{ jail_name }} + ════════════════════════════════════════════════════════════════ + Current: {{ jail_origin.stdout | trim }} + Target: zroot/jails/templates/{{ userland }}@base + + This will: + 1. Stop the jail + 2. Rename existing dataset to *.old.<timestamp> + 3. Clone fresh from {{ userland }} + ════════════════════════════════════════════════════════════════ + + Press Enter to continue or Ctrl+C to abort + when: + - jail_exists.rc == 0 + - "userland + '@base' not in jail_origin.stdout" + +- name: "Migrate {{ jail_name }} to {{ userland }}" + shell: | + service jail stop {{ jail_name }} || true + zfs rename zroot/jails/containers/{{ jail_name }} zroot/jails/containers/{{ jail_name }}.old.$(date +%s) + when: + - jail_exists.rc == 0 + - "userland + '@base' not in jail_origin.stdout" + delegate_to: "{{ jail_delegate_host }}" + +- name: "Clone {{ jail_name }} from template" + shell: "zfs clone zroot/jails/templates/{{ userland }}@base zroot/jails/containers/{{ jail_name }}" + when: jail_exists.rc != 0 or (jail_origin.stdout is defined and userland + '@base' not in jail_origin.stdout) + delegate_to: "{{ jail_delegate_host }}" + +- name: "Create directories for {{ jail_name }}" + file: + path: "/usr/local/jails/containers/{{ jail_name }}{{ item }}" + state: directory + owner: root + group: wheel + mode: "0755" + loop: "{{ dirs | default([]) }}" + delegate_to: "{{ jail_delegate_host }}" + +- name: "Create mount point sources for {{ jail_name }}" + file: + path: "{{ item.src }}" + state: directory + loop: "{{ nullfs | default([]) }}" + loop_control: + label: "{{ item.src }}" + delegate_to: "{{ jail_delegate_host }}" + +- name: "Create mount point destinations for {{ jail_name }}" + file: + path: "/usr/local/jails/containers/{{ jail_name }}{{ item.dst }}" + state: directory + owner: root + group: wheel + mode: "0755" + loop: "{{ nullfs | default([]) }}" + loop_control: + label: "{{ item.dst }}" + delegate_to: "{{ jail_delegate_host }}" + +- name: "Deploy jail.conf.d/{{ jail_name }}.conf" + template: + src: jail_conf.j2 + dest: "/etc/jail.conf.d/{{ jail_name }}.conf" + owner: root + group: wheel + mode: "0644" + vars: + jail: + name: "{{ jail_name }}" + num: "{{ jail_num }}" + ip: "{{ jail_lan_cidr | ipv4_nth_cidr(jail_num | int + jail_lan_offset | int) }}" + devfs_ruleset: "{{ devfs_ruleset | default(4) }}" + options: "{{ jail_conf_options | default([]) }}" + default_route: "{{ not no_default_route | default(false) }}" + exec_prestart: "{{ exec_prestart | default([]) }}" + exec_start: "{{ exec_start | default([]) }}" + exec_poststart: "{{ exec_poststart | default([]) }}" + exec_prestop: "{{ exec_prestop | default([]) }}" + exec_stop: "{{ exec_stop | default([]) }}" + exec_poststop: "{{ exec_poststop | default([]) }}" + mounts: "{{ nullfs | default([]) }}" + delegate_to: "{{ jail_delegate_host }}" + +- name: "Start {{ jail_name }} jail" + shell: "service jail start {{ jail_name }}" + register: jail_start + failed_when: "jail_start.rc != 0 and 'already exists' not in jail_start.stdout" + changed_when: "'already exists' not in jail_start.stdout" + delegate_to: "{{ jail_delegate_host }}" + +# In-jail provisioning +- name: Install packages + shell: "pkg install -y {{ pkg | join(' ') }}" + environment: + ASSUME_ALWAYS_YES: "yes" + when: pkg is defined and pkg | length > 0 + register: pkg_result + changed_when: "'Number of packages to be installed' in pkg_result.stdout" + +- name: Create parent directories for files + file: + path: "{{ item.dest | dirname }}" + state: directory + owner: root + group: wheel + mode: "0755" + loop: "{{ files | default([]) }}" + loop_control: + label: "{{ item.dest | dirname }}" + when: files is defined + +- name: Deploy files + template: + src: "{{ jail_role_dir }}/templates/{{ item.src }}" + dest: "{{ item.dest }}" + owner: "{{ item.owner | default('root') }}" + group: "{{ item.group | default('wheel') }}" + mode: "{{ item.mode | default('0644') }}" + loop: "{{ files | default([]) }}" + loop_control: + label: "{{ item.dest }}" + when: files is defined + notify: Restart jail services + +- name: Enable services + community.general.sysrc: + name: "{{ item }}_enable" + value: "YES" + loop: "{{ services | default([]) }}" + +- name: Set sysrc values + community.general.sysrc: + name: "{{ item.name }}" + value: "{{ item.value }}" + loop: "{{ sysrc | default([]) }}" + when: sysrc is defined + +- name: Set sysctl values + sysctl: + name: "{{ item.name }}" + value: "{{ item.value }}" + state: present + loop: "{{ sysctl | default([]) }}" + when: sysctl is defined diff --git a/roles/jail/tasks/main.yml b/roles/jail/tasks/main.yml index be9d9c1..88886ec 100644 --- a/roles/jail/tasks/main.yml +++ b/roles/jail/tasks/main.yml @@ -1,172 +1,2 @@ -# Host-side setup (runs on the jail host via SSH) -- name: "Check if {{ jail_name }} container exists" - shell: "zfs list -o name | grep -Fxq 'zroot/jails/containers/{{ jail_name }}'" - failed_when: false - changed_when: false - register: jail_exists - delegate_to: "{{ jail_delegate_host }}" - -- name: "Check {{ jail_name }} userland version" - shell: "zfs get -H -o value origin zroot/jails/containers/{{ jail_name }}" - register: jail_origin - changed_when: false - when: jail_exists.rc == 0 - delegate_to: "{{ jail_delegate_host }}" - -- name: "*** MIGRATION REQUIRED: {{ jail_name }} ***" - pause: - prompt: | - - ════════════════════════════════════════════════════════════════ - JAIL USERLAND MIGRATION: {{ jail_name }} - ════════════════════════════════════════════════════════════════ - Current: {{ jail_origin.stdout | trim }} - Target: zroot/jails/templates/{{ userland }}@base - - This will: - 1. Stop the jail - 2. Rename existing dataset to *.old.<timestamp> - 3. Clone fresh from {{ userland }} - ════════════════════════════════════════════════════════════════ - - Press Enter to continue or Ctrl+C to abort - when: - - jail_exists.rc == 0 - - "userland + '@base' not in jail_origin.stdout" - -- name: "Migrate {{ jail_name }} to {{ userland }}" - shell: | - service jail stop {{ jail_name }} || true - zfs rename zroot/jails/containers/{{ jail_name }} zroot/jails/containers/{{ jail_name }}.old.$(date +%s) - when: - - jail_exists.rc == 0 - - "userland + '@base' not in jail_origin.stdout" - delegate_to: "{{ jail_delegate_host }}" - -- name: "Clone {{ jail_name }} from template" - shell: "zfs clone zroot/jails/templates/{{ userland }}@base zroot/jails/containers/{{ jail_name }}" - when: jail_exists.rc != 0 or (jail_origin.stdout is defined and userland + '@base' not in jail_origin.stdout) - delegate_to: "{{ jail_delegate_host }}" - -- name: "Create directories for {{ jail_name }}" - file: - path: "/usr/local/jails/containers/{{ jail_name }}{{ item }}" - state: directory - owner: root - group: wheel - mode: "0755" - loop: "{{ dirs | default([]) }}" - delegate_to: "{{ jail_delegate_host }}" - -- name: "Create mount point sources for {{ jail_name }}" - file: - path: "{{ item.src }}" - state: directory - loop: "{{ nullfs | default([]) }}" - loop_control: - label: "{{ item.src }}" - delegate_to: "{{ jail_delegate_host }}" - -- name: "Create mount point destinations for {{ jail_name }}" - file: - path: "/usr/local/jails/containers/{{ jail_name }}{{ item.dst }}" - state: directory - owner: root - group: wheel - mode: "0755" - loop: "{{ nullfs | default([]) }}" - loop_control: - label: "{{ item.dst }}" - delegate_to: "{{ jail_delegate_host }}" - -- name: "Deploy jail.conf.d/{{ jail_name }}.conf" - template: - src: jail_conf.j2 - dest: "/etc/jail.conf.d/{{ jail_name }}.conf" - owner: root - group: wheel - mode: "0644" - vars: - jail: - name: "{{ jail_name }}" - num: "{{ jail_num }}" - ip: "{{ jail_lan_cidr | ipv4_nth_cidr(jail_num | int + jail_lan_offset | int) }}" - devfs_ruleset: "{{ devfs_ruleset | default(4) }}" - options: "{{ jail_conf_options | default([]) }}" - default_route: "{{ not no_default_route | default(false) }}" - exec_prestart: "{{ exec_prestart | default([]) }}" - exec_start: "{{ exec_start | default([]) }}" - exec_poststart: "{{ exec_poststart | default([]) }}" - exec_prestop: "{{ exec_prestop | default([]) }}" - exec_stop: "{{ exec_stop | default([]) }}" - exec_poststop: "{{ exec_poststop | default([]) }}" - mounts: "{{ nullfs | default([]) }}" - delegate_to: "{{ jail_delegate_host }}" - -- name: "Start {{ jail_name }} jail" - shell: "service jail start {{ jail_name }}" - register: jail_start - failed_when: "jail_start.rc != 0 and 'already exists' not in jail_start.stdout" - changed_when: "'already exists' not in jail_start.stdout" - delegate_to: "{{ jail_delegate_host }}" - -# In-jail provisioning (runs inside the jail via jailexec) -- name: Install packages - shell: "pkg install -y {{ pkg | join(' ') }}" - environment: - ASSUME_ALWAYS_YES: "yes" - when: pkg is defined and pkg | length > 0 - register: pkg_result - changed_when: "'Number of packages to be installed' in pkg_result.stdout" - -- name: Create parent directories for files - file: - path: "{{ item.dest | dirname }}" - state: directory - owner: root - group: wheel - mode: "0755" - loop: "{{ files | default([]) }}" - loop_control: - label: "{{ item.dest | dirname }}" - when: files is defined - -- name: Deploy files - template: - src: "{{ jail_role_dir }}/templates/{{ item.src }}" - dest: "{{ item.dest }}" - owner: "{{ item.owner | default('root') }}" - group: "{{ item.group | default('wheel') }}" - mode: "{{ item.mode | default('0644') }}" - loop: "{{ files | default([]) }}" - loop_control: - label: "{{ item.dest }}" - when: files is defined - notify: Restart jail services - -- name: Enable services - community.general.sysrc: - name: "{{ item }}_enable" - value: "YES" - loop: "{{ services | default([]) }}" - -- name: Start services - service: - name: "{{ item }}" - state: started - loop: "{{ services | default([]) }}" - -- name: Set sysctl values - sysctl: - name: "{{ item.name }}" - value: "{{ item.value }}" - state: present - loop: "{{ sysctl | default([]) }}" - when: sysctl is defined - -- name: Set sysrc values - community.general.sysrc: - name: "{{ item.name }}" - value: "{{ item.value }}" - loop: "{{ sysrc | default([]) }}" - when: sysrc is defined +- include_tasks: jail_setup.yml +- include_tasks: jail_launch.yml diff --git a/roles/jails/01_ingress/tasks/main.yml b/roles/jails/01_ingress/tasks/main.yml index 5b56286..8248c3f 100644 --- a/roles/jails/01_ingress/tasks/main.yml +++ b/roles/jails/01_ingress/tasks/main.yml @@ -36,6 +36,7 @@ - import_role: name: jail + tasks_from: jail_setup - name: Check if TLS certs exist stat: @@ -47,3 +48,7 @@ pause: prompt: "Run certbot manually in the ingress jail to obtain certs, then press Enter." when: is_prod and not (_certbot_certs.stat.exists | default(true)) + +- import_role: + name: jail + tasks_from: jail_launch diff --git a/roles/jails/02_postgres/defaults/main.yml b/roles/jails/02_postgres/defaults/main.yml index a6ea7d9..ec54e55 100644 --- a/roles/jails/02_postgres/defaults/main.yml +++ b/roles/jails/02_postgres/defaults/main.yml @@ -8,7 +8,8 @@ jail_conf_options: pkg: - postgresql18-server -services: [] +services: + - postgresql pg_users: - spliit diff --git a/roles/jails/02_postgres/tasks/main.yml b/roles/jails/02_postgres/tasks/main.yml index 12365d0..226e734 100644 --- a/roles/jails/02_postgres/tasks/main.yml +++ b/roles/jails/02_postgres/tasks/main.yml @@ -1,5 +1,6 @@ - import_role: name: jail + tasks_from: jail_setup - name: Check if database is initialized stat: @@ -10,11 +11,6 @@ shell: /usr/local/etc/rc.d/postgresql initdb when: not _pg_data.stat.exists -- name: Enable postgresql - community.general.sysrc: - name: postgresql_enable - value: "YES" - - name: Allow LAN connections in pg_hba.conf lineinfile: path: /var/db/postgres/data18/pg_hba.conf @@ -29,14 +25,16 @@ regexp: "^listen_addresses" notify: Restart postgresql -- name: Flush handlers - meta: flush_handlers +- import_role: + name: jail + tasks_from: jail_launch - name: Create database users - shell: "su -l postgres -c \"psql -tc \\\"SELECT 1 FROM pg_roles WHERE rolname='{{ item }}'\\\"\" | grep -q 1 || su -l postgres -c \"createuser {{ item }}\"" + shell: "su -l postgres -c \"psql -tc \\\"SELECT 1 FROM pg_roles WHERE rolname='{{ item }}'\\\"\" | grep -q 1 || su -l postgres -c \"psql -c \\\"CREATE ROLE {{ item }} LOGIN PASSWORD '{{ pg_user_passwords[item] }}'\\\"\"" loop: "{{ pg_users }}" register: _pg_user changed_when: "'CREATE ROLE' in _pg_user.stdout" + no_log: true - name: Create databases shell: "su -l postgres -c \"psql -tc \\\"SELECT 1 FROM pg_database WHERE datname='{{ item.name }}'\\\"\" | grep -q 1 || su -l postgres -c \"createdb -O {{ item.owner }} {{ item.name }}\"" diff --git a/roles/jails/09_redis/defaults/main.yml b/roles/jails/09_redis/defaults/main.yml index 5416267..bb34d92 100644 --- a/roles/jails/09_redis/defaults/main.yml +++ b/roles/jails/09_redis/defaults/main.yml @@ -1 +1,7 @@ userland: "15.0-RELEASE" + +pkg: + - valkey + +services: + - valkey diff --git a/roles/jails/09_redis/handlers/main.yml b/roles/jails/09_redis/handlers/main.yml new file mode 100644 index 0000000..0ad139c --- /dev/null +++ b/roles/jails/09_redis/handlers/main.yml @@ -0,0 +1,4 @@ +- name: Restart valkey + service: + name: valkey + state: restarted diff --git a/roles/jails/09_redis/tasks/main.yml b/roles/jails/09_redis/tasks/main.yml index 2abdaff..9e79df1 100644 --- a/roles/jails/09_redis/tasks/main.yml +++ b/roles/jails/09_redis/tasks/main.yml @@ -1,2 +1,28 @@ - import_role: name: jail + tasks_from: jail_setup + +- name: Configure bind address + lineinfile: + path: /usr/local/etc/valkey.conf + line: "bind * -::*" + regexp: "^bind " + notify: Restart valkey + +- name: Configure protected-mode + lineinfile: + path: /usr/local/etc/valkey.conf + line: "protected-mode yes" + regexp: "^protected-mode" + notify: Restart valkey + +- name: Configure requirepass + lineinfile: + path: /usr/local/etc/valkey.conf + line: "requirepass {{ valkey_password }}" + regexp: "^requirepass" + notify: Restart valkey + +- import_role: + name: jail + tasks_from: jail_launch |
