Skip to content

--test-config overwrites an existing persistence database with an empty database #3712

Description

@CyrilB69

Summary

Running mosquitto --test-config -c <config> with built-in persistence enabled overwrites an existing persistence database with a new empty database, even though the command reports that the configuration is valid and is documented as not starting the broker.

This can silently remove retained messages, persistent client sessions, subscriptions, and queued client messages.

Environment

  • Mosquitto broker: 2.1.2-0mosquitto1~bookworm1
  • Mosquitto clients: 2.1.2-0mosquitto1~bookworm1
  • Installed from the official Eclipse Mosquitto Debian repository
  • OS: Debian GNU/Linux 12 (bookworm), amd64
  • Runtime: unprivileged LXC container
  • Persistence: built-in mosquitto.db persistence, no persistence plugin

Minimal reproducer

Run as root on a system where the mosquitto user exists. It uses an isolated temporary directory and TCP port 28883.

#!/bin/sh
set -eu

workdir=$(mktemp -d /tmp/mosquitto-test-config.XXXXXX)
cleanup() {
    if [ -f "$workdir/broker.pid" ]; then
        kill "$(cat "$workdir/broker.pid")" 2>/dev/null || true
    fi
    rm -rf "$workdir"
}
trap cleanup EXIT INT TERM

mkdir "$workdir/data"
chown mosquitto:mosquitto "$workdir" "$workdir/data"
chmod 0750 "$workdir" "$workdir/data"

cat > "$workdir/mosquitto.conf" <<EOF
listener 28883 127.0.0.1
allow_anonymous true
persistence true
persistence_location $workdir/data/
log_dest stdout
EOF
chown mosquitto:mosquitto "$workdir/mosquitto.conf"

mosquitto -c "$workdir/mosquitto.conf" > "$workdir/broker.log" 2>&1 &
broker_pid=$!
printf '%s\n' "$broker_pid" > "$workdir/broker.pid"

sleep 1
mosquitto_pub -h 127.0.0.1 -p 28883 \
    -t test/retained -m keep-me -r

kill "$broker_pid"
wait "$broker_pid"
rm "$workdir/broker.pid"

echo BEFORE
stat -c 'size=%s' "$workdir/data/mosquitto.db"
sha256sum "$workdir/data/mosquitto.db"

echo TEST_CONFIG
mosquitto --test-config -c "$workdir/mosquitto.conf"

echo AFTER
stat -c 'size=%s' "$workdir/data/mosquitto.db"
sha256sum "$workdir/data/mosquitto.db"

Actual result

BEFORE
size=164
febc9c816352b46407c8ce591a7f3c99b1b6ca985f84e0586666ebb573a23c73  .../data/mosquitto.db

TEST_CONFIG
1786540850: Configuration file is OK.
1786540850: mosquitto version 2.1.2 terminating
1786540850: Saving in-memory database to .../data//mosquitto.db.

AFTER
size=47
98569e29ce43ccf0d13743a099dd9e7d890a4e0b25cc8a8db3cfa081c9708364  .../data/mosquitto.db

The 47-byte file is an empty persistence database. The retained message is lost.

I first encountered this with a stopped production broker: a 2,407,332-byte persistence database was replaced by the same 47-byte empty database. I restored it from a snapshot, then reproduced the behavior independently with the script above.

Expected result

--test-config should only parse and validate the configuration. It should not create, truncate, replace, or otherwise modify the configured persistence database.

The current man page describes it as:

Load the config file specified with -c, and verify that it is valid but do not start the broker.

Possible cause

The output suggests that the --test-config path reaches normal shutdown persistence saving, but without first loading the existing persistence database. It therefore saves an empty in-memory database over the existing file.

Workaround

For now, configuration validation can be performed against a copied configuration with either:

persistence false

or a temporary persistence_location. Backing up mosquitto.db before using --test-config also prevents permanent data loss.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    Status: AvailableNo one has claimed responsibility for resolving this issue.

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions