Some checks failed
Deploy server-up (dev) / deploy (push) Failing after 6s
Backups (core/backups.py, core/scheduler.py): - Terugzetten met een klik: stack stoppen, huidige map opzij, uitpakken, starten. Mislukt het uitpakken, dan wordt de oude situatie teruggeplaatst. - Bewaarbeleid: aantal per stack en/of maximale leeftijd; de nieuwste backup van een stack blijft altijd staan. - Geplande backups (dagelijks/wekelijks) via een eigen planner in de app, geen cron. Een gemiste ronde loopt bij de eerstvolgende gelegenheid alsnog. - Automatisch een backup voor het bijwerken of verwijderen van een stack. Mislukt die, dan gaat de actie door - anders kun je een kapotte stack niet meer opruimen. - Uitpakken met tarfile + filter="data": absolute paden en ..-ingangen worden geweigerd. Met een kaal `tar xzf` kon een geprepareerd archief buiten de stackmap schrijven. - Twee bugs in de oude implementatie: de returncode van tar werd genegeerd (mislukte backup gold als succes) en backups binnen dezelfde seconde overschreven elkaar. Updates per app (core/stackupdates.py, core/registry.py): - Badge op de stackkaart als er een nieuwer image is; bijwerken doet de bestaande update-knop. - Vergelijking via de Registry API v2 (Docker-Content-Digest) in plaats van `docker manifest inspect`: dat laatste geeft per platform een aparte digest terwijl RepoDigests de manifest-list-digest bevat, wat bij elk multi-arch image permanent "update beschikbaar" zou opleveren. - Drie statussen: update / current / unknown. Lokaal gebouwd, nog niet gepulld of registry onbereikbaar geeft unknown en dus geen badge. - Dagelijkse achtergrondcheck, resultaten 6 uur gecached. Verder: - docs/backups.md, met nadruk op wat er niet in een backup zit: de Docker-volumes met de eigenlijke appdata. - Backup-instellingen onder Instellingen; backup-geschiedenis per stack. - 197 tests groen (40 nieuwe). Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01C7oLCRYzY5ixJ5Sv8Y8EFb
138 lines
4.9 KiB
Markdown
138 lines
4.9 KiB
Markdown
# Backups
|
|
|
|
Server Up maakt backups van je stacks: handmatig, automatisch vóór risicovolle
|
|
acties, of op een schema. Terugzetten kan met één klik.
|
|
|
|
---
|
|
|
|
## ⚠️ Lees dit eerst: wat zit er wél en niet in
|
|
|
|
Een backup is een `.tar.gz` van de **stackmap** in je library. Daar zitten in:
|
|
|
|
- het compose-bestand
|
|
- het `.env`-bestand (met je wachtwoorden en tokens)
|
|
- eventuele configuratiebestanden die naast de compose staan
|
|
- `.serverup.json` met de metadata van de installatie
|
|
|
|
Wat er **niet** in zit: de Docker-volumes met de eigenlijke gegevens van de app.
|
|
|
|
| Voorbeeld | In de backup? |
|
|
|---|---|
|
|
| De compose van Vaultwarden | ✅ |
|
|
| Je `ADMIN_TOKEN` uit `.env` | ✅ |
|
|
| De wachtwoordkluis van Vaultwarden zelf | ❌ |
|
|
| De database van Paperless | ❌ |
|
|
| Je foto's in Immich | ❌ |
|
|
|
|
Je kunt hiermee dus een stack terugzetten zoals hij geconfigureerd stond, maar
|
|
niet de inhoud ervan herstellen. Wil je dat ook, dan zijn er twee routes:
|
|
|
|
1. **Bind mounts in plaats van named volumes.** Staat je data in
|
|
`/opt/serverup/appdata/<app>` en zit die map binnen je stackmap, dan gaat hij
|
|
wél mee. De meeste templates in `apps/` gebruiken `data_dir` daarvoor.
|
|
2. **Een aparte volume-backup** met bijvoorbeeld `restic` of `borg` naast Server
|
|
Up. Voor grote datasets is dat sowieso beter dan een tar per keer.
|
|
|
|
> Omdat een backup je `.env` bevat, staan er wachtwoorden in. `BACKUP_DIR` hoort
|
|
> dus dezelfde bescherming te hebben als de rest van `/data`.
|
|
|
|
---
|
|
|
|
## Een backup maken
|
|
|
|
**Per stack** — de archiefknop op de stackkaart maakt er direct een. De
|
|
geschiedenisknop ernaast toont alle backups van die stack, met de mogelijkheid
|
|
om terug te zetten of te verwijderen.
|
|
|
|
**Automatisch vóór risicovolle acties** — standaard aan voor:
|
|
|
|
- **bijwerken** van een stack (`compose pull` + `up`), want een nieuwe
|
|
image-versie kan een compose-wijziging nodig hebben;
|
|
- **verwijderen** van een stack, maar alleen als je "verwijder ook de bestanden"
|
|
kiest — bij het enkel stoppen van containers valt er niets te verliezen.
|
|
|
|
Uit te zetten onder **Instellingen → Backups**. Mislukt zo'n automatische
|
|
backup, dan gaat de actie alsnog door: anders zou je een kapotte stack niet meer
|
|
kunnen opruimen. De melding komt wel in het joblog.
|
|
|
|
**Gepland** — dagelijks of wekelijks, rond een uur dat je zelf kiest. De
|
|
planner draait in de applicatie zelf (geen cron nodig) en onthoudt in
|
|
`config.json` wanneer hij voor het laatst gelopen heeft. Stond de server uit op
|
|
het geplande moment, dan loopt de backup bij de eerstvolgende gelegenheid alsnog.
|
|
|
|
---
|
|
|
|
## Bewaarbeleid
|
|
|
|
Twee regels, die allebei tegelijk gelden:
|
|
|
|
| Instelling | Betekenis |
|
|
|---|---|
|
|
| `BACKUP_KEEP` | Hoeveel backups per stack je bewaart. `0` = onbeperkt. |
|
|
| `BACKUP_MAX_AGE_DAYS` | Alles ouder dan dit aantal dagen gaat weg. `0` = geen limiet. |
|
|
|
|
**De nieuwste backup van een stack blijft altijd staan**, ook als hij ouder is
|
|
dan de maximale leeftijd. Anders sta je na een lange vakantie met lege handen.
|
|
|
|
Opruimen gebeurt na elke nieuwe backup van die stack, en na een geplande ronde.
|
|
|
|
---
|
|
|
|
## Terugzetten
|
|
|
|
De geschiedenisknop op de stackkaart → **Terugzetten**. Wat er dan gebeurt:
|
|
|
|
```
|
|
1. docker compose down stack stoppen
|
|
2. huidige map opzij zetten als <stack>.restore-<tijdstempel>
|
|
3. archief uitpakken
|
|
4. opzijgezette map weggooien
|
|
5. docker compose up -d stack starten
|
|
```
|
|
|
|
Gaat stap 3 mis — een beschadigd archief, of een archief dat buiten de stackmap
|
|
probeert te schrijven — dan wordt de opzijgezette map teruggeplaatst. Je raakt
|
|
je stack dus niet kwijt aan een kapotte backup.
|
|
|
|
Een backup van stack A kun je niet over stack B heen zetten; dat wordt geweigerd
|
|
op basis van de metadata.
|
|
|
|
### Veiligheid
|
|
|
|
Archieven worden uitgepakt met Pythons `tarfile` en `filter="data"`. Dat weigert
|
|
absolute paden, `..`-ingangen, symlinks die buiten de map wijzen en
|
|
apparaatbestanden. Met een kaal `tar xzf` zou een geprepareerd archief bestanden
|
|
elders op de host kunnen neerzetten.
|
|
|
|
---
|
|
|
|
## Instellingen
|
|
|
|
| Sleutel | Standaard | Betekenis |
|
|
|---|---|---|
|
|
| `BACKUP_DIR` | `/opt/serverup/backups` | Waar de archieven komen |
|
|
| `BACKUP_KEEP` | `5` | Aantal per stack |
|
|
| `BACKUP_MAX_AGE_DAYS` | `0` | Maximale leeftijd in dagen |
|
|
| `BACKUP_SCHEDULE` | `off` | `off` / `daily` / `weekly` |
|
|
| `BACKUP_SCHEDULE_HOUR` | `3` | Rond welk uur de geplande ronde draait |
|
|
| `BACKUP_BEFORE_UPDATE` | `true` | Backup vóór het bijwerken van een stack |
|
|
| `BACKUP_BEFORE_REMOVE` | `true` | Backup vóór het verwijderen van bestanden |
|
|
|
|
---
|
|
|
|
## Handmatig
|
|
|
|
De archieven zijn gewone tarballs — je hebt Server Up niet nodig om erbij te
|
|
kunnen:
|
|
|
|
```bash
|
|
# Bekijken wat erin zit
|
|
tar tzf /opt/serverup/backups/vaultwarden_20260726_030000.tar.gz
|
|
|
|
# Ergens anders uitpakken
|
|
tar xzf /opt/serverup/backups/vaultwarden_20260726_030000.tar.gz -C /tmp/herstel
|
|
```
|
|
|
|
Naast elk archief staat een `.json` met de stacknaam, het tijdstip, de grootte
|
|
en de reden (handmatig, gepland, voor-update, voor-remove). Ontbreekt dat
|
|
bestand, dan leidt Server Up de gegevens af uit de bestandsnaam.
|