Ansible nmcli Module — Configure Network Connections

Introduction

Configure Network Connections. This guide provides practical Ansible examples, configuration patterns, and best practices for implementing this in production environments.

Overview

Effective use of Ansible nmcli Module requires understanding both the Ansible modules involved and the underlying technology. This guide covers both aspects with real-world examples.

Prerequisites

---
- name: Ensure prerequisites
  hosts: all
  become: true
  tasks:
    - name: Install required packages
      ansible.builtin.package:
        name:
          - python3
          - python3-pip
        state: present

Basic Implementation

---
- name: Configure Network Connections
  hosts: all
  become: true
  vars:
    app_name: myapp
    environment: production

  tasks:
    - name: Validate environment
      ansible.builtin.assert:
        that:
          - environment in ['development', 'staging', 'production']
        fail_msg: "Invalid environment: {{ environment }}"

    - name: Create directory structure
      ansible.builtin.file:
        path: "{{ item }}"
        state: directory
        mode: '0755'
      loop:
        - /opt/{{ app_name }}
        - /opt/{{ app_name }}/config
        - /opt/{{ app_name }}/data
        - /opt/{{ app_name }}/logs

    - name: Deploy configuration
      ansible.builtin.template:
        src: "config.j2"
        dest: "/opt/{{ app_name }}/config/main.yml"
        mode: '0644'
        validate: 'python3 -c "import yaml; yaml.safe_load(open(\"%s\"))"'
      notify: Restart application

Advanced Configuration

    - name: Configure with environment-specific values
      ansible.builtin.template:
        src: "{{ environment }}-config.j2"
        dest: "/opt/{{ app_name }}/config/env.yml"
        mode: '0644'
      vars:
        debug_mode: "{{ environment != 'production' }}"
        log_level: "{{ 'info' if environment == 'production' else 'debug' }}"

    - name: Set up monitoring
      ansible.builtin.template:
        src: monitoring.j2
        dest: "/opt/{{ app_name }}/config/monitoring.yml"
      when: monitoring_enabled | default(true)

Role Structure

roles/nmcli-module/
├── defaults/
│   └── main.yml          # Default variables
├── handlers/
│   └── main.yml          # Service restart handlers
├── meta/
│   └── main.yml          # Role metadata and dependencies
├── tasks/
│   ├── main.yml          # Main task entry point
│   ├── install.yml       # Installation tasks
│   ├── configure.yml     # Configuration tasks
│   └── verify.yml        # Verification tasks
├── templates/
│   └── config.j2         # Jinja2 templates
├── tests/
│   └── test.yml          # Test playbook
└── vars/
    └── main.yml          # Role-specific variables

Error Handling

    - name: Deploy with rollback
      block:
        - name: Back up current configuration
          ansible.builtin.copy:
            src: "/opt/{{ app_name }}/config/"
            dest: "/opt/{{ app_name }}/config.bak/"
            remote_src: true

        - name: Apply new configuration
          ansible.builtin.template:
            src: config.j2
            dest: "/opt/{{ app_name }}/config/main.yml"

        - name: Verify new configuration
          ansible.builtin.command:
            cmd: "/opt/{{ app_name }}/bin/validate-config"
          changed_when: false

      rescue:
        - name: Rollback on failure
          ansible.builtin.copy:
            src: "/opt/{{ app_name }}/config.bak/"
            dest: "/opt/{{ app_name }}/config/"
            remote_src: true

        - name: Notify about failure
          ansible.builtin.debug:
            msg: "Deployment failed on {{ inventory_hostname }} — rolled back"

      always:
        - name: Clean up backup
          ansible.builtin.file:
            path: "/opt/{{ app_name }}/config.bak"
            state: absent

Handlers

  handlers:
    - name: Restart application
      ansible.builtin.systemd:
        name: "{{ app_name }}"
        state: restarted
        daemon_reload: true

    - name: Reload configuration
      ansible.builtin.systemd:
        name: "{{ app_name }}"
        state: reloaded

Testing

# Dry run
ansible-playbook site.yml --check --diff

# Limit to specific hosts
ansible-playbook site.yml --limit webservers

# Run specific tags
ansible-playbook site.yml --tags configure

# Verbose output for debugging
ansible-playbook site.yml -vvv

Troubleshooting

IssueSolution
Variable undefinedCheck defaults/main.yml and variable precedence
Template errorValidate Jinja2 syntax with ansible-playbook --syntax-check
Permission deniedVerify become: true and sudo configuration
Handler not triggeredEnsure task reports changed status
Idempotency issuesTest with --check to verify no unexpected changes

Best Practices

  1. Use roles for reusable, modular automation
  2. Parameterize everything — avoid hardcoded values
  3. Test in staging first — never deploy directly to production
  4. Use check mode for validation: --check --diff
  5. Document your playbooks with comments and README files
  6. Version control all playbooks and roles in Git
  7. Use tags for selective task execution
  8. Implement error handling with block/rescue/always

Conclusion

This guide covered the practical implementation of Ansible nmcli Module. Start with the basic examples, customize for your environment, and gradually add error handling, monitoring, and CI/CD integration as your automation matures.