Sysible Flashback keeps the history of your fleet's configuration. Every host running a Sysible agent sends its tracked configuration files in, and Flashback keeps every version of every one of them — so the question "what did this file look like before the change, and who changed it" has an answer that does not depend on anyone having remembered to take a backup.
From the console you can, for any host and any file:
Flashback ships inside the SLOP stack and is reached at https://<server-ip>/flashback/. It needs no separate install.
manuals/shots/flashback/console.png and re-run python3 tools/generate_manuals.py flashback.For the platform it runs in — installation, accounts, TLS and single sign-on — see the Sysible Linux Operations Platform guide.
It is not a general backup system. It stores configuration files, not data volumes, databases or whole filesystems — and it stores changes, not a copy per day. For machine-level backup and restore, use the Controller's backup tooling.
Nothing is pulled. The host's agent pushes a snapshot of its tracked files, and Flashback records a new version of a file only when its content differs from that file's most recent stored version. A fleet that is not changing produces almost no new rows, which is what makes keeping every version affordable.
The capture is driven by the Controller: it is the Controller's Flashback wiring that tells agents what to capture and where to send it. If that wiring is missing, no host can capture anything, and the console says so once at the top of the hosts column rather than letting every row read as a stale agent.
You do not have to wait for the next poll. The hosts column offers:
A capture is a request, not an instruction executed inline: the host's agent performs it on its next check-in, so rows stop saying "no backup captured yet" on their own shortly afterwards.
Hosts are grouped by environment, the same grouping the rest of the suite uses, because a flat list of opaque host identifiers tells an operator nothing about which box they are looking at. Groups fold, and on a large fleet they start folded.
Above the list is a filter. It matches the host name, its identifier, its address and its environment, so typing prod finds the production group and web finds the web boxes wherever they live. A match inside a folded group opens that group rather than hiding the result.
A host here typically has several hundred to a thousand captured files, so the files column has its own filter. Terms are space-separated and all must match, in any order — x11 session finds /etc/X11/Xsession without you having to remember how the path is spelled. The count beside the box says how many of the total are showing.
Both filters stay pinned to the top of their column while the list scrolls, and Escape clears either one.
manuals/shots/flashback/file-search.png and re-run python3 tools/generate_manuals.py flashback.Pick a host, then a file, then a version. The versions column shows each stored version with its timestamp, size and content hash, newest first and marked current.
With a version selected you get four actions:
View this version renders the file in the browser. A binary file says so rather than showing you replacement characters, and anything over 512 KB shows its first 512 KB with a note to download the rest — a browser asked to lay out megabytes of text stops responding.
Download this version gives you the exact bytes, named with the version's short hash so two downloads of the same path do not collide.
Restore this version queues a restore (see below).
Pick a second version to diff the two. Selecting another version in the same file turns the pane into a unified diff with additions and removals marked.
manuals/shots/flashback/view-version.png and re-run python3 tools/generate_manuals.py flashback.Restore this version queues the restore and asks you to confirm first. What happens next:
Restores are recorded. Each host's row carries its recent restores, and the audit log records who asked for what.
Compare files across hosts answers the question an operator usually arrives with after an incident: this box behaves differently — is its config different?
Pick a path that several hosts have, and Flashback shows you which hosts hold which content for it, grouped so that identical boxes collapse together and the odd one out is obvious. From there you can diff any two of them.
Hosts that have no stored copy of that path are listed separately rather than silently omitted — "this host does not have this file" and "this host has it and it matches" are different answers.
manuals/shots/flashback/compare.png and re-run python3 tools/generate_manuals.py flashback.Flashback uses the platform's three roles, asserted by SLOP:
| Role | Can |
|---|---|
superuser | Everything, including restores |
operator | Browse, view, download, diff, request captures, restore |
auditor | Browse, view, download, diff — and nothing that changes a host |
An auditor sees the whole history. What an auditor does not get is the Restore button or the capture buttons, and the API refuses those calls as well as hiding them — the console not showing a control is a convenience, not the enforcement.
Flashback keeps the 50 most recent versions per file by default, set with SYSIBLE_FLASHBACK_KEEP. When a file exceeds that, its oldest versions are pruned and the content they referenced is garbage-collected if no other version still points at it.
Because a version is only written when the content actually changed, 50 versions of a file is 50 real changes to it, not 50 days of an unchanged file. On most configuration this is years of history.
Per-host history never covered the thing doing the managing: lose the SLOP host and every managed machine's /etc was recorded in detail while the stack that read it was not recorded at all.
Flashback captures the platform's shape alongside the hosts — the compose file that defines the stack, the gateway's Caddyfile, the portal, and an inventory of the named volumes. It is stored under a reserved id that cannot collide with a hostname, and it diffs and restores like any other file history.
.env — which holds the SSO shared secret, the updater secret and both service tokens — is not captured at all, and any secret-shaped value in a file that is captured is replaced, keeping the key so a diff can still tell "the SSO secret is set" from "it is missing". Compose variable references like ${SYSIBLE_FLASHBACK_AGENT_TOKEN:-} are kept as-is: they are the wiring, not a credential, and blanking them would turn the most useful artefact here into a list of keys.Restoring the platform means re-running install.sh, which mints fresh secrets, and then comparing the result against the captured shape.
Everything is in the flashback-data Docker volume: the SQLite index and the stored content, de-duplicated by hash so that a file identical across two hundred hosts is stored once.
That volume is the whole product. Back it up — the app can be rebuilt from source in minutes, and the history cannot be rebuilt at all.
docker volume prune. Nothing reads the name but Docker. If you have scripts that back this volume up, they need no change.SYSIBLE_FLASHBACK_AGENT_TOKEN), distinct from any operator's session. Only the Controller holds that token — managed hosts never see it, they talk to the Controller and it relays./etc/ssh, credentials in service configs, tokens in environment files. Flashback is therefore as sensitive as the hosts it protects. Give auditor to people who should read config history, and treat the flashback-data volume with the same care as a password store.SYSIBLE_FLASHBACK_AGENT_BIND at 0.0.0.0. The agent endpoint takes the host identifier from the caller and authenticates with one token shared by everything that posts snapshots, so publishing it on every interface means anything holding that token can write any host's config history and read the restores queued for it. That is safe as shipped only because the port is on the Docker bridge and only the Controller has the token. Flashback prints a warning at startup if this is set to a wildcard; do not configure it that way unless you have given each agent its own credential.No hosts at all. The Controller is not pointed at Flashback, or no agent has checked in yet. The banner at the top of the hosts column says which.
A host is listed but has no files. It has been seen but has not captured yet. Use Back up now on its row and give it one check-in interval.
A file I expect is not there. Flashback stores what the agent was told to capture. The capture set is configured in the Controller, not here.
"No backup captured yet" after pressing Back up now. The request is queued for the agent's next check-in; the console re-reads shortly afterwards. If it persists past a couple of intervals, check that host's agent in the Controller.
A restore was queued but nothing changed. The agent has not checked in, or it has and the service using the file has not been restarted. Check the host's restore activity for the acknowledgement.
| Variable | Default | Meaning |
|---|---|---|
SYSIBLE_FLASHBACK_KEEP | 50 | Versions kept per file before pruning |
SYSIBLE_FLASHBACK_DATA | /data | Where the index and content live |
SYSIBLE_FLASHBACK_AGENT_TOKEN | — | Token agents present when posting snapshots |
SYSIBLE_FLASHBACK_AGENT_BIND | 172.17.0.1 | Address the agent endpoint binds to |
SYSIBLE_FLASHBACK_AGENT_PORT | 8770 | Port the agent endpoint binds to |
SYSIBLE_FLASHBACK_TRUST_GATEWAY_AUTH | 1 in SLOP | Honour the identity SLOP asserts |
SYSIBLE_FLASHBACK_MAX_REQUEST_BYTES | — | Largest snapshot accepted |
SYSIBLE_FLASHBACK_* prefix. Flashback reads SYSIBLE_FLASHBACK_* only, and deliberately does not fall back to the other: the two products want several of the same setting names, and the backup tool quietly using the config manager's token would not show up until the day you needed a restore.