501 iocage host

Use case

Configure iocage host.

Tree

shell > tree .
.
├── ansible.cfg
├── group_vars
│   └── all
│       └── iocage.yml
├── host_vars
│   └── iocage_04
│       ├── iocage.yml
│       ├── loader.yml
│       ├── login.yml
│       ├── network.yml
│       ├── packages.yml
│       ├── pf.yml
│       └── zfs.yml
├── iocage.ini
├── pb-all.yml
├── pb-iocage.yml
├── pb-loader.yml
├── pb-login.yml
├── pb-network.yml
├── pb-packages.yml
├── pb-pf.yml
└── pb-zfs.yml

Synopsis

At the managed node iocage_04:

  • configure /home/admin/.login_conf

  • install packages

  • configure /boot/loader.conf

  • configure network

  • configure pf

  • create ZFS pool iocage

  • activate iocage pool iocage

  • fetch release

  • test iocage sanity.

Requirements

Roles:

Notes

ansible.cfg

[defaults]
gathering = explicit
callback_result_format = yaml
display_skipped_hosts = false

[connection]
pipelining = true

Inventory iocage.ini

iocage_04 ansible_host=10.1.0.29

[iocage]
iocage_04

[iocage:vars]
ansible_user=admin
ansible_become=true
ansible_python_interpreter=auto_silent

group_vars

group_vars/all/iocage.yml
fp_backup: true

host_vars

host_vars/iocage_04/loader.yml
fp_loader_conf_template: ''
fp_loader_conf:
  - {name: vfs.zfs.prefetch.disable, value: "0"}
  - {name: net.link.bridge.pfil_member, value: "0"}
  - {name: net.link.bridge.pfil_bridge, value: "0"}
  - {name: net.link.bridge.inherit_mac, value: "1"}
fp_loader_conf_modules:
  - {name: if_bridge, value: "YES" }
host_vars/iocage_04/login.yml
fp_login_conf_local:
  - user: admin
    class: me
    conf:
      - "{{ fp_login_conf_local_iocage }}"

fp_login_conf_local_iocage:
  - charset=UTF-8
  - lang=en_US.UTF-8
  - setenv=LC_COLLATE=C
host_vars/iocage_04/network.yml
fn_gateway_enable: true
fn_defaultrouter: 10.1.0.10
fn_cloned_interfaces:
  - interface: bridge0
fn_interfaces:
  - {interface: bridge0, options: inet 10.1.0.29/24, create: addm igb0}
  - {interface: igb0, options: up -tso -vlanhwtso}
host_vars/iocage_04/packages.yml
fp_packages:
  - {list: custom, enabled: true}
pkg_dict_amd64_dict:
  custom:
    - security/py-fail2ban
    - security/sshguard
    - sysutils/iocage
host_vars/iocage_04/pf.yml
pf_install: false  # The packages are installed in the playbook pb-packages.yml
pf_blacklistd: true
pf_fail2ban: true
pf_sshguard: true

pf_enable: true
pf_blacklistd_enable: true
pf_fail2ban_enable: true
pf_sshguard_enable: true

pf_type: default2
pf_log_enable: true
pf_ext_if: bridge0
pf_log_all_blocked: log
pf_pass_icmp_types: [echoreq, unreach]
pf_pass_icmp6_types: [echoreq, unreach]
pf_local_net: 10.1.0.0/24

pf_macros:
  ext_if: "{{ pf_ext_if }}"
  localnet: "{{ pf_local_net }}"
  logall: "{{ pf_log_all_blocked }}"
  icmp_types: "{{ pf_pass_icmp_types }}"
  icmp6_types: "{{ pf_pass_icmp6_types }}"

pf_options:
  - set skip on lo0
  - set block-policy return
  - set loginterface $ext_if

pf_tables:
  - table <sshabuse> persist

pf_normalization:
  - scrub in on $ext_if all fragment reassemble

pf_translation:
  - "{{ pf_rules_rdr }}"
  - nat on $ext_if from $localnet to any -> ($ext_if)

