522 iocage templates ansible-syslogng-*

Use case

Configure and run a log server. Configure log clients and test them. Use syslog-ng. Create templates ansible-syslogng-server and ansible-syslogng-client. Create the jails from the templates.

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
├── files
│   ├── pkgs-logclient.json
│   └── pkgs-logserver.json
├── group_vars
│   └── all
│       ├── common.yml
│       └── project-hosts.yml
├── hosts
│   └── 05_iocage.yml
├── host_vars
│   ├── ansible_syslogng_client
│   │   └── syslog-ng-client.yml
│   ├── ansible_syslogng_server
│   │   └── syslog-ng-server.yml
│   └── iocage_05
│       └── template.yml
├── iocage.ini
├── pb-create-jails.yml
├── pb-iocage-template-stop-convert.yml
├── pb-iocage-template.yml
├── pb-logclient-test.yml
├── pb-logclient.yml
├── pb-logserver-test.yml
└── pb-logserver.yml

Synopsis

  • At a managed node:

    Use the role vbotka.freebsd.iocage_template to create templates:

    • ansible-syslogng-server

    • ansible-syslogng-client

    In the playbook pb-create-jails.yml:

    • Create jails from the created templates

  • In the inventory group log_servers configure and test syslog-ng server.

  • In the inventory group log_clients configure and test syslog-ng client.

Requirements

Note

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

hosts/05_iocage.yml
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

group_vars/all/common.yml
ansible_python_interpreter: auto_silent
group_vars/all/project-hosts.yml
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
    # templates
    ansible_syslogng_server: 172.16.99.41

host_vars

host_vars/ansible_syslogng_client/syslog-ng-client.yml
fp_syslogd: true
fp_syslogd_enable: false
fp_syslogd_conf_sanity: false

fp_syslogng: true
fp_syslogng_enable: true
fp_syslogng_conf_template: syslog-ng.conf.j2
fp_syslogng_conf:
  header:
    - '@version:4.8'
    - '@include "scl.conf"'
  options:
    - threaded(yes)
    - group("wheel")
    - perm(0640)
  source:
    s_system:
      - unix-dgram("/var/run/log")
      - unix-dgram("/var/run/logpriv" perm(0600))
      - internal()
    s_ansible:
      - file("/var/log/ansible.log" follow-freq(1) program-override("ansible"))
  destination:
    d_network:
      - network("{{ project_hosts[iocage_tags.vmm]['log_server'] }}" port(514) transport("tcp"))
  filter:
    f_messages:
      - level(info..emerg) and not facility(auth, authpriv, lpr, mail, news, daemon)
    f_daemon:
      - facility(daemon)
  log:
    - source: s_system
      filter: f_daemon
      destination: d_network
    - source: s_system
      filter: f_messages
      destination: d_network
    - source: s_ansible
      destination: d_network
host_vars/ansible_syslogng_server/syslog-ng-server.yml
fp_syslogd: true
fp_syslogd_enable: false
fp_syslogd_conf_sanity: false

fp_syslogng: true
fp_syslogng_enable: true
fp_syslogng_conf_template: syslog-ng.conf.j2
fp_syslogng_conf:
  header:
    - '@version:4.8'
    - '@include "scl.conf"'
  options:
    - threaded(yes)
    - group("wheel")
    - perm(0640)
  source:
    s_system:
      - unix-dgram("/var/run/log")
      - unix-dgram("/var/run/logpriv" perm(0600))
      - internal()
    s_ansible:
      - file("/var/log/ansible.log" follow-freq(1) program-override("ansible"))
    s_remote:
      - tcp(port(514))
  destination:
    d_local:
      - file("/var/log/remote/${HOST}/${YEAR}_${MONTH}_${DAY}.log" create-dirs(yes))
  filter:
    f_messages:
      - level(notice..emerg) and not facility(auth, authpriv, lpr, mail, news, daemon)
    f_daemon:
      - facility(daemon)
  log:
    - source: s_remote
      destination: d_local
    - source: s_system
      filter: f_daemon
      destination: d_local
    - source: s_system
      filter: f_messages
      destination: d_local
    - source: s_ansible
      destination: d_local
