# Backups

> Online snapshots of the configuration, an export that carries the stored passwords to another machine, a restore that is scheduled for the next start rather than applied live, and the rebuild of the run-history index.

Backups is the one row of the DATA group on the Settings page. The card takes a copy of the station's configuration while everything keeps running, writes the one file that carries the stored passwords to another machine, lists everything it holds, schedules one of those copies to replace the configuration at the next start, and rebuilds the index of recorded runs when that list looks wrong. It opens with "Snapshot the app configuration (devices, tags, logic, dashboards, settings and the images, icons and symbols of your library) so you can roll back. Recorded runs and their history live separately and are never affected by a backup or restore." The page takes the **Change settings** permission.

## What a backup contains {#what-a-backup-contains}

A backup is an online copy of the configuration database, taken with SQLite's backup mechanism so it is consistent even while the app writes (the write-ahead log included). It holds everything that database holds: the drivers' devices and tags, the Logic address space (variables with their retentive values, actions, triggers, alarms), dashboards, Process models, units, procedures, recipes, evaluations and templates, local users and roles, the OPC UA server configuration, and the settings of this page. Beside the database file the station copies the user asset folder (the images, icons and symbols of your library) into a sibling folder, so a restore brings the pictures back too, and an optional note goes into a sidecar file.

The files live in the `backups` folder of the station's data root: `config-20260902-141500.db` (with a `-2` suffix if that second already has one), `config-20260902-141500.assets` and `config-20260902-141500.db.note.json`. An export is a single file beside them, `config-export-20260902-141500.glabconfig`.

A backup never contains recorded runs and their files, the run-history index, the durable events journal, the crash marker, the log files, the window placement and zoom, the account token store, or the certificate stores of the OPC UA server. Credentials inside the database (device secrets, the OPC UA server password) are stored as ciphertext bound to the Windows user and machine that entered them: a backup opened elsewhere restores the whole configuration but reads every one of those as not configured, to be entered again. The export below is the one file that carries them.

## Creating a backup {#creating-a-backup}

| Field | What it is | Values / default | Effect |
| --- | --- | --- | --- |
| Note | "Optional note stored with the backup or export", the field beside the buttons. | Up to 200 characters; empty by default and cleared after each backup or export. | Written to the note sidecar of a backup and into the header of an export, and shown under that file's row. |

| Command | What it does | Greyed when (situation) | Not drawn when (role) |
| --- | --- | --- | --- |
| Open folder | Opens the backups folder in Explorer, creating it if needed. The station's window answers the request itself, and only for an existing folder of this installation: anything else reports "That is not a folder this station opens. Nothing was opened.", the same words whether the folder lies outside the installation or is simply not there, so the answer tells the asker nothing it did not already know. A folder Windows will not open reports "The operating system could not open it." | In a browser on another device: "Available on the station's local desktop only." | Never. |
| Create backup | Takes the snapshot, then reports "Backup 'config-….db' created." in the status bar, or "Backup failed: …". | While another backup command runs (the card is dimmed). | Never. |

Creating a backup is read-only engineering work: it runs while a unit runs and never overlaps a configuration change. While the runtime is stopped this page is not drawn at all (see [Settings](settings)), so no backup command can be reached until the runtime is back. A station whose configuration database does not exist yet is refused with "The configuration database does not exist yet."

## Export for another machine {#export-for-another-machine}

Under the backup buttons, a second block with its own heading, **Export for another machine**, opens with the reason it exists: "A backup leaves the stored passwords behind: device passwords and the OPC UA server password only open on this Windows account, on this machine. An export is one file that carries them too, sealed with a password you choose here, so a new machine takes the station over whole. Keep that password somewhere safe: it is the only thing that opens the file, and it cannot be recovered here."

