Lfops
Ansible Collection of roles, playbooks & plugins for Linux-based cloud infrastructure. Covers OS hardening, MariaDB, Icinga2, Nextcloud, FreeIPA, KVM & more. Bitwarden & Cloud integration.
Install / Use
/learn @Linuxfabrik/LfopsREADME
LFOps
LFOps is a comprehensive Ansible Collection providing 145+ playbooks and 160+ roles to bootstrap and manage Linux-based IT infrastructures. It covers the full server lifecycle -- from initial provisioning and hardening to application deployment, monitoring, and automated backups. LFOps supports RHEL 8/9/10, Debian, and Ubuntu.
Table of Contents
- Requirements
- Installation
- Mitogen
- Using ansible-navigator
- Usage
- Configuration
- Documentation
- Compatibility
- Tips, Tricks & Troubleshooting
- Contributing
- License
Requirements
- Ansible: ansible-core >= 2.16
- Python on the controller: >= 3.10 (ansible-core 2.16/2.17) or >= 3.11 (ansible-core 2.18)
- Python on managed nodes: >= 3.6
- Dependencies: The collection depends on several community collections (see
requirements.yml). These are installed automatically when usingansible-galaxy.
Which ansible-core version should I use?
| ansible-core | Controller Python | Managed Node Python | RHEL 8 (Python 3.6) | |--------------|-------------------|---------------------|----------------------| | 2.16 | 3.10 -- 3.12 | 3.6 -- 3.12 | works out of the box | | 2.17 | 3.10 -- 3.12 | 3.7 -- 3.12 | needs Python >= 3.7 | | 2.18 | 3.11 -- 3.14 | 3.8 -- 3.13 | needs Python >= 3.8 |
If you manage RHEL 8 hosts with the default system Python (3.6), use ansible-core 2.16. If all your managed nodes have Python >= 3.8 (e.g. RHEL 9+, Debian 12+, Ubuntu 22.04+), you can use ansible-core 2.18 for the latest features.
Installation
Using ansible-galaxy
# Install the collection and its dependencies
ansible-galaxy collection install linuxfabrik.lfops
# Alternatively, install from Git directly
ansible-galaxy collection install git+https://github.com/Linuxfabrik/lfops.git
To install the dependencies separately:
ansible-galaxy collection install -r requirements.yml
Development Setup
If you want to contribute or test local changes, clone the repository and symlink it into Ansible's collection path:
git clone git@github.com:Linuxfabrik/lfops.git /path/to/lfops
mkdir -p ~/.ansible/collections/ansible_collections/linuxfabrik
ln -s /path/to/lfops ~/.ansible/collections/ansible_collections/linuxfabrik/lfops
Important: The symlink target must be named lfops and point to the cloned repository root (which contains the galaxy.yml).
To verify the collection is detected:
ansible-galaxy collection list | grep linuxfabrik
Mitogen
Mitogen is an optional but recommended performance optimization for Ansible. It replaces the default SSH-based task execution with a persistent Python-to-Python channel, significantly reducing connection overhead and speeding up playbook runs.
Mitogen with ansible-playbook
Install Mitogen into your Ansible virtual environment:
pip install mitogen
Determine the strategy plugins path (this depends on the Python version in your venv):
python3 -c "import os, ansible_mitogen; print(os.path.join(ansible_mitogen.__path__[0], 'plugins', 'strategy'))"
Add the output to your ansible.cfg:
[defaults]
strategy_plugins = /path/to/venv/lib/pythonX.Y/site-packages/ansible_mitogen/plugins/strategy
strategy = mitogen_linear
Since the strategy_plugins path contains the Python version, it differs per venv. If you use multiple venvs (e.g. ansible-core 2.16 and 2.18), either use separate ansible.cfg files or install Mitogen to a shared location:
pip install --target=/opt/mitogen mitogen
[defaults]
strategy_plugins = /opt/mitogen/ansible_mitogen/plugins/strategy
strategy = mitogen_linear
Important: Do not set ANSIBLE_STRATEGY=mitogen_linear via shell aliases or environment variables. This is hard to debug and overrides the config file silently. Always configure Mitogen in ansible.cfg.
Mitogen with ansible-navigator
The LFOps Execution Environment container image already includes Mitogen with the strategy plugins available at /opt/mitogen/ansible_mitogen/plugins/strategy. To enable it, add the following to the ansible.cfg used by ansible-navigator:
[defaults]
strategy_plugins = /opt/mitogen/ansible_mitogen/plugins/strategy
strategy = mitogen_linear
Mitogen Compatibility
| ansible-core | Mitogen | Controller Python | |--------------|----------|-------------------| | 2.16 | >= 0.3.7 | 3.10 -- 3.14 | | 2.17 | >= 0.3.7 | 3.10 -- 3.14 | | 2.18 | >= 0.3.7 | 3.11 -- 3.14 |
Always keep Mitogen up to date (pip install --upgrade mitogen). If you encounter SyntaxError: future feature annotations is not defined, either the Mitogen version is outdated or the Python version on the remote host is too old (< 3.7).
Using ansible-navigator
LFOps provides a pre-built Execution Environment (EE) container image that includes all dependencies:
pip install ansible-navigator
Configure ansible-navigator.yml in your project directory:
ansible-navigator:
execution-environment:
container-engine: podman # or docker
enabled: true
image: ghcr.io/linuxfabrik/lfops_ee:latest
pull:
policy: missing
mode: stdout
Then run playbooks using ansible-navigator instead of ansible-playbook:
ansible-navigator run linuxfabrik.lfops.setup_basic \
--inventory path/to/inventory \
--limit myhost
The EE is based on Rocky Linux 9 with ansible-core 2.16, Python 3.11, and includes Mitogen for accelerated execution. See execution-environment.yml for the full build definition. Public container images are available on GitHub Container Registry.
Usage
Running a Playbook
Each playbook requires the target host to be in a specific inventory group named lfops_<playbook_name>. For example, to run the php playbook against myhost:
- Add the host to the
lfops_phpgroup in your inventory. - Run the playbook:
ansible-playbook linuxfabrik.lfops.php \
--inventory path/to/inventory \
--limit myhost
Use --diff to see changes, --check for dry-run mode, and --tags to run specific parts of a playbook.
Typical Workflow Example
Add your host to the required groups in the inventory:
[lfops_hetzner_vm]
myhost
[lfops_setup_basic]
myhost
[lfops_monitoring_plugins]
myhost
[lfops_setup_nextcloud]
myhost
Then run the playbooks in order:
# Provision the VM
ansible-playbook --inventory path/to/inventory linuxfabrik.lfops.hetzner_vm --limit myhost
# Basic setup (hardening, SSH, firewall, chrony, etc.)
ansible-playbook --inventory path/to/inventory linuxfabrik.lfops.setup_basic --limit myhost
# Deploy monitoring
ansible-playbook --inventory path/to/inventory linuxfabrik.lfops.monitoring_plugins --limit myhost
# Deploy a full application stack (playbooks prefixed by "setup_" include all dependencies)
ansible-playbook --inventory path/to/inventory linuxfabrik.lfops.setup_nextcloud --limit myhost
# Change specific settings afterwards, e.g. PHP
ansible-playbook --inventory path/to/inventory linuxfabrik.lfops.setup_nextcloud --limit myhost --tags php
The "all" Playbook
The linuxfabrik.lfops.all playbook imports all other playbooks. This is useful when a change affects multiple playbooks. For example, to deploy an updated MariaDB dump script to all hosts that have MariaDB (whether installed directly or as part of WordPress, Nextcloud, etc.):
ansible-playbook --inventory path/to/inventory linuxfabrik.lfops.all --tags mariadb