host_vars/iocage_05/template.yml
fit_templates:
  ansible-syslogng-server:
    release: 15.0-RELEASE
    pkglist: /tmp/ansible/ansible-syslogng-server/pkgs-logserver.json
    properties:
      ip4: disable
      ip6: disable
      ip6_addr: none
      boot: 0
      defaultrouter: "{{ project_hosts[inventory_hostname]['defaultrouter'] }}"
      ip4_addr: "vnet0|{{ project_hosts[inventory_hostname]['ansible_syslogng_server'] }}/24"
      vnet: 1
      notes: '"vmm={{ inventory_hostname }} alias=ansible_syslogng_server"'
  ansible-syslogng-client:
    release: 15.0-RELEASE
    pkglist: /tmp/ansible/ansible-syslogng-client/pkgs-logclient.json
    properties:
      ip4: disable
      ip6: disable
      ip6_addr: none
      boot: 0
      bpf: 1
      dhcp: 1
      vnet: 1
      notes: '"vmm={{ inventory_hostname }} alias=ansible_syslogng_client"'

# Do not stop jails. Configure them first. Then stop and convert them to templates.
fit_stop: false
fit_template: false
      
log_server_properties:
  ip4: disable
  ip6: disable
  ip6_addr: none
  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
  boot: 1
  bpf: 1
  dhcp: 1
  vnet: 1

log_clients:
  - foo
  - bar

files

files/pkgs-logclient.json
{
    "pkgs": [
        "sudo",
	"syslog-ng"
        ]
}
files/pkgs-logserver.json
{
    "pkgs": [
        "lnav",
        "sudo",
	"syslog-ng"
        ]
}

Playbook pb-iocage-template.yml

---
- name: Create iocage templates.
  hosts: iocage

  roles:

    - vbotka.freebsd.iocage_template

Playbook output - Create iocage templates

(env) > ansible-playbook pb-iocage-template.yml -i iocage.ini
PLAY [Create iocage templates.] ************************************************

TASK [vbotka.freebsd.iocage_template : Setup: Get iocage list of templates.] ***
ok: [iocage_05]

TASK [vbotka.freebsd.iocage_template : Setup: Get activated pool.] *************
ok: [iocage_05]

TASK [vbotka.freebsd.iocage_template : Pkglist: Create directories for pkglist files.] ***
ok: [iocage_05] => (item=ansible-syslogng-server /tmp/ansible/ansible-syslogng-server)
ok: [iocage_05] => (item=ansible-syslogng-client /tmp/ansible/ansible-syslogng-client)

TASK [vbotka.freebsd.iocage_template : Pkglist: Copy pkglist files.] ***********
ok: [iocage_05] => (item=ansible-syslogng-server /tmp/ansible/ansible-syslogng-server/pkgs-logserver.json)
ok: [iocage_05] => (item=ansible-syslogng-client /tmp/ansible/ansible-syslogng-client/pkgs-logclient.json)

TASK [vbotka.freebsd.iocage_template : Create: Get iocage list of jails.] ******
ok: [iocage_05]

TASK [vbotka.freebsd.iocage_template : Create: Create jails.] ******************
changed: [iocage_05] => (item=ansible-syslogng-server 15.0-RELEASE)
changed: [iocage_05] => (item=ansible-syslogng-client 15.0-RELEASE)

TASK [vbotka.freebsd.iocage_template : Start: Get iocage list of jails.] *******
ok: [iocage_05]

TASK [vbotka.freebsd.iocage_template : Start: Start jails.] ********************
ok: [iocage_05]

PLAY RECAP *********************************************************************
iocage_05                  : ok=8    changed=1    unreachable=0    failed=0    skipped=39   rescued=0    ignored=0   

Playbook pb-logserver.yml

---
- name: Configure and start Log Server.
  hosts: ansible_syslogng_server
    
  tasks:

    - name: Stop and disable syslogd
      ansible.builtin.import_role:
        name: vbotka.freebsd.postinstall
        tasks_from: syslogd.yml

    - name: Configure and start syslog-ng
      ansible.builtin.import_role:
        name: vbotka.freebsd.postinstall
        tasks_from: syslog-ng.yml

Playbook output - Configure and start Log Server

(env) > ansible-playbook pb-logserver.yml -i hosts
PLAY [Configure and start Log Server.] *****************************************

TASK [vbotka.freebsd.postinstall : Rcconf: Configure syslogd_enable in /etc/rc.conf] ***
changed: [ansible_syslogng_server]

