Ansible on FreeBSD 14 Automation Complete Guide
By Luca Berton · Published 2024-01-01 · Category: installation
Automate FreeBSD 14 servers with Ansible: pkg, rc.conf, jails, ZFS, pf firewall, and FreeBSD-specific modules.
FreeBSD 14 (14.0 GA Nov 2023, 14.2 currently latest) is the modern FreeBSD release line. It ships OpenSSH 9.5, OpenZFS 2.2, pf firewall, and bhyve hypervisor. ESR through ~2027. Ansible automates pkg, rc.conf, jails, ZFS pools/datasets, and pf rules. This is the master Ansible guide for FreeBSD 14.
FreeBSD 14 release facts
| Item | Value | |---|---| | Release | 2023-11-20 (14.0) | | Latest | 14.2 | | Default shell | sh (root), tcsh (toor) | | Package manager | pkg | | Init | rc.d | | Firewall | pf | | Hypervisor | bhyve |
See also: Ansible FreeBSD Jail Management: jailexec Connection Plugin Guide
Ansible-core compatibility
Use ansible-core 2.18 LTS. Bootstrap Python via pkg:
pkg install -y python311 py311-pip
[freebsd14]
fbsd14-01.example.com
[freebsd14:vars]
ansible_user=root
ansible_python_interpreter=/usr/local/bin/python3.11
Baseline playbook
- name: FreeBSD 14 baseline
hosts: freebsd14
tasks:
- name: Update pkg
community.general.pkgng:
name: "*"
state: latest
- name: Install baseline packages
community.general.pkgng:
name:
- vim
- curl
- htop
- tmux
- sudo
- bash
- rsync
- py311-pip
state: present
- name: Set timezone
ansible.builtin.command: tzsetup -s UTC
changed_when: false
See also: Ansible on NetBSD 10 Automation Complete Guide
rc.conf management
- name: Configure /etc/rc.conf
hosts: freebsd14
tasks:
- name: Set sshd
ansible.builtin.lineinfile:
path: /etc/rc.conf
regexp: '^sshd_enable='
line: 'sshd_enable="YES"'
- name: Set hostname
ansible.builtin.lineinfile:
path: /etc/rc.conf
regexp: '^hostname='
line: 'hostname="{{ inventory_hostname }}"'
- name: Set static IP
ansible.builtin.lineinfile:
path: /etc/rc.conf
regexp: "^ifconfig_{{ iface }}="
line: 'ifconfig_{{ iface }}="inet {{ host_ip }} netmask 255.255.255.0"'
ZFS pools and datasets
- name: Manage ZFS
hosts: freebsd14
tasks:
- name: Create dataset
community.general.zfs:
name: zroot/var/log/audit
state: present
extra_zfs_properties:
compression: lz4
atime: 'off'
- name: Set quota
community.general.zfs:
name: zroot/var/log/audit
state: present
extra_zfs_properties:
quota: 10G
See also: Ansible on OpenBSD 7.6 Automation Complete Guide
pf firewall
- name: Configure pf
hosts: freebsd14
handlers:
- name: reload pf
ansible.builtin.command: pfctl -f /etc/pf.conf
tasks:
- name: Drop pf.conf
ansible.builtin.copy:
dest: /etc/pf.conf
mode: "0644"
content: |
ext_if = "vtnet0"
set skip on lo
block in all
pass in on $ext_if proto tcp from any to ($ext_if) port {22, 443}
pass out all keep state
notify: reload pf
- name: Enable pf at boot
ansible.builtin.lineinfile:
path: /etc/rc.conf
regexp: '^pf_enable='
line: 'pf_enable="YES"'
Jails
- name: Create a jail
hosts: freebsd14
tasks:
- name: Install ezjail
community.general.pkgng: { name: ezjail, state: present }
- name: Bootstrap jail base
ansible.builtin.command: ezjail-admin install -p
args:
creates: /usr/jails/basejail/usr/bin/sh
- name: Create jail
ansible.builtin.command: ezjail-admin create web01 'lo1|10.10.0.10'
args:
creates: /usr/jails/web01
- name: Start jails
ansible.builtin.lineinfile:
path: /etc/rc.conf
regexp: '^ezjail_enable='
line: 'ezjail_enable="YES"'
- name: Service ezjail start
ansible.builtin.command: service ezjail start
register: ej
changed_when: "'Starting jails' in ej.stdout"
Best practices
• Prefer pkg binaries over ports for repeatable installs; usecommunity.general.pkgng.
• Manage /etc/rc.conf with lineinfile for idempotency.
• Use ZFS snapshots before any pkg upgrade and roll back via zfs rollback.
• pf rules belong in version control; reload via the handler pattern.
Conclusion
FreeBSD 14 + Ansible delivers reproducible BSD servers with ZFS, jails, and pf. The community.general collection covers most modules, with lineinfile filling the rc.conf gap.
Category: installation