Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 4 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,12 +15,15 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

### Breaking Changes

* **playbook:setup_basic**: The `at` role is no longer installed by `setup_basic`, as nothing in the base setup uses `at` anymore. Existing hosts keep it; new installs do not get it. If you rely on `at` / `atd`, install it separately with the `linuxfabrik.lfops.at` role.
* **role:system_update**: Host reboots are now performed at one configurable maintenance window by the new `schedule_reboot` role (see Added). Adjust in your inventory: `system_update__update_time` to `schedule_reboot__reboot_time__group_var` (now a plain time of day, e.g. `'04:00'`), and any `system_update__icinga2_*` reboot-downtime settings to `schedule_reboot__icinga2_*`.
* **role:apache_httpd, role:apache_tomcat, role:mastodon, role:postgresql_server**: Rename tags to the project-wide naming scheme. `apache_httpd:config` becomes `apache_httpd:configure`, and `apache_tomcat:users`, `mastodon:users`, `postgresql_server:users` and `postgresql_server:databases` lose their trailing `s` (`...:user`, `...:database`). Adjust any `--tags` / `--skip-tags` invocations and automation that reference the old tag names.
* **role:minio_client, role:objectstore_backup**: Both roles and their playbooks (`playbooks/minio_client.yml`, `playbooks/objectstore_backup.yml`) have been removed, along with the corresponding role blocks in `playbooks/setup_nextcloud.yml` and the `setup_nextcloud__skip_minio_client` / `setup_nextcloud__skip_objectstore_backup` variables. MinIO Server has been archived as no-longer-maintained since February 2026, and we are moving away from using object storage for critical data. Users relying on these roles must replace the MinIO-based object-store backup with their own solution (e.g. `rclone`); the `mc` binary, its config under `/etc/mc/`, the `objectstore-backup` systemd timer/service, and `/usr/local/bin/mc-mirror.sh` are no longer managed by lfops and will remain on existing hosts until removed manually ([#241](https://github.com/Linuxfabrik/lfops/issues/241)).
* **role:infomaniak_vm**: Always create a managed port for every entry in `infomaniak_vm__networks`, even when no `fixed_ip` is set. Previously only networks with a `fixed_ip` got a managed port; networks without one relied on OpenStack's auto-created port. To avoid creating unused (but billed) managed ports on VMs provisioned under the old behavior, make sure to manually rename the existing port in OpenStack to match the `port_name`. Note that this port will not survive VM deletion / detachment, since it was automatically created and therefore is owned by OpenStack, not the user.

### Added

* **role:schedule_reboot**: New role. Provides a single, windowed reboot mechanism: a request spool (`/run/schedule-reboot/`), an ad-hoc `schedule-reboot` command, and one actor that performs a single reboot for all pending requests at a configurable window (`schedule_reboot__reboot_time__*`), setting an Icinga downtime around it. Other roles request a reboot instead of rebooting themselves; `system_update` uses it.
* **testing**: Add a Molecule-based test framework that runs the playbooks (and through them the roles) against throwaway libvirt/KVM VMs or Podman containers. Scenarios live under `extensions/molecule`; see the Testing section in `CONTRIBUTING.md`.
* **role:icinga2_master, role:icingadb, role:icingaweb2, role:icingaweb2_module_reporting, role:icingaweb2_module_x509**: Add explicit Ubuntu variable files, making Ubuntu support visible alongside Debian. The Icinga repository, GPG key and package names were verified on Debian 13 and Ubuntu 24.04.
* **role:nextcloud**: Add `meta/argument_specs.yml` declaring the user-facing variables, so role-entry validation catches type mismatches and missing mandatory variables.
Expand All @@ -36,7 +39,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
* **plugin:platform_select**: New filter plugin for selecting a value from a platform-keyed dictionary by OS family / distribution / version.
* **role:alternatives**: Support managing `subcommands` (slaves/followers) and the Red Hat-only `family` grouping. The role now also ensures the alternatives tooling is installed (`chkconfig` on RHEL 8, `alternatives` on RHEL 9/10; bundled with `dpkg` on Debian/Ubuntu), and can be included without variables as a no-op.
* **role:redis**: Add template for version 8.8
* **role:system_update**: Add a security lane for Rocky Linux. A second timer (twice a day by default) installs only Rocky Linux security hot-fixes from the dedicated `security` repository (provided by `repo_baseos`) and reboots the host if needed. The reboot time is steered per host group (for example immediately on test hosts, deferred to the evening on production hosts). Enabled by default; a no-op where the `security` repository is not enabled, and can be turned off with `system_update__security_enabled: false`. This keeps critical security fixes flowing daily while the regular update lane stays on its weekly schedule.
* **role:system_update**: Add a security lane for Rocky Linux. A daily timer installs only Rocky Linux security hot-fixes from the dedicated `security` repository (provided by `repo_baseos`) and requests a reboot if needed, which is performed at the host's maintenance window (`schedule_reboot__reboot_time__*`). Enabled by default; a no-op where the `security` repository is not enabled, and can be turned off with `system_update__security_enabled: false`. This keeps critical security fixes flowing daily while the regular update lane stays on its weekly schedule.
* **role:mariadb_server**: Add `mariadb_server__cnf_innodb_snapshot_isolation` variable (MariaDB 10.6+), defaulting to `'ON'`.
* **role:repo_baseos**: Add the Rocky Linux `security` repository (critical CVE fixes), enabled by default. Opt out per host or group via `repo_baseos__security_repo_enabled__host_var` / `repo_baseos__security_repo_enabled__group_var`.
* **role:chromium_headless**: New role. Provides a hardened, socket-activated headless Chromium backend (started on the first request, stopped again after an idle timeout, so it uses no RAM while unused) for tools such as the Icinga Web 2 PDF Export Module. Installs `chromium-headless` from EPEL instead of Google's proprietary repository.
Expand Down
1 change: 1 addition & 0 deletions COMPATIBILITY.md
Original file line number Diff line number Diff line change
Expand Up @@ -148,6 +148,7 @@ Which Ansible role is proven to run on which OS?
| repo_sury | x | x | - | - | | (x) | (x) | (x) | |
| rocketchat | | | x | (x) | (x) | | | | Fedora 35 |
| rsyslog | | | x | x | x | | | | |
| schedule_reboot | x | x | x | x | x | (x) | (x) | (x) | |
| selinux | (x) | (x) | x | x | x | (x) | (x) | (x) | |
| shared | | | | | | | | | controller-side helper, target OS irrelevant |
| shell | (x) | (x) | x | x | x | (x) | (x) | (x) | |
Expand Down
2 changes: 1 addition & 1 deletion CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -638,7 +638,7 @@ Make sure to use the following format when passing multiple injections to avoid
* Do not use `{{ template_run_date }}` inside the template. It is the date that the template was rendered, which is done during every Ansible run. This means that the task will always be changed, even if nothing else changed in the template, therefore breaking idempotency.
* Use the target path for the file in the `template` folder, for example: `templates/etc/httpd/sites-available/default.conf.j2`. This makes it clear what the file is for, and avoids name collisions.
* Always use the `.j2` file extension for files in the `template` folder.
* If deploying self-written scripts, copy them to `/usr/local/sbin` (due to SELinux).
* If deploying self-written scripts, copy them to `/usr/local/sbin` (due to SELinux). Internal helper scripts that are only ever run by a systemd unit (not invoked by an admin and not exec'd by a confined domain) MAY instead live in `/usr/local/libexec`. Files there get the `usr_t` type, and the targeted policy lets a root `oneshot` service (which runs in `init_t`) execute them in place via `execute_no_trans`, so there is no AVC denial on RHEL/Rocky 8, 9 and 10. Keep admin-invokable commands in `/usr/local/sbin`, and never put a script a confined domain must exec under `/usr/local/libexec`.
* Keep templates as close to the original file as possible. This makes handling of rpmnew/rpmsave files easier.
* Add the following task after deploying a file that might get rpmnew or rpmsave files (or their Debian equivalents):
```yaml
Expand Down
14 changes: 11 additions & 3 deletions playbooks/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -989,6 +989,15 @@ Calls the following roles (in order):
* [rsyslog](https://github.com/Linuxfabrik/lfops/tree/main/roles/rsyslog)


## schedule_reboot.yml

Calls the following roles (in order):

* [postfix](https://github.com/Linuxfabrik/lfops/tree/main/roles/postfix): `schedule_reboot__skip_postfix`
* [mailto_root](https://github.com/Linuxfabrik/lfops/tree/main/roles/mailto_root): `schedule_reboot__skip_mailto_root`
* [schedule_reboot](https://github.com/Linuxfabrik/lfops/tree/main/roles/schedule_reboot)


## selinux.yml

Calls the following roles (in order):
Expand Down Expand Up @@ -1024,7 +1033,6 @@ Calls the following roles (in order):
* [glances](https://github.com/Linuxfabrik/lfops/tree/main/roles/glances): `setup_basic__skip_glances`
* [tools](https://github.com/Linuxfabrik/lfops/tree/main/roles/tools): `setup_basic__skip_tools`
* [tmux](https://github.com/Linuxfabrik/lfops/tree/main/roles/tmux): `setup_basic__skip_tmux`
* [at](https://github.com/Linuxfabrik/lfops/tree/main/roles/at): `setup_basic__skip_at`
* [yum_utils](https://github.com/Linuxfabrik/lfops/tree/main/roles/yum_utils): `setup_basic__skip_yum_utils`
* [lvm](https://github.com/Linuxfabrik/lfops/tree/main/roles/lvm): `setup_basic__skip_lvm`
* [sshd](https://github.com/Linuxfabrik/lfops/tree/main/roles/sshd): `setup_basic__skip_sshd`
Expand All @@ -1033,6 +1041,7 @@ Calls the following roles (in order):
* [mailx](https://github.com/Linuxfabrik/lfops/tree/main/roles/mailx): `setup_basic__skip_mailx`
* [postfix](https://github.com/Linuxfabrik/lfops/tree/main/roles/postfix): `setup_basic__skip_postfix`
* [mailto_root](https://github.com/Linuxfabrik/lfops/tree/main/roles/mailto_root): `setup_basic__skip_mailto_root`
* [schedule_reboot](https://github.com/Linuxfabrik/lfops/tree/main/roles/schedule_reboot): `setup_basic__skip_schedule_reboot`
* [system_update](https://github.com/Linuxfabrik/lfops/tree/main/roles/system_update): `setup_basic__skip_system_update`
* [python_venv](https://github.com/Linuxfabrik/lfops/tree/main/roles/python_venv): `setup_basic__skip_python_venv`
* [duplicity](https://github.com/Linuxfabrik/lfops/tree/main/roles/duplicity): `setup_basic__skip_duplicity`
Expand Down Expand Up @@ -1319,10 +1328,9 @@ Calls the following roles (in order):
Calls the following roles (in order):

* [yum_utils](https://github.com/Linuxfabrik/lfops/tree/main/roles/yum_utils): `system_update__skip_yum_utils`
* [at](https://github.com/Linuxfabrik/lfops/tree/main/roles/at)
* [mailx](https://github.com/Linuxfabrik/lfops/tree/main/roles/mailx)
* [postfix](https://github.com/Linuxfabrik/lfops/tree/main/roles/postfix): `system_update__skip_postfix`
* [mailto_root](https://github.com/Linuxfabrik/lfops/tree/main/roles/mailto_root): `system_update__skip_mailto_root`
* [schedule_reboot](https://github.com/Linuxfabrik/lfops/tree/main/roles/schedule_reboot)
* [system_update](https://github.com/Linuxfabrik/lfops/tree/main/roles/system_update)


Expand Down
1 change: 1 addition & 0 deletions playbooks/all.yml
Original file line number Diff line number Diff line change
Expand Up @@ -120,6 +120,7 @@
- import_playbook: 'repo_rpmfusion.yml'
- import_playbook: 'repo_sury.yml'
- import_playbook: 'rsyslog.yml'
- import_playbook: 'schedule_reboot.yml'
- import_playbook: 'selinux.yml'
- import_playbook: 'setup_basic.yml'
- import_playbook: 'setup_grav.yml'
Expand Down
43 changes: 43 additions & 0 deletions playbooks/schedule_reboot.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
- name: 'Playbook linuxfabrik.lfops.schedule_reboot'
hosts:
- 'lfops_schedule_reboot'

pre_tasks:
- ansible.builtin.import_role:
name: 'shared'
tasks_from: 'log-start.yml'
tags:
- 'always'

- ansible.builtin.import_role:
name: 'shared'
tasks_from: 'global-variables.yml'
tags:
- 'always'


roles:

- role: 'linuxfabrik.lfops.postfix'
postfix__aliases__dependent_var: '{{
mailto_root__postfix__aliases__dependent_var
}}'
postfix__sender_canonicals__dependent_var: '{{
mailto_root__postfix__sender_canonicals__dependent_var
}}'
when:
- 'not schedule_reboot__skip_postfix | d(false)'

- role: 'linuxfabrik.lfops.mailto_root'
when:
- 'not schedule_reboot__skip_mailto_root | d(false)'

- role: 'linuxfabrik.lfops.schedule_reboot'


post_tasks:
- ansible.builtin.import_role:
name: 'shared'
tasks_from: 'log-end.yml'
tags:
- 'always'
8 changes: 4 additions & 4 deletions playbooks/setup_basic.yml
Original file line number Diff line number Diff line change
Expand Up @@ -124,10 +124,6 @@
when:
- 'not setup_basic__skip_tmux | d(false)'

- role: 'linuxfabrik.lfops.at'
when:
- 'not setup_basic__skip_at | d(false)'

- role: 'linuxfabrik.lfops.yum_utils'
when:
- 'not setup_basic__skip_yum_utils | d(false)'
Expand Down Expand Up @@ -176,6 +172,10 @@


# === Automatic updates ===
- role: 'linuxfabrik.lfops.schedule_reboot'
when:
- 'not setup_basic__skip_schedule_reboot | d(false)'

- role: 'linuxfabrik.lfops.system_update'
when:
- 'not setup_basic__skip_system_update | d(false)'
Expand Down
5 changes: 2 additions & 3 deletions playbooks/system_update.yml
Original file line number Diff line number Diff line change
Expand Up @@ -23,9 +23,6 @@
- 'ansible_facts["os_family"] == "RedHat"'
- 'not system_update__skip_yum_utils | d(false)'

- role: 'linuxfabrik.lfops.at'
- role: 'linuxfabrik.lfops.mailx'

- role: 'linuxfabrik.lfops.postfix'
postfix__aliases__dependent_var: '{{
mailto_root__postfix__aliases__dependent_var
Expand All @@ -40,6 +37,8 @@
when:
- 'not system_update__skip_mailto_root | d(false)'

- role: 'linuxfabrik.lfops.schedule_reboot'

- role: 'linuxfabrik.lfops.system_update'


Expand Down
Loading