Kihagyás

Dokumentáció a biztonsági mentés szolgáltatásunkhoz

Backup szolgáltatásunk alapjául a restic mentőrendszert választottuk, ehhez szolgáltatunk backend infrastruktúrát.

Miért a restic?

Futottak még

A restic előtt több ismert OSS backup megoldást kipróbáltunk: duplicity, borg, rclone és természetesen a jó öreg tar (amit a szalagos mentésekhez persze használunk még).

Ezek közül használhatóságban, teljesítményben, működésben a restic volt számunkra a legszimpatikusabb.

  • open-source: auditálható kód, nyílt forrás
  • cross-platform: elérhető Mac OS, Linux, BSD, Windows rendszerekre
  • támogatja a végponti deduplikációt, tömörítést, titkosítást
  • JSON kimenettel integrálható más rendszerekhez
  • többszálú végrehajtás (GOMAXPROCS)
  • nagyon sok fajta repository-t támogat
  • saját REST alapú backendje is van, amit append-only hozzáféréssel lehet megvédeni
  • forrásként nem csak filerendszerből, hanem stdin-ről is képes adatot fogadni, így beintegrálható konténer/VM/adatbázis mentésekbe
  • EU (Németország) vezető fejlesztők, security-first szemlélettel.

A restic telepítése

A mentést végző restic az alkalmazás hivatalos oldaláról letölthető, illetve a legtöbb disztribúcióban elérhető és egyszerű binárisként telepíthető:

A restic weboldala - telepítés leírása

Ismerkedés

Ha számodra ez az első találkozás a restic mentőeszközzel, javasoljuk, hogy egy lokális repository segítségével tanuld meg az alapokat. Az alábbiakat ajánljuk első lépésként:

Üzembehelyezés

Repo aktiválása

Egyszerhasználatos link

Az aktiváló URL-t csak egyszer lehet megnyitni. A kiírt kapcsolódási adatokat mentsd el.

Az ismerkedés után a nálunk hostolt REST backendet üzembehelyezve megkezdheted a valódi mentések beállítását. Az aktiváláshoz szükséges URL-t emailben küldjük meg a rendelés visszaigazolásaként. Az első megnyitáskor legenerálódnak a hozzáférési adatok. Az URL megnyitásakor generált jelszót mi nem tároljuk el (csak hash formájában).

Az aktiváló URL-t parancssorból is megnyithatod (curl), nincs benne Javascript.

A kapott 2 export sort bash-ben közvetlenül felhasználhatod, más shellnél / OS-nél értelemszerűen kell eljárni.

A RESTIC_REPOSITORY tárolja a connect stringet, amivel a restic-kel csatlakozhatsz a nálunk hostolt tárhely eléréséhez.
A RESTIC_PASSWORD_FILE pedig a helyi titkosító kulcsodat tárolja. Kezdetben ez értelemszerűen üres.

Javasoljuk, hogy hozz létre a home könyvtáradban egy .restic nevű könyvtárat, azon belül egy .env nevű file-t:

umask 077
cd
mkdir -p .restic
cd .restic
touch .env

Az aktiváló URL által kiírt két export sort másold bele a kedvenc szövegszerkesztőddel, majd ezt a file-t pedig olvasd fel minden bejelentkezéskor, pl. a .bashrc-ben:

source ~/.restic/.env

Figyelem!

Ezt a titkosító kulcsot a mi rendszerünktől függetlenül kell megvédened, enélkül nem fogsz hozzáférni a nálunk tárolt mentésekhez.

