ansible cfad67a3a1 Remove static inventory, use only dynamic libvirt inventory
Remove static hosts.yml inventory file and configure pure dynamic
inventory discovery using community.libvirt.libvirt plugin.

Changes:

1. Removed Static Inventory:
   - Deleted inventories/development/hosts.yml
   - All host definitions now come from libvirt dynamic discovery
   - Complies with CLAUDE.md requirement for dynamic inventories

2. Updated libvirt_kvm.yml Dynamic Inventory:
   - Changed URI from local to remote: qemu+ssh://grok@grok.home.serneels.xyz/system
   - Configures automatic VM discovery from grokbox hypervisor
   - Creates dynamic groups: kvm_guests, running_vms, small_vms, large_vms
   - Creates keyed groups by state and OS
   - Extracts IP addresses from guest_info

3. Created Host Variables Override:
   - inventories/development/host_vars/pihole.yml
   - inventories/development/host_vars/mymx.yml
   - inventories/development/host_vars/derp.yml
   - Override ansible_connection from libvirt_qemu to ssh
   - Set ansible_host to IP addresses (192.168.122.x)

4. Updated Group Variables:
   - inventories/development/group_vars/kvm_guests.yml
   - Added ansible_connection: ssh to force SSH over libvirt
   - Maintains ProxyJump configuration through grokbox
   - SSH connection multiplexing settings preserved

5. Added .gitignore:
   - Exclude stats/ directory from version control
   - Prevents system_info role output from being committed

Dynamic Inventory Discovery:
- Automatically discovers VMs: pihole, mymx, derp
- Groups by state: running_vms, stopped_vms
- Groups by size: small_vms (≤2GB), medium_vms (2-8GB), large_vms (>8GB)
- Groups by OS: os_debian, os_unknown
- Creates UUID-based groups for unique identification

Connection Method:
- Discovery: libvirt plugin queries grokbox via SSH
- Execution: SSH with ProxyJump through grokbox
- Authentication: SSH keys (ansible user)
- Network: Private 192.168.122.0/24 via NAT

Testing Results:
 Dynamic inventory discovers all 3 VMs
 Groups created correctly (kvm_guests, running_vms, etc.)
 pihole: Connection successful via ProxyJump
⚠️  mymx, derp: SSH key authentication needed (not inventory issue)

Benefits:
- No manual inventory maintenance required
- VMs automatically added/removed based on libvirt state
- Dynamic grouping by resource allocation
- Centralized management through grokbox
- CLAUDE.md compliant (no static inventories in production-like envs)

Usage:
# List all discovered VMs
ansible-inventory -i inventories/development/ --graph

# Ping all KVM guests
ansible -i inventories/development/ kvm_guests -m ping

# Run playbook on running VMs
ansible-playbook -i inventories/development/ site.yml --limit running_vms

Migration Note:
The static inventory (hosts.yml) contained some hosts not managed
by libvirt (odin, seed). These external hosts need to be managed
via separate dynamic inventory sources or added back if required.

Related Documentation:
- docs/network-access-patterns.md (ProxyJump configuration)
- inventories/production/README.md (dynamic inventory examples)

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-11 02:10:54 +01:00

Ansible Infrastructure Automation

Enterprise-grade Ansible infrastructure with security-first principles, modularity, and scalability.

Quick Start

# Test connectivity with SSH config inventory
ansible all -i plugins/inventory/ssh_config_inventory.py -m ping

# Test connectivity with Libvirt dynamic inventory
ansible running_vms -i plugins/inventory/libvirt_kvm.py -m ping

# Use static development inventory
ansible all -i inventories/development/hosts.yml -m ping

# Run a playbook
ansible-playbook -i inventories/development/hosts.yml site.yml

Project Structure

.
├── README.md                       # This file
├── CLAUDE.md                       # Development guidelines and standards
├── ansible.cfg                     # Ansible configuration
├── site.yml                        # Master playbook
│
├── inventories/                    # Inventory configurations
│   ├── production/                 # Production (dynamic only)
│   ├── staging/                    # Staging (dynamic only)
│   └── development/                # Development environment
│       ├── hosts.yml               # Static inventory
│       ├── libvirt_kvm.yml         # Libvirt config
│       └── group_vars/             # Group variables
│           ├── all.yml
│           ├── kvm_guests.yml
│           └── hypervisors.yml
│
├── plugins/                        # Custom plugins
│   └── inventory/                  # Dynamic inventory scripts
│       ├── ssh_config_inventory.py # SSH config parser
│       └── libvirt_kvm.py          # Libvirt/KVM discovery
│
├── roles/                          # Ansible roles
├── playbooks/                      # Playbooks
├── collections/                    # Ansible collections
│
├── docs/                           # Documentation
│   ├── inventory.md                # Inventory documentation
│   └── [other docs]
│
└── cheatsheets/                    # Quick reference guides
    └── inventory.md                # Inventory cheatsheet

Infrastructure Overview

Current Environment

Component Type Description
odin External VPS Mail server (Debian 13)
grokbox Hypervisor KVM/libvirt host (physical)
pihole VM Guest DNS/DHCP server (via grokbox)
mymx VM Guest Mail server (via grokbox)
derp VM Guest Development VM (via grokbox)
seed VM Guest Discovery pending

Network Architecture