TASK [vbotka.freebsd.postinstall : Syslog-ng: Sanity fp_syslogng_conf is empty.] ***
ok: [ansible_syslogng_server]

TASK [vbotka.freebsd.postinstall : Syslog-ng: Configure /usr/local/etc/syslog-ng.conf] ***
changed: [ansible_syslogng_server]

TASK [vbotka.freebsd.postinstall : Rcconf: Configure syslog_ng_enable in /etc/rc.conf] ***
changed: [ansible_syslogng_server]

RUNNING HANDLER [vbotka.freebsd.postinstall : Start syslog-ng] *****************
changed: [ansible_syslogng_server]

RUNNING HANDLER [vbotka.freebsd.postinstall : Reload syslog-ng] ****************
ok: [ansible_syslogng_server]

RUNNING HANDLER [vbotka.freebsd.postinstall : Stop syslogd] ********************
ok: [ansible_syslogng_server]

PLAY RECAP *********************************************************************
ansible_syslogng_server    : ok=7    changed=4    unreachable=0    failed=0    skipped=19   rescued=0    ignored=0   

Playbook pb-logclient.yml

---
- name: Configure Log Client.
  hosts: ansible_syslogng_client
    
  tasks:

    - name: Stop and disable syslogd
      ansible.builtin.import_role:
        name: vbotka.freebsd.postinstall
        tasks_from: syslogd.yml

    - name: Configure syslog-ng
      ansible.builtin.import_role:
        name: vbotka.freebsd.postinstall
        tasks_from: syslog-ng.yml

Playbook output - Configure and start Log Client

(env) > ansible-playbook pb-logclient.yml -i hosts
PLAY [Configure Log Client.] ***************************************************

TASK [vbotka.freebsd.postinstall : Rcconf: Configure syslogd_enable in /etc/rc.conf] ***
changed: [ansible_syslogng_client]

TASK [vbotka.freebsd.postinstall : Syslog-ng: Sanity fp_syslogng_conf is empty.] ***
ok: [ansible_syslogng_client]

TASK [vbotka.freebsd.postinstall : Syslog-ng: Configure /usr/local/etc/syslog-ng.conf] ***
changed: [ansible_syslogng_client]

TASK [vbotka.freebsd.postinstall : Rcconf: Configure syslog_ng_enable in /etc/rc.conf] ***
changed: [ansible_syslogng_client]

RUNNING HANDLER [vbotka.freebsd.postinstall : Start syslog-ng] *****************
changed: [ansible_syslogng_client]

RUNNING HANDLER [vbotka.freebsd.postinstall : Reload syslog-ng] ****************
ok: [ansible_syslogng_client]

RUNNING HANDLER [vbotka.freebsd.postinstall : Stop syslogd] ********************
ok: [ansible_syslogng_client]

PLAY RECAP *********************************************************************
ansible_syslogng_client    : ok=7    changed=4    unreachable=0    failed=0    skipped=19   rescued=0    ignored=0   

Playbook pb-iocage-template-stop-convert.yml

---
- name: Stop and convert ansible-syslogng-* to templates.
  hosts: iocage_05

  vars:

    iocage_jails: "{{ out.stdout | vbotka.freebsd.iocage('jails') }}"

  tasks:

    - name: Get iocage list of jails.
      register: out
      changed_when: false
      ansible.builtin.command: iocage list --long

    - name: Stop ansible-syslogng-server and convert it to template.
      when: iocage_jails is contains('ansible-syslogng-server')
      block:

        - name: Stop ansible-syslogng-server
          ansible.builtin.command: iocage stop ansible-syslogng-server

        - name: Convert ansible-syslogng-server jail to template.
          ansible.builtin.command: iocage set template=1 ansible-syslogng-server

    - name: Stop ansible-syslogng-client and convert it to template.
      when: iocage_jails is contains('ansible-syslogng-client')
      block:

        - name: Stop ansible-syslogng-client
          ansible.builtin.command: iocage stop ansible-syslogng-client

        - name: Convert ansible-syslogng-client jail to template.
          ansible.builtin.command: iocage set template=1 ansible-syslogng-client

Playbook output - Convert ansible-syslogng-* to templates