pf_filtering:
  - antispoof for $ext_if
  - "{{ pf_anchors }}"
  - block $logall all
  - pass inet proto icmp icmp-type $icmp_types
  - pass inet6 proto icmp6 icmp6-type $icmp6_types
  - pass from { self, $localnet } to any keep state

pf_blacklistd_conf_local:
  - {adr: ssh, type: stream, proto: '*', owner: '*', name: '*', nfail: '3', disable: 24h}
  - {adr: ftp, type: stream, proto: '*', owner: '*', name: '*', nfail: '3', disable: 24h}
  - {adr: smtp, type: stream, proto: '*', owner: '*', name: '*', nfail: '3', disable: 24h}
  - {adr: smtps, type: stream, proto: '*', owner: '*', name: '*', nfail: '3', disable: 24h}
  - {adr: submission, type: stream, proto: '*', owner: '*', name: '*', nfail: '3', disable: 24h}
  - {adr: '*', type: '*', proto: '*', owner: '*', name: '*', nfail: '3', disable: '60'}
pf_blacklistd_flags: '-r'
pf_blacklistd_rcconf:
  - {name: blacklistd_flags, value: "{{ pf_blacklistd_flags }}"}
host_vars/iocage_04/zfs.yml
fzfs_enable: true
fzfs_pools:
  iocage:
    vdevs:
      - disks:
          - /dev/ada2
          - /dev/ada3

Note

Destroy the GPT tables on the disks you want to create the pool from. For example,

[iocage_04]# gpart destroy -F ada2
[iocage_04]# gpart destroy -F ada3

Otherwise, you’ll see the bellow complains in the dmesg

GEOM: ada2: the primary GPT table is corrupt or invalid.
GEOM: ada2: using the secondary instead -- recovery strongly advised.
GEOM: ada3: the primary GPT table is corrupt or invalid.
GEOM: ada3: using the secondary instead -- recovery strongly advised.

There is no reason for any GPT tables if the whole disks are used by a pool

[iocage_04]# zpool status iocage
  pool: iocage
 state: ONLINE
config:

        NAME        STATE     READ WRITE CKSUM
        iocage      ONLINE       0     0     0
          ada2      ONLINE       0     0     0
          ada3      ONLINE       0     0     0

errors: No known data errors
host_vars/iocage_04/iocage.yml
freebsd_iocage_install: false  # The packages are installed in the playbook pb-packages.yml

freebsd_iocage_mount: /iocage/iocage
freebsd_iocage_pool: iocage
freebsd_iocage_pool_mount: /iocage

freebsd_iocage_sanity_zfs_pool_active: true

Playbooks

pb-login.yml
- name: Configure login.conf
  hosts: iocage
  gather_facts: true

  tasks:

    - name: Configure login.conf
      ansible.builtin.import_role:
        name: vbotka.freebsd.postinstall
        tasks_from: login
pb-packages.yml
- name: Install packages.
  hosts: iocage
  gather_facts: true

  tasks:

    - name: Install packages.
      ansible.builtin.import_role:
        name: vbotka.freebsd.postinstall
        tasks_from: packages
pb-loader.yml
- name: Configure loader.conf
  hosts: iocage
  gather_facts: true

  tasks:

    - name: Configure /boot/loader.conf
      ansible.builtin.import_role:
        name: vbotka.freebsd.postinstall
        tasks_from: loader
pb-network.yml
- name: Configure network.
  hosts: iocage
  gather_facts: true

  roles:
    - vbotka.freebsd.network
pb-pf.yml
- name: Configure pf.
  hosts: iocage
  gather_facts: true

  roles:
    - vbotka.freebsd.pf
pb-zfs.yml
- name: Configure ZFS.
  hosts: iocage
  gather_facts: true

  roles:
    - vbotka.freebsd.zfs
pb-iocage.yml
- name: Configure iocage.
  hosts: iocage
  gather_facts: true

  roles:
    - vbotka.freebsd.iocage

Playbooks’ outputs

Configure /home/admin/.login_conf

(env) > ansible-playbook pb-login.yml -i iocage.ini
PLAY [Configure login.conf] ****************************************************

TASK [Gathering Facts] *********************************************************
ok: [iocage_04]

