Spaces:
Sleeping
Sleeping
| {% extends "base.html" %} | |
| {% block title %}Backups - SQLite Admin{% endblock %} | |
| {% block content %} | |
| <div class="backups-page"> | |
| <div class="page-header"> | |
| <h1>πΎ Backup Management</h1> | |
| <a href="/admin/dashboard" class="btn-secondary">β Back to Dashboard</a> | |
| </div> | |
| <!-- HF Diagnostics --> | |
| <div class="card {% if 'β' in hf_diagnosis.overall_status %}error-card{% endif %}"> | |
| <h2>π§ HF Setup Diagnostics</h2> | |
| <div class="diagnostics"> | |
| {% for check in hf_diagnosis.checks %} | |
| <div class="diag-item"> | |
| <span class="diag-name">{{ check.name }}</span> | |
| <span class="diag-status">{{ check.status }}</span> | |
| <span class="diag-value">{{ check.value }}</span> | |
| </div> | |
| {% endfor %} | |
| <div class="diag-overall"> | |
| <strong>{{ hf_diagnosis.overall_status }}</strong> | |
| </div> | |
| </div> | |
| </div> | |
| <!-- Health Status --> | |
| <div class="card"> | |
| <h2>Database Status</h2> | |
| <div class="health-grid"> | |
| <div class="health-item"> | |
| <span class="label">Integrity</span> | |
| <span class="value {% if health.integrity == 'ok' %}success{% else %}error{% endif %}"> | |
| {{ health.integrity }} | |
| </span> | |
| </div> | |
| <div class="health-item"> | |
| <span class="label">Size</span> | |
| <span class="value">{{ health.db_size_mb }} MB</span> | |
| </div> | |
| </div> | |
| </div> | |
| <!-- Create Backup --> | |
| <div class="card"> | |
| <h2>Create Backup</h2> | |
| <p class="info-text"> | |
| Create a backup of your database. Backups are stored locally and can be uploaded to HF Bucket for persistence. | |
| </p> | |
| <div class="backup-actions"> | |
| <form method="POST" action="/admin/backups/create" style="display:inline;"> | |
| <input type="hidden" name="backup_type" value="snapshot"> | |
| <button type="submit" class="btn-primary">πΈ Create Snapshot</button> | |
| </form> | |
| <form method="POST" action="/admin/backups/create" style="display:inline;"> | |
| <input type="hidden" name="backup_type" value="compressed"> | |
| <button type="submit" class="btn-secondary">ποΈ Compressed Snapshot</button> | |
| </form> | |
| <form method="POST" action="/admin/backups/create" style="display:inline;"> | |
| <input type="hidden" name="backup_type" value="vacuum"> | |
| <button type="submit" class="btn-secondary">π§Ή VACUUM Snapshot</button> | |
| </form> | |
| <form method="POST" action="/admin/backups/create" style="display:inline;"> | |
| <input type="hidden" name="backup_type" value="hf_upload"> | |
| <button type="submit" class="btn-primary">βοΈ Upload to HF Bucket</button> | |
| </form> | |
| </div> | |
| </div> | |
| <!-- Local Snapshots --> | |
| <div class="card"> | |
| <h2>π Local Snapshots</h2> | |
| <p class="info-text"> | |
| Directory: <code>{{ backups.snapshot_dir }}</code><br> | |
| HF Bucket Repo: <code>{{ backups.hf_bucket_repo }}</code><br> | |
| HF Token: <code>{% if backups.hf_token_set %}β Set{% else %}β Not Set{% endif %}</code> | |
| </p> | |
| {% if backups.local_snapshots %} | |
| <table class="data-table"> | |
| <thead> | |
| <tr> | |
| <th>Filename</th> | |
| <th>Size</th> | |
| <th>Modified</th> | |
| <th>Actions</th> | |
| </tr> | |
| </thead> | |
| <tbody> | |
| {% for snapshot in backups.local_snapshots %} | |
| <tr> | |
| <td class="code">{{ snapshot.name }}</td> | |
| <td>{{ snapshot.size_mb }} MB</td> | |
| <td>{{ snapshot.modified }}</td> | |
| <td> | |
| <a href="/admin/backups/download/{{ snapshot.name }}" class="btn-small">β¬οΈ Download</a> | |
| </td> | |
| </tr> | |
| {% endfor %} | |
| </tbody> | |
| </table> | |
| {% else %} | |
| <p class="empty-state">No local snapshots yet. Create one above!</p> | |
| {% endif %} | |
| </div> | |
| <!-- Quick API Test --> | |
| <div class="card"> | |
| <h2>π§ͺ Quick Test</h2> | |
| <p class="info-text">Use these API endpoints to test backup functionality:</p> | |
| <div class="quick-queries"> | |
| <code>GET /admin/api/diagnostics</code> - Check HF setup<br> | |
| <code>POST /admin/api/backup/test</code> - Test backup creation<br> | |
| <code>POST /admin/api/backup/upload</code> - Upload to HF Bucket | |
| </div> | |
| </div> | |
| <!-- Backup Strategy Info --> | |
| <div class="card"> | |
| <h2>π 3-Layer Backup Strategy</h2> | |
| <div class="strategy-info"> | |
| <div class="strategy-layer"> | |
| <h3>Layer 1: Litestream (Automatic)</h3> | |
| <p>Real-time replication to local file. Catches every write with max 1 second data loss.</p> | |
| </div> | |
| <div class="strategy-layer"> | |
| <h3>Layer 2: Python sqlite3.backup()</h3> | |
| <p>On-demand atomic snapshots. Consistent backups while DB is in use. Compressed with gzip.</p> | |
| </div> | |
| <div class="strategy-layer"> | |
| <h3>Layer 3: HF Bucket Upload</h3> | |
| <p>Persistent storage on HuggingFace. 100GB free private storage. Survives container restarts.</p> | |
| </div> | |
| </div> | |
| </div> | |
| </div> | |
| {% endblock %} | |