(env) > ansible-playbook pb-iocage-template-stop-convert.yml -i iocage.ini
PLAY [Stop and convert ansible-syslogng-* to templates.] ***********************

TASK [Get iocage list of jails.] ***********************************************
ok: [iocage_05]

TASK [Stop ansible-syslogng-server] ********************************************
changed: [iocage_05]

TASK [Convert ansible-syslogng-server jail to template.] ***********************
changed: [iocage_05]

TASK [Stop ansible-syslogng-client] ********************************************
changed: [iocage_05]

TASK [Convert ansible-syslogng-client jail to template.] ***********************
changed: [iocage_05]

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

List templates

shell > ssh admin@iocage_05 sudo iocage list -lt
+------+-------------------------+------+-------+----------+--------------+-----------------------+-----+----------+----------+
| JID  |          NAME           | BOOT | STATE |   TYPE   |   RELEASE    |          IP4          | IP6 | TEMPLATE | BASEJAIL |
+======+=========================+======+=======+==========+==============+=======================+=====+==========+==========+
| None | ansible-init            | off  | down  | template | 15.0-RELEASE | DHCP (not running)    | -   | -        | no       |
+------+-------------------------+------+-------+----------+--------------+-----------------------+-----+----------+----------+
| None | ansible-repos           | off  | down  | template | 15.0-RELEASE | DHCP (not running)    | -   | -        | no       |
+------+-------------------------+------+-------+----------+--------------+-----------------------+-----+----------+----------+
| None | ansible-syslogng-client | off  | down  | template | 15.0-RELEASE | DHCP (not running)    | -   | -        | no       |
+------+-------------------------+------+-------+----------+--------------+-----------------------+-----+----------+----------+
| None | ansible-syslogng-server | off  | down  | template | 15.0-RELEASE | vnet0|172.16.99.41/24 | -   | -        | no       |
+------+-------------------------+------+-------+----------+--------------+-----------------------+-----+----------+----------+

Playbook pb-create-jails.yml

---
- name: Create jails from iocage templates.
  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 | replace('-', '_') }}"
        _properties: >-
          {% for k, v in log_client_properties.items() %}
          {{ k }}={{ v }}
          {% endfor %}
          notes={{ _notes }}
      ansible.builtin.command: >
        iocage create
        --name {{ item }}
        --template ansible-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 create
        --name log-server
        --template ansible-syslogng-server
        {{ _properties }}

Playbook output - Create jails from iocage templates

