All checks were successful
Deploy server-up (dev) / deploy (push) Successful in 1m22s
Het onbewaakte deel was de zwakke plek: geplande taken draaiden 's nachts en een storing kwam alleen in het auditlog terecht. Meldingen (core/notify.py): - ntfy, webhook (Discord/Slack/Gotify) en e-mail, alle drie met de standaardbibliotheek. - Gebeurtenissen: mislukte backup, onleesbaar archief, vastgelopen taak, weinig schijfruimte, beschikbare update, gestopte container. - Eén bericht per ronde; bij schijfruimte en gestopte containers alleen bij de overgang, zodat je niet elk uur hetzelfde krijgt. - Testknop die eerst opslaat, zodat je test wat je net hebt ingevuld. - send() gooit nooit: het kanaal mag de taak die de melding veroorzaakte niet alsnog laten omvallen. Schijfruimte (core/diskspace.py): - Controle vóór elke backup; past het niet, dan weigeren in plaats van halverwege afbreken. - DISK_MIN_FREE_GB blijft gereserveerd, DISK_WARN_PCT kleurt de balk rood. - Per filesystem één regel in de backuplijst. Backups controleren: - Elk nieuw archief wordt helemaal uitgelezen (tar-structuur plus gzip-checksum, die aan het eind staat). - Diepe variant pakt echt uit naar een tijdelijke map, met dezelfde beperkingen als een echt herstel. - Resultaat staat in de metadata en als schildje in de lijst. Backups de deur uit: - Downloadknop. - BACKUP_OFFSITE_DIR kopieert elke nieuwe backup naar een gemounte schijf, NFS- of SMB-share, via .part zodat een afgebroken kopie herkenbaar onaf is. - Ruimtecontrole op de bestemming, want een weggevallen mount laat vaak een lege map op de systeemschijf achter. NOTIFY_TOKEN en NOTIFY_EMAIL_PASSWORD zijn write-only. Nieuw: docs/meldingen.md; docs/backups.md uitgebreid. Getest tegen een draaiende server met een echte ontvanger. 1064 tests groen. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01C7oLCRYzY5ixJ5Sv8Y8EFb
213 lines
8 KiB
Markdown
213 lines
8 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 |
|
|
| `BACKUP_VERIFY` | `true` | Elk nieuw archief meteen controleren |
|
|
| `BACKUP_OFFSITE_DIR` | leeg | Tweede bestemming, bijvoorbeeld een gemounte schijf |
|
|
| `DISK_MIN_FREE_GB` | `2` | Reserve die vrij moet blijven |
|
|
| `DISK_WARN_PCT` | `10` | Onder dit percentage waarschuwt de interface |
|
|
|
|
---
|
|
|
|
## Controleren
|
|
|
|
Een backup die je nooit leest is een aanname. Server Up leest daarom elk nieuw
|
|
archief meteen helemaal uit: dat controleert de tar-structuur én de
|
|
gzip-checksum. Die checksum staat aan het eind, dus een archief dat halverwege
|
|
is afgebroken valt hier door de mand terwijl het in een lijst compleet lijkt.
|
|
Mislukt dat, dan meldt de backup zich als fout — het archief blijft wel staan,
|
|
zodat je kunt zien wat er mis is.
|
|
|
|
In de backuplijst staat achter elk archief een schildje: groen als het gelezen
|
|
is, rood met de foutmelding als het beschadigd is.
|
|
|
|
Met de knop **Controleren** doe je het handmatig over. Wil je zekerder weten dat
|
|
terugzetten écht werkt, gebruik dan de diepe variant (`{"deep": true}` op
|
|
`/api/backups/<bestand>/verify`): die pakt het archief uit naar een tijdelijke
|
|
map met dezelfde beperkingen als een echt herstel, en ruimt die daarna op.
|
|
|
|
Uitzetten kan met `BACKUP_VERIFY`; bij hele grote stacks kost het merkbaar tijd.
|
|
|
|
---
|
|
|
|
## Schijfruimte
|
|
|
|
Vóór elke backup wordt gekeken of het er redelijkerwijs in past. De schatting is
|
|
de ongecomprimeerde grootte van de stackmap — bewust aan de veilige kant, want
|
|
gzip maakt het kleiner. Past het niet, dan wordt de backup **geweigerd** in
|
|
plaats van halverwege afgebroken: een half archief ziet er in een lijst compleet
|
|
uit.
|
|
|
|
Daarbovenop blijft `DISK_MIN_FREE_GB` gereserveerd. Een volle schijf op een
|
|
Docker-host breekt alles, niet alleen Server Up.
|
|
|
|
Zakt een schijf onder `DISK_WARN_PCT`, dan waarschuwt de interface en — als je
|
|
meldingen hebt ingesteld — krijg je bericht. Dat gebeurt eenmalig bij de
|
|
overgang, niet elke ronde opnieuw.
|
|
|
|
---
|
|
|
|
## Een tweede bestemming
|
|
|
|
Backups staan standaard op dezelfde schijf als de data die ze moeten
|
|
beschermen. Gaat die schijf stuk, dan ben je allebei kwijt. Zet daarom
|
|
`BACKUP_OFFSITE_DIR` op een absoluut pad naar een **gemounte schijf, NFS- of
|
|
SMB-share**:
|
|
|
|
```bash
|
|
BACKUP_OFFSITE_DIR=/mnt/nas/serverup-backups
|
|
```
|
|
|
|
Elke nieuwe backup wordt daar naartoe gekopieerd, archief én metadata. Een
|
|
bestaande backup kopieer je alsnog met de wolkknop in de lijst.
|
|
|
|
Het kopiëren gaat eerst onder de naam `.part` en wordt daarna hernoemd, zodat
|
|
een afgebroken kopie herkenbaar onaf blijft. Valt de mount weg, dan bestaat het
|
|
pad vaak nog als lege map op je systeemschijf — daarom wordt eerst gecontroleerd
|
|
of er ruimte is, zodat je niet ongemerkt de verkeerde schijf vult.
|
|
|
|
> Dit is bewust een gewone mapkopie: dat werkt met USB, NAS en netwerkschijven
|
|
> zonder extra software en zonder dat wij een wachtwoord hoeven te bewaren.
|
|
> Wil je het echt buiten de deur, mount dan een externe opslag of laat een
|
|
> `rsync`-taak van je NAS de map ophalen.
|
|
|
|
---
|
|
|
|
## Downloaden
|
|
|
|
Met de downloadknop haal je een archief naar je eigen apparaat. Dat is de
|
|
snelste manier om een kopie te hebben die niets met deze server te maken heeft.
|
|
|
|
---
|
|
|
|
## 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.
|