Salt-Minion for Automation

Salt-Minion integrates VyOS with SaltStack for centralized configuration management and automation of network devices.

Overview

What is SaltStack

SaltStack is a configuration management and orchestration system:

  • IT infrastructure automation
  • Remote command execution
  • Configuration management
  • Infrastructure as Code approach
  • Event-driven architecture
  • Python-based solution

Salt Architecture

Salt Master:

  • Central management server
  • Stores states and pillars
  • Manages minions
  • Performs orchestration

Salt Minion:

  • Agent on the managed device
  • Executes commands from the Master
  • Sends data and events
  • Applies configurations

Salt Proxy Minion:

  • For devices that cannot run an agent
  • Uses SSH/NETCONF/API
  • Support for network devices
  • Netmiko for VyOS

Capabilities for VyOS

  • Operational commands - running show commands
  • Configuration management - applying configurations
  • Batch operations - bulk changes
  • Event monitoring - tracking events
  • Inventory management - hardware accounting
  • Compliance checking - verifying compliance

Installing Salt Master

Installation on the Management Server

Ubuntu/Debian:

# Add SaltStack repository
curl -fsSL https://packages.broadcom.com/artifactory/api/gpg/key/public | sudo tee /etc/apt/keyrings/salt-archive-keyring.gpg
echo "deb [signed-by=/etc/apt/keyrings/salt-archive-keyring.gpg arch=amd64] https://packages.broadcom.com/artifactory/saltproject-deb/ stable main" | sudo tee /etc/apt/sources.list.d/salt.list

# Install Salt Master
sudo apt update
sudo apt install salt-master salt-minion salt-ssh

# Start service
sudo systemctl enable salt-master
sudo systemctl start salt-master

CentOS/RHEL:

# Add repository
sudo yum install https://repo.saltproject.io/salt/py3/redhat/8/x86_64/latest/salt-repo-latest.el8.noarch.rpm

# Install
sudo yum install salt-master salt-minion

# Start
sudo systemctl enable salt-master
sudo systemctl start salt-master

Basic Master Configuration

/etc/salt/master:

interface: 0.0.0.0
auto_accept: False
file_roots:
  base:
    - /srv/salt/states
pillar_roots:
  base:
    - /srv/salt/pillars

Creating the directory structure:

sudo mkdir -p /srv/salt/{states,pillars}
sudo systemctl restart salt-master

Configuring Salt-Minion on VyOS

Basic Setup

Minimal configuration:

set service salt-minion id 'vyos-router-01'
set service salt-minion master '192.0.2.250'
commit
save

Parameters:

  • id - unique minion identifier
  • master - IP or hostname of the Salt Master

Advanced Configuration

set service salt-minion id 'vyos-edge-router'
set service salt-minion master '192.0.2.250'
set service salt-minion hash md5
set service salt-minion interval 60
commit
save

Parameters:

  • hash - hashing algorithm (md5, sha256)
  • interval - Master check interval (seconds)

Multiple Masters

set service salt-minion id 'vyos-router-01'
set service salt-minion master '192.0.2.250'
set service salt-minion master '192.0.2.251'
commit
save

Accepting Keys on the Master

Viewing Pending Keys

On the Salt Master:

sudo salt-key -L

Output:

Accepted Keys:
Denied Keys:
Unaccepted Keys:
vyos-router-01
Rejected Keys:

Accepting a Key

Accept a specific key:

sudo salt-key -a vyos-router-01

Accept all keys (use with caution!):

sudo salt-key -A

Removing a Key

sudo salt-key -d vyos-router-01

Verifying the Connection

sudo salt 'vyos-router-01' test.ping

Output:

vyos-router-01:
    True

Salt Proxy Minion for VyOS

What is a Proxy Minion

A Proxy Minion is used when:

  • An agent cannot be installed on the device
  • Management via SSH/API is required
  • Network devices lack Salt support

Configuring the Netmiko Proxy

Installing Netmiko on the Salt Master:

sudo pip3 install netmiko

Creating a Pillar for the device:

/srv/salt/pillars/vyos-proxy.sls:

proxy:
  proxytype: netmiko
  device_type: vyos
  host: 192.0.2.10
  username: vyos
  password: vyos_password
  secret: enable_password

Top file for Pillars:

/srv/salt/pillars/top.sls:

base:
  'vyos-proxy-01':
    - vyos-proxy

Starting the Proxy Minion

sudo salt-proxy --proxyid=vyos-proxy-01 -d

Or via systemd:

/etc/systemd/system/salt-proxy@.service:

[Unit]
Description=Salt Proxy Minion %i
After=network.target

[Service]
Type=notify
NotifyAccess=all
ExecStart=/usr/bin/salt-proxy --proxyid=%i
Restart=always

[Install]
WantedBy=multi-user.target

Startup:

sudo systemctl enable salt-proxy@vyos-proxy-01
sudo systemctl start salt-proxy@vyos-proxy-01

Accepting the Proxy Minion Key

sudo salt-key -a vyos-proxy-01

Basic Operations

Verifying the Connection

All minions:

sudo salt '*' test.ping

A specific minion:

sudo salt 'vyos-router-01' test.ping

By glob pattern:

sudo salt 'vyos-*' test.ping

Retrieving Information

System version:

sudo salt 'vyos-router-01' test.version

Network interfaces:

sudo salt 'vyos-router-01' network.interfaces

Interface details:

sudo salt 'vyos-router-01' network.interface eth0

Executing Commands

Shell commands:

sudo salt 'vyos-router-01' cmd.run 'show version'

Multiple commands:

sudo salt 'vyos-router-01' cmd.run 'show interfaces; show system uptime'

Managing VyOS Configuration

Via Proxy Minion with Netmiko

Sending a configuration command:

sudo salt 'vyos-proxy-01' netmiko.send_config config_commands="['set interfaces ethernet eth0 description WAN_Link']" commit=True

Multiple commands:

sudo salt 'vyos-proxy-01' netmiko.send_config \
  config_commands="['set system host-name vyos-edge', 'set system domain-name example.com']" \
  commit=True

States for Configuration

Creating a State file:

/srv/salt/states/vyos-basic.sls:

configure_hostname:
  netmiko.send_config:
    - config_commands:
        - set system host-name vyos-router-01
        - set system domain-name corp.local
    - commit: True

configure_ntp:
  netmiko.send_config:
    - config_commands:
        - set system ntp server 0.pool.ntp.org
        - set system ntp server 1.pool.ntp.org
    - commit: True

configure_dns:
  netmiko.send_config:
    - config_commands:
        - set system name-server 8.8.8.8
        - set system name-server 8.8.4.4
    - commit: True

Applying the State:

sudo salt 'vyos-proxy-01' state.apply vyos-basic

Batch Configuration

File with commands:

/srv/salt/states/commands.txt:

set interfaces ethernet eth1 description LAN
set interfaces ethernet eth1 address 192.168.1.1/24
set service ssh port 22
set service ssh listen-address 0.0.0.0

State to apply it:

/srv/salt/states/vyos-config.sls:

apply_config_from_file:
  netmiko.send_config:
    - config_file: salt://commands.txt
    - commit: True

Application:

sudo salt 'vyos-proxy-01' state.apply vyos-config

Automation Examples

Example 1: Basic System Setup

/srv/salt/states/vyos-system.sls:

system_hostname:
  netmiko.send_config:
    - config_commands:
        - set system host-name {{ pillar['hostname'] }}
    - commit: True

system_timezone:
  netmiko.send_config:
    - config_commands:
        - set system time-zone {{ pillar['timezone'] }}
    - commit: True

system_users:
  netmiko.send_config:
    - config_commands:
        - set system login user admin authentication plaintext-password {{ pillar['admin_password'] }}
        - set system login user admin level admin
    - commit: True

/srv/salt/pillars/vyos-router-01.sls:

hostname: vyos-edge-01
timezone: Europe/Moscow
admin_password: SecurePassword123!

Example 2: Interface Configuration

/srv/salt/states/vyos-interfaces.sls:

{% for iface, config in pillar['interfaces'].items() %}
configure_{{ iface }}:
  netmiko.send_config:
    - config_commands:
        - set interfaces ethernet {{ iface }} description '{{ config.description }}'
        {% if config.address %}
        - set interfaces ethernet {{ iface }} address {{ config.address }}
        {% endif %}
        {% if config.dhcp %}
        - set interfaces ethernet {{ iface }} address dhcp
        {% endif %}
    - commit: True
{% endfor %}

/srv/salt/pillars/vyos-router-01.sls:

interfaces:
  eth0:
    description: "WAN Interface"
    dhcp: true
  eth1:
    description: "LAN Interface"
    address: "192.168.1.1/24"
  eth2:
    description: "DMZ Interface"
    address: "192.168.100.1/24"

Example 3: Firewall Configuration

/srv/salt/states/vyos-firewall.sls:

firewall_wan_local:
  netmiko.send_config:
    - config_commands:
        - set firewall ipv4 name WAN_LOCAL default-action drop
        - set firewall ipv4 name WAN_LOCAL rule 10 action accept
        - set firewall ipv4 name WAN_LOCAL rule 10 state established
        - set firewall ipv4 name WAN_LOCAL rule 10 state related
        - set firewall ipv4 name WAN_LOCAL rule 20 action drop
        - set firewall ipv4 name WAN_LOCAL rule 20 state invalid
        - set firewall ipv4 name WAN_LOCAL rule 30 action accept
        - set firewall ipv4 name WAN_LOCAL rule 30 protocol icmp
        - set interfaces ethernet eth0 firewall in name WAN_LOCAL
    - commit: True

Example 4: NAT Deployment

/srv/salt/states/vyos-nat.sls:

configure_nat:
  netmiko.send_config:
    - config_commands:
        - set nat source rule 100 outbound-interface name eth0
        - set nat source rule 100 source address 192.168.1.0/24
        - set nat source rule 100 translation address masquerade
    - commit: True

Example 5: DHCP Server

/srv/salt/states/vyos-dhcp.sls:

configure_dhcp_server:
  netmiko.send_config:
    - config_commands:
        - set service dhcp-server shared-network-name LAN subnet 192.168.1.0/24 option default-router 192.168.1.1
        - set service dhcp-server shared-network-name LAN subnet 192.168.1.0/24 option name-server 192.168.1.1
        - set service dhcp-server shared-network-name LAN subnet 192.168.1.0/24 range 0 start 192.168.1.100
        - set service dhcp-server shared-network-name LAN subnet 192.168.1.0/24 range 0 stop 192.168.1.200
        - set service dhcp-server shared-network-name LAN subnet 192.168.1.0/24 subnet-id 1
    - commit: True

Retrieving Information from VyOS

Operational Commands

Via proxy minion:

# Show version
sudo salt 'vyos-proxy-01' netmiko.send_command command="show version"

# Show configuration
sudo salt 'vyos-proxy-01' netmiko.send_command command="show configuration"

# Show interfaces
sudo salt 'vyos-proxy-01' netmiko.send_command command="show interfaces"

# Show route table
sudo salt 'vyos-proxy-01' netmiko.send_command command="show ip route"

Grains (Facts System)

Retrieving all grains:

sudo salt 'vyos-router-01' grains.items

A specific grain:

sudo salt 'vyos-router-01' grains.get os

Monitoring and Events

Event Bus

Subscribing to events:

sudo salt-run state.event pretty=True

Reactor System

Automatic actions in response to events:

/etc/salt/master.d/reactor.conf:

reactor:
  - 'salt/minion/*/start':
    - /srv/salt/reactors/minion-start.sls

/srv/salt/reactors/minion-start.sls:

send_notification:
  local.cmd.run:
    - tgt: salt-master
    - arg:
      - echo "Minion {{ data['id'] }} started" | mail -s "Minion Start" admin@example.com

Operational Commands

On VyOS

Checking salt-minion status:

show service salt-minion

Restarting salt-minion:

restart salt-minion

On the Salt Master

List of all keys:

sudo salt-key -L

List of minions:

sudo salt '*' test.ping

Applying a state:

sudo salt 'vyos-router-01' state.apply

Highstate (all states):

sudo salt 'vyos-router-01' state.highstate

Troubleshooting

Minion Does Not Connect

Problem: The minion does not appear in the key list.

Diagnostics:

On VyOS:

show service salt-minion
show log | grep salt

On the Master:

sudo systemctl status salt-master
sudo tail -f /var/log/salt/master

Solution:

# Check Master reachability
ping 192.0.2.250

# Check ports (4505, 4506)
telnet 192.0.2.250 4505
telnet 192.0.2.250 4506

# Firewall on the Master
sudo firewall-cmd --add-port=4505-4506/tcp --permanent
sudo firewall-cmd --reload

Key Is Not Accepted

Problem: salt-key does not show the minion.

Solution:

Restart the minion on VyOS:

restart salt-minion

On the Master:

# Remove the old key
sudo salt-key -d vyos-router-01

# Wait for the new one
sudo salt-key -L

Commands Do Not Run

Problem: salt 'minion' test.ping returns no result.

Diagnostics:

# Check that the key is accepted
sudo salt-key -L

# Verbose mode
sudo salt 'vyos-router-01' test.ping -l debug

Solution:

# Restart the master
sudo systemctl restart salt-master

# Restart the minion
restart salt-minion  # on VyOS

Proxy Minion Issues

Problem: The proxy minion does not connect to VyOS.

Diagnostics:

# Check the logs
sudo journalctl -u salt-proxy@vyos-proxy-01 -f

# Test SSH
ssh vyos@192.0.2.10

Solution:

# Check the pillar
sudo salt 'vyos-proxy-01' pillar.items

