Introduction
Microsoft offers several open source utilities for quite some time now. One is the Microsoft ODBC Driver for SQL Server on Linux which can be leveraged with unixodbc. In my case, I need this driver to query Microsoft SQL Server for my Zabbix ODBC monitoring, to execute native SQL queries for monitoring purposes. As I have to take control over 30+ Zabbix Proxies, I’m currently transforming all of them into Salt minions. My goal here is to achieve 100% automation, as soon as I install the Salt minion on a fresh Debian Linux.
The problem
In Saltstack the state declaration to install a package through the default package manager is straight forward:
msodbcsql17:
pkg.installed:
- require:
- sls: microsoft.repo
Sadly the SQL driver requires an EULA to be accepted, which you can see when installing manually via: apt install msodbcsql17

To squeeze this into configuration management automation via Saltstack, Chef, Puppet or Ansible, there also is a request at Microsoft, which hasn’t been solved yet:
https://feedback.azure.com/forums/908035-sql-server/suggestions/32901982-ability-to-automate-installation-for-linux-driver
To give this a short summary, the “problem” is, that there is a standard for “answer-files” for deb packages called debconf. This answers can be made visible AFTER the setup, so you can automate future setups:
apt install msodbcsql17 debconf-get-selections | grep -i mso sodbcsql17 msodbcsql/accept_eula boolean true
To convert this debconf selection into reusable code for future deployments, you could write something like this:
Accept Microsoft Eula:
debconf.set:
- name: msodbcsql17
- data:
'msodbcsql/accept_eula': {'type': 'boolean', 'value': True }
Sadly the msodbcsql17 deb package ignores this settings, which is the reason Markus Kuhn and Jan Katins posted updated GitHub code Gists which would solve this issue.
The solution
As this wasn’t implemented by Microsoft just yet, I dug into the original files and searched for the install behavior. In the Microsoft repository in the msodbcsql17 deb file archive is a file called “preinst”. It has a function which starts with the following IF function:
#!/bin/bash -e
. /usr/share/debconf/confmodule
check_eula_acceptance()
{
if [ "$ACCEPT_EULA" != "y" ] && [ "$ACCEPT_EULA" != "Y" ]; then
db_set msodbcsql/accept_eula false
db_fset msodbcsql/accept_eula seen false
db_input high msodbcsql/accept_eula || true
db_go
db_get msodbcsql/accept_eula
if [ "$RET" != "true" ]; then
echo "ERROR: The EULA was not accepted. Installation aborted." >&2
exit 1
fi
fi
db_set msodbcsql/accept_eula true
}
As you can see, nobody (seems to) care about debconf, but checks the value of a BASH variable. This led me to the conclusion, that an environment variable managed by saltstack could solve the issue:
Accept Microsoft Eula:
environ.setenv:
- name: ACCEPT_EULA
- value: Y
Which results in the following unattended package install state for saltstack:
msodbcsql17:
pkg.installed:
- require:
- sls: microsoft.repo
- environ: Accept Microsoft Eula
Result of state.apply:
root@salt:~# salt 'FQDN' state.apply
FQDN:
----------
ID: microsoft_repo
Function: pkgrepo.managed
Name: deb [arch=amd64] https://packages.microsoft.com/repos/microsoft-debian-stretch-prod stretch main
Result: True
Comment: Package repo 'deb [arch=amd64] https://packages.microsoft.com/repos/microsoft-debian-stretch-prod stretch main' already configured
Started: 11:44:37.049133
Duration: 24.016 ms
Changes:
----------
ID: Accept Microsoft Eula
Function: environ.setenv
Name: ACCEPT_EULA
Result: True
Comment: Environ values were set
Started: 11:44:39.616346
Duration: 0.551 ms
Changes:
----------
ACCEPT_EULA:
Y
----------
ID: microsoft_software
Function: pkg.installed
Result: True
Comment: The following packages were installed/updated: msodbcsql17
The following packages were already installed: tree, ncdu, nmap, bc, powershell, tcpdump, unixodbc, curl, apt-transport-https
Started: 11:44:39.617206
Duration: 4394.078 ms
Changes:
----------
msodbcsql17:
----------
new:
17.2.0.1-1
old:
Summary for FQDN
------------
Succeeded: 5 (changed=2)
Failed: 0
------------
Total states run: 5
Total run time: 4.639 s
Appendix: The Microsoft repository
As I use a saltstack state to manage the Microsoft repository in my example code, it might be interesting for others to see my state declaration for it:
{% if salt['grains.get']('os_family') == 'Debian' -%}
microsoft_repo:
pkgrepo.managed:
- humanname: Microsoft repository
- name: deb [arch=amd64] https://packages.microsoft.com/repos/microsoft-{{ salt['grains.get']('os')|lower }}-{{ salt['grains.get']('oscodename')|lower }}-prod {{ salt['grains.get']('oscodename')|lower }} main
- file: /etc/apt/sources.list.d/microsoft.list
- key_url: https://packages.microsoft.com/keys/microsoft.asc
- architectures: amd64
- clean_file: True
{% endif -%}