#5816 "Restoring mode": while a backup goes back in, the scheduler holds, ingest and HTMX answer 503 with Retry-After (agents keep their samples), and every page says what is happening. A safety backup of Steward as it stands is made first, to /data/backups and the bucket. The backup's key is put in place, the restore audited, and Steward exits with code 3 so Swarm, compose or systemd starts it fresh. A failed in-place restore changes nothing and says why on Backups; a full replace that fails after the wipe restarts into first-run setup. #5817 "Settings → Backups: Restore": a Restore button on each sent backup and on the file card. The chosen backup is checked (the same comparison as Check, now a shared partial) and held server-side for an hour under a token; it starts only once the admin types "restore", and an older backup also needs "Replace everything" ticked. A newer backup, or one whose key can't open its secrets, gets no button. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
59 lines
3.3 KiB
HTML
59 lines
3.3 KiB
HTML
{# settings/backup_restore.html — restoring a backup, before anything changes
|
|
(#5817): what it would bring back (the same check as Check, #5823), what a
|
|
restore does, then a typed confirmation. A backup that can't go in says
|
|
why and offers no button. #}
|
|
{% extends "base.html" %}
|
|
{% from "_macros.html" import crumbs %}
|
|
{% from "settings/_tabs.html" import settings_tabs %}
|
|
{% block title %}Settings — Backups — Restore — Steward{% endblock %}
|
|
{% block section_tabs %}{{ settings_tabs("backups") }}{% endblock %}
|
|
{% block breadcrumb %}{{ crumbs([("Settings", "/settings/"), ("Backups", "/settings/backups/"), ("Restore " ~ (name or "a backup"), "")]) }}{% endblock %}
|
|
{% block content %}
|
|
{% if not report %}
|
|
<p class="page-verdict"><span class="tone-crit">{{ name or "The backup" }} can't be restored. {{ error }}</span></p>
|
|
{% else %}
|
|
{% include "settings/_backup_report.html" %}
|
|
|
|
<div class="card" style="max-width:640px;margin-top:1.25rem;">
|
|
<h2 class="section-title" style="margin-bottom:0.5rem;">Restore {{ name }}</h2>
|
|
{% if report.schema == "newer" %}
|
|
<p class="tone-crit">This Steward is older than the one that made the backup. Update Steward, then restore it.</p>
|
|
{% elif not report.ok %}
|
|
<p class="tone-crit">Its key doesn't open all of its secrets, so passwords and keys wouldn't come back. Restore a
|
|
different backup.</p>
|
|
{% else %}
|
|
<ul class="field-hint" style="margin:0 0 1rem 1.1rem;line-height:1.6;">
|
|
<li>A safety backup of Steward as it stands is made first, on <code>/data/backups</code> and the bucket, so
|
|
this can be undone the same way.</li>
|
|
{% if report.schema == "same" %}
|
|
<li>Settings, users, hosts, monitors, rules and dashboards become the backup's. The audit log and the history
|
|
of what is still here stay; history of anything the backup doesn't have goes with it.</li>
|
|
<li>If anything goes wrong part-way, nothing changes.</li>
|
|
{% else %}
|
|
<li><span class="tone-warn">The backup is from an older Steward, so it replaces everything</span>: the audit
|
|
log, alert history, metrics and check results go too, and Steward brings the backup up to date as it
|
|
starts. If this fails part-way, Steward starts empty, at first-run setup, where the safety backup can be
|
|
uploaded.</li>
|
|
{% endif %}
|
|
<li>While it runs, pages say Steward is restoring and agents hold their readings. Steward then restarts, and
|
|
you sign in again as a user from the backup.</li>
|
|
</ul>
|
|
{% if error %}<p class="tone-crit" style="margin-bottom:0.75rem;">{{ error }}</p>{% endif %}
|
|
<form method="post" action="/settings/backups/restore/start/">{{ csrf_field() }}
|
|
<input type="hidden" name="token" value="{{ held.token }}">
|
|
{% if report.schema == "older" %}
|
|
<label style="display:flex;align-items:center;gap:0.4rem;font-weight:normal;margin-bottom:0.75rem;">
|
|
<input type="checkbox" name="replace_all"> Replace everything, history included</label>
|
|
{% endif %}
|
|
<div class="form-group" style="max-width:260px;">
|
|
<label for="r-confirm">Type <code>{{ word }}</code> to confirm</label>
|
|
<input type="text" id="r-confirm" name="confirm" autocomplete="off" required>
|
|
</div>
|
|
<button type="submit" class="btn btn-danger">Restore</button>
|
|
</form>
|
|
{% endif %}
|
|
</div>
|
|
{% endif %}
|
|
<p style="margin-top:1rem;"><a href="/settings/backups/">Back to Backups</a></p>
|
|
{% endblock %}
|