Automatische DB-Backups: nächtlich, gzip, Rotation, optional Discord-Upload
- SQLite-Online-Backup (WAL-sicher) täglich 03:00 → data/backups/*.db.gz, 14 Tage Rotation - Optional Offsite-Kopie als Upload in einen privaten Discord-Kanal (Setting) - Setup-Seite: Toggle, Upload-Kanal, 'Backup jetzt'-Button; letztes Backup im Status-Panel Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -134,6 +134,10 @@ export default function Settings({ me }) {
|
||||
<div className="stat"><span className="stat-value">{data.status.devlogs}</span><span className="stat-label">Devlogs</span></div>
|
||||
<div className="stat"><span className="stat-value">{data.status.commits}</span><span className="stat-label">Commits</span></div>
|
||||
<div className="stat"><span className="stat-value">{fmtBytes(data.status.dbSizeBytes)}</span><span className="stat-label">Datenbank</span></div>
|
||||
<div className="stat">
|
||||
<span className="stat-value">{data.status.lastBackup ? data.status.lastBackup.slice(0, 10) : '—'}</span>
|
||||
<span className="stat-label">Letztes Backup</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -282,6 +286,35 @@ export default function Settings({ me }) {
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Backups */}
|
||||
<div className="settings-section">
|
||||
<h2 className="settings-title">// Backups</h2>
|
||||
<div className="field">
|
||||
<label className="toggle">
|
||||
<input
|
||||
type="checkbox"
|
||||
checked={form.backup_enabled}
|
||||
onChange={(e) => setForm({ ...form, backup_enabled: e.target.checked })}
|
||||
/>
|
||||
<span>Nächtliches DB-Backup (03:00)</span>
|
||||
<span className="field-hint">gzip nach data/backups/, 14 Tage Rotation</span>
|
||||
</label>
|
||||
</div>
|
||||
<div className="field">
|
||||
<label>Upload-Kanal <span className="field-hint">Offsite-Kopie in einen PRIVATEN Kanal — leer = nur lokal</span></label>
|
||||
<div className="field-row">
|
||||
<select
|
||||
value={form.backup_channel_id ?? ''}
|
||||
onChange={(e) => setForm({ ...form, backup_channel_id: e.target.value })}
|
||||
>
|
||||
<option value="">— nur lokal —</option>
|
||||
{channelOptions}
|
||||
</select>
|
||||
<button className="btn" onClick={() => sendTest('backup')}>Backup jetzt</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* API-Keys */}
|
||||
<div className="settings-section">
|
||||
<h2 className="settings-title">// API-Keys (/api/v1)</h2>
|
||||
|
||||
Reference in New Issue
Block a user