TASK [vbotka.freebsd.postinstall : Login: Create local .login_conf] ************
ok: [iocage_04] => (item=admin)

PLAY RECAP *********************************************************************
iocage_04                  : ok=2    changed=0    unreachable=0    failed=0    skipped=1    rescued=0    ignored=0   

Install packages

(env) > ansible-playbook pb-packages.yml -i iocage.ini
PLAY [Install packages.] *******************************************************

TASK [Gathering Facts] *********************************************************
ok: [iocage_04]

TASK [vbotka.freebsd.postinstall : Packages: Set _fp_pkg_enabled and _fp_pkg_dict for amd64] ***
ok: [iocage_04]

TASK [vbotka.freebsd.postinstall : Packages: Assert all items in _fp_pkg_enabled are available in _fp_pkg_dict] ***
ok: [iocage_04]

TASK [vbotka.freebsd.postinstall : Packages: Assert freebsd_install_method in [packages, ports]] ***
ok: [iocage_04]

TASK [vbotka.freebsd.postinstall : Packages: Install packages] *****************
included: /scratch/collections/ansible_collections/vbotka/freebsd/roles/postinstall/tasks/packages-install.yml for iocage_04 => (item=custom)

TASK [vbotka.freebsd.postinstall : Packages-install: Install packages list custom] ***
ok: [iocage_04]

PLAY RECAP *********************************************************************
iocage_04                  : ok=6    changed=0    unreachable=0    failed=0    skipped=7    rescued=0    ignored=0   

Configure /boot/loader.conf

(env) > ansible-playbook pb-loader.yml -i iocage.ini
PLAY [Configure loader.conf] ***************************************************

TASK [Gathering Facts] *********************************************************
ok: [iocage_04]

TASK [vbotka.freebsd.postinstall : Loader: Backup orig /boot/loader.conf] ******
ok: [iocage_04]

TASK [vbotka.freebsd.postinstall : Loader: Configure by sysctl /boot/loader.conf] ***
ok: [iocage_04] => (item={'name': 'vfs.zfs.prefetch.disable', 'value': '0'})
ok: [iocage_04] => (item={'name': 'net.link.bridge.pfil_member', 'value': '0'})
ok: [iocage_04] => (item={'name': 'net.link.bridge.pfil_bridge', 'value': '0'})
ok: [iocage_04] => (item={'name': 'net.link.bridge.inherit_mac', 'value': '1'})

TASK [vbotka.freebsd.postinstall : Loader: Configure modules by sysctl /boot/loader.conf] ***
ok: [iocage_04] => (item={'name': 'if_bridge', 'value': 'YES'})

TASK [vbotka.freebsd.postinstall : Loader: Get sysctls settable via loader.] ***
ok: [iocage_04]

PLAY RECAP *********************************************************************
iocage_04                  : ok=5    changed=0    unreachable=0    failed=0    skipped=4    rescued=0    ignored=0   

Note

Reboot if you see this message

[MESSAGE] Reboot to activate configuration in /boot/loader.conf

Configure network

(env) > ansible-playbook pb-network.yml -i iocage.ini
PLAY [Configure network.] ******************************************************

TASK [Gathering Facts] *********************************************************
ok: [iocage_04]

TASK [vbotka.freebsd.network : Interfaces: Configure interfaces create_args in /etc/rc.conf] ***
ok: [iocage_04] => (item={'interface': 'bridge0', 'options': 'inet 10.1.0.29/24', 'create': 'addm igb0'})

TASK [vbotka.freebsd.network : Interfaces: Configure interfaces options in /etc/rc.conf] ***
ok: [iocage_04] => (item={'interface': 'bridge0', 'options': 'inet 10.1.0.29/24', 'create': 'addm igb0'})
ok: [iocage_04] => (item={'interface': 'igb0', 'options': 'up -tso -vlanhwtso'})

TASK [vbotka.freebsd.network : Cloned-interfaces: Configure cloned_interfaces in /etc/rc.conf] ***
ok: [iocage_04] => (item={'interface': 'bridge0'})

TASK [vbotka.freebsd.network : Routing: Set defaultrouter in /etc/rc.conf] *****
ok: [iocage_04]

