Skip to content

MSSQL backups fail silently in 4.9.0: mssql-tools18 never installs (MSSQL_VERSION typo 118.6.1.1-1) #490

Description

@cfoellmann

Summary

In nfrastack/db-backup:4.9.0 the MSSQL client tools are missing from the image, so every MSSQL backup fails. The Containerfile intends to install them on both amd64 and arm64, but MSSQL_VERSION has a leading 1 typo, so the download and the subsequent apk add fail during the build.

Symptom

An MSSQL job fails in under a second, every run. By default the cause is invisible — silent wraps the sqlcmd call and the routine still reports exit code 0:

[NOTICE] ** [01-...__vault] Dumping MSSQL database: 'vault'
[ERROR]  ** [01-...__vault] DB Backup of 'mssql_vault_..._20260824-123429.bak.zst' reported errors
[ERROR]  ** [01-...__vault] Skipping encryption because backup did not complete successfully
[ERROR]  ** [01-...__vault] Skipping moving DB Backup to final location because backup did not complete successfully
[INFO]   ** [01-...__vault] Backup 01 routines finish time: ... with exit code 0

With SHOW_OUTPUT=TRUE the actual error appears:

sudo: /opt/mssql-tools18/bin/sqlcmd: command not found

Evidence from inside the container

Architecture is x86_64, i.e. the supported path:

# uname -m
x86_64

# ls /opt
microsoft  mysql

# find /opt/microsoft
/opt/microsoft
/opt/microsoft/msodbcsql18
/opt/microsoft/msodbcsql18/ACCEPT_EULA

# find / -name 'sqlcmd*' -not -path '/proc/*'
(no output)

# apk info | grep -iE 'sql|odbc'
postgresql-common
postgresql18-client
sqlite
sqlite-libs

Neither msodbcsql18 nor mssql-tools18 is installed. The only trace of the MSSQL block is the ACCEPT_EULA marker, which is created by mkdir -p/touch before the two curl/apk add calls — so the block starts and then fails.

Cause

Containerfile:

MSODBC_VERSION=18.6.1.1-1 \
MSSQL_VERSION=118.6.1.1-1 \

MSSQL_VERSION has a leading 1. The resulting URL

https://download.microsoft.com/download/b60bb8b6-.../mssql-tools18_118.6.1.1-1_amd64.apk

does not exist. Since curl -sSL -O is used without -f, the failure is not surfaced as a non-zero exit; the apk add of both packages then fails, and with it the whole && chain in that if block — after the EULA marker has been created. CHANGELOG.md for 4.1.99 states MSSQL 18.6.1-1, which matches 18.6.1.1-1, the value already used for MSODBC_VERSION.

Suggested fix

-    MSSQL_VERSION=118.6.1.1-1 \
+    MSSQL_VERSION=18.6.1.1-1 \

Two hardening suggestions while you're in there:

  • Add -f (or --fail-with-body) to the curl -O calls in the MSSQL block, so a bad URL fails the build instead of producing a file that apk then rejects.
  • Consider not routing the sqlcmd invocation through silent at rootfs/container/functions/10-dbbackup:532, or at least logging its stderr on a non-zero exit. As it stands, a missing client is indistinguishable from a wrong password or a permissions problem, and the run still ends with exit code 0.

Environment

  • Image: nfrastack/db-backup:4.9.0 (Docker Hub, amd64; also present in the 2026-08-23 rebuild)
  • Base: Alpine 3.24.1
  • Host: x86_64, Docker standalone
  • DB_TYPE=mssql, DB01_MSSQL_MODE default (DATABASE), target is a ghcr.io/bitwarden/mssql container

Not mentioned in the 4.9.0 or 4.9.1 changelog entries, so I assume it is unnoticed rather than known.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions