OpenBSD Handbook

    Theme
    • Part I. Install & Configure
      • Introduction to OpenBSD
      • Installing OpenBSD
      • The X Window System
      • Networking on OpenBSD
      • System Configuration
      • OpenBSD Basics
      • Managing Software: Packages and Ports
    • Part II. Daily Operations
      • OpenBSD Desktop Environments
      • Multimedia
      • Printing
      • Linux Compatibility
      • Windows Compatibility
      • Games
    • Part III. System Administration
      • Virtualization
      • Storage and File Systems
      • Updating and Upgrading
      • Localization
      • The OpenBSD Boot Process
      • Security
    • Part IV. Networking & Daemons
      • Services
        • Database
          • MariaDB
          • PostgreSQL
          • Redis
          • memcached
        • Directory
          • YP (NIS)
          • LDAP
        • File
          • NFS
          • Samba
        • FTP Services
          • ftpd
          • ProFTPD
          • vsftpd
          • Pure-FTPd
          • TFTP
        • Mail
          • OpenSMTPD Mail Server
          • Dovecot IMAP and POP3 Server
          • Postfix
          • Exim
          • Rspamd
        • Name
          • Unbound DNS Resolver
          • NSD Authoritative DNS Server
          • BIND DNS Server
        • Networking
          • OpenBGPD
          • rad
          • DHCP on OpenBSD
          • slaacd
        • Web
          • Apache HTTP Server
          • nginx Web Server
          • OpenBSD httpd Web Server
          • relayd Reverse Proxy
        • Logging
          • syslogd
        • Monitoring
          • SNMP
        • Remote Access
          • Audit OpenSSH
          • OpenSSH Server
        • File Synchronization
          • rsync
        • Messaging
          • RabbitMQ Message Broker
        • Time
          • NTP Time Synchronization
        • Load Balancing
          • Build Redundant Load-Balanced Gateways
          • Load Balance Services with NAT or DSR
          • Build an HA HTTPS Load Balancer
      • PF
        • pfctl cheat sheet
        • PF Anchors
        • PF Filter Rules
        • PF Forwarding
        • PF Lists and Macros
        • PF Load Balancing
        • PF Logging
        • PF NAT
        • PF Options
        • PF Policies
        • PF Shortcuts
        • PF Tables
      • Advanced Networking
        • High Availability and State Replication
        • Multi-WAN and Policy-Based Routing
        • VPN and Cryptographic Tunneling
        • Classic and Lightweight Tunnels
        • IPv6 at Scale
        • QoS and Traffic Shaping
        • MPLS and Label Distribution
        • Network Services at Scale
        • Virtualization and Host Networking
        • Large-Scale L2 and L3 Design
        • Telemetry, Logging, and Flow Export
        • Hardening and Operational Safety
        • Reference Architectures
        • Troubleshooting Playbooks
      • Serial Communication
    • Part V. Miscellaneous
      • Virtualization Cheat Sheet
      • OpenBSD Cheatsheet
      • How-to Guides
        • Installation and First Boot
          • Complete the First 30 Minutes After Installation
          • Check Hardware Compatibility Before Installing
          • Bootstrap Wi-Fi Firmware Without Ethernet
          • Run OpenBSD as a Virtual Machine Guest
          • Install OpenBSD on a VPS or Cloud Server
          • Install OpenBSD with Full-Disk Encryption
          • Dual-Boot OpenBSD on a UEFI System
          • Automate OpenBSD Installation with Autoinstall and PXE
        • Desktops and Laptops
          • Set Up OpenBSD as a Laptop or Workstation
          • Configure Laptop Power Management
          • Troubleshoot Web Browsers on OpenBSD
          • Use Plan 9 Tools on OpenBSD
          • Build a Minimal Desktop with suckless Tools
          • Install Z shell (zsh)
        • Networking and Remote Access
          • Create an Administrator Account with doas and SSH Keys
          • Configure Secure Remote Access with OpenSSH
          • Use FIDO Security Keys with OpenSSH
          • Configure Wi-Fi Roaming and Wired Failover
          • Troubleshoot PF, NAT, and Routing
          • Route Multiple VLANs with PF
          • Configure a Road-Warrior WireGuard VPN
          • Route IPv6 Networks without NAT
          • Test OpenBGPD with Two Providers
          • Unlock an Internal Service with an SSH Key
          • Build a Simple Router and Firewall
        • Servers and Services
          • Set Up WordPress on OpenBSD
          • Build a Mail Server with OpenSMTPD, Dovecot, and Rspamd
        • Security, Maintenance and Recovery
          • Establish a Conservative Security Baseline
          • Recover Access and Reset the Root Password
          • Collect OpenBSD Diagnostic Evidence
          • Troubleshoot Package Installation and Update Failures
          • Schedule Recurring Maintenance
          • Monitor an OpenBSD System
          • Back Up and Restore an OpenBSD System
          • Configure softraid RAID1
          • Recover an OpenBSD System That Does Not Boot
        • Building, Automation and Virtual Machines
          • Manage OpenBSD with Ansible
          • Build Third-Party Software from Ports
          • Build OpenBSD from Source
          • Plan a Docker Workload Migration to OpenBSD
      • OpenBSD for Linux Users
      • OpenBSD for FreeBSD Users
      • OpenBSD for macOS Users
    • OpenBSD FAQ
    • OpenBSD Architectures
      • OpenBSD Package Search
        • Synopsis
        • Define the Trust Boundary
        • Install Python on the Managed Node
        • Create the Inventory
        • Configure doas Permissions
        • Install the OpenBSD Collection Support
        • Run an Idempotent Package Playbook
        • Manage Configuration Safely
        • Diagnose Failures

        Manage OpenBSD with Ansible

        Synopsis #

        Ansible can manage OpenBSD over SSH, but most modules require a packaged Python interpreter on each managed node. Privileged tasks also require an explicit doas(1) policy. This guide prepares one node, tests access without root privileges, configures doas, and installs a package with a playbook that can be run repeatedly.

        Ansible is not an OpenBSD base-system component. The controller, ansible-core, and collections have their own support cycles. Confirm their current OpenBSD notes before upgrading an automation environment.

        Define the Trust Boundary #

        An automation controller can distribute commands and files to every managed node. Protect its SSH keys, inventory, vault material, logs, and backups accordingly. Use a dedicated named account on managed nodes and do not permit direct root SSH login.

        Before automating tasks, set up:

        • a working console or independent recovery path;
        • a verified named administrator account;
        • a host-key verification process;
        • a backup of every file the first playbook will manage;
        • a small initial host group rather than the entire fleet.

        Create an Administrator Account and Configure Secure Remote Access provide the OpenBSD access baseline.

        Install Python on the Managed Node #

        Ansible’s raw module can operate without Python, but ordinary modules cannot. On the managed OpenBSD node, search the current package set and install the Python 3 meta-package selected for that release:

        pkg_info -Q python
          # Inspect available Python package stems
        doas pkg_add python%3
          # Install the current Python 3 package selected by the package tools
        /usr/local/bin/python3 --version
          # Confirm the stable interpreter path used by inventory
        

        If package selection is ambiguous, choose the maintained Python 3 package explicitly rather than hard-coding a minor version from an older guide. Keep Python updated with the rest of the installed packages.

        Create the Inventory #

        On the Ansible controller, create an inventory file such as inventory.ini:

        [openbsd]
        router1.example.net ansible_user=automation
        
        [openbsd:vars]
        ansible_python_interpreter=/usr/local/bin/python3
        ansible_become=true
        ansible_become_method=doas
        ansible_become_user=root
        

        The host name, account, and grouping are examples. Use verified DNS or addresses and retain SSH host-key checking. Do not use ansible_ssh_common_args to disable host-key verification.

        Test SSH before invoking Ansible:

        ssh automation@router1.example.net
        

        Then test the Python module path without privilege elevation:

        ansible openbsd -i inventory.ini -m ansible.builtin.ping -e ansible_become=false
        

        Ansible’s ping module tests module execution; it does not send ICMP echo requests.

        Configure doas Permissions #

        Ansible normally executes temporary module code as the target user. A command-specific doas.conf rule cannot authorize arbitrary privileged modules safely. Choose one of these models:

        1. Require the automation account’s password and run playbooks with --ask-become-pass.
        2. Grant passwordless elevation to a tightly protected automation account and treat its SSH key as a root credential.
        3. Avoid general elevation and use narrowly designed raw tasks that match command-specific rules, accepting that some module features may not work.

        For the interactive-password model, add this rule to /etc/doas.conf on the managed node:

        permit automation as root
        

        Parse the policy and test the exact identity with doas(1) :

        doas -C /etc/doas.conf
          # Parse the complete policy without executing a command
        doas -u root id
          # Confirm authentication and target identity from the automation account
        

        Run privileged playbooks with --ask-become-pass. An unrestricted nopass account can act as root. Protect it with dedicated SSH keys, restrict its source addresses where practical, and monitor its use.

        Install the OpenBSD Collection Support #

        The community.general.openbsd_pkg module is distributed in the community.general collection and is not part of ansible-core. Install and record the collection on the controller:

        ansible-galaxy collection install community.general
        ansible-galaxy collection list community.general
        

        Pin collection versions in the automation project’s requirements file when repeatable controller builds are required.

        Run an Idempotent Package Playbook #

        Create openbsd-baseline.yml on the controller:

        ---
        - name: Maintain a small OpenBSD package baseline
          hosts: openbsd
          gather_facts: true
          become: true
        
          tasks:
            - name: Ensure rsync is installed
              community.general.openbsd_pkg:
                name: rsync--
                state: present
        
            - name: Record the managed node release
              ansible.builtin.command: uname -a
              register: openbsd_uname
              changed_when: false
        
            - name: Display the managed node release
              ansible.builtin.debug:
                var: openbsd_uname.stdout
        

        Use rsync-- to select the package without optional flavors, so the task does not prompt for a choice.

        Run syntax and dry-run checks first:

        ansible-playbook -i inventory.ini openbsd-baseline.yml --syntax-check
          # Parse inventory and playbook structure
        ansible-playbook -i inventory.ini openbsd-baseline.yml --check --diff --ask-become-pass --limit router1.example.net
          # Preview the first managed node
        ansible-playbook -i inventory.ini openbsd-baseline.yml --ask-become-pass --limit router1.example.net
          # Apply only after the preview and recovery plan are acceptable
        

        Check mode is a prediction and not every module can model all changes. Keep the first production run limited and inspect the resulting package and log state on the node.

        Manage Configuration Safely #

        For each managed file:

        • render to a temporary path or use module validation where available;
        • preserve owner, group, and mode explicitly;
        • notify a handler only when content changes;
        • validate daemon syntax before reload;
        • keep the previous remote session and recovery route available;
        • avoid overwriting package examples or local secrets without a documented merge policy.

        Start with low-risk changes, such as installing a package, before automating sysupgrade, PF replacement, disk operations, or SSH authentication. Test repeated runs, limit the initial host group, and establish a recovery procedure before changing more hosts.

        Diagnose Failures #

        Use -vvv only in protected logs because output can contain paths, variables, command lines, and remote data. Separate SSH, Python interpreter, become, module, and target-command failures. Confirm the same SSH account and doas action manually on the affected node before changing playbook logic.

        Report a bug
        • Synopsis
        • Define the Trust Boundary
        • Install Python on the Managed Node
        • Create the Inventory
        • Configure doas Permissions
        • Install the OpenBSD Collection Support
        • Run an Idempotent Package Playbook
        • Manage Configuration Safely
        • Diagnose Failures