TASK [vbotka.freebsd.network : Routing: Set gateway_enable=YES in /etc/rc.conf] ***
ok: [iocage_04]

TASK [vbotka.freebsd.network : Routing: Remove list of static routes from /etc/rc.conf] ***
ok: [iocage_04]

PLAY RECAP *********************************************************************
iocage_04                  : ok=7    changed=0    unreachable=0    failed=0    skipped=16   rescued=0    ignored=0   

Configure pf

(env) > ansible-playbook pb-pf.yml -i iocage.ini
PLAY [Configure pf.] ***********************************************************

TASK [Gathering Facts] *********************************************************
ok: [iocage_04]

TASK [vbotka.freebsd.pf : Rcconf-blacklistd: Stat /etc/rc.d/blacklistd] ********
ok: [iocage_04]

TASK [vbotka.freebsd.pf : Blacklistd: Backup /etc/blacklistd.conf.orig] ********
ok: [iocage_04]

TASK [vbotka.freebsd.pf : Blacklistd: Configure /etc/blacklistd.conf] **********
ok: [iocage_04]

TASK [vbotka.freebsd.pf : Rcconf-fail2ban: Stat /usr/local/etc/rc.d/fail2ban] ***
ok: [iocage_04]

TASK [vbotka.freebsd.pf : Fail2ban: Configure /usr/local/etc/fail2ban/fail2ban.local] ***
ok: [iocage_04]

TASK [vbotka.freebsd.pf : Fail2ban: Configure /usr/local/etc/fail2ban/jail.local] ***
ok: [iocage_04]

TASK [vbotka.freebsd.pf : Rcconf-sshguard: Stat /usr/local/etc/rc.d/sshguard] ***
ok: [iocage_04]

TASK [vbotka.freebsd.pf : Configure sshguard.conf] *****************************
ok: [iocage_04] => (item={'key': 'BACKEND', 'value': '/usr/local/libexec/sshg-fw-pf'})
ok: [iocage_04] => (item={'key': 'WHITELIST_FILE', 'value': '/usr/local/etc/sshguard.whitelist'})

TASK [vbotka.freebsd.pf : Pfconf: Configure and validate rules using template default2-pf.conf.j2] ***
ok: [iocage_04]

TASK [vbotka.freebsd.pf : Rcconf-blacklistd: Enable and start blacklistd.] *****
ok: [iocage_04]

TASK [vbotka.freebsd.pf : Rcconf-blacklistd: Configure blacklistd.] ************
ok: [iocage_04] => (item={'name': 'blacklistd_flags', 'value': '-r'})

TASK [vbotka.freebsd.pf : Rcconf-fail2ban: Enable and start fail2ban.] *********
ok: [iocage_04]

TASK [vbotka.freebsd.pf : Rcconf-fail2ban: Configure fail2ban.] ****************
ok: [iocage_04] => (item={'name': 'fail2ban_flags', 'value': ''})

TASK [vbotka.freebsd.pf : Rcconf-sshguard: Enable and start sshguard.] *********
ok: [iocage_04]

TASK [vbotka.freebsd.pf : Rcconf-pf: Enable and start pf.] *********************
ok: [iocage_04]

TASK [vbotka.freebsd.pf : Rcconf-pflog: Enable and start pflog.] ***************
ok: [iocage_04]

PLAY RECAP *********************************************************************
iocage_04                  : ok=17   changed=0    unreachable=0    failed=0    skipped=39   rescued=0    ignored=0   

Configure ZFS

(env) > ansible-playbook pb-zfs.yml -i iocage.ini
PLAY [Configure ZFS.] **********************************************************

TASK [Gathering Facts] *********************************************************
ok: [iocage_04]

TASK [Sysctl: Include vbotka.freebsd.postinstall sysctl] ***********************
included: vbotka.freebsd.postinstall for iocage_04

TASK [vbotka.freebsd.postinstall : Sysctl: Get sysctls settable via loader.] ***
ok: [iocage_04]

TASK [vbotka.freebsd.zfs : Rcconf: Enable and Start zfs] ***********************
ok: [iocage_04]

TASK [vbotka.freebsd.zfs : Pools: Get zpool status.] ***************************
ok: [iocage_04]

TASK [vbotka.freebsd.zfs : Pools: Sanity: No fzfs_pools disks already in other pools.] ***
ok: [iocage_04]

TASK [vbotka.freebsd.zfs : Pools: Sanity: No fzfs_pools disks already mounted.] ***
ok: [iocage_04]

TASK [vbotka.freebsd.zfs : Pools: Sanity: fzfs_pools disks are unique.] ********
ok: [iocage_04]

TASK [vbotka.freebsd.zfs : Pools: WARNING | community.general.zpool skipped.] ***
ok: [iocage_04] => 
    msg: |-
        # - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
        # WARNING:
        #
        # The module community.general.zpool is not idempotent. It crashes
        # when running repeatedly. Because of the poor quality, the module
        # community.general.zpool will be skipped for pools:
        # ['iocage']
        #
        # Configure the skipped pools manually, if necessary.
        # - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

TASK [vbotka.freebsd.zfs : Facts: Run zpool_facts] *****************************
ok: [iocage_04]

TASK [vbotka.freebsd.zfs : Manage: Sanity all pools available.] ****************
ok: [iocage_04]

PLAY RECAP *********************************************************************
iocage_04                  : ok=11   changed=0    unreachable=0    failed=0    skipped=16   rescued=0    ignored=0   

See also

Module community.general.zpool Known issues.

Activate iocage

(env) > ansible-playbook pb-iocage.yml -i iocage.ini \
                                       -t freebsd_iocage_activate -e freebsd_iocage_activate=true \
                                       -e freebsd_iocage_debug=true
PLAY [Configure iocage.] *******************************************************

TASK [Gathering Facts] *********************************************************
ok: [iocage_04]

TASK [vbotka.freebsd.iocage : Activate: Activate iocage pool iocage] ***********
ok: [iocage_04]

TASK [vbotka.freebsd.iocage : Activate: Debug result freebsd_iocage_debug=true] ***
ok: [iocage_04] => 
    result:
        changed: false
        cmd:
        - iocage
        - activate
        - iocage
        delta: null
        end: null
        failed: false
        msg: Did not run command since '/iocage/iocage' exists
        rc: 0
        start: null
        stderr: ''
        stderr_lines: []
        stdout: skipped, since /iocage/iocage exists
        stdout_lines:
        - skipped, since /iocage/iocage exists

PLAY RECAP *********************************************************************
iocage_04                  : ok=3    changed=0    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0   

Fetch release

Note

This example is not updated to the current release and serves a demonstration purpose only.

[iocage_04]# iocage fetch --release 14.3-RELEASE
Creating iocage/iocage
Creating iocage/iocage/download
Creating iocage/iocage/images
Creating iocage/iocage/jails
Creating iocage/iocage/log
Creating iocage/iocage/releases
Creating iocage/iocage/templates
Default configuration missing, creating one
Fetching: 14.3-RELEASE

Downloading: MANIFEST [####################] 100% 
Downloading: base.txz [####################] 100% 
Downloading: lib32.txz [####################] 100% 
Downloading: src.txz [####################] 100% 
Extracting: base.txz... 
Extracting: lib32.txz... 
Extracting: src.txz... 

* Updating 14.3-RELEASE to the latest patch level... 
Looking up update.FreeBSD.org mirrors... 3 mirrors found.
Fetching public key from update2.freebsd.org... done.
Fetching metadata signature for 14.3-RELEASE from update2.freebsd.org... done.
Fetching metadata index... done.
Fetching 2 metadata files... done.
Inspecting system... done.
Preparing to download files... done.
Fetching 8 patches..... done.
Applying patches... done.
The following files will be updated as part of updating to
14.3-RELEASE-p1:
/bin/freebsd-version
/lib/libzpool.so.2
/rescue/[
/rescue/bectl
/rescue/bsdlabel
...
/rescue/zstd
/rescue/zstdcat
/rescue/zstdmt
/usr/lib/libzpool.a
/usr/lib32/libzpool.a
/usr/lib32/libzpool.so.2
/usr/src/sys/conf/newvers.sh
/usr/src/sys/contrib/openzfs/module/zfs/dmu_send.c
Installing updates... done.

Sanity iocage

(env) > ansible-playbook pb-iocage.yml -i iocage.ini -t freebsd_iocage_sanity
PLAY [Configure iocage.] *******************************************************

TASK [Gathering Facts] *********************************************************
ok: [iocage_04]

TASK [vbotka.freebsd.iocage : Sanity: Service start, restart, and stop are mutually exclusive] ***
ok: [iocage_04]

TASK [vbotka.freebsd.iocage : Sanity: Get environment.] ************************
ok: [iocage_04]

TASK [vbotka.freebsd.iocage : Sanity: Environment LANG = en_US.UTF-8] **********
ok: [iocage_04]

TASK [vbotka.freebsd.iocage : Sanity: Environment LC_COLLATE = C] **************
ok: [iocage_04]

TASK [vbotka.freebsd.iocage : Sanity: Get mounts] ******************************
ok: [iocage_04]

TASK [vbotka.freebsd.iocage : Sanity: /dev/fd mounted to fdescfs] **************
ok: [iocage_04]

TASK [vbotka.freebsd.iocage : Sanity: Get sysctl kern.conftxt] *****************
ok: [iocage_04]

TASK [vbotka.freebsd.iocage : Sanity: Mandatory kernel options VIMAGE, RACCT, and RCTL.] ***
ok: [iocage_04]

TASK [vbotka.freebsd.iocage : Sanity: Read /boot/loader.conf] ******************
ok: [iocage_04]

TASK [vbotka.freebsd.iocage : Sanity: kern.racct.enable = 1] *******************
ok: [iocage_04]

TASK [vbotka.freebsd.iocage : Sanity: Get sysctl security.jail.jailed] *********
ok: [iocage_04]

TASK [vbotka.freebsd.iocage : Sanity: Not in jail.] ****************************
ok: [iocage_04]

TASK [vbotka.freebsd.iocage : Sanity: Get ZFS pools.] **************************
ok: [iocage_04]

TASK [vbotka.freebsd.iocage : Sanity: ZFS pool exists.] ************************
ok: [iocage_04]

TASK [vbotka.freebsd.iocage : Sanity: Get ZFS datasets.] ***********************
ok: [iocage_04]

TASK [vbotka.freebsd.iocage : Sanity: ZFS pool activated.] *********************
ok: [iocage_04]

PLAY RECAP *********************************************************************
iocage_04                  : ok=17   changed=0    unreachable=0    failed=0    skipped=9    rescued=0    ignored=0   

All playbooks

pb-all.yml
- ansible.builtin.import_playbook: pb-login.yml
- ansible.builtin.import_playbook: pb-packages.yml
- ansible.builtin.import_playbook: pb-loader.yml
- ansible.builtin.import_playbook: pb-network.yml
- ansible.builtin.import_playbook: pb-pf.yml
- ansible.builtin.import_playbook: pb-zfs.yml
- ansible.builtin.import_playbook: pb-iocage.yml

All playbooks output

(env) > ANSIBLE_DISPLAY_OK_HOSTS=false ansible-playbook pb-all.yml -i iocage.ini
PLAY [Configure login.conf] ****************************************************

PLAY [Install packages.] *******************************************************

TASK [vbotka.freebsd.postinstall : Packages: Install packages] *****************
included: /scratch/collections/ansible_collections/vbotka/freebsd/roles/postinstall/tasks/packages-install.yml for iocage_04 => (item=custom)

PLAY [Configure loader.conf] ***************************************************

PLAY [Configure network.] ******************************************************

PLAY [Configure pf.] ***********************************************************

PLAY [Configure ZFS.] **********************************************************

TASK [Sysctl: Include vbotka.freebsd.postinstall sysctl] ***********************
included: vbotka.freebsd.postinstall for iocage_04

PLAY [Configure iocage.] *******************************************************

PLAY RECAP *********************************************************************
iocage_04                  : ok=67   changed=0    unreachable=0    failed=0    skipped=146  rescued=0    ignored=0