Backups
Expand a host on Backups and click Backup Now beside a user database. This action
does not depend on Enabled or a saved schedule. To schedule a database, check
Enabled, enter a five-field Cron Schedule, choose Retention, and click Update.
The default 0 12 * * * runs daily at noon in the
CMDB server’s local time. Uncheck Enabled and click Update to remove its cron job.
Retention is saved as policy only; automatic file deletion is not implemented.
Cron scheduling
The Cron interface uses python-crontab
to manage the cmdb account’s crontab. Each entry has an exact comment marker,
cmdb-backup-schedule-<id>. Updates replace only that schedule’s entry; unrelated
cron jobs are preserved. The configured expression is DCMDB.BACKUP_CRON,
currently 0 12 * * *.
Cron invokes the installed venv directly:
0 12 * * * /opt/prod/cmdb/.venv/bin/python -B /opt/prod/cmdb/cmdb-backup.py --schedule-id 12 # cmdb-backup-schedule-12
The runner reads /etc/cmdb/database.env, loads the policy, and calls the shared
BackupManager and SSHDb code to execute one backup and record its outcome. It
does not contact or require the web service. A missing or disabled schedule is
a successful no-op. Success exits 0; dump, permission, configuration, and tool
errors exit 1. Backup attempts store the error when database access is available.
Cron handles process timing; there is no application scheduling loop.
Update saves Enabled, Cron Schedule, and Retention, then writes the cron entry.
Cron Schedule uses the same 20-character-wide text field as Patching, with
backend validation for the five cron fields.
A cron write failure rolls back the database edit and reports an error. If an
update fails, retry it to reconcile the settings and cron entry. Deleting a policy
through DELETE /api/backup-schedules/<id> removes its cron entry and preserves
backup history. Disabling via the UI retains the policy with Enabled cleared.
Backups page
The title box reads CMDB Backups, with both words at the same heading size.
The Inventory view similarly reads CMDB Inventory.
Application, Databases, and Backup Vault have their own bordered panels, in that order.
All three panels start collapsed. Click a title row or press Enter or Space while
the row is focused to expand or collapse its contents. Databases reveals its host
sections; Backup Vault reveals the directory, table, and Scan Filesystem button.
Application groups discovered declarations by host, then application. Host headings
show the application count in parentheses, such as Wintermute (1). Only named
directory deployments from CMDB_COMPONENTS
and matched database connections from CMDB_DATABASES
appear; installation roots, operating systems, MariaDB server
directories, and applications without declared data are excluded. Previously
recorded declarations remain eligible when later scans omit them, following the
inventory’s preservation rules.
Each application table shows Component, Type, Location, Enabled, Cron Schedule,
Update, Retention, Last Backup, Actions, and Status. Each directory or database
has its own policy and Backup Now button. Defaults and scheduling behavior match
Databases; declared databases share their existing database policy and backup history.
Saving a database policy updates its displayed settings in both panels.
The title row keeps Most recent backup: YYYY-MM-DD HH:MM right aligned,
using the newest recorded successful backup’s completion time in browser-local
time. The timestamp is blank when no backups are recorded or files cannot be loaded.
Backup Vault lists all recorded successful database and directory backups,
newest completion first (newest record first when times match). Its columns are
Date (YYYY-MM-DD) and Time (HH:MM:SS in browser-local time), Elapsed Time (HH:MM:SS), Machine (short hostname
or IP address), Database / Component, Filename (the file name only), Size, Status, and Actions.
Size uses the recorded byte count, displayed as B, KB, MB, GB, or larger units
in steps of 1,024, with one decimal place for KB and above. Missing values are blank.
Machine and source labels come from a snapshot saved when the attempt starts.
Later inventory edits or removal do not change those labels or hide backup files.
The filter row below the column headings filters each data column as you type.
Filters match part of the displayed text, ignoring case, and combine across columns.
Clear filters restores all rows. Filters stay in place when the table refreshes;
the Status filter applies only while the Status column is visible after a scan.
The configured Backup directory appears below the heading. Scan Filesystem sits
at the bottom left of the vault panel, below the table.
Elapsed Time measures whole seconds from CMDB’s attempt creation to completion,
including queue time, preparation, dumping, and checksum calculation. Hours do
not wrap at 24. While a job is starting or running, its progress message is
“Processing backup job…”.
The table refreshes when the view opens and after an observed backup completes.
Failed and running attempts are excluded. The Status column is hidden until Scan
Filesystem is clicked. It checks each recorded path through the local backup agent,
displaying Found or Missing.
This checks filesystem metadata only, without reading dump contents or checking checksums.
Access errors report a failed scan rather than marking files missing.
Every row offers Delete with a simple Cancel / Delete confirmation naming the file.
Deletion removes the recorded dump file through the local backup agent, then its
Backup record. A missing file still allows record cleanup. File access failures
keep the record; refresh before retrying after an error. Deletion is confined to
regular files inside the backup directory and preserves inventory and schedules.
Deleted records stay gone on refresh. Scan status is
temporary; reopening or refreshing the table hides the Status column and requires
another scan.
Execution
Directory backups run on the application’s host as cmdbagent, archiving the
declared directory and its contents into a gzip-compressed tarball. Relative
declarations already resolve to absolute inventory paths during discovery.
The agent needs read access to the source and write access to the backup directory;
missing directories or permission failures are recorded as failed attempts.
Symlinks within the archive remain symlinks. Backing up / or a directory
containing the backup destination is refused. Archives capture files while the
application is running; they do not provide an application-consistent snapshot.
The directory backup path is:
/imports/disk1/backups/<host>/files/<host>-<application>-<directory>-YYYY-MM-DD_HH:MM:SS.tgz
For example, MyCount’s pages/marketing directory on Wintermute produces
wintermute/files/wintermute-mycount-marketing-2026-10-07_15:53:01.tgz.
The application name is lowercased and the directory name is the final path
segment; unsafe filename characters are percent-encoded. Timestamps use UTC.
Directory jobs use the same timeout, temporary-file publication, shared-filesystem
locking, byte count, SHA-256 checksum, and no-overwrite behavior as database dumps.
The Vault supports scanning and deleting either file type. Deleting an application
retains directory backup history and archives and disables its directory policies.
Retention deletion remains unimplemented for both backup types.
Backup Now records an attempt and queues it on the web service’s worker. Duplicate
manual requests for the same active model item return the same attempt ID.
The cron runner executes synchronously in its own process. Both use BackupManager
for bookkeeping and close their CMDB connections before remote work.
Preparation saves the machine identity, environment/site, source names and path,
and known software name/version together with the attempt in a transaction.
Execution uses those saved values. The source path is separate from the resulting
backup file’s pathname. See
backup attempts
for the snapshot fields and inventory reference.
SSHDb runs mariadb-dump as cmdbagent on the database host, using the local
MariaDB socket. Neuromancer uses the existing local command path without SSH.
DCMDB.BACKUP_DIR is /imports/disk1/backups. The output location is:
/imports/disk1/backups/<host>/db/<database>/mariadb-<host>-<database>-YYYY-MM-DD_HH:MM:SS.dump
The host is the short inventory hostname, falling back to its IP. Unsafe filename characters are percent-encoded. The database part of the filename is limited to 80 encoded characters. Filenames use the UTC start date and time to the second, without fractional seconds or an attempt-ID suffix. An existing filename is never overwritten. The record stores the relative pathname, size, and SHA-256 checksum.
The host first accesses the base directory, triggering autofs where configured.
Local storage is also supported, including the backing directory on Wintermute,
the NFS server. No filesystem-type check is performed.
It creates the <host>/db/<database> directory if needed and its temporary file there,
dumps directly there, then computes the size and checksum on that host. It
publishes the completed file with a hard link and removes the temporary name,
without copying the file across filesystems or through the CMDB server.
Files use mode 600. A shared-filesystem lock prevents concurrent dumps of the
same database, including a remote command surviving a CMDB restart.
The dump includes database creation statements, data, views, triggers, routines,
and events. --single-transaction --quick provides a consistent InnoDB snapshot;
nontransactional tables and concurrent schema changes require additional care.
See mariadb-dump.
Prerequisites and outcomes
Every database host must provide the backup directory and allow cmdbagent to
write to it. For NFS mounts, ownership and permissions must work with the NFS
server’s UID/GID mapping. Installation does not change NFS configuration.
Install/upgrade grants the local agent database dump privileges. Remote agents
with old grants are reprovisioned through the existing root SSH path.
The host-side command is limited to DCMDB.BACKUP_TIMEOUT_SECONDS (3600 seconds).
Normal failures clean up temporary files and record the error. A force kill or
storage outage can leave a .part file. A lost connection may leave file outcome
unknown; CMDB does not infer success without returned metadata.
The page polls the record while the backup runs. Success updates Last Backup in browser-local time. Failure displays the recorded error and preserves the last successful timestamp. Reloading the view reconnects to the latest attempt. Restarting or viewing the web service does not modify running attempts, which may belong to independent cron processes. Interrupted jobs are not automatically recovered or retried. If completion cannot be saved, the manager logs the error; the standalone runner exits unsuccessfully.
Mirroring is provided by the storage system outside CMDB. Existing dump files are never overwritten by backup creation. Vault deletion explicitly removes a selected dump.
Delete a database
Update sits beside Cron Schedule in an unlabeled column. Actions contains
Backup Now and Delete. Delete requires typing the exact database name and drops
that database on the selected host. The name cmdb (case-insensitive) and MariaDB
system databases are blocked by the API workflow and host helper. An active
backup also blocks deletion.
Before dropping, CMDB disables the backup schedule. If deletion fails afterward, the schedule remains disabled. A successful drop removes the database from the live inventory association, preserving its model identity, backup records, and files. A later scan can rediscover a recreated database. SSH deletion uses administrative root access; local deletion requires the helper installed by the normal upgrade.