aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJan Tuomi <jan@jantuomi.fi>2026-05-16 19:19:07 +0300
committerJan Tuomi <jan@jantuomi.fi>2026-05-16 19:19:07 +0300
commit75732c1a9aa1fed11794f509d33bdea5171d41c0 (patch)
tree057717d5e3010b77f15b9fd36806e691fbfc0853
parentb97ed17f3747345ccf83ddd7c2b4349f43c73e98 (diff)
Set up redis jail, improve role setup
-rw-r--r--roles/jail/tasks/jail_launch.yml8
-rw-r--r--roles/jail/tasks/jail_setup.yml166
-rw-r--r--roles/jail/tasks/main.yml174
-rw-r--r--roles/jails/01_ingress/tasks/main.yml5
-rw-r--r--roles/jails/02_postgres/defaults/main.yml3
-rw-r--r--roles/jails/02_postgres/tasks/main.yml14
-rw-r--r--roles/jails/09_redis/defaults/main.yml6
-rw-r--r--roles/jails/09_redis/handlers/main.yml4
-rw-r--r--roles/jails/09_redis/tasks/main.yml26
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