Internet
    │
    ├─── odin (65.108.217.156) ─────────── External VPS
    │
    └─── grokbox (grok.home.serneels.xyz)
             │
             └─── virbr0 (192.168.122.0/24) ── NAT Network
                      │
                      ├─── pihole (192.168.122.12)
                      ├─── mymx (192.168.122.119)
                      ├─── derp (192.168.122.99)
                      └─── seed (192.168.129.1)

Available Inventory Solutions

1. SSH Config Parser (Dynamic)

Best for: Quick discovery from existing SSH configuration

ansible all -i plugins/inventory/ssh_config_inventory.py --list-hosts

2. Libvirt/KVM Dynamic Inventory

Best for: Real-time VM discovery with state and resource information

ansible running_vms -i plugins/inventory/libvirt_kvm.py -m ping

3. Static YAML Inventory (Development)

Best for: Detailed host metadata and development environments

ansible all -i inventories/development/hosts.yml --list-hosts

Key Features

Security-First Design

  • SELinux/AppArmor enforcement
  • Automated security updates
  • SSH hardening (key-based auth, no root login)
  • File integrity monitoring (AIDE)
  • System auditing (auditd)
  • Secrets management with Ansible Vault

Scalability

  • Dynamic inventory for infrastructure discovery
  • Fact caching for performance
  • Parallel execution with configurable forks
  • ProxyJump for nested VM access
  • Efficient SSH connection reuse

Modularity & Reusability

  • Role-based architecture
  • OS-agnostic design (Debian/RHEL families)
  • Comprehensive variable management
  • Task tagging for selective execution
  • Molecule testing framework

Documentation

Document Description
CLAUDE.md Complete development guidelines and standards
docs/inventory.md Inventory configuration and usage
cheatsheets/inventory.md Quick reference guide

Requirements

Control Node

  • Python 3.6+
  • Ansible 2.10+
  • SSH client with ProxyJump support

Managed Nodes

  • Python 3.x
  • SSH server
  • ansible user with passwordless sudo

Optional Dependencies

# For libvirt dynamic inventory
apt-get install python3-libvirt  # Debian/Ubuntu
dnf install python3-libvirt      # RHEL/Rocky/Fedora

Configuration

ansible.cfg Example

[defaults]
inventory = ./inventories/development/hosts.yml
roles_path = ./roles
collections_path = ./collections
remote_user = ansible
become = True
become_method = sudo

# Performance
forks = 20
gathering = smart
fact_caching = jsonfile
fact_caching_connection = /tmp/ansible_facts
fact_caching_timeout = 86400

# SSH
host_key_checking = False
ssh_args = -o ControlMaster=auto -o ControlPersist=600s

[inventory]
enable_plugins = yaml, ini, script, auto

[privilege_escalation]
become = True
become_method = sudo
become_user = root
become_ask_pass = False

Common Tasks

Test Connectivity

# All hosts
ansible all -i <inventory> -m ping

# Specific group
ansible kvm_guests -i <inventory> -m ping

# With verbose output
ansible all -i <inventory> -m ping -vvv

Gather Facts

ansible all -i <inventory> -m setup

Run Ad-Hoc Commands

# Check uptime
ansible all -i <inventory> -m shell -a "uptime"

# Check disk usage
ansible all -i <inventory> -m shell -a "df -h"

# List running VMs on hypervisor
ansible hypervisors -i <inventory> -m shell -a "virsh list --all"

Execute Playbooks

# Full run
ansible-playbook -i <inventory> site.yml

# Check mode (dry-run)
ansible-playbook -i <inventory> site.yml --check

# Limit to group
ansible-playbook -i <inventory> site.yml --limit kvm_guests

# With tags
ansible-playbook -i <inventory> site.yml --tags "install,configure"

Development Guidelines

Please refer to CLAUDE.md for complete development guidelines including:

  • Security requirements
  • Role development standards
  • Testing procedures
  • Documentation requirements
  • LVM partitioning schema
  • Package management
  • And much more...

Troubleshooting

Connection Issues

# Test SSH connectivity
ssh -J grokbox ansible@192.168.122.12

# Test with verbose Ansible
ansible pihole -i <inventory> -m ping -vvv

# Check SSH config
cat ~/.ssh/config

Inventory Issues

# Validate inventory
ansible-inventory -i <inventory> --list

# Check specific host
ansible-inventory -i <inventory> --host <hostname>

# Graph structure
ansible-inventory -i <inventory> --graph

Python/Libvirt Issues

# Check Python version
ansible all -i <inventory> -m setup -a "filter=ansible_python_version"

# Install libvirt support
apt-get install python3-libvirt  # Debian/Ubuntu
dnf install python3-libvirt      # RHEL/Rocky

# Test libvirt connection
virsh -c qemu+ssh://grok@grok.home.serneels.xyz/system list

Contributing

  1. Follow guidelines in CLAUDE.md
  2. Use feature branches for development
  3. Test roles with Molecule
  4. Update documentation
  5. Create pull request for review

Security

  • Never commit secrets to version control
  • Use Ansible Vault for sensitive data
  • Rotate SSH keys every 90-180 days
  • Regular security audits with Lynis/OpenSCAP
  • Keep systems updated with automatic security patches

Support


Project Version: 1.0.0 Last Updated: 2025-11-10 Maintainer: Ansible Infrastructure Team

Description
Ansible infrastructure automation and configuration management
Readme 436 KiB
Languages
Jinja 57.7%
Python 39.5%
Shell 2.8%