(env) > ansible-playbook pb-create-jails.yml.yml -i iocage.ini -i hosts
PLAY [Create jails from iocage templates.] *************************************

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 |
+======+==============================+======+=======+==========+==============+=======================+=====+=========================+==========+
| 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      |
+------+------------------------------+------+-------+----------+--------------+-----------------------+-----+-------------------------+----------+
| 40   | bar                          | on   | up    | jail     | 15.0-RELEASE | epair0b|172.16.99.103 | -   | ansible-syslogng-client | no       |
+------+------------------------------+------+-------+----------+--------------+-----------------------+-----+-------------------------+----------+
| 39   | foo                          | on   | up    | jail     | 15.0-RELEASE | epair0b|172.16.99.184 | -   | ansible-syslogng-client | no       |
+------+------------------------------+------+-------+----------+--------------+-----------------------+-----+-------------------------+----------+
| 41   | log-server                   | on   | up    | jail     | 15.0-RELEASE | vnet0|172.16.99.10/24 | -   | ansible-syslogng-server | no       |
+------+------------------------------+------+-------+----------+--------------+-----------------------+-----+-------------------------+----------+
| 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 90815.

        shell> loggen -i -S -n 1 localhost 514
        count=1, rate = 26315.79 msg/sec
        average rate = 2.00 msg/sec, count=1, time=0.50044, (average) msg size=256, bandwidth=0.50 kB/sec

        shell> sleep 5; find /var/log/remote/localhost/ -name *.log | xargs cat
        Jun 28 14:23:58 localhost prg00000[1234]: seq: 0000000000, thread: 0000, runid: 1782649438, stamp: 2026-06-28T14:23:58 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 = 142857.14 msg/sec
        average rate = 2.00 msg/sec, count=1, time=0.500452, (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.500429, (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/localhost/2026_06_28.log)
changed: [log_server] => (item=/var/log/remote/172.16.99.184/2026_06_28.log)
changed: [log_server] => (item=/var/log/remote/172.16.99.103/2026_06_28.log)

TASK [Display log files.] ******************************************************
ok: [log_server] => (item=['cat', '/var/log/remote/localhost/2026_06_28.log']) => 
    msg: |-
        Jun 28 14:23:58 localhost prg00000[1234]: seq: 0000000000, thread: 0000, runid: 1782649438, stamp: 2026-06-28T14:23:58 PADDPADDPADDPADDPADDPADDPADDPADDPADDPADDPADDPADDPADDPADDPADDPADDPADDPADDPADDPADDPADDPADDPADDPADDPADDPADDPADDPADDPADDPADDPADDPADD

        - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
ok: [log_server] => (item=['cat', '/var/log/remote/172.16.99.184/2026_06_28.log']) => 
    msg: |-
        Jun 28 14:12:28 172.16.99.184 prg00000[1234]: seq: 0000000000, thread: 0000, runid: 1782648748, stamp: 2026-06-28T14:12:28 PADDPADDPADDPADDPADDPADDPADDPADDPADDPADDPADDPADDPADDPADDPADDPADDPADDPADDPADDPADDPADDPADDPADDPADDPADDPADDPADDPADDPADDPADDPADDPADD
        Jun 28 14:11:35 172.16.99.184 syslog-ng[89155]: syslog-ng starting up; version='4.11.0'
        Jun 28 14:11:35 172.16.99.184 1 2026-06-28T14:11:35.457755+02:00 foo /usr/sbin/cron 89303 - - (CRON) WARNING (madvise() failed)
        Jun 28 14:11:42 172.16.99.184 syslog-ng[89155]: Syslog connection failed; fd='19', server='AF_INET(172.16.99.10:514)', error='Connection refused (61)', time_reopen='60'
        Jun 28 14:12:28 172.16.99.184 1 2026-06-28T14:12:28.818408+02:00 foo ansible-ansible.legacy.command 91801 - - Invoked with _raw_params=loggen -i -S -n 1 172.16.99.10 514 _uses_shell=False expand_argument_vars=True stdin_add_newline=True strip_empty_ends=True cmd=None argv=None chdir=None executable=None creates=None removes=None stdin=None
        Jun 28 14:12:42 172.16.99.184 syslog-ng[89155]: Syslog connection established; fd='5', server='AF_INET(172.16.99.10:514)', local='AF_INET(0.0.0.0:0)'
        Jun 28 14:15:11 172.16.99.184 1 2026-06-28T14:15:11.003847+02:00 foo /usr/sbin/cron 91856 - - (root) CMD (/usr/libexec/atrun)
        Jun 28 14:16:34 172.16.99.184 1 2026-06-28T14:16:34.809042+02:00 foo dhclient 88873 - - DHCPREQUEST on epair0b to 172.16.99.1 port 67
        Jun 28 14:16:34 172.16.99.184 1 2026-06-28T14:16:34.813740+02:00 foo dhclient 88873 - - DHCPACK from 172.16.99.1
        Jun 28 14:16:34 172.16.99.184 1 2026-06-28T14:16:34.835214+02:00 foo dhclient 88873 - - bound to 172.16.99.184 -- renewal in 300 seconds.
        Jun 28 14:20:01 172.16.99.184 1 2026-06-28T14:20:01.004591+02:00 foo /usr/sbin/cron 91893 - - (root) CMD (/usr/libexec/atrun)
        Jun 28 14:21:34 172.16.99.184 1 2026-06-28T14:21:34.964845+02:00 foo dhclient 88873 - - DHCPREQUEST on epair0b to 172.16.99.1 port 67
        Jun 28 14:21:34 172.16.99.184 1 2026-06-28T14:21:34.969362+02:00 foo dhclient 88873 - - DHCPACK from 172.16.99.1
        Jun 28 14:21:35 172.16.99.184 1 2026-06-28T14:21:35.025172+02:00 foo dhclient 88873 - - bound to 172.16.99.184 -- renewal in 299 seconds.
        Jun 28 14:21:35 172.16.99.184 syslog-ng[89155]: Log statistics; processed='global(payload_reallocs)=0', memory_usage='dst.network(d_network#0,tcp,172.16.99.10:514)=0', processed='center(received)=13', dropped='global(internal_source)=0', processed='global(internal_source)=3', queued='global(internal_source)=0', processed='source(s_system)=13', truncated_count='dst.network(d_network#0,tcp,172.16.99.10:514)=0', processed='dst.network(d_network#0,tcp,172.16.99.10:514)=13', eps_last_1h='dst.network(d_network#0,tcp,172.16.99.10:514)=0', processed='source(s_ansible)=0', eps_last_24h='dst.network(d_network#0,tcp,172.16.99.10:514)=0', processed='center(queued)=13', msg_size_max='dst.network(d_network#0,tcp,172.16.99.10:514)=342', processed='src.internal(s_system#2)=3', stamp='src.internal(s_system#2)=1782648762', dropped='dst.network(d_network#0,tcp,172.16.99.10:514)=0', queued='dst.network(d_network#0,tcp,172.16.99.10:514)=0', written='dst.network(d_network#0,tcp,172.16.99.10:514)=13', queued='global(scratch_buffers_bytes)=0', truncated_bytes='dst.network(d_network#0,tcp,172.16.99.10:514)=0', processed='destination(d_network)=13', processed='global(msg_clones)=0', eps_since_start='dst.network(d_network#0,tcp,172.16.99.10:514)=0', processed='global(sdata_updates)=0', msg_size_avg='dst.network(d_network#0,tcp,172.16.99.10:514)=146', queued='global(scratch_buffers_count)=0'
        Jun 28 14:22:00 172.16.99.184 1 2026-06-28T14:22:00.004436+02:00 foo /usr/sbin/cron 91936 - - (operator) CMD (/usr/libexec/save-entropy)
        Jun 28 14:25:00 172.16.99.184 1 2026-06-28T14:25:00.884806+02:00 foo ansible-ansible.legacy.command 92511 - - Invoked with _raw_params=loggen -i -S -n 1 172.16.99.10 514 _uses_shell=False expand_argument_vars=True stdin_add_newline=True strip_empty_ends=True cmd=None argv=None chdir=None executable=None creates=None removes=None stdin=None
        Jun 28 14:25:00 172.16.99.184 prg00000[1234]: seq: 0000000000, thread: 0000, runid: 1782649500, stamp: 2026-06-28T14:25:00 PADDPADDPADDPADDPADDPADDPADDPADDPADDPADDPADDPADDPADDPADDPADDPADDPADDPADDPADDPADDPADDPADDPADDPADDPADDPADDPADDPADDPADDPADDPADDPADD

        - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
ok: [log_server] => (item=['cat', '/var/log/remote/172.16.99.103/2026_06_28.log']) => 
    msg: |-
        Jun 28 14:12:27 172.16.99.103 prg00000[1234]: seq: 0000000000, thread: 0000, runid: 1782648747, stamp: 2026-06-28T14:12:27 PADDPADDPADDPADDPADDPADDPADDPADDPADDPADDPADDPADDPADDPADDPADDPADDPADDPADDPADDPADDPADDPADDPADDPADDPADDPADDPADDPADDPADDPADDPADDPADD
        Jun 28 14:11:40 172.16.99.103 syslog-ng[90080]: syslog-ng starting up; version='4.11.0'
        Jun 28 14:11:40 172.16.99.103 1 2026-06-28T14:11:40.406632+02:00 bar /usr/sbin/cron 90228 - - (CRON) WARNING (madvise() failed)
        Jun 28 14:11:42 172.16.99.103 syslog-ng[90080]: Syslog connection failed; fd='19', server='AF_INET(172.16.99.10:514)', error='Connection refused (61)', time_reopen='60'
        Jun 28 14:12:27 172.16.99.103 1 2026-06-28T14:12:27.938282+02:00 bar ansible-ansible.legacy.command 91799 - - Invoked with _raw_params=loggen -i -S -n 1 172.16.99.10 514 _uses_shell=False expand_argument_vars=True stdin_add_newline=True strip_empty_ends=True cmd=None argv=None chdir=None executable=None creates=None removes=None stdin=None
        Jun 28 14:12:42 172.16.99.103 syslog-ng[90080]: Syslog connection established; fd='5', server='AF_INET(172.16.99.10:514)', local='AF_INET(0.0.0.0:0)'
        Jun 28 14:15:09 172.16.99.103 1 2026-06-28T14:15:09.004729+02:00 bar /usr/sbin/cron 91858 - - (root) CMD (/usr/libexec/atrun)
        Jun 28 14:16:39 172.16.99.103 1 2026-06-28T14:16:39.845530+02:00 bar dhclient 89798 - - DHCPREQUEST on epair0b to 172.16.99.1 port 67
        Jun 28 14:16:39 172.16.99.103 1 2026-06-28T14:16:39.850100+02:00 bar dhclient 89798 - - DHCPACK from 172.16.99.1
        Jun 28 14:16:39 172.16.99.103 1 2026-06-28T14:16:39.906171+02:00 bar dhclient 89798 - - bound to 172.16.99.103 -- renewal in 300 seconds.
        Jun 28 14:20:01 172.16.99.103 1 2026-06-28T14:20:01.003935+02:00 bar /usr/sbin/cron 91890 - - (root) CMD (/usr/libexec/atrun)
        Jun 28 14:21:40 172.16.99.103 1 2026-06-28T14:21:40.046729+02:00 bar dhclient 89798 - - DHCPREQUEST on epair0b to 172.16.99.1 port 67
        Jun 28 14:21:40 172.16.99.103 1 2026-06-28T14:21:40.050582+02:00 bar dhclient 89798 - - DHCPACK from 172.16.99.1
        Jun 28 14:21:40 172.16.99.103 1 2026-06-28T14:21:40.068633+02:00 bar dhclient 89798 - - bound to 172.16.99.103 -- renewal in 300 seconds.
        Jun 28 14:21:40 172.16.99.103 syslog-ng[90080]: Log statistics; processed='global(payload_reallocs)=0', memory_usage='dst.network(d_network#0,tcp,172.16.99.10:514)=0', processed='center(received)=13', dropped='global(internal_source)=0', processed='global(internal_source)=3', queued='global(internal_source)=0', processed='source(s_system)=13', truncated_count='dst.network(d_network#0,tcp,172.16.99.10:514)=0', processed='dst.network(d_network#0,tcp,172.16.99.10:514)=13', eps_last_1h='dst.network(d_network#0,tcp,172.16.99.10:514)=0', processed='source(s_ansible)=0', eps_last_24h='dst.network(d_network#0,tcp,172.16.99.10:514)=0', processed='center(queued)=13', msg_size_max='dst.network(d_network#0,tcp,172.16.99.10:514)=342', processed='src.internal(s_system#2)=3', stamp='src.internal(s_system#2)=1782648762', dropped='dst.network(d_network#0,tcp,172.16.99.10:514)=0', queued='dst.network(d_network#0,tcp,172.16.99.10:514)=0', written='dst.network(d_network#0,tcp,172.16.99.10:514)=13', queued='global(scratch_buffers_bytes)=0', truncated_bytes='dst.network(d_network#0,tcp,172.16.99.10:514)=0', processed='destination(d_network)=13', processed='global(msg_clones)=0', eps_since_start='dst.network(d_network#0,tcp,172.16.99.10:514)=0', processed='global(sdata_updates)=0', msg_size_avg='dst.network(d_network#0,tcp,172.16.99.10:514)=146', queued='global(scratch_buffers_count)=0'
        Jun 28 14:22:00 172.16.99.103 1 2026-06-28T14:22:00.004444+02:00 bar /usr/sbin/cron 91938 - - (operator) CMD (/usr/libexec/save-entropy)
        Jun 28 14:25:00 172.16.99.103 1 2026-06-28T14:25:00.003520+02:00 bar /usr/sbin/cron 92521 - - (root) CMD (/usr/libexec/atrun)
        Jun 28 14:25:00 172.16.99.103 1 2026-06-28T14:25:00.884675+02:00 bar ansible-ansible.legacy.command 92510 - - Invoked with _raw_params=loggen -i -S -n 1 172.16.99.10 514 _uses_shell=False expand_argument_vars=True stdin_add_newline=True strip_empty_ends=True cmd=None argv=None chdir=None executable=None creates=None removes=None stdin=None
        Jun 28 14:25:00 172.16.99.103 prg00000[1234]: seq: 0000000000, thread: 0000, runid: 1782649500, stamp: 2026-06-28T14:25:00 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:

shell > iocage console log-server
root@log-server:~ # lnav -r /var/log/remote/