521 iocage plugins ansible-pull-syslogng-*
Use case
Configure and run a log server. Configure log clients and test them. Use syslog-ng. Clone the
iocage plugins ansible-pull-syslogng-server and ansible-pull-syslogng-client.
Quoting syslog-ng - FreeBSD Wiki:
“One of the most typical use of syslog-ng is central log aggregation. … It collects log messages on TCP port 514 and saves them to directories and files based on sender host name and current date.”
Tree
shell > tree .
.
├── ansible.cfg
├── group_vars
│ └── all
│ ├── common.yml
│ └── project-hosts.yml
├── hosts
│ └── 05_iocage.yml
├── host_vars
│ └── iocage_05
│ └── syslog-ng.yml
├── iocage.ini
├── pb-create-jails.yml
├── pb-logclient-test.yml
└── pb-logserver-test.yml
Synopsis
At a managed node:
In the playbook vbotka.freebsd.pb_iocage_plugins.yml fetch the iocage plugins:
ansible-pull-syslogng-serveransible-pull-syslogng-client
In the playbook
pb-create-jails.yml:Clone jails from the fetched iocage plugins
In the inventory group
log_serverstest syslog-ng server.In the inventory group
log_clientstest syslog-ng client.
Requirements
-
ansible-pull-syslogng-serveransible-pull-syslogng-client
Configuration repositories for
ansible-pull:playbook vbotka.freebsd.pb_iocage_plugins.yml
Important
For security reasons, you might want to create private repositories with the iocage plugins and configurations. See the example 523 iocage template ansible-repos
Note
This example creates the same functionality as the example 522 iocage templates ansible-syslogng-*. The
iocage pluginsare used here instead ofiocage templates.The same functionality is created also in the example 526 Log server and clients (ansible_init).
In this example, DHCP was provided by the iocage host. See 440 Configure DHCP and pf.
ansible.cfg
[defaults]
callback_result_format = yaml
deprecation_warnings = false
display_skipped_hosts = false
gathering = explicit
interpreter_python = auto_silent
log_path = /var/log/ansible.log
[connection]
pipelining = true
Inventory iocage.ini
iocage_05
[iocage]
iocage_05
[iocage:vars]
ansible_user=admin
ansible_become=true
ansible_python_interpreter=auto_silent
hosts
plugin: vbotka.freebsd.iocage
host: iocage_05
user: admin
sudo: true
get_properties: true
inventory_hostname_tag: alias
compose:
iocage_tags: dict(iocage_properties.notes | regex_findall('(\w+)=([\w\-]+)'))
iocage_classes: iocage_properties.notes | regex_findall('(?<=class=)[\w\-]+|(?<=,)[\w\-]+')
# connection plugin vbotka.freebsd.jailexec
ansible_connection: "'vbotka.freebsd.jailexec'"
ansible_jail_host: dict(iocage_properties.notes | regex_findall('(\w+)=([\w\-]+)')).vmm | d('none')
ansible_jail_name: iocage_jid
ansible_jail_privilege_escalation: "'sudo'"
groups:
log_servers: iocage_classes is contains('log-server')
log_clients: iocage_classes is contains('log-client')
keyed_groups:
- prefix: state
key: iocage_state
- prefix: vmm
key: iocage_tags.vmm
group_vars
ansible_python_interpreter: auto_silent
project_hosts:
iocage_05:
defaultrouter: 172.16.99.1
log_server: 172.16.99.10
# repositories
repos: 172.16.99.21
repos_devel: 172.16.99.22
# plugins
ansible_pull_syslogng_server: 172.16.99.31
host_vars
enabled_plugins:
- ansible-pull-syslogng-client
- ansible-pull-syslogng-server
plugins:
ansible-pull-syslogng-server:
git: https://github.com/vbotka/iocage-plugins
branch: main
properties:
ip4: disable
ip6: disable
ip6_addr: none
boot: 0
defaultrouter: "{{ project_hosts[inventory_hostname]['defaultrouter'] }}"
ip4_addr: "vnet0|{{ project_hosts[inventory_hostname]['ansible_pull_syslogng_server'] }}/24"
vnet: 1
ansible-pull-syslogng-client:
git: https://github.com/vbotka/iocage-plugins
branch: main
properties:
ip4: disable
ip6: disable
ip6_addr: none
boot: 0
bpf: 1
dhcp: 1
vnet: 1
log_server_properties:
ip4: disable
ip6: disable
ip6_addr: none
type: jail
boot: 1
defaultrouter: "{{ project_hosts[inventory_hostname]['defaultrouter'] }}"
ip4_addr: "vnet0|{{ project_hosts[inventory_hostname]['log_server'] }}/24"
vnet: 1
log_client_properties:
ip4: disable
ip6: disable
ip6_addr: none
type: jail
boot: 1
bpf: 1
dhcp: 1
vnet: 1
log_clients:
- foo
- bar
Playbook output - Fetch iocage plugins
(env) > ansible-playbook vbotka.freebsd.pb_iocage_plugins.yml \
-i iocage.ini \
-t enabled_plugins \
-e debug=true
PLAY [Fetch and stop iocage plugins.] ******************************************
TASK [One tag is required.] ****************************************************
ok: [iocage_05]
TASK [Test the tag is known.] **************************************************
ok: [iocage_05]
TASK [Get already fetched plugins.] ********************************************
ok: [iocage_05]
TASK [Debug fetched plugins debug=true] ****************************************
ok: [iocage_05] =>
msg: |-
iocage_plugins:
ansible-pull-syslogng-client:
boot: 'off'
doc_url: '-'
ip4: '-'
ip4_dict:
ip4: []
msg: DHCP (not running)
ip6: '-'
jid: None
portal: '-'
release: 15.0-RELEASE
state: down
template: '-'
type: pluginv2
ansible-pull-syslogng-server:
boot: 'off'
doc_url: '-'
ip4: 172.16.99.31
ip4_dict:
ip4:
- ifc: vnet0
ip: 172.16.99.31
mask: '24'
msg: ''
ip6: '-'
jid: None
portal: '-'
release: 15.0-RELEASE
state: down
template: '-'
type: pluginv2
ansible-pull-test:
boot: 'off'
doc_url: '-'
ip4: '-'
ip4_dict:
ip4: []
msg: DHCP (not running)
ip6: '-'
jid: None
portal: '-'
release: 15.0-RELEASE
state: down
template: '-'
type: pluginv2
plugins:
ansible-pull-syslogng-client:
branch: main
git: https://github.com/vbotka/iocage-plugins
properties:
boot: 0
bpf: 1
dhcp: 1
ip4: disable
ip6: disable
ip6_addr: none
vnet: 1
ansible-pull-syslogng-server:
branch: main
git: https://github.com/vbotka/iocage-plugins
properties:
boot: 0
defaultrouter: 172.16.99.1
ip4: disable
ip4_addr: vnet0|172.16.99.31/24
ip6: disable
ip6_addr: none
vnet: 1
TASK [Set required plugins.] ***************************************************
ok: [iocage_05]
TASK [Debug selected plugins debug=true] ***************************************
ok: [iocage_05] =>
msg: |-
required_plugins:
- ansible-pull-syslogng-client
- ansible-pull-syslogng-server
selected_plugins:
[]
TASK [Check all required plugins are included in the dictionary plugins.] ******
ok: [iocage_05]
PLAY RECAP *********************************************************************
iocage_05 : ok=7 changed=0 unreachable=0 failed=0 skipped=3 rescued=0 ignored=0
List iocage plugins
shell > ssh admin@iocage_05 sudo iocage list -P
+------+------------------------------+------+-------+----------+--------------+-----------------------+-----+----------+--------+---------+
| JID | NAME | BOOT | STATE | TYPE | RELEASE | IP4 | IP6 | TEMPLATE | PORTAL | DOC_URL |
+======+==============================+======+=======+==========+==============+=======================+=====+==========+========+=========+
| None | ansible-pull-syslogng-client | off | down | pluginv2 | 15.0-RELEASE | DHCP (not running) | - | - | - | - |
+------+------------------------------+------+-------+----------+--------------+-----------------------+-----+----------+--------+---------+
| None | ansible-pull-syslogng-server | off | down | pluginv2 | 15.0-RELEASE | vnet0|172.16.99.31/24 | - | - | - | - |
+------+------------------------------+------+-------+----------+--------------+-----------------------+-----+----------+--------+---------+
| None | ansible-pull-test | off | down | pluginv2 | 15.0-RELEASE | DHCP (not running) | - | - | - | - |
+------+------------------------------+------+-------+----------+--------------+-----------------------+-----+----------+--------+---------+
Playbook pb-create-jails.yml
---
- name: Create jails from iocage plugins.
hosts: iocage_05
vars:
client_exist: "{{ groups.all | intersect(log_clients) }}"
tasks:
- name: log_client exist.
when: client_exist | length > 0
block:
- name: Assert log_client is in groups.log_clients
vars:
missing: "{{ client_exist | difference(groups.log_clients | d([])) }}"
ansible.builtin.assert:
that: missing | length == 0
fail_msg: "[ERR] {{ missing | join(', ') }} not in group log_clients"
quiet: true
- name: Display message.
ansible.builtin.debug:
msg: "[INFO] {{ client_exist | join(', ') }} exist(s)."
- name: Create log clients.
vars:
_notes: >-
"vmm={{ inventory_hostname }}
class=log-client
alias={{ item }}"
_properties: >-
{% for k, v in log_client_properties.items() %}
{{ k }}={{ v }}
{% endfor %}
notes={{ _notes }}
ansible.builtin.command: >
iocage clone
--newmac
ansible-pull-syslogng-client
{{ _properties }}
loop: "{{ log_clients | difference(client_exist) }}"
- name: End of host if log_server exists.
when: groups.all is contains('log_server')
block:
- name: Assert log_server is in groups.log_servers
ansible.builtin.assert:
that: groups.log_servers | d([]) is contains('log_server')
fail_msg: '[ERR] log_server not in groups.log_servers'
quiet: true
- name: Display message.
ansible.builtin.debug:
msg: '[INFO] log_server exists.'
- name: End of host.
ansible.builtin.meta: end_host
- name: Create log_server
vars:
_notes: >-
"vmm={{ inventory_hostname }}
class=log-server
alias=log_server"
_properties: >-
{% for k, v in log_server_properties.items() %}
{{ k }}={{ v }}
{% endfor %}
notes={{ _notes }}
ansible.builtin.command: >
iocage clone
--newmac
ansible-pull-syslogng-server
{{ _properties }}
Playbook output - Create jails from iocage plugins
(env) > ansible-playbook pb-create-jails.yml.yml -i iocage.ini -i hosts
PLAY [Create jails from iocage plugins.] ***************************************
TASK [Create log clients.] *****************************************************
changed: [iocage_05] => (item=foo)
changed: [iocage_05] => (item=bar)
TASK [Create log_server] *******************************************************
changed: [iocage_05]
PLAY RECAP *********************************************************************
iocage_05 : ok=2 changed=2 unreachable=0 failed=0 skipped=4 rescued=0 ignored=0
Inventory graph
shell > ansible-inventory -i hosts --graph
@all:
|--@ungrouped:
|--@state_down:
| |--ansible-pull-syslogng-client
| |--ansible-pull-syslogng-server
| |--ansible-pull-test
|--@state_up:
| |--repos
| |--bar
| |--foo
| |--log_server
| |--repos_devel
|--@vmm_iocage_05:
| |--repos
| |--bar
| |--foo
| |--log_server
| |--repos_devel
|--@log_clients:
| |--bar
| |--foo
|--@log_servers:
| |--log_server
List jails
shell > ssh admin@iocage_05 sudo iocage list -l
+------+--------------------------------------+------+-------+----------+--------------+-----------------------+-----+------------------------------+----------+
| JID | NAME | BOOT | STATE | TYPE | RELEASE | IP4 | IP6 | TEMPLATE | BASEJAIL |
+======+======================================+======+=======+==========+==============+=======================+=====+==============================+==========+
| 26 | ae577716-d682-4f90-9f80-d54ef87bb00e | on | up | jail | 15.0-RELEASE | epair0b|172.16.99.192 | - | ansible-pull-syslogng-client | yes |
+------+--------------------------------------+------+-------+----------+--------------+-----------------------+-----+------------------------------+----------+
| None | ansible-pull-syslogng-client | off | down | pluginv2 | 15.0-RELEASE | DHCP (not running) | - | - | yes |
+------+--------------------------------------+------+-------+----------+--------------+-----------------------+-----+------------------------------+----------+
| None | ansible-pull-syslogng-server | off | down | pluginv2 | 15.0-RELEASE | vnet0|172.16.99.31/24 | - | - | yes |
+------+--------------------------------------+------+-------+----------+--------------+-----------------------+-----+------------------------------+----------+
| None | ansible-pull-test | off | down | pluginv2 | 15.0-RELEASE | DHCP (not running) | - | - | yes |
+------+--------------------------------------+------+-------+----------+--------------+-----------------------+-----+------------------------------+----------+
| 25 | be7bcbc8-af70-4784-86a4-34811ba1136f | on | up | jail | 15.0-RELEASE | epair0b|172.16.99.191 | - | ansible-pull-syslogng-client | yes |
+------+--------------------------------------+------+-------+----------+--------------+-----------------------+-----+------------------------------+----------+
| 27 | fce96a84-8d2a-451f-8887-f4aebb0ad31a | on | up | jail | 15.0-RELEASE | vnet0|172.16.99.10/24 | - | ansible-pull-syslogng-server | yes |
+------+--------------------------------------+------+-------+----------+--------------+-----------------------+-----+------------------------------+----------+
| 2 | repos | on | up | jail | 15.0-RELEASE | vnet0|172.16.99.21/24 | - | ansible-repos | no |
+------+--------------------------------------+------+-------+----------+--------------+-----------------------+-----+------------------------------+----------+
| 3 | repos-devel | on | up | jail | 15.0-RELEASE | vnet0|172.16.99.22/24 | - | ansible-repos | no |
+------+--------------------------------------+------+-------+----------+--------------+-----------------------+-----+------------------------------+----------+
Playbook pb-logserver-test.yml
---
- name: Test Log Server.
hosts: log_servers
tasks:
- name: Run commands.
register: out
ansible.builtin.shell: "{{ item }}"
loop:
- rm -rf /var/log/remote/localhost/*
- service syslog-ng status
- loggen -i -S -n 1 localhost 514
- sleep 5; find /var/log/remote/localhost/ -name *.log | xargs cat
- name: Debug.
when: debug | d(false) | bool
ansible.builtin.debug:
msg: |
{% for i in out.results %}
shell> {{ i.item }}
{% if i.stdout | length > 0 %}
{{ i.stdout }}
{% endif %}
{% if i.stderr | length > 0 %}
{{ i.stderr }}
{% endif %}
{% endfor %}
Playbook output - Test Log Server
(env) > ansible-playbook pb-logserver-test.yml -i hosts -e debug=true
PLAY [Test Log Server.] ********************************************************
TASK [Run commands.] ***********************************************************
changed: [log_server] => (item=rm -rf /var/log/remote/localhost/*)
changed: [log_server] => (item=service syslog-ng status)
changed: [log_server] => (item=loggen -i -S -n 1 localhost 514)
changed: [log_server] => (item=sleep 5; find /var/log/remote/localhost/ -name *.log | xargs cat)
TASK [Debug.] ******************************************************************
ok: [log_server] =>
msg: |-
shell> rm -rf /var/log/remote/localhost/*
shell> service syslog-ng status
syslog_ng is running as pid 59400.
shell> loggen -i -S -n 1 localhost 514
count=1, rate = 125000.00 msg/sec
average rate = 2.00 msg/sec, count=1, time=0.500228, (average) msg size=256, bandwidth=0.50 kB/sec
shell> sleep 5; find /var/log/remote/localhost/ -name *.log | xargs cat
Jun 28 10:53:09 localhost prg00000[1234]: seq: 0000000000, thread: 0000, runid: 1782636789, stamp: 2026-06-28T10:53:09 PADDPADDPADDPADDPADDPADDPADDPADDPADDPADDPADDPADDPADDPADDPADDPADDPADDPADDPADDPADDPADDPADDPADDPADDPADDPADDPADDPADDPADDPADDPADDPADD
PLAY RECAP *********************************************************************
log_server : ok=2 changed=1 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
Playbook pb-logclient-test.yml
---
- name: Test Log Clients.
hosts: log_clients
vars:
log_server: "{{ hostvars['log_server']['iocage_ip4'] }}"
tasks:
- name: Run loggen
register: out
ansible.builtin.command: "loggen -i -S -n 1 {{ log_server }} 514"
- name: Debug.
ansible.builtin.debug:
var: out.stderr
- name: Display the logs.
hosts: log_server
tasks:
- name: Get log files paths.
register: out
ansible.builtin.find:
paths: /var/log/remote
recurse: true
patterns: '*.log'
- name: Get log files.
register: out
ansible.builtin.command: "cat {{ item }}"
loop: "{{ out.files | map(attribute='path') }}"
- name: Display log files.
ansible.builtin.debug:
msg: |
{{ item.stdout }}
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
loop: "{{ out.results }}"
loop_control:
label: "{{ item.cmd }}"
Playbook output - Test Log Clients
(env) > ansible-playbook pb-logclient-test.yml -i hosts
PLAY [Test Log Clients.] *******************************************************
TASK [Run loggen] **************************************************************
changed: [foo]
changed: [bar]
TASK [Debug.] ******************************************************************
ok: [bar] =>
out.stderr: |-
count=1, rate = 166666.67 msg/sec
average rate = 2.00 msg/sec, count=1, time=0.500381, (average) msg size=256, bandwidth=0.50 kB/sec
ok: [foo] =>
out.stderr: |-
count=1, rate = 125000.00 msg/sec
average rate = 2.00 msg/sec, count=1, time=0.500329, (average) msg size=256, bandwidth=0.50 kB/sec
PLAY [Display the logs.] *******************************************************
TASK [Get log files paths.] ****************************************************
ok: [log_server]
TASK [Get log files.] **********************************************************
changed: [log_server] => (item=/var/log/remote/172.16.99.192/2026_06_28.log)
changed: [log_server] => (item=/var/log/remote/172.16.99.191/2026_06_28.log)
TASK [Display log files.] ******************************************************
ok: [log_server] => (item=['cat', '/var/log/remote/172.16.99.192/2026_06_28.log']) =>
msg: |-
Jun 28 10:52:06 172.16.99.192 prg00000[1234]: seq: 0000000000, thread: 0000, runid: 1782636726, stamp: 2026-06-28T10:52:06 PADDPADDPADDPADDPADDPADDPADDPADDPADDPADDPADDPADDPADDPADDPADDPADDPADDPADDPADDPADDPADDPADDPADDPADDPADDPADDPADDPADDPADDPADDPADDPADD
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
ok: [log_server] => (item=['cat', '/var/log/remote/172.16.99.191/2026_06_28.log']) =>
msg: |-
Jun 28 10:52:06 172.16.99.191 prg00000[1234]: seq: 0000000000, thread: 0000, runid: 1782636726, stamp: 2026-06-28T10:52:06 PADDPADDPADDPADDPADDPADDPADDPADDPADDPADDPADDPADDPADDPADDPADDPADDPADDPADDPADDPADDPADDPADDPADDPADDPADDPADDPADDPADDPADDPADDPADDPADD
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
PLAY RECAP *********************************************************************
bar : ok=2 changed=1 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
foo : ok=2 changed=1 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
log_server : ok=3 changed=1 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
Hint
Use lnav utility on the log server to display all logfiles in the the directory
/var/log/remote. For example,
shell > iocage console c8a9d789-fa02-4ce3-af66-41c848f87b0f
root@c8a9d789-fa02-4ce3-af66-41c848f87b0f:~ # lnav -r /var/log/remote/
To find the UUID, run iocage list -l and look for the jail created from the template
ansible-pull-syslogng-server.