How to Set Up Windows Server 2019 with Salt

SaltStack (Salt) is a powerful configuration management and remote execution tool that supports Windows Server 2019 as a first-class managed platform. Salt uses a master/minion architecture where a Salt Master server manages Salt Minions installed on client machines. Salt states (written in YAML with Jinja2 templating) describe the desired configuration of minion machines, and Salt can also execute arbitrary commands across fleets of servers simultaneously. Its speed, event-driven automation, and excellent Windows support make it a compelling choice for managing Windows Server environments.

Salt Architecture for Windows

The Salt Master runs on Linux (typically) and communicates with Salt Minions using ZeroMQ messaging over TCP ports 4505 (publish) and 4506 (return). The Salt Minion is a Windows service that accepts commands from the master, applies state files, and returns results. Salt also supports a masterless mode (salt-call –local) where a minion applies states without a master, useful for bootstrapping or standalone management.

Installing the Salt Minion on Windows Server 2019

Download the Salt Minion installer from the SaltStack website. The installer includes all dependencies including Python and creates a Windows service that starts automatically.

# Download Salt Minion installer
$SaltVersion = "3006.5"
$SaltInstaller = "Salt-Minion-$SaltVersion-Py3-AMD64-Setup.exe"
Invoke-WebRequest -Uri "https://repo.saltproject.io/windows/$SaltInstaller" `
    -OutFile "C:Temp$SaltInstaller"

# Install silently, pointing to the Salt Master
Start-Process "C:Temp$SaltInstaller" -ArgumentList `
    "/S /master=saltmaster.corp.local /minion-name=websvr01.corp.local" `
    -Wait

# Verify installation
C:Saltsalt-call.bat --version

# Start the Salt Minion service
Start-Service salt-minion
Get-Service salt-minion | Select-Object Status, StartType

Configuring the Salt Minion

The minion configuration file is located at C:Saltconfminion. Key settings include the master address, minion ID, and log level.

# C:Saltconfminion configuration
$MinionConfig = @"
master: saltmaster.corp.local
id: websvr01.corp.local
log_level: warning
log_file: C:Saltvarlogsaltminion
hash_type: sha256
grains:
  environment: production
  role: webserver
  datacenter: dc1
"@

$MinionConfig | Out-File "C:Saltconfminion" -Encoding UTF8

# Restart the minion after configuration change
Restart-Service salt-minion

Accepting the Minion Key on the Master

# On the Salt Master (Linux) - list pending key requests
salt-key -L

# Output shows:
# Unaccepted Keys:
# websvr01.corp.local

# Accept the minion key
salt-key -a websvr01.corp.local

# Accept all pending keys (use carefully in production)
salt-key -A

# Test connectivity to the Windows minion
salt websvr01.corp.local test.ping

# Test connectivity to all minions
salt '*' test.ping

Running Remote Commands with Salt

Salt’s execution modules allow you to run commands on Windows minions from the Salt Master without writing state files. This is useful for ad-hoc administration.

# Execute a PowerShell command on a Windows minion
salt websvr01.corp.local cmd.powershell "Get-WindowsFeature | Where-Object { $_.InstallState -eq 'Installed' } | Select-Object Name"

# Run a command on all Windows minions (using grains targeting)
salt -G 'os:windows' cmd.run 'systeminfo | findstr "OS Name"'

# Get system information
salt websvr01.corp.local grains.items

# Check disk space
salt websvr01.corp.local disk.usage

# List running services
salt websvr01.corp.local service.get_all

Writing Salt States for Windows Server 2019

Salt states are YAML files stored on the Salt Master that describe desired configuration. Create state files to configure IIS, install features, manage services, and deploy files.

# /srv/salt/windows/webserver.sls

# Install IIS Web Server feature
install_iis:
  win_feature.present:
    - name: Web-Server
    - recurse: True

# Install ASP.NET 4.5
install_aspnet:
  win_feature.present:
    - name: Web-Asp-Net45
    - require:
      - win_feature: install_iis

# Ensure W3SVC service is running
w3svc_running:
  service.running:
    - name: W3SVC
    - enable: True
    - require:
      - win_feature: install_iis

# Create web application directory
create_webroot:
  file.directory:
    - name: 'C:inetpubmyapp'
    - makedirs: True

# Deploy application config file
deploy_webconfig:
  file.managed:
    - name: 'C:inetpubmyappweb.config'
    - source: salt://windows/files/web.config
    - require:
      - file: create_webroot

Managing Windows Registry with Salt

# /srv/salt/windows/registry.sls

# Set application registry values
HKLMSOFTWAREMyAppInstallPath:
  reg.present:
    - name: HKLMSOFTWAREMyApp
    - vname: InstallPath
    - vdata: 'C:Program FilesMyApp'
    - vtype: REG_SZ

HKLMSOFTWAREMyAppLogLevel:
  reg.present:
    - name: HKLMSOFTWAREMyApp
    - vname: LogLevel
    - vdata: 2
    - vtype: REG_DWORD

# Security hardening registry entry
disable_auto_shares:
  reg.present:
    - name: HKLMSYSTEMCurrentControlSetServicesLanmanServerParameters
    - vname: AutoShareWks
    - vdata: 0
    - vtype: REG_DWORD

Applying States to Windows Minions

# Apply a specific state to one minion
salt websvr01.corp.local state.apply windows.webserver

# Apply multiple states
salt websvr01.corp.local state.apply windows.webserver,windows.registry

# Apply all states defined in top.sls (highstate)
salt websvr01.corp.local state.highstate

# Dry run (test mode - shows what would change)
salt websvr01.corp.local state.apply windows.webserver test=True

# Apply state to all Windows servers
salt -G 'os:windows' state.apply windows.webserver

Using Salt Grains for Targeting

Grains are inventory data collected from each minion (OS version, IP address, CPU, memory, custom grains). Use grains to target commands and states to specific groups of servers.

# Target Windows Server 2019 specifically
salt -G 'os_family:Windows' state.highstate

# Target by custom grain
salt -G 'role:webserver' state.apply windows.webserver

# Compound targeting
salt -C 'G@os_family:Windows and G@environment:production' state.highstate

# View grains on a minion
salt websvr01.corp.local grains.items | grep -E 'os|environment|role'

Using Pillars for Sensitive Configuration Data

# /srv/pillar/windows/webserver.sls (not accessible to minions directly)
webserver:
  db_host: 'sqlserver.corp.local'
  db_name: 'ProductionDB'
  db_user: 'webapp_user'
  db_password: 'SecretDatabasePassword123!'
  smtp_server: 'mail.corp.local'
# Reference pillar data in a state
deploy_appconfig:
  file.managed:
    - name: 'C:MyAppconfig.ini'
    - contents: |
        [database]
        host={{ pillar['webserver']['db_host'] }}
        name={{ pillar['webserver']['db_name'] }}
        user={{ pillar['webserver']['db_user'] }}
        password={{ pillar['webserver']['db_password'] }}

Conclusion

Salt provides a high-performance, event-driven configuration management and remote execution platform that works excellently with Windows Server 2019. The combination of Salt states for declarative configuration, execution modules for ad-hoc command execution, grains for intelligent targeting, and pillars for secure data management gives administrators comprehensive control over Windows server fleets. Salt’s speed advantage over other tools — it can apply changes to thousands of servers in seconds — makes it particularly valuable for large Windows Server environments requiring rapid configuration changes or compliance enforcement.