The configurator does not just generate a one-time config archive — it continuously monitors the live database configuration and tracks drift between what replication-manager expects to be deployed and what is actually running. This lets you detect unplanned changes, preserve intentional deviations, and keep config in a known state across rolling restarts and node replacements.
Each server's data directory contains three override files that sit in etc/mysql/custom.d/ inside the config archive (read after all tag-generated fragments):
{datadir}/{cluster}/{host_port}/
├── 01_preserved.cnf server-specific locked values
├── 02_delta.cnf calculated drift (expected vs deployed)
└── 03_agreed.cnf manually accepted deviations
These files are not generated from tags — they represent the state of the deployed server relative to the configurator's expectations, and are managed by replication-manager automatically (with overrides you can set via API or GUI).
Variables listed here are frozen for this server. The configurator will not attempt to change them during regeneration. Use this for server-specific paths, hardware-specific tuning, or any setting that legitimately differs from the rest of the cluster.
Example: a server with a different disk layout needs a custom innodb_data_home_dir:
[mysqld]
# Preserved — non-standard disk layout on this host
innodb_data_home_dir = /data2/mysql
Written automatically by replication-manager on every monitoring tick. It contains variables where the deployed (on-disk) value differs from the expected (tag-generated) value. This file tells you exactly what diverged and by how much.
The delta file has a 4-layer safety framework for writing runtime values:
version, have_ssl) are excludedIf the delta is empty after a config regeneration and restart, the server is fully converged.
When an operator clicks Accept on a delta variable, it means "I agree with the compliance value — apply it on next restart." The variable is removed from 02_delta.cnf and tracked in 03_agreed.cnf so it doesn't reappear in delta before the database restarts.
agreed.cnf is NOT deployed to the database config. An empty agreed.cnf is written to custom.d/ to overwrite any stale entries from previous versions. The real agreed.cnf stays in replication-manager's data directory as internal state.
After the database restarts, the compliance value takes effect (nothing overrides it), the runtime matches compliance, and the agreed entry is no longer needed.
agreed.cnf also surfaces unknown variables — variables in the compliance tags that the database doesn't recognize. These are detected by the dbjobs validation (mariadbd --help --verbose) and shown with a red "UNKNOWN" badge so the operator can fix the compliance tag (e.g. add loose_ prefix).
Accepting a variable via API:
POST /api/clusters/{clusterName}/servers/{serverName}/variables-accept?variableName=max_connections
The variable diff — the heart of config tracking — compares two snapshots: what the compliance module expects the config to be, and what the database server actually has deployed. Understanding when and how these snapshots are generated is key to using the configurator effectively.
Each server's data directory contains two temporary files used for comparison:
{datadir}/{cluster}/{host_port}/
├── dummy.cnf ← "expected" config (what tags generate)
├── current.cnf ← "deployed" config (what the server is running)
dummy.cnf — Expected config:
Generated by running mariadbd --defaults-file=<dummy> --print-defaults against a synthetic config file that includes only the tag-generated conf.d/ fragments. This produces the full list of variables as the compliance module would configure them — without any preserved/delta/agreed overrides. The dbjobs script fetches a fresh copy of the config tarball, creates a dummy my.cnf that includes only conf.d/, and sends the output to replication-manager via TCP.
current.cnf — Deployed config:
Generated by running mariadbd --defaults-file=<actual my.cnf> --print-defaults on the database host. This reads the server's real config file chain (including conf.d/ from tags + custom.d/ from preserved/delta/agreed overrides) and produces the full list of variables the server would start with. Also sent to replication-manager via TCP by the dbjobs script.
The snapshots are refreshed when a config refresh cookie is set. This happens:
| Trigger | When |
|---|---|
| Server init | First time replication-manager connects to a server |
| Config change detected | Checksum of deployed config files changes |
| Tag added/removed | Operator modifies DB tags in the configurator |
| Compliance accepted | New compliance module applied |
| Manual refresh | Operator clicks refresh config in the GUI |
| Variable preserved/accepted | After any variable state change |
When the cookie is set, the dbjobs script (via SSH or container entrypoint) detects it via need-config-refresh API, runs the print-defaults for both dummy and current configs, and streams the results back to replication-manager.
After both dummy.cnf and current.cnf are received:
Parse both files — each variable name is normalized (hyphens → underscores, loose_ prefix stripped) and stored in a VariablesMap with two values per variable: Config (from dummy.cnf) and Deployed (from current.cnf)
Compare — for each variable, IsEqual() checks if Config.String() == Deployed.String(). A variable is "in diff" if:
Apply preserved state — variables in 01_preserved.cnf (server-specific) and preserved_variables.cnf (cluster-wide) are loaded. Preserved variables are excluded from the delta.
Write delta — remaining differences are written to 02_delta.cnf. Variables with no Config counterpart (deployed but not in compliance) are prefixed with loose_ so they remain valid across version upgrades.
Copy to tarball — 01_preserved.cnf and 02_delta.cnf are included in the next config.tar.gz generation under etc/mysql/custom.d/, where MariaDB reads them after the tag-generated conf.d/. An empty 03_agreed.cnf is also written to overwrite any stale entries from previous versions — the real agreed.cnf stays in replication-manager's data directory as internal state.
Each variable in the diff view has one of these states:
| State | Meaning | File | Deployed to DB |
|---|---|---|---|
| Delta | Deployed differs from expected, no action taken yet | 02_delta.cnf |
Yes — protects current DB value |
| Preserved | Operator chose to keep the deployed value | 01_preserved.cnf |
Yes — overrides compliance tag |
| Accepted | Operator chose to accept the compliance value | 03_agreed.cnf |
No — internal tracking only |
| Unknown | Variable in compliance not recognized by DB | 03_agreed.cnf |
No — scrubbed from delta/preserved |
| Dropped | Variable was deprecated and operator accepted removal | dropped_variables.json |
No |
loose_ Prefix — Safe Variable NamingMariaDB and MySQL handle the loose_ prefix specially:
loose_, applies the value normallyThis makes loose_ essential for cross-vendor compatibility (MySQL-only variables on MariaDB, or vice versa) and version safety (variables removed in newer versions).
Where replication-manager uses loose_:
| Context | When loose_ is added |
|---|---|
02_delta.cnf |
Variables with delta:no-config (deployed but not in compliance) are automatically prefixed with loose_ |
01_preserved.cnf |
Variables with no compliance counterpart (Config == nil) get loose_ prefix |
| Compliance tags | Tag authors should use loose_ for any variable that may not exist on all target DB versions/vendors |
Without loose_, unknown variables crash the database on restart. This is the most common cause of failed rolling restarts after compliance tag changes.
Example — MySQL vs MariaDB:
A compliance tag that works on both vendors:
[mysqld]
# MySQL-only — MariaDB ignores it silently
loose_binlog_rows_query_log_events = 1
[mariadb]
# MariaDB-only — MySQL ignores the [mariadb] section entirely
loose_binlog_annotate_row_events = 1
Without the loose_ prefix, deploying binlog_rows_query_log_events to a MariaDB server would prevent it from starting.
Unknown variable detection: The dbjobs script runs mariadbd --help --verbose to detect variables in the compliance config that the database doesn't recognize. These are flagged in the configurator's agreed panel with a red "UNKNOWN" badge. The fix is to either add loose_ prefix to the variable in the compliance tag, or remove it entirely.
When replication-manager reads cnf files back, normalizeConfigVarName() strips the loose_ prefix so the variable name matches correctly for comparison across all three files.
When the configurator detects a difference between the compliance tags and the running database, the variable enters the delta. From there, the operator decides what to do:
Accept — "The compliance value is correct, apply it on next restart."
agreed.cnf to suppress delta regeneration until restartPreserve — "My DB value is correct, keep it permanently."
01_preserved.cnf (deployed to DB, overrides compliance tag)Example — encryption setup:
encryption tag to enable table encryptionencryption tag (tag was only needed for initial setup)innodb_encrypt_tables, etc.) as delta:no-config01_preserved.cnfThe config tracking system requires the dbjobs script running on each database host. The configurator cannot compute the delta on its own — it needs dbjobs to:
mariadbd --print-defaults to produce dummy.cnf (what the tags expect)mariadbd --print-defaults on the actual my.cnf to produce current.cnf (what the DB is running)mariadbd --help --verbose to detect variables the DB doesn't recognizeWithout dbjobs, the dummy.cnf and current.cnf files are empty, the delta is empty, and the configurator shows no differences. The dbjobs script runs automatically on provisioned servers (via container entrypoint or SSH). For on-premise setups, ensure dbjobs is scheduled via cron or systemd.
Unknown variable detection: during step 3, dbjobs checks whether the database binary recognizes all variables in the compliance config. Variables that are unknown (e.g. MySQL-only variable on MariaDB, or a variable removed in a newer version) are flagged with # unknown:varname=value markers. Replication-manager receives these markers and:
The operator should fix the compliance tag (add loose_ prefix or remove the variable) to resolve the issue.
Preserved variables can be defined at three levels. When they conflict, higher priority wins:
| Priority | Level | Where stored | How to manage |
|---|---|---|---|
| 1 (highest) | Per-server | {datadir}/{cluster}/{host_port}/01_preserved.cnf |
Variables tab → Preserve button on a specific server |
| 2 | Cluster-wide | {working-dir}/{cluster-name}/preserved_variables.cnf |
Settings → Preserved Variables Editor, or API |
| 3 (lowest) | Legacy config | prov-db-config-preserve-vars in TOML |
Settings → Preserved Configs tab (deprecated) |
Set from the Variables tab in the ClusterDB page. When you click "Preserve" on a variable for a specific server, the value is written to that server's 01_preserved.cnf. This overrides any cluster-wide setting for the same variable on this server.
API:
POST /api/clusters/{cluster}/servers/{server}/variables-preserve?variableName=max_connections
POST /api/clusters/{cluster}/servers/{server}/variables-accept?variableName=max_connections
POST /api/clusters/{cluster}/servers/{server}/variables-clear?variableName=max_connections
Stored in preserved_variables.cnf in the cluster's working directory. These apply to all servers in the cluster unless a server has its own per-server override or is explicitly excluded.
The file format is a [mysqld] section with optional per-server exclusions:
[mysqld]
# Preserved across all servers
max_connections = 500
innodb_buffer_pool_size = 4G
# Exclude specific servers from this variable
# max_connections.exclude = db1234567890,db9876543210
Managed via:
GET /POST /api/clusters/{cluster}/settings/preserved-variables-cnfChanges are applied immediately — replication-manager reloads preserved variables without restart.
prov-db-config-preserve-vars = "innodb_data_home_dir=/var/lib/mysql;max_connections=1000"
Semicolon-separated list in the TOML config. Still functional but deprecated. On first boot, if preserved_variables.cnf doesn't exist yet and this key is set, replication-manager automatically migrates the values to preserved_variables.cnf. Variable names are normalized (lowercase, hyphens to underscores, loose_ prefix stripped) during migration.
After migration, the preserved_variables.cnf takes priority and the legacy key can be removed from the TOML.
On every config refresh cycle:
01_preserved.cnf → mark variables as PreservedSource: "server-specific" (Priority 1)preserved_variables.cnf → apply only to variables NOT already set by per-server (Priority 2). Check server exclusions.prov-db-config-preserve-vars → apply only to variables NOT already set by either of the above (Priority 3)02_delta.cnf → all remaining differences (not preserved, not accepted, not dropped)prov-db-config| Description | Enable the configurator's config tracking and deployment. When false, dbjobs skips all config-related work (no print-defaults, no delta computation, no config push). All other dbjobs features (backups, optimize, log collection) continue to work normally. Use this when you manage your own my.cnf and don't use the tag-based configurator. |
| Type | Boolean |
| Default | true |
Available as a toggle in Settings > Scheduler > Enable Configurator.
prov-db-config-preserve| Description | Include the override files (01_preserved.cnf, 02_delta.cnf, and an empty 03_agreed.cnf) in the generated config.tar.gz under custom.d/. When false, the config tarball only contains tag-generated fragments — a clean config with no overrides. Only relevant when prov-db-config is true. |
| Type | Boolean |
| Default | true |
prov-db-config-preserve-vars (deprecated)| Description | Semicolon-separated list of variable names (or name=value pairs) to preserve. Deprecated — use preserved_variables.cnf instead. Values are auto-migrated to preserved_variables.cnf on first boot if the file doesn't exist yet. |
| Type | String |
| Default | "" |
Variable actions can be performed from two places in the GUI, both working per-server:
The Config Override Files panel in the Configurator tab shows the three config files (01_preserved.cnf, 02_delta.cnf, 03_agreed.cnf) for each server. Select a server from the dropdown to view its config state.
Each variable in the delta panel has two action buttons:
| Button | Action | Effect |
|---|---|---|
| Accept (checkmark) | Accept the compliance value | Variable removed from delta. Compliance tag value applies on next DB restart. Tracked in agreed.cnf until restart. |
| Preserve (lock) | Keep the current DB value | Variable moves to 01_preserved.cnf (deployed to DB). Removed from delta. DB keeps its current value across restarts. |
Variables in the preserved panel have a Remove (trash) button that clears the preservation and returns the variable to delta.
The Variables tab in the ClusterDB page (per-server view) shows every runtime variable alongside its compliance value. This gives a complete side-by-side view of what the server is running vs what the configurator expects.
From this tab you can:
This is useful for reviewing the full variable list rather than just the differences, and for acting on variables that may not appear in the delta (e.g. variables where the values match but you want to lock them).
The dbjobs script validates the compliance config against the database binary after fetching it. It runs mariadbd --help --verbose to detect variables that the database doesn't recognize.
Unknown variables are:
Common causes:
To fix: add loose_ prefix to the variable in the compliance tag (makes the DB ignore it silently if unrecognized), or remove it from the tag.
replication-manager detects when the deployed config changes on disk (checksum comparison). When a change is detected:
mariadbd --print-defaults for both dummy and current configs02_delta.cnf) is recalculatedThis happens within the normal monitoring loop interval (monitoring-ticker), so config drift is detected quickly without polling overhead.
Before the database is running (e.g., during provisioning or after a crash), replication-manager can read configuration values directly from the deployed .cnf files rather than from SHOW VARIABLES. This allows it to know the intended configuration even for offline servers.
The read order mirrors MySQL's include chain:
my.cnf with includedir directivesconf.d/ fragments (tag-generated)custom.d/ overrides (preserved, delta, agreed)Variables read this way are used for topology decisions, failover calculations, and provisioning validation.