208 Create iocage template for ansible-pull
TODO: Run ansible-pull on boot.
Use case
Create iocage template ansible_client_pull that will use ansible-pull.
Tree
shell> tree .
.
├── ansible.cfg
├── files
│ └── pk_admins.txt
├── host_vars
│ └── iocage_04
│ └── iocage.yml
└── iocage.ini
Synopsis
At the iocage host
iocage_04in the playbook vbotka.freebsd.pb_iocage_template.yml, use the modules:vbotka.freebsd.iocageto create, start, stop, and convert jail to templates.vbotka.freebsd.iocageexec to create a user and set .ssh ownership.community.general.sysrcto configure/etc/rc.confansible.posix.authorized_keyto configure public keys.ansible.builtin.lineinfileto configure/usr/local/etc/sudoersconfigure
dhclient hooks
Requirements
root privilege in the managed nodes.
Notes
TBD
See also
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
host_vars
freebsd_iocage_pool: iocage
freebsd_iocage_pool_mount: /iocage
freebsd_iocage_mount: /iocage/iocage
templates:
ansible_client_pull:
release: 15.0-RELEASE
properties:
bpf: 1
dhcp: 1
vnet: 1
dhclient: "{{ act_dhclient | dict2items }}"
rcconf: "{{ act_rcconf | dict2items }}"
pkglist: /tmp/ansible/ansible_client_pull/pkgs.json
act_user: admin
act_pk: pk_admins.txt
act_sudo: true
act_rcconf:
iocage_enable: "YES"
sshd_enable: "YES"
act_dhclient:
dhclient-exit-hooks: |
case "$reason" in
"BOUND"|"REBIND"|"REBOOT"|"RENEW")
echo $new_ip_address > /var/db/dhclient-hook.address.$interface
;;
esac
Note
The variables act_* are used to configure the template
The user
act_userwill be created in the template.The user
act_userwill serve as Ansibleremote_userThe file
act_pkprovides the public keys allowed to ssh toact_userThe dhclient hooks
act_dhclientwill be created in/etc
Create the file files/pkgs.json
{
"pkgs": [
"git",
"python311",
"py311-ansible",
"sudo"
]
}
Warning
The user
act_usermust exist on theiocagehost. Otherwise, the moduleansible.posix.authorized_keywill crash. Seeplaybooks/pb_iocage_template/pk.ymlThe file
files/pk_admins.txtwas sanitized. Fit the public keys to your needsshell> cat files/pk_admins.txt ssh-rsa <sanitized> admin@controller
Playbook output - Create templates
Limit the inventory to iocage_04
(env) > ansible-playbook vbotka.freebsd.pb_iocage_template.yml \
-i iocage.ini -l iocage_04 \
-e debug=true
PLAY [Create Ansible client templates.] ****************************************
TASK [Setup: Get iocage list of templates.] ************************************
ok: [iocage_04]
TASK [Setup: Set dictionary iocage_templates] **********************************
ok: [iocage_04]
TASK [Setup: Display iocage_templates debug=true] ******************************
ok: [iocage_04] =>
iocage_templates:
ansible_client:
basejail: 'no'
boot: 'off'
ip4: '-'
ip4_dict:
ip4: []
msg: DHCP (not running)
ip6: '-'
jid: None
release: 15.0-RELEASE-p3
state: down
template: '-'
type: template
ansible_client_apache:
basejail: 'no'
boot: 'off'
ip4: '-'
ip4_dict:
ip4: []
msg: DHCP (not running)
ip6: '-'
jid: None
release: 15.0-RELEASE-p3
state: down
template: '-'
type: template
TASK [Pkglist: Create directories for pkglist files.] **************************
ok: [iocage_04] => (item=ansible_client_pull /tmp/ansible/ansible_client_pull/pkgs.json)
TASK [Pkglist: Copy pkglist files.] ********************************************
ok: [iocage_04] => (item=ansible_client_pull /tmp/ansible/ansible_client_pull/pkgs.json)
TASK [Create: Create templates.] ***********************************************
changed: [iocage_04] => (item=ansible_client_pull 15.0-RELEASE)
TASK [Start: Display iocage_jails debug=true] **********************************
ok: [iocage_04] =>
iocage_jails:
ansible_client_pull:
basejail: 'no'
boot: 'off'
ip4: DHCP (not running)
ip6: '-'
jid: None
name: ansible_client_pull
properties:
CONFIG_VERSION: '33'
allow_chflags: '0'
allow_mlock: '0'
allow_mount: '0'
allow_mount_devfs: '0'
allow_mount_fdescfs: '0'
allow_mount_fusefs: '0'
allow_mount_linprocfs: '0'
allow_mount_linsysfs: '0'
allow_mount_nullfs: '0'
allow_mount_procfs: '0'
allow_mount_tmpfs: '0'
allow_mount_zfs: '0'
allow_nfsd: '0'
allow_quotas: '0'
allow_raw_sockets: '0'
allow_set_hostname: '1'
allow_socket_af: '0'
allow_sysvipc: '0'
allow_tun: '0'
allow_vmm: '0'
assign_localhost: '0'
available: readonly
basejail: '0'
boot: '0'
bpf: '1'
children_max: '0'
cloned_release: 15.0-RELEASE
comment: none
compression: 'on'
compressratio: readonly
coredumpsize: 'off'
count: '1'
cpuset: 'off'
cputime: 'off'
datasize: 'off'
dedup: 'off'
defaultrouter: auto
defaultrouter6: auto
depends: none
devfs_ruleset: '4'
dhcp: '1'
enforce_statfs: '2'
exec_clean: '1'
exec_created: /usr/bin/true
exec_fib: '0'
exec_jail_user: root
exec_poststart: /usr/bin/true
exec_poststop: /usr/bin/true
exec_prestart: /usr/bin/true
exec_prestop: /usr/bin/true
exec_start: /bin/sh /etc/rc
exec_stop: /bin/sh /etc/rc.shutdown
exec_system_jail_user: '0'
exec_system_user: root
exec_timeout: '60'
host_domainname: none
host_hostname: ansible-client-pull
host_hostuuid: ansible_client_pull
host_time: '1'
hostid: d6add9ad-8b6e-4316-a226-345a60532b41
hostid_strict_check: '0'
interfaces: vnet0:bridge0
ip4: new
ip4_addr: none
ip4_saddrsel: '1'
ip6: new
ip6_addr: none
ip6_saddrsel: '1'
ip_hostname: '0'
jail_zfs: '0'
jail_zfs_dataset: iocage/jails/ansible_client_pull/data
jail_zfs_mountpoint: none
last_started: '2026-02-24 22:35:58'
localhost_ip: none
login_flags: -f root
mac_prefix: 5a9cfc
maxproc: 'off'
memorylocked: 'off'
memoryuse: 'off'
min_dyn_devfs_ruleset: '1000'
mount_devfs: '1'
mount_fdescfs: '1'
mount_linprocfs: '0'
mount_procfs: '0'
mountpoint: readonly
msgqqueued: 'off'
msgqsize: 'off'
nat: '0'
nat_backend: ipfw
nat_forwards: none
nat_interface: none
nat_prefix: '172.16'
nmsgq: 'off'
notes: none
nsem: 'off'
nsemop: 'off'
nshm: 'off'
nthr: 'off'
openfiles: 'off'
origin: readonly
owner: root
pcpu: 'off'
plugin_name: none
plugin_repository: none
priority: '99'
pseudoterminals: 'off'
quota: none
readbps: 'off'
readiops: 'off'
release: 15.0-RELEASE-p3
reservation: none
resolver: /etc/resolv.conf
rlimits: 'off'
rtsold: '0'
securelevel: '2'
shmsize: 'off'
stacksize: 'off'
state: down
stop_timeout: '30'
swapuse: 'off'
sync_state: none
sync_target: none
sync_tgt_zpool: none
sysvmsg: new
sysvsem: new
sysvshm: new
template: '0'
type: jail
used: readonly
vmemoryuse: 'off'
vnet: '1'
vnet0_mac: 5a9cfc7e220c 5a9cfc7e220d
vnet0_mtu: auto
vnet1_mac: none
vnet1_mtu: auto
vnet2_mac: none
vnet2_mtu: auto
vnet3_mac: none
vnet3_mtu: auto
vnet_default_interface: none
vnet_default_mtu: '1500'
vnet_interfaces: none
wallclock: 'off'
writebps: 'off'
writeiops: 'off'
release: 15.0-RELEASE-p3
state: down
template: '-'
type: jail
TASK [Start: Start jails.] *****************************************************
ok: [iocage_04]
TASK [User: Create user.] ******************************************************
changed: [iocage_04] => (item=ansible_client_pull admin)
TASK [Pk: The keys are valid.] *************************************************
ok: [iocage_04] =>
changed: false
msg: All assertions passed
TASK [Pk: Configure public keys.] **********************************************
changed: [iocage_04] => (item=ansible_client_pull admin)
TASK [Pk: Chown .ssh] **********************************************************
ok: [iocage_04] => (item=ansible_client_pull admin)
TASK [Sudo: Configure sudo.] ***************************************************
changed: [iocage_04] => (item=ansible_client_pull admin)
TASK [Dhclient: Configure hooks.] **********************************************
changed: [iocage_04] => (item=ansible_client_pull dhclient-exit-hooks)
TASK [Rcconf: Configure /etc/rc.conf] ******************************************
changed: [iocage_04] => (item=ansible_client_pull iocage_enable YES)
changed: [iocage_04] => (item=ansible_client_pull sshd_enable YES)
TASK [Stop: Display iocage_jails debug=true] ***********************************
ok: [iocage_04] =>
iocage_jails:
ansible_client_pull:
basejail: 'no'
boot: 'off'
ip4: epair0b|10.1.0.212
ip6: '-'
jid: '75'
name: ansible_client_pull
properties:
CONFIG_VERSION: '33'
allow_chflags: '0'
allow_mlock: '0'
allow_mount: '0'
allow_mount_devfs: '0'
allow_mount_fdescfs: '0'
allow_mount_fusefs: '0'
allow_mount_linprocfs: '0'
allow_mount_linsysfs: '0'
allow_mount_nullfs: '0'
allow_mount_procfs: '0'
allow_mount_tmpfs: '0'
allow_mount_zfs: '0'
allow_nfsd: '0'
allow_quotas: '0'
allow_raw_sockets: '0'
allow_set_hostname: '1'
allow_socket_af: '0'
allow_sysvipc: '0'
allow_tun: '0'
allow_vmm: '0'
assign_localhost: '0'
available: readonly
basejail: '0'
boot: '0'
bpf: '1'
children_max: '0'
cloned_release: 15.0-RELEASE
comment: none
compression: 'on'
compressratio: readonly
coredumpsize: 'off'
count: '1'
cpuset: 'off'
cputime: 'off'
datasize: 'off'
dedup: 'off'
defaultrouter: auto
defaultrouter6: auto
depends: none
devfs_ruleset: '4'
dhcp: '1'
enforce_statfs: '2'
exec_clean: '1'
exec_created: /usr/bin/true
exec_fib: '0'
exec_jail_user: root
exec_poststart: /usr/bin/true
exec_poststop: /usr/bin/true
exec_prestart: /usr/bin/true
exec_prestop: /usr/bin/true
exec_start: /bin/sh /etc/rc
exec_stop: /bin/sh /etc/rc.shutdown
exec_system_jail_user: '0'
exec_system_user: root
exec_timeout: '60'
host_domainname: none
host_hostname: ansible-client-pull
host_hostuuid: ansible_client_pull
host_time: '1'
hostid: d6add9ad-8b6e-4316-a226-345a60532b41
hostid_strict_check: '0'
interfaces: vnet0:bridge0
ip4: new
ip4_addr: none
ip4_saddrsel: '1'
ip6: new
ip6_addr: none
ip6_saddrsel: '1'
ip_hostname: '0'
jail_zfs: '0'
jail_zfs_dataset: iocage/jails/ansible_client_pull/data
jail_zfs_mountpoint: none
last_started: '2026-02-24 22:37:16'
localhost_ip: none
login_flags: -f root
mac_prefix: 5a9cfc
maxproc: 'off'
memorylocked: 'off'
memoryuse: 'off'
min_dyn_devfs_ruleset: '1000'
mount_devfs: '1'
mount_fdescfs: '1'
mount_linprocfs: '0'
mount_procfs: '0'
mountpoint: readonly
msgqqueued: 'off'
msgqsize: 'off'
nat: '0'
nat_backend: ipfw
nat_forwards: none
nat_interface: none
nat_prefix: '172.16'
nmsgq: 'off'
notes: none
nsem: 'off'
nsemop: 'off'
nshm: 'off'
nthr: 'off'
openfiles: 'off'
origin: readonly
owner: root
pcpu: 'off'
plugin_name: none
plugin_repository: none
priority: '99'
pseudoterminals: 'off'
quota: none
readbps: 'off'
readiops: 'off'
release: 15.0-RELEASE-p3
reservation: none
resolver: /etc/resolv.conf
rlimits: 'off'
rtsold: '0'
securelevel: '2'
shmsize: 'off'
stacksize: 'off'
state: up
stop_timeout: '30'
swapuse: 'off'
sync_state: none
sync_target: none
sync_tgt_zpool: none
sysvmsg: new
sysvsem: new
sysvshm: new
template: '0'
type: jail
used: readonly
vmemoryuse: 'off'
vnet: '1'
vnet0_mac: 5a9cfc7e220c 5a9cfc7e220d
vnet0_mtu: auto
vnet1_mac: none
vnet1_mtu: auto
vnet2_mac: none
vnet2_mtu: auto
vnet3_mac: none
vnet3_mtu: auto
vnet_default_interface: none
vnet_default_mtu: '1500'
vnet_interfaces: none
wallclock: 'off'
writebps: 'off'
writeiops: 'off'
release: 15.0-RELEASE-p3
state: up
template: '-'
type: jail
TASK [Stop: Stop jails.] *******************************************************
ok: [iocage_04]
TASK [Template: Set template.] *************************************************
ok: [iocage_04] => (item=ansible_client_pull)
PLAY RECAP *********************************************************************
iocage_04 : ok=18 changed=6 unreachable=0 failed=0 skipped=24 rescued=0 ignored=0
Templates at iocage_04
[iocage_04]# iocage list -lt
+------+-----------------------+------+-------+----------+-----------------+--------------------+-----+----------+----------+
| JID | NAME | BOOT | STATE | TYPE | RELEASE | IP4 | IP6 | TEMPLATE | BASEJAIL |
+======+=======================+======+=======+==========+=================+====================+=====+==========+==========+
| None | ansible_client | off | down | template | 15.0-RELEASE-p3 | DHCP (not running) | - | - | no |
+------+-----------------------+------+-------+----------+-----------------+--------------------+-----+----------+----------+
| None | ansible_client_apache | off | down | template | 15.0-RELEASE-p3 | DHCP (not running) | - | - | no |
+------+-----------------------+------+-------+----------+-----------------+--------------------+-----+----------+----------+
| None | ansible_client_pull | off | down | template | 15.0-RELEASE-p3 | DHCP (not running) | - | - | no |
+------+-----------------------+------+-------+----------+-----------------+--------------------+-----+----------+----------+