diff options
Diffstat (limited to 'roles/jail')
| -rw-r--r-- | roles/jail/handlers/main.yml | 5 | ||||
| -rw-r--r-- | roles/jail/tasks/main.yml | 175 | ||||
| -rw-r--r-- | roles/jail/templates/jail_conf.j2 | 56 |
3 files changed, 236 insertions, 0 deletions
diff --git a/roles/jail/handlers/main.yml b/roles/jail/handlers/main.yml new file mode 100644 index 0000000..5375cb8 --- /dev/null +++ b/roles/jail/handlers/main.yml @@ -0,0 +1,5 @@ +- name: Restart jail services + service: + name: "{{ item }}" + state: restarted + loop: "{{ services | default([]) }}" diff --git a/roles/jail/tasks/main.yml b/roles/jail/tasks/main.yml new file mode 100644 index 0000000..be72e3b --- /dev/null +++ b/roles/jail/tasks/main.yml @@ -0,0 +1,175 @@ +# 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 + owner: root + group: wheel + mode: "0755" + 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 diff --git a/roles/jail/templates/jail_conf.j2 b/roles/jail/templates/jail_conf.j2 new file mode 100644 index 0000000..2a0ea27 --- /dev/null +++ b/roles/jail/templates/jail_conf.j2 @@ -0,0 +1,56 @@ +{{ jail.name }} { + vnet; + persist; + exec.clean; + allow.raw_sockets; + mount.devfs; +{% for opt in jail.options %} + {{ opt }}; +{% endfor %} + + devfs_ruleset = {{ jail.devfs_ruleset }}; + host.hostname = "{{ jail.name }}"; + path = "/usr/local/jails/containers/${name}"; + + exec.start = "/bin/sh /etc/rc"; + exec.stop = "/bin/sh /etc/rc.shutdown"; + + # LAN epair + exec.prestart += "ifconfig epl{{ jail.num }}a destroy 2>/dev/null || true"; + exec.prestart += "ifconfig epair{{ jail.num }}000 create"; + exec.prestart += "ifconfig epair{{ jail.num }}000a name epl{{ jail.num }}a"; + exec.prestart += "ifconfig epair{{ jail.num }}000b name epl{{ jail.num }}b"; + exec.prestart += "ifconfig epl{{ jail.num }}b ether random"; + exec.prestart += "ifconfig brlan0 addm epl{{ jail.num }}a"; + exec.poststart += "ifconfig epl{{ jail.num }}b vnet ${name}"; + exec.poststart += "ifconfig epl{{ jail.num }}a up"; + exec.poststart += "jexec ${name} ifconfig epl{{ jail.num }}b up"; + exec.poststart += "jexec ${name} ifconfig epl{{ jail.num }}b {{ jail.ip }}"; + exec.poststart += "jexec ${name} route delete default || true"; +{% if jail.default_route %} + exec.poststart += "jexec ${name} route add default {{ ingress_ip }} || true"; +{% endif %} + exec.poststop += "ifconfig epl{{ jail.num }}a destroy 2>/dev/null || true"; +{% for cmd in jail.exec_prestart %} + exec.prestart += "{{ cmd }}"; +{% endfor %} +{% for cmd in jail.exec_start %} + exec.start += "{{ cmd }}"; +{% endfor %} +{% for cmd in jail.exec_poststart %} + exec.poststart += "{{ cmd }}"; +{% endfor %} +{% for cmd in jail.exec_prestop %} + exec.prestop += "{{ cmd }}"; +{% endfor %} +{% for cmd in jail.exec_stop %} + exec.stop += "{{ cmd }}"; +{% endfor %} +{% for cmd in jail.exec_poststop %} + exec.poststop += "{{ cmd }}"; +{% endfor %} +{% for mount in jail.mounts %} + exec.prestart += "mount -t nullfs {{ mount.src }} /usr/local/jails/containers/{{ jail.name }}{{ mount.dst }} || true"; + exec.poststop += "umount /usr/local/jails/containers/{{ jail.name }}{{ mount.dst }} || true"; +{% endfor %} +} |