Kérlek gondoskodj a megfelelő védelméről (külön eszközön / kinyomtatva / archiválva / QR kódként / Shamir's Secret Sharing Scheme alapján stb).

Ha ki- és belépés után a fenti két környezeti változóban benne vannak a megfelelő értékek, akkor a mentési rendszered használatra kész.

echo $RESTIC_REPOSITORY
echo $RESTIC_PASSWORD_FILE

Titkosító kulcs generálása

Először is a RESTIC_PASSWORD_FILE változó által mutatott file-ba bele kell tenni a titkosító kulcsodat. Használhatsz tetszőleges szöveget, vagy létrehozhatsz egy véletlenszerű kulcsot például így:

openssl rand -base64 48 > $RESTIC_PASSWORD_FILE

Vagy akár generálhatod a random.org oldalról is:

curl -s "https://www.random.org/passwords/?num=1&len=32&format=plain&rnd=new" > $RESTIC_PASSWORD_FILE

Rögtön ezután kérlek mentsd el a generált kulcsfile-t több biztonságos helyre.

Repo inicializálás

Ha a fenti két változó be van állítva, és a titkosító kulcs létezik, a restic működésre kész; a restic init paranccsal inicializálhatjuk a backup repository-t:

$ restic init
created restic repository **** at rest:https://***:***@***:***/***/

Please note that knowledge of your password is required to access the repository. 
Losing your password means that your data is irrecoverably lost.

Használat

Szimuláció

Mivel az általunk biztosított backup tárhely ún. append-only módban működik, a feltöltött mentéseket nem lehet letörölni. Ezért érdemes először a -n paraméterrel szimulációs módban (dry-mode) indítani a mentést, és csak utána élesben.

Dry-mode

A szimulációs mód megmutatja, hogy mennyi file-t, mekkora méretben töltöttünk volna fel éles mentés indításakor.

A dry-mode természetesen figyelembe veszi a deduplikációt, tömöríthetőséget is.

$ restic backup src -n
repository faf1502e opened (version 2, compression level auto)
no parent snapshot found, will read all files
[0:00]          0 index files loaded

Files:       40764 new,     0 changed,     0 unmodified
Dirs:         6762 new,     0 changed,     0 unmodified
Would add to the repository: 674.592 MiB (429.521 MiB stored)

processed 40764 files, 1.132 GiB in 0:02

A példában a 3 különböző méret magyarázata:

  1.132 GiB: eredeti méret
675.507 MiB: deduplikált méret
428.348 MiB: deduplikált + tömörített méret

Include/Exclude

A szimulált mentés során láthatjuk az elmentett fileokat, és előfordulhat, hogy valamit ki szeretnénk hagyni. Például a cache fileokat az --exclude-caches opcióval, vagy egyéb fileokat / könyvtárakat az --exclude segítségével.

Vagy más megközelítéssel, inkább a mentendő fileokat sorolnánk fel. Ebben a --files-from, --files-from-verbatim és a --files-from-raw paraméterek a barátaink. További információ erről a restic dokumentációjában.

Mentés

Többszörös mentés

Egy mentésben egyszerre akár több filerendszert is menthetünk, végeredményként a deduplikáció ugyanolyan hatásos lesz, mintha külön-külön indítottuk volna.

A tényleges mentéshez egyszerűen a -n kapcsoló nélkül elindítjuk a restic backup parancsot.

restic backup src

Különleges (konténer / VM /adatbázis) mentésekhez láthatsz példákat a következő szakaszban.

Mentési paraméterek

Leggyakrabban a --tag paramétert használjuk, a mentések csoportosításához. Segítségével megadható egy vagy több címke az adott mentéshez; és ez alapján szűrhetjük vagy csoportosíthatjuk a mentések listáját. A többi mentési paraméter:

Usage:
  restic backup [flags] [FILE/DIR] ...

Flags:
  -n, --dry-run                                do not upload or write any data, just show what would be done
  -e, --exclude pattern                        exclude a pattern (can be specified multiple times)
      --exclude-caches                         excludes cache directories that are marked with a CACHEDIR.TAG file. See https://bford.info/cachedir/ for the Cache Directory Tagging Standard
      --exclude-file file                      read exclude patterns from a file (can be specified multiple times)
      --exclude-if-present filename[:header]   takes filename[:header], exclude contents of directories containing filename (except filename itself) if header of that file is as provided (can be specified multiple times)
      --exclude-larger-than size               max size of the files to be backed up (allowed suffixes: k/K, m/M, g/G, t/T)
      --files-from file                        read the files to backup from file (can be combined with file args; can be specified multiple times)
      --files-from-raw file                    read the files to backup from file (can be combined with file args; can be specified multiple times)
      --files-from-verbatim file               read the files to backup from file (can be combined with file args; can be specified multiple times)
  -f, --force                                  force re-reading the source files/directories (overrides the "parent" flag)
  -g, --group-by group                         group snapshots by host, paths and/or tags, separated by comma (disable grouping with '') (default host,paths)
  -h, --help                                   help for backup
  -H, --host hostname                          set the hostname for the snapshot manually (default: $RESTIC_HOST). To prevent an expensive rescan use the "parent" flag
      --iexclude pattern                       same as --exclude pattern but ignores the casing of filenames
      --iexclude-file file                     same as --exclude-file but ignores casing of filenames in patterns
      --ignore-ctime                           ignore ctime changes when checking for modified files
      --ignore-inode                           ignore inode number and ctime changes when checking for modified files
      --no-scan                                do not run scanner to estimate size of backup
  -x, --one-file-system                        exclude other file systems, don't cross filesystem boundaries and subvolumes
      --parent snapshot                        use this parent snapshot (default: latest snapshot in the group determined by --group-by and not newer than the timestamp determined by --time)
      --read-concurrency n                     read n files concurrently (default: $RESTIC_READ_CONCURRENCY or 2)
      --skip-if-unchanged                      skip snapshot creation if identical to parent snapshot
      --stdin                                  read backup from stdin
      --stdin-filename filename                filename to use when reading from stdin (default "stdin")
      --stdin-from-command                     interpret arguments as command to execute and store its stdout
      --tag tags                               add tags for the new snapshot in the format `tag[,tag,...]` (can be specified multiple times) (default [])
      --time time                              time of the backup (ex. '2012-11-01 22:08:41') (default: now)
      --with-atime                             store the atime for all files and directories

A restic weboldala - mentési paraméterek használata

Differenciális mentés

Mivel a restic automatikus deduplikációt használ, nem kell külön megadni extra opciót ahhoz, hogy differenciális mentést készítsünk; minden mentés alapértelmezetten differenciális: az utolsó mentéshez viszonyított változásokat tölti csak fel a repository-ba.

Statisztika

A restic stats paranccsal lekérdezhetjük a backup repository helyfoglalási statisztikáit. A -mode=raw-data paraméterrel láthatjuk a mentések deduplikált és tömörített+titkosított méretét.

$ restic stats
repository faf1502e opened (version 2, compression level auto)
[0:00] 100.00%  1 / 1 index files loaded
scanning...
Stats in restore-size mode:
     Snapshots processed:  1
        Total File Count:  47573
              Total Size:  1.132 GiB


$ restic stats --mode=raw-data
repository faf1502e opened (version 2, compression level auto)
[0:00] 100.00%  1 / 1 index files loaded
scanning...
Stats in raw-data mode:
     Snapshots processed:  1
        Total Blob Count:  29974
 Total Uncompressed Size:  675.507 MiB
              Total Size:  428.348 MiB
    Compression Progress:  100.00%
       Compression Ratio:  1.58x
Compression Space Saving:  36.59%

Listázás

A restic a mentéseket snapshotnak (pillanatfelvételnek) hívja.

# restic snapshots
repository 1252e1b3 opened (version 2, compression level auto)
ID        Time                 Host        Tags        Paths
-----------------------------------------------------------------------
...
a61e25ac  2024-10-18 10:57:02  elit.demo   daily       /etc
                                                       /home
                                                       /root
                                                       /var/www/virtual

c9b20477  2024-10-18 14:57:01  elit.demo   daily       /etc
                                                       /home
                                                       /root
                                                       /var/www/virtual
-----------------------------------------------------------------------
399 snapshots

A listákat szűrhetjük különböző paraméterekkel:

restic snapshots --tag beforeOSupdate --latest 1

Státuszoldal

A szolgáltatás megrendelésekor az aktiváló URL mellett a státuszoldal elérését is megküldjük. Itt láthatjuk:

  • a legfontosabb metaadatokat láthatjuk a mentésről és annak további mentéseiről
  • a restic snapshots által mutatott pillanatfelvételek aktuális védelmi szintjét
  • szolgáltatásunk státuszát az adott mentési tárhelyre vonatkozóan

Demo backup státuszoldal - élő

Adatvisszaállítás

restic restore latest --target /mnt/restore

Vagy a legutolsó mentés helyett visszaállíthatunk egy konkrét snapshotot is:

restic restore 4c3954be --target /mnt/restore

Különleges helyzetek

Több repo egy helyről

Természetesen több mentési tárhellyel is rendelkezhetünk. A hozzájuk tartozó környezeti változókat a fentiek szerint az aktiváláshoz kaphatjuk meg, viszont érdemes nevesítve, például a .<repo>.env fileokban tárolni. Ezek között váltani a szokott módon lehet:

source ~/.restic/.<repo>.env

Több repo-nál akár közös titkosító kulcsot is lehet használni, ha a biztonsági megfontolások nem indokolják a különválasztást. Ilyenkor a .<repo>.env fileokat megfelelően kell beállítani, hogy a restic meghívása előtt a RESTIC_PASSWORD_FILE környezeti változó a megfelelő kulcsfile-ra mutasson.

Biztonsági figyelmeztetés

A titkosító kulcs másolását a hostok között mindenképpen biztonságos csatornán át végezzük!

Egy repo több helyről

Természetesen több helyről is használhatunk egy közös repository-t megfelelő paraméterezéssel (a connect string és a titkosító kulcsnak is ugyanaz).

Integráció

JSON output

A --json paraméterrel minden kimenet JSON formátumban érkezik. Az átláthatóság kedvéért belecsatornázzuk a jq JSON processor eszközbe:

restic snapshots --latest 1 --json | jq
[
  {
    "time": "2024-10-18T14:57:01.660261362+02:00",
    "parent": "a61e25ac90fdc9d950202a664bd8f722c21a02b5c0ab929a90858d685b89ccfe",
    "tree": "ffd37ccf0ed4f6b38f6a0f1c22cdcab78995931df40a51d39f6ebf79e4d54f32",
    "paths": [
      "/etc",
      "/home",
      "/root",
      "/var/www/virtual"
    ],
    "hostname": "elit.demo",
    "username": "root",
    "tags": [
      "daily"
    ],
    "program_version": "restic 0.17.1",
    "id": "c9b20477839047164f91884b2ae781c6c90c7a65e3cd8f00c6a75ca30b90f243",
    "short_id": "c9b20477"
  }
]

Vagy akár a mentés kimenetét is kérhetjük így:

restic backup -q src --json | jq
{
  "message_type": "summary",
  "files_new": 44947,
  "files_changed": 0,
  "files_unmodified": 0,
  "dirs_new": 7637,
  "dirs_changed": 0,
  "dirs_unmodified": 0,
  "data_blobs": 23761,
  "tree_blobs": 7499,
  "data_added": 724480721,
  "data_added_packed": 458246748,
  "total_files_processed": 44947,
  "total_bytes_processed": 1289898238,
  "total_duration": 2.3820655,
  "snapshot_id": "70e51399b2a91b78b8ab271b8d939f370123f68719b2ba397d488caac34005a0"
}

SQL dump

Kisebb adatbázisokat akár közvetlenül beledumpolhatunk a restic-be a stdin interfészén keresztül. Érdemes tömörítés nélkül, hogy a deduplikáció hatékony legyen. Így csak a változott / új adatok fognak felkerülni a mentési repository-ba.

mysqldump --all-databases --single-transaction=TRUE \
    --hex-blob --routines --events --triggers --default-character-set=utf8 \
    | restic backup --stdin --stdin-filename alldb.sql

Nagyobb adatbázisokat a mentési terhelés csökkentése miatt céleszközzel (és azt tovább is küldhetjük a restic-nek), esetleg slave adatbázison keresztül praktikus menteni.

LXD konténerek mentése

Csak gondolatébresztőnek egy példa LXD konténerizációhoz. Végiggyaloglunk a konténereken, kiexportáljuk a teljes konténert (konfigurációval együtt), és beküldjük a restic repository-ba. Ha az adott konténerben MySQL szerver fut, akkor még egy SQL dumpot is készítünk a konzisztens mentés érdekében.

Természetesen az így készült mentésekre is érvényes, hogy csak a változások foglalnak új helyet, hiszen a restic elvégzi a deduplikációt, tömörítést és a titkosítást.

for c in `lxc list -c n -f csv`
do
  lxc export $c --compression=none --instance-only - | $RESTIC backup --stdin --stdin-filename $c/exp --tag container
  lxc exec $c -- bash -c "systemctl is-active --quiet mysql"
  if [ $? -eq 0 ]; then
    lxc exec $c -- bash -c "mysqldump --all-databases --single-transaction=TRUE --hex-blob --routines --events --triggers --default-character-set=utf8 2>/dev/null" 2>/dev/null | $RESTIC backup --stdin --stdin-filename $c/db --tag container --tag db
  fi
done

VM mentések

Fentiek mintájára virtuális gépek is menthetőek restic segítségével, például:

vzdump vm01 --mode snapshot --stdout --compress 0 | restic backup --stdin --stdin-filename vm01.vma 

Technikai segítség

Ha bármilyen kérdésed lenne az általad használt rendszerek mentésével kapcsolatban, keress minket a [email protected] emailcímen.