Deploy Network Configuration
This role manages multi-VLAN network configuration across heterogeneous systems in the homelab environment.
Deploy Network Configuration Role
Overview
This role manages multi-VLAN network configuration across heterogeneous systems in the homelab environment. It deploys routing tables, NetworkManager configurations for RedHat systems, NetworkManager dispatcher scripts for Docker servers, custom routing scripts with systemd services for OpenMediaVault, and /etc/network/interfaces configuration for Proxmox and ZoneMinder. The role includes comprehensive safety features including confirmation prompts, check mode support, configuration backups, and connectivity validation to prevent accidental network disruption.
Purpose
- Multi-VLAN Management: Configure complex network setups with multiple VLANs
- OS-Specific Configuration: Support RedHat NetworkManager and Debian ifupdown
- Routing Tables: Configure custom routing tables for policy-based routing
- Dispatcher Scripts: NetworkManager event-driven network configuration
- Configuration Validation: Prevent drift from manual changes
- Safe Deployment: Confirmation prompts and connectivity validation
- Backup Integration: Automatic backup before changes
Requirements
- Ansible 2.9 or higher
- Target systems: RedHat/Rocky Linux or Debian/Ubuntu
- Root or sudo privileges
- Console or IPMI access (strongly recommended)
- Working network connectivity before first run
- Backup of existing network configuration
- Manual initial network setup completed
Important: Initial Setup Required
CRITICAL: This role is designed for configuration validation and drift prevention, not initial network setup.
Why manual setup first?
- Ansible requires network connectivity to run
- Network configuration changes could break the Ansible connection
- Manual setup ensures a known working state
This role’s purpose: Maintain and validate network configuration after manual bootstrap.
What is Policy-Based Routing?
Policy-based routing allows routing decisions based on criteria beyond destination address:
Standard routing:
Packet to 192.168.x.x → Check routing table → Use default gateway
Policy-based routing:
Packet from VLAN10 → Use routing table 100 (mgmt gateway)
Packet from VLAN12 → Use routing table 101 (servers gateway)
Use cases:
- Multi-homed servers (multiple network interfaces)
- VLAN segmentation with separate gateways
- Load balancing across interfaces
- Source-based routing decisions
Role Variables
Optional Variables
| Variable | Default | Description |
|---|---|---|
deploy_network_configuration_require_confirmation | true | Prompt before changes |
deploy_network_configuration_rt_tables | See defaults | Routing table definitions |
deploy_network_configuration_interfaces | undefined | Per-host interface config |
deploy_network_configuration_nm_service_name | NetworkManager | NetworkManager service |
deploy_network_configuration_nm_connections_dir | /etc/NetworkManager/system-connections | Connection files path |
deploy_network_configuration_nm_dispatcher_dir | /etc/NetworkManager/dispatcher.d | Dispatcher scripts path |
deploy_network_configuration_interfaces_file | /etc/network/interfaces | Debian interfaces file |
deploy_network_configuration_networking_service_name | networking | Debian networking service |
deploy_network_configuration_rt_tables_file_default | /usr/share/iproute2/rt_tables | Routing tables file |
deploy_network_configuration_rt_tables_file_omv | /etc/iproute2/rt_tables | OMV routing tables file |
deploy_network_configuration_omv_routing_script_path | /usr/local/bin/setup-omv-routing.sh | OMV routing script |
deploy_network_configuration_omv_routing_service_name | omv-routing.service | OMV systemd service |
Variable Details
deploy_network_configuration_require_confirmation
Whether to prompt for confirmation before applying network changes.
Default: true (safe mode, prompts before changes)
Disable for automation:
deploy_network_configuration_require_confirmation: false
Prompt shown:
========================================
WARNING: Network Configuration Changes
========================================
About to modify network configuration on: hostname
This could potentially disconnect your Ansible connection.
Recommendations:
- Ensure you have console/IPMI access available
- Review changes with --check mode first
- Have a rollback plan ready
Press Ctrl+C and then 'A' to abort
Press ENTER to continue
========================================
Recommended: Keep enabled unless running in CI/CD with known-good config
deploy_network_configuration_rt_tables
Routing table definitions for policy-based routing.
Default:
deploy_network_configuration_rt_tables:
- id: 100
name: mgmt
- id: 101
name: servers
Custom tables:
deploy_network_configuration_rt_tables:
- id: 10
name: vlan10
- id: 20
name: vlan20
- id: 30
name: vlan30
Result: Entries added to routing tables file:
# Custom routing tables for policy-based routing
100 mgmt
101 servers
Usage: Enables ip route add ... table mgmt commands
deploy_network_configuration_interfaces
Per-host interface configuration variable.
Important: This variable is not defined by default. Each host must define its own configuration.
Example (in host_vars/docker.yml):
deploy_network_configuration_interfaces:
vlan10:
ip: 192.168.x.x
gateway: 192.168.x.x
vlan12:
ip: 192.168.x.x
gateway: 192.168.x.x
Role behavior: If deploy_network_configuration_interfaces is undefined, role skips that host.
Purpose: Signal to role that this host has network configuration to deploy.
Dependencies
No Ansible role dependencies, but requires:
- Working network connectivity (manual initial setup)
- Console or IPMI access for recovery
- Configuration files prepared (see below)
Often used with:
- nas_mount or nas_mount_systemd: Mount NAS before network config
- deploy_ssh_keys: Ensure SSH access before network changes
Example Playbook
Basic Usage (All Systems)
---
- name: Deploy Network Configuration
hosts: all
become: true
roles:
- deploy_network_configuration
With Confirmation Disabled (CI/CD)
---
- name: Deploy Network Config (Automated)
hosts: all
become: true
vars:
deploy_network_configuration_require_confirmation: false
roles:
- deploy_network_configuration
Check Mode First (Safe Practice)
# Preview changes without applying
ansible-playbook deploy_network.yml --check --diff
# Apply after reviewing
ansible-playbook deploy_network.yml
Specific Hosts Only
---
- name: Deploy Network Config to Docker Host
hosts: docker
become: true
roles:
- deploy_network_configuration
What This Role Does
1. Display Confirmation Prompt (if enabled)
Shows warning with recommendations.
When: deploy_network_configuration_require_confirmation: true (default)
Skipped if:
- Confirmation disabled
- Host doesn’t have
deploy_network_configuration_interfacesdefined
2. Deploy Routing Tables Configuration
File: /usr/share/iproute2/rt_tables (most) or /etc/iproute2/rt_tables (OMV)
Content added:
# Custom routing tables for policy-based routing
100 mgmt
101 servers
Purpose: Enables named routing tables for policy-based routing
3. Deploy OS-Specific Network Configuration
RedHat NetworkManager (Centreon, Docker, Grafana, Graylog, etc.):
- Copies
.nmconnectionfiles to/etc/NetworkManager/system-connections/ - Sets permissions:
0600(root only, security requirement) - Copies dispatcher scripts to
/etc/NetworkManager/dispatcher.d/ - Sets permissions:
0755(executable) - Reloads or restarts NetworkManager
Debian NetworkManager (OpenMediaVault):
- Deploys custom routing script to
/usr/local/bin/setup-omv-routing.sh - Creates systemd service:
omv-routing.service - Service runs after
network-online.target - Enables and starts service
- Configures nginx to bind web interface to management VLAN IP
- Preserves localhost bindings for local access
- Restarts nginx when configuration changes
Debian ifupdown (Proxmox, ZoneMinder):
- Deploys
/etc/network/interfacesfrom template - Creates backup of existing configuration first
- Restarts networking service
4. Validate Network Connectivity
After configuration changes:
- Waits up to 60 seconds for network to stabilize
- Tests Ansible connectivity
- Reports success or failure
If validation fails: You have console access to troubleshoot
Supported System Configurations
RedHat/Rocky Linux (NetworkManager)
Hosts: Centreon, Docker, Grafana, Graylog, Graylog-Data1
Configuration files required:
files/<hostname>/*.nmconnection- NetworkManager connection filesfiles/<hostname>/dispatcher.d/*- NetworkManager dispatcher scripts
Example directory structure:
files/
└── docker/
├── vlan10-enp2s0.nmconnection
├── vlan12-enp2s0.nmconnection
└── dispatcher.d/
└── 99-custom-routes
Connection file format (.nmconnection):
[connection]
id=vlan10-enp2s0
type=vlan
interface-name=enp2s0.10
[vlan]
parent=enp2s0
id=10
[ipv4]
method=manual
address1=192.168.x.x/24
gateway=192.168.x.x
route1=192.168.x.x/24,0.0.0.0,100
Key points:
- Permissions:
0600(NetworkManager requirement) - Owner:
root:root - Format: INI-style configuration
Debian with NetworkManager (OpenMediaVault)
Hosts: prxmx-omv
Configuration files required:
templates/<hostname>/setup-omv-routing.sh.j2- Custom routing script templatetemplates/<hostname>/omv-routing.service.j2- Systemd service template
Script example (setup-omv-routing.sh.j2):
#!/bin/bash
# Setup policy-based routing for OMV
# Add routes to mgmt table
ip route add default via 192.168.x.x table mgmt
ip rule add from 192.168.x.x/24 table mgmt
# Add routes to servers table
ip route add default via 192.168.x.x table servers
ip rule add from 192.168.x.x/24 table servers
Systemd service: omv-routing.service
- Runs once at boot
- After:
network-online.target - Type:
oneshot - RemainAfterExit:
yes
Nginx web interface binding: The role automatically configures OpenMediaVault’s nginx web interface to bind only to:
- Management VLAN IP (e.g.,
192.168.x.x:80and192.168.x.x:443) - Localhost (
127.0.0.1:80and127.0.0.1:443)
This enhances security by preventing web interface access from other VLANs. The configuration:
- Modifies
/etc/nginx/sites-enabled/openmediavault-webgui - Handles both wildcard (
*) and existing IP configurations - Preserves localhost bindings for local access
- Automatically restarts nginx when changes are made
- Is idempotent (safe to run multiple times)
Debian with ifupdown (Proxmox, ZoneMinder)
Hosts: Proxmox, ZoneMinder
Template required:
templates/<hostname>/interfaces.j2
Template example:
# /etc/network/interfaces
auto lo
iface lo inet loopback
# VLAN10 - Management
auto enp1s0.10
iface enp1s0.10 inet static
address 192.168.x.x/24
gateway 192.168.x.x
vlan-raw-device enp1s0
post-up ip route add 192.168.x.x/24 dev enp1s0.10 table mgmt
post-up ip rule add from 192.168.x.x table mgmt
# VLAN12 - Servers
auto enp1s0.12
iface enp1s0.12 inet static
address 192.168.x.x/24
vlan-raw-device enp1s0
post-up ip route add default via 192.168.x.x table servers
post-up ip rule add from 192.168.x.x table servers
NetworkManager Dispatcher Scripts
Purpose: Run commands when NetworkManager events occur
Event types:
up: Interface brought updown: Interface brought downpre-up: Before interface comes uppost-down: After interface goes down
Script naming: Scripts run alphabetically (use numeric prefix)
10-script: Runs early99-script: Runs late
Example dispatcher script:
#!/bin/bash
# /etc/NetworkManager/dispatcher.d/99-custom-routes
# Only run on interface up events
[ "$2" != "up" ] && exit 0
# Configure policy-based routing
if [ "$1" = "enp2s0.10" ]; then
ip route add default via 192.168.x.x table mgmt
ip rule add from 192.168.x.x/24 table mgmt
fi
Permissions: 0755 (executable)
File Locations
| System Type | Configuration File | Purpose |
|---|---|---|
| RedHat | /etc/NetworkManager/system-connections/*.nmconnection | Connection definitions |
| RedHat | /etc/NetworkManager/dispatcher.d/* | Event scripts |
| OMV | /usr/local/bin/setup-omv-routing.sh | Custom routing |
| OMV | /etc/systemd/system/omv-routing.service | Systemd service |
| OMV | /etc/nginx/sites-enabled/openmediavault-webgui | Nginx web interface config |
| Proxmox/ZM | /etc/network/interfaces | Interface config |
| All | /usr/share/iproute2/rt_tables | Routing tables |
| OMV | /etc/iproute2/rt_tables | Routing tables (OMV) |
Configuration Workflow
Recommended process:
- Manual initial setup: Configure network during OS installation
- Backup configuration: Save working config files from system
- Add to role: Place files in role’s
files/ortemplates/ - Test with —check: Preview changes before applying
ansible-playbook deploy_network.yml --check --diff - Deploy role: Apply configuration
- Maintain: Role prevents drift from manual changes
Security Considerations
- Confirmation Prompts: Prevent accidental network disruption
- File Permissions: NetworkManager files must be
0600(sensitive) - Dispatcher Scripts: Must be
0755(executable) - Backup Before Changes: Automatic backup of existing config
- Console Access Recommended: In case network connection lost
- Check Mode Support: Preview changes safely
- Validation: Connectivity tested after changes
Tags
This role does not define any tags. Use playbook-level tags if needed:
- hosts: all
roles:
- deploy_network_configuration
tags:
- network
- infrastructure
- routing
Notes
- Role runs on target systems (not localhost)
become: truerequired for network configuration- Skips hosts without
deploy_network_configuration_interfacesdefined - NetworkManager systems reload configuration without full restart
- Debian ifupdown systems restart networking service (brief interruption)
- Confirmation prompt appears per-host if enabled
- Compatible with RedHat, Rocky Linux, Debian, Ubuntu
- Manual initial setup required (Ansible needs connectivity)
- Configuration files must be prepared in role directories
Troubleshooting
Connection lost after running role
Symptom: Ansible loses connection to host
Immediate action:
- Access via console/IPMI
- Check interface status:
ip addr,ip link - Check routing:
ip route show table all - Restore from backup if needed
For NetworkManager systems:
# Check NetworkManager status
systemctl status NetworkManager
# Restart NetworkManager
systemctl restart NetworkManager
# Check connection files
nmcli connection show
# Activate connection
nmcli connection up vlan10-enp2s0
For ifupdown systems:
# Check interface status
ip addr show
# Bring interface up
ifup enp1s0.10
# Restore from backup
cp /etc/network/interfaces.backup /etc/network/interfaces
systemctl restart networking
NetworkManager connection file not applied
Symptom: Changes not taking effect
Check permissions:
ls -la /etc/NetworkManager/system-connections/
# Should be: -rw------- root root (0600)
Fix permissions:
chmod 0600 /etc/NetworkManager/system-connections/*.nmconnection
Reload NetworkManager:
systemctl reload NetworkManager
# Or
nmcli connection reload
Dispatcher script not executing
Symptom: Routes not added after network up
Check permissions:
ls -la /etc/NetworkManager/dispatcher.d/
# Should be: -rwxr-xr-x root root (0755)
Fix permissions:
chmod 0755 /etc/NetworkManager/dispatcher.d/*
Test script manually:
# Run dispatcher script manually
/etc/NetworkManager/dispatcher.d/99-custom-routes enp2s0.10 up
Check logs:
journalctl -u NetworkManager -f
# Watch for dispatcher events
Routing table entries not added
Symptom: ip route show table mgmt returns empty
Check rt_tables file:
cat /usr/share/iproute2/rt_tables | grep mgmt
# Should show: 100 mgmt
Check routing rules:
ip rule show
# Should see entries like:
# from 192.168.x.x/24 lookup mgmt
Add manually for testing:
ip route add default via 192.168.x.x table mgmt
ip rule add from 192.168.x.x/24 table mgmt
Validation fails after deployment
Symptom: Role reports validation failure
Causes:
- Network not fully up yet (wait longer)
- Configuration error (wrong IP/gateway)
- Firewall blocking connectivity
Manual validation:
# From affected host
ping 192.168.x.x # Gateway
ping 8.8.8.8 # Internet
# Check connectivity to Ansible controller
nc -zv ansible-controller-ip 22
Testing the Role
Preview Changes (Safe)
# Check mode with diff
ansible-playbook deploy_network.yml --check --diff --limit docker
# Shows what would change without applying
Verify Configuration Files
After role runs:
# NetworkManager systems
ls -la /etc/NetworkManager/system-connections/
nmcli connection show
# Debian ifupdown systems
cat /etc/network/interfaces
# Routing tables
cat /usr/share/iproute2/rt_tables
ip route show table all
Test Network Connectivity
# Check interfaces
ip addr show
# Check routing
ip route show
ip route show table mgmt
ip route show table servers
# Check rules
ip rule show
# Test connectivity
ping 192.168.x.x
ping 8.8.8.8
Best Practices
- Always use —check first: Preview changes before applying
- Maintain console access: Have IPMI/console ready during changes
- Backup configurations: Role creates backups automatically
- Test on non-critical hosts first: Validate on test systems
- Document changes: Keep notes on network design
- Version control: Store configuration files in git
- Manual initial setup: Bootstrap connectivity before Ansible
- Maintenance windows: Apply during scheduled downtime
- Have rollback plan: Know how to restore from backup
- Validate after changes: Ensure connectivity restored
Common Network Scenarios
Scenario 1: Docker Host with VLANs
Requirements:
- VLAN10: Management (192.168.x.x/24)
- VLAN12: Servers (192.168.x.x/24)
- Policy-based routing: Each VLAN uses own gateway
Files needed:
files/docker/vlan10-enp2s0.nmconnectionfiles/docker/vlan12-enp2s0.nmconnectionfiles/docker/dispatcher.d/99-routing
Scenario 2: Proxmox with Multiple Interfaces
Requirements:
- VLAN10: Management
- VLAN12: VM network
- VLAN14: Storage network
Template needed:
templates/proxmox/interfaces.j2
Scenario 3: OpenMediaVault NAS
Requirements:
- Multiple network interfaces for different VLANs
- Custom routing to ensure management via VLAN10
- Storage access via VLAN12
- Web interface accessible only from management VLAN
Files needed:
templates/prxmx-omv/setup-omv-routing.sh.j2templates/prxmx-omv/omv-routing.service.j2
Automatic configuration:
- Nginx web interface binds to management VLAN IP only
- Localhost access preserved for local management
Related Roles
This role is often used with:
- nas_mount: Mount NAS before network changes
- nas_mount_systemd: Mount NAS with systemd
- deploy_ssh_keys: Ensure SSH access maintained
- System installation roles: Initial setup after OS install
Recovery Procedures
Complete Network Failure
- Access via console/IPMI
- Identify issue: Check logs, interface status
- Restore from backup:
# NetworkManager
cp /etc/NetworkManager/system-connections/*.backup /etc/NetworkManager/system-connections/
systemctl restart NetworkManager
# ifupdown
cp /etc/network/interfaces.backup /etc/network/interfaces
systemctl restart networking
- Manual configuration: Reconfigure manually if needed
- Update role files: Fix configuration in role before re-running
License
MIT
Author
Created for homelab infrastructure management.