# Verify the credentials in the pillar
# Make sure netmiko is installed
sudo pip3 install --upgrade netmiko

Netmiko Errors

Problem: “Authentication failed” or “Connection timeout”.

Solution:

Check the Pillar:

sudo salt 'vyos-proxy-01' pillar.get proxy

Update the credentials:

# /srv/salt/pillars/vyos-proxy.sls
proxy:
  proxytype: netmiko
  device_type: vyos
  host: 192.0.2.10
  username: correct_user
  password: correct_password

Refresh the pillar:

sudo salt 'vyos-proxy-01' saltutil.refresh_pillar

Security

Security Recommendations

  1. Protecting the Master:
# /etc/salt/master
auto_accept: False
client_acl:
  admin:
    - .*
publisher_acl:
  admin:
    - .*
  1. Firewall on the Master:
# Only from known networks
sudo firewall-cmd --add-rich-rule='rule family="ipv4" source address="192.0.2.0/24" port protocol="tcp" port="4505-4506" accept' --permanent
sudo firewall-cmd --reload
  1. Encrypting Pillars:
# Generate the key
sudo salt-key --gen-keys=master

# /etc/salt/master
pillar_opts: False
gpg_keydir: /etc/salt/gpgkeys
  1. Key Rotation:
# Remove the old key
sudo salt-key -d vyos-router-01

# The minion will generate a new one on restart
restart salt-minion
  1. Action Auditing:
# /etc/salt/master
return_job: True
job_cache: True
keep_jobs: 24
  1. Restricting Commands:
# /etc/salt/master
publisher_acl:
  operator:
    - test.ping
    - network.interface
  admin:
    - .*

Best Practices

  1. Use Pillars for secrets:

    • Store passwords in pillars
    • Encrypt sensitive data
    • Restrict access to pillars
  2. Version control for States:

    • Keep states in Git
    • Code review changes
    • Test before applying
  3. Testing before production:

# Test mode
sudo salt 'vyos-router-01' state.apply test=True

# Single minion first
sudo salt 'vyos-router-01' state.apply vyos-config

# Then batch
sudo salt 'vyos-*' state.apply vyos-config
  1. Backup before changes:
# Save config before applying a state
sudo salt 'vyos-proxy-01' netmiko.send_command command="save /config/backup-$(date +%Y%m%d).config"
  1. Monitoring results:
# Check job results
sudo salt-run jobs.list_jobs

# Specific job
sudo salt-run jobs.lookup_jid <job_id>
  1. Documentation:

    • Describe your states
    • Comment your pillars
    • Maintain a changelog
  2. File organization:

/srv/salt/
├── states/
│   ├── base/
│   │   ├── init.sls
│   │   └── packages.sls
│   ├── network/
│   │   ├── vyos-interfaces.sls
│   │   ├── vyos-firewall.sls
│   │   └── vyos-nat.sls
│   └── services/
│       ├── vyos-dhcp.sls
│       └── vyos-dns.sls
└── pillars/
    ├── top.sls
    ├── network/
    │   └── vyos-devices.sls
    └── secrets/
        └── credentials.sls
  1. Regular updates:
    • Update the Salt Master
    • Update the Minions
    • Watch for security bulletins

Integration with Other Systems

Gitlab CI/CD

.gitlab-ci.yml:

stages:
  - test
  - deploy

test_state:
  stage: test
  script:
    - salt 'vyos-test' state.apply vyos-config test=True

deploy_production:
  stage: deploy
  script:
    - salt 'vyos-prod-*' state.apply vyos-config
  only:
    - main
  when: manual

Ansible + Salt

Using Salt as an execution engine for Ansible:

# playbook.yml
- hosts: localhost
  tasks:
    - name: Apply Salt state to VyOS
      command: salt 'vyos-*' state.apply vyos-config

Prometheus Monitoring

Salt for collecting metrics:

# Custom grain for metrics
sudo salt 'vyos-*' grains.set monitoring:enabled True

Conclusion

Salt-Minion provides powerful capabilities for automating VyOS:

  • Centralized management - a single point of control
  • Configuration as Code - configuration versioning
  • Scalability - managing many devices at once
  • Flexibility - support for both direct minion and proxy minion
  • Event-driven - event-based automation
  • Integration - integration with the CI/CD pipeline

Key use cases:

  • Bulk configuration deployment
  • Standardizing settings
  • Automating routine tasks
  • Compliance checking
  • Centralized management of network infrastructure

A proper Salt setup enables efficient management of VyOS routers at enterprise scale and simplifies operations in cloud environments.

Reviewed by OpenNix LLC · Last updated on