| Field | What it is | Values / default | Effect |
| --- | --- | --- | --- |
| Password for the export | The password the file is sealed with, and the only thing that ever opens it again. | At least 8 characters; empty by default and cleared after each export. | Derives the key every stored credential is resealed under. It is never kept anywhere: an export whose password nobody remembers cannot be opened by anybody, this application included. |
| Repeat the password | The same password again, so a typing slip is caught before the file is written. | Must match the field beside it. | Nothing on its own; Export stays refused while the two differ. |

The Note field above is shared with the backup buttons: it travels inside the export too, and is shown under its row.

| Command | What it does | Greyed when (situation) | Not drawn when (role) |
| --- | --- | --- | --- |
| Export | Writes one `config-export-20260902-141500.glabconfig` in the same `backups` folder and reports "Export '…' created with N stored credentials." A credential this Windows account could not read is counted apart, in the error tone: "Export '…' created with N stored credentials. M stored credentials could not be read on this Windows account and stayed behind: enter them again on the new machine." | While another backup command runs ("Another backup command is still running."), while the password is shorter than eight characters ("Choose a password of at least 8 characters for the export.") and while the two fields differ ("The two passwords are different."). | Never: writing an export asks for the same **Change settings** permission the page itself already takes, because the file it produces is every credential the station holds under a password its author picks. |

The export is one archive carrying a consistent copy of the configuration database, the user assets beside it, and a header. Every column the configuration protects is read through this machine's vault on the way out and resealed under the export password; the header carries the salt, the work factor and one constant sealed with the derived key, which is enough to tell a right password from a wrong one and nothing else. Which columns travel is read off the configuration itself, so a credential added later travels without anyone remembering a list. Writing an export is read-only engineering work, exactly like a backup, so it runs while a unit runs; it is journalled, because a copy of every credential the station holds has just left the vault.

An export is restored from the list below, with **Restore** on its row. That asks "Restore from an export": "'…' carries the configuration of the machine it was written on and the passwords stored with it. Type the password it was written with: the passwords are put into this machine's vault, and the configuration replaces the current one when you restart the app. The current configuration is saved automatically first, and recorded runs are not affected.", with a **Password of the export** field; Restore stays refused while it is empty ("Type the password this export was written with."). A wrong password writes nothing and leaves the dialog open, with the reason in the status bar, so the next attempt is right there: "That password does not open this export. It is the password chosen on the machine the export was written on, and there is no way to recover it here." A right one opens the export into an ordinary backup of this machine, puts the credentials it carried into this machine's vault, schedules that backup for the next start and reports "'…' was opened and its passwords stored on this machine. The configuration is restored on the next restart."; from there it is the ordinary restore described below, and the backup left in the list is the record of what arrived, so the same restore can be repeated later without the export or its password. The export file itself is never modified, so the same file still opens on a third machine.

Neither half of this is an agent's to do: there is no export tool, and no way to restore an export through the [Agent](agent) page, because the password is the operator's and one an agent minted or was handed would live in a transcript. `backup_list` marks an export (`portableExport`), and `backup_restore` refuses it naming this page: "'…' is a configuration export for another machine. It carries its stored passwords sealed under the password chosen when it was written, so it is restored from Settings, Backups, where that password can be typed."

## The list {#the-list}

Backups and exports share the one list, most recent first, because the question they answer is the same one: which of these do I restore. Each row shows when it was created, in the station's date and time format, then what the file is (**Backup** or **Export for another machine**), its name and its size, and the note when there is one. The size is everything that file occupies, which is everything deleting it frees: for a backup, the database copy, its note and its asset snapshot, whose images are the larger half on a station that uses them; for an export, the one archive. The list is read when the page opens and after each command here, so a backup an agent created through the [Agent](agent) page appears the next time the page is opened.

| Command | What it does | Greyed when (situation) | Not drawn when (role) |
| --- | --- | --- | --- |
| Restore | On a backup, asks "Restore configuration": "Schedule '…' to replace the current configuration when the app restarts? The current configuration will be saved automatically first. Recorded runs are not affected.", with Yes and No. Yes schedules the restore and reports "'…' will be restored on the next restart." On an export it is the same decision and asks for the password instead, in the dialog described above. | While a unit is running ("Configuration is locked while a Unit is running."). | Never. |
| Delete | Asks "Delete backup": "Permanently delete the backup '…'? This cannot be undone." Yes removes the database copy, its note and its asset snapshot, and reports "Backup '…' deleted." An export is named for what it is and for what goes with it, "Delete export": "Permanently delete the export '…'? The passwords it carries go with it. This cannot be undone.", then "Export '…' deleted." | Never while this page is drawn. | Never. |

Restore is refused, with the reason in the status bar, when a recording is active ("A recording is active. Stop it before scheduling a configuration restore."), when the file is not a configuration backup at all ("'…' is not a Ganter Lab configuration backup and cannot be restored."), and when it was written by a database this version does not know, such as a newer release ("'…' is not a configuration backup this version of Ganter Lab can restore. It may belong to another database, or to a newer version of the application."). Delete refuses the backup that is scheduled: "'…' is scheduled to be restored. Cancel the pending restore first." Retention is yours: nothing here deletes backups on its own, and an agent can create and list backups but never delete one.

## Restore scheduled {#restore-scheduled}

Scheduling writes a marker in the data root, and the card shows the caution banner **Restore scheduled**: "'…' will be restored when you restart the app. The current configuration is saved automatically first.", with a **Cancel** button that removes the marker and reports "Pending restore cancelled.". Nothing changes until the app starts again.

At the next start, before anything opens the configuration, the app validates the file again, snapshots the configuration being replaced as `config-pre-restore-<timestamp>.db` with the note "Automatic snapshot taken before restoring '…'." and its own asset copy (so a restore is itself reversible), swaps the database file, restores the asset snapshot when the backup carried one, and clears the marker. A start that has a Process run to resume defers instead: the restore stays scheduled with the reason "The restore remains scheduled because a Process run must resume with the current configuration." and applies at a later start. A backup file that disappeared, or that fails validation, is reported and the marker is cleared so the next starts are not held up. Once the database is swapped the restore counts as applied even if a later step, such as the asset copy, fails; that failure is reported as a warning naming where the previous images were saved.

## Configuration restored: review required {#configuration-restored-review-required}

After an applied restore the card shows a second caution banner, **Configuration restored: review required**: "Review the restored settings, Models, Units, Procedures, codes, counters and label printer queues; verify Histories; rebuild the run-history index only if the history list is missing or inconsistent." It stays until you press **Dismiss**. A restore performs no reconciliation of its own: queue names come back as configuration, but Windows printers are not discovered or corrected, and counters are what the backup held.

## Rebuild run-history index {#rebuild-run-history-index}

| Command | What it does | Greyed when (situation) | Not drawn when (role) |
| --- | --- | --- | --- |
| Rebuild | "Reconstructs the list of recorded runs by scanning the run files. Use this if the history list looks incomplete after a restore or a file move. The run files themselves are the source of truth." Reports "History index rebuilt: N recovered, N removed, N unreadable (N run files)." | While another backup command runs. | Never. |

The rescan gives a run file without an index entry its entry back (from the run's own frozen snapshot, or as a failed run if the app died mid-run), drops entries whose file is gone, rebuilds the productivity projections from every readable file, and skips a foreign or corrupt `.db` after identifying it read-only, counting it as unreadable without modifying it. It then refreshes the productivity snapshots the Process page shows. It never touches a run file's recorded evidence.

## What this section does not do {#what-this-section-does-not-do}

There is no automatic or scheduled backup, no retention policy, no backup to another location (copy the files from the folder), no partial restore, and no restore of run history: recorded runs are files of their own under the data root, and the index is rebuilt from them. The export is not a backup to another location either: it is written to the same folder, and carrying it to the machine that needs it is still yours to do. Importing and exporting runs is done on the [Histories](histories) page.
