
Image by: Tara Winstead
Imagine it is 2:00 AM on a Tuesday. A critical security vulnerability has been discovered, requiring an immediate firewall policy update across fifty global branches. In the old era of networking, a junior admin would manually log into each device, risking typos and configuration drift. In the modern era, you execute a single Ansible playbook, and the entire network is patched in minutes. As enterprise networks grow in complexity, the ability to automate Cisco and Fortinet network configurations using Ansible playbooks has shifted from a “luxury” to a fundamental requirement for any competent system and network administrator. This comprehensive guide provides a practical roadmap to mastering network automation, from securing your credentials with Ansible Vault to implementing robust rollback strategies that ensure your uptime remains uninterrupted.
The evolution of network automation
For decades, network administration was defined by the Command Line Interface (CLI). Engineers would SSH into individual switches or firewalls, executing commands line by line. While this method offers granular control, it is inherently unscalable and prone to human error. Statistical data from network automation studies suggest that a significant percentage of network outages are caused by manual configuration errors rather than hardware failures.
Enter Ansible. Unlike traditional configuration management tools that require agent installation on the managed devices, Ansible is “agentless.” It communicates via standard protocols like SSH or APIs (such as FortiOS API or NETCONF for Cisco). This makes it uniquely suited for networking hardware, where you cannot simply install a software agent on a proprietary Cisco IOS image or a Fortinet FortiGate appliance.
The shift toward automating Cisco and Fortinet network configurations is driven by three primary factors:
- Scalability: Managing 5 devices is easy; managing 500 requires a programmatic approach.
- Consistency: Automation ensures that “Policy A” is applied identically across every branch, eliminating “configuration drift.”
- Speed: Deployment cycles that used to take weeks of scheduled maintenance windows can now be completed in a single afternoon.
By adopting an automation-first mindset, administrators transition from “firefighters” reacting to individual device issues to “architects” designing resilient, self-healing infrastructure. This guide will bridge the gap between manual CLI operations and professional-grade automation engineering.
Setting up your automation environment
Before you can push a single command to a production switch, you must build a stable control node environment. Your control node is the machine where Ansible is installed. This can be a dedicated Linux workstation, a virtual machine, or even a containerized environment. For professional workflows, using a Linux-based system (such as Ubuntu or RHEL) is highly recommended to ensure full compatibility with all Ansible modules.
Prerequisites and SSH key setup
To interact with Cisco and Fortinet devices, your control node needs a secure communication channel. While password authentication is possible, SSH key-based authentication is the gold standard for automation. Using keys eliminates the need to pass plain-text passwords through your playbooks and allows for more streamlined, non-interactive logins.
To generate a secure key pair, use the following command on your control node:
ssh-keygen -t rsa -b 4096
Once generated, you must import the public key into the `enable` or `admin` user configuration on your target devices. For Cisco devices, this involves using the `ip ssh pubkey-chain` command. For Fortinet, it involves importing the key through the CLI or the GUI under the administrator settings. Once this is done, your Ansible tasks can connect seamlessly without human intervention.
Installing necessary collections
Ansible relies on “collections” to communicate with specific vendors. You won’t find Cisco or Fortinet capabilities in the core Ansible engine alone. You must install the specialized collections via `ansible-galaxy`. For a multi-vendor environment, your installation commands would look like this:
ansible-galaxy collection install cisco.iosansible-galaxy collection install fortinet.fortimanageransible-galaxy collection collection install community.network
Having the correct versions of these collections is vital. If you are running an older version of Cisco IOS, a newer collection might use a module that your device doesn’t support. Always document your environment to maintain consistency across your team.
Managing inventory and secure credentials
An automation script is only as good as the data it consumes. In Ansible, the inventory file is the “source of truth” that tells the playbook which devices to talk to, their IP addresses, and their specific characteristics. A poorly structured inventory is the primary cause of “blast radius” issues, where an automation task intended for a lab device accidentally hits a core production router.
Structured inventory files
For large enterprises, we move away from simple flat files to hierarchical inventory structures. This allows you to group devices by function (e.g., [switches], [firewalls], [core_routers]) or by location (e.g., [london_office], [ny_datacenter]). You can then apply different variables to entire groups at once.
| Inventory Component | Purpose | Description | Example Value |
|---|---|---|
| Hosts | The individual device IP or hostname. | 192.168.1.1 |
| Groups | Logical collections of similar devices. | fortigate_firewalls |
| Host Vars | Variables specific to one single device. | snmp_community: public |
| Group Vars | Variables applied to all devices in a group. | ntp_server: 10.0.0.1 |
Securing secrets with Ansible Vault
Never, under any circumstances, store administrative passwords or SSH keys in plain text within your playbooks or inventory files. This is a critical security violation. Instead, use Ansible Vault. Ansible Vault allows you to encrypt specific strings or entire files, ensuring that even if your Git repository is compromised, your network credentials remain safe.
To create an encrypted password file, use:
ansible-vault create credentials.yml
Inside this file, you would store sensitive data like this:
ansible_user: admin ansible_password: SuperSecretPassword123! ansible_become_pass: ManagementPassword!
When running your playbook, you simply include the `–ask-vault-pass` flag. This ensures that the sensitive information is decrypted only in memory during the execution of the task, keeping your infrastructure secure. If you want to learn more about modern DevOps security practices, checking out advanced automation frameworks can help refine these workflows.
Implementing Cisco and Fortinet playbooks
Now that the environment is set up and the credentials are secure, we can move to the core objective: pushing configuration changes. When automating Cisco and Fortinet network configurations, the goal is to use declarative or idempotent modules. Idempotency means that if you run the same playbook twice, the second time it will do nothing because the desired state has already been reached. This is the key to stable automation.
Cisco IOS automation examples
Cisco devices are often managed using the `ios_config` or `ios_command` modules. The `ios_config` module is preferred for setting up policies because it is designed to ensure the configuration matches the playbook. For example, to update a VLAN on a Cisco switch:
- name: Configure VLAN 10 for Marketing
cisco.ios.ios_vlan:
vlan-id: 10
name: Marketing
state: present
Fortinet FortiGate automation examples
Fortinet devices rely heavily on REST APIs, and Ansible interacts with them through specialized modules. Managing firewall policies is significantly faster with Ansible than via the CLI. Instead of manually creating rules, you can define a list of “allow” rules in a YAML file and push them to the FortiGate.
A typical Fortinet task for updating an address object might look like this:
- name: Add new trusted host to FortiGate
fortinet.fortimanager.fm_firewall_address:
name: "Admin_PC_Remote"
subnet: "192.168.50.10/32"
status: "include"
By using these modules, you reduce the “human element” in the configuration process. Instead of an engineer typing `set address 192.168.50.10/32`, the machine interprets a data structure, ensuring no syntax errors are introduced during the deployment phase.
Operational safety: Dry-runs and rollbacks
The greatest fear of any network administrator is the “fat-finger” error—an accidental command that shuts down a core uplink and brings down the entire building. To mitigate this, professional automation pipelines incorporate two critical safety mechanisms: Dry-runs (Check Mode) and Rollback Strategies.
Implementing check mode
Ansible’s `–check` flag is a lifesaver. When you run a playbook in “check mode,” Ansible simulates the changes it *would* make without actually applying them to the hardware. This is colloquially known as a “dry-run.”
In a professional CI/CD pipeline, you should always run a dry-run first. If the dry-run shows that 50 devices will be modified, you can inspect the “diff” (the difference between current and proposed state) to ensure the changes are exactly what you intended. This step is non-negotiable for enterprise-grade network management.
Rollback strategies
Even with a dry-run, things can go wrong. A command might be syntactically correct but logically catastrophic (e.g., accidentally applying an ACL that blocks your SSH access). A robust automation strategy includes a “rollback” plan. There are two primary ways to handle this:
- Configuration Checkpointing: Before applying changes, use an Ansible task to trigger a “checkpoint” or “archive” on the Cisco
