Ładowanie

YunoHost – kopia zapasowa

🇬🇧 Go to english version of this post / Przejdź do angielskiej wersji tego wpisu

W poprzednich wpisach opisałem jak zainstalować środowisko YunoHost oraz jak uruchomić na nim pierwszą aplikacji – instancję WriteFreely. Następnym naturalnym krokiem jaki wykonałby każdy rozsądny admin jest stworzenie systemu, który po pierwsze będzie tworzył kopie zapasowe uruchomionej infrastruktury, a po drugie zabezpieczy te kopie na wypadek, gdyby serwer, na którym jest to wszystko uruchomione, nagle stwierdził, że to dobry moment na sprawienie problemów.

Na początek dla ułatwienia zdefiniujmy sobie robocze nazewnictwo dla dwóch maszyn, których będę używał w tym wpisie:

  • serwer z YunoHost – maszyna, na której zainstalowany jest YunoHost i której kopię zapasową będziemy robić,
  • serwer do backup’ów – dowolna inna maszyna z Linuxem, może to być komputer, serwer domowy lub VPS, na którym będziemy przechowywać stworzone kopie zapasowe.

Zadania do wykonania na serwerze z YunoHost

Zacznijmy od połączenia się przez SSH do serwera z YunoHost. Teraz stworzymy zadanie cykliczne, które w sposób zautomatyzowany będzie wykonywało dwie kopie dziennie. Jedna z nich będzie powstała o 5:00, a druga o 15:00. Zadanie tworzenia kopii zapasowej musi być wykonywane z uprawnieniami root, więc w pierwszej kolejności musimy przełączyć się właśnie na roota.

sudo su

Zostaniemy poproszeni o podanie hasła do naszego konta administratora YunoHost. Otwieramy tablicę zadań Cron, a raczej tworzymy ją, bo jeżeli wcześniej nie była używana to domyślnie nie istnieje:

crontab -e

Pojawi się krótki konfigurator, w którym musimy określić jakiego edytora tekstu chcemy użyć. Dla mnie domyślnym jest nano, więc wybieram opcję 1. /bin/nano, czyli wciskam 1 i ENTER. Zostanie otwarta nasza tablica, na której początku będzie dość długi komentarz. Możemy całkowicie usunąć ten tekst lub po prostu go pominąć i przejść na koniec pliku. Tablica crontab działa tak, że jedno zadanie to jedna linijka, która składa się z formuły definiującej interwał (częstotliwość) uruchamiania oraz polecenia, programu lub ścieżki do skryptu, które mają zostać wykonane. Notacja formuły interwału składa się z pięciu części, kolejno – minuta, godzina, dzień miesiąca, miesiąc, dzień tygodnia. Bardzo pomocna tutaj jest strona Crontab Guru. Dla naszego zadania polecenie w tablicy zadań Cron powinno wyglądać tak:

0 5,15 * * * yunohost backup create

Taka notacja oznacza, że polecenie yunohost backup create (wbudowane w YunoHost gotowe polecenie do wywołania tworzenia kopii zapasowej) będzie wykonywane w minucie 0, godzin 5 i 15, każdego dnia, każdego miesiąca, bez względu jaki to dzień tygodnia. Tablicę zamykamy tak samo jak zawsze wychodzimy z edytora tekstowego nano (ctrl+x, y, ENTER).

Super istotne jest, aby na obu serwerach mieć zsynchronizowane strefy czasowe, dlatego dla pewności ustawmy strefę odpowiednią dla Polski:

timedatectl set-timezone Europe/Warsaw

Dodatkowo, po każdej zmianie w tablicy zadań Cron należy pamiętać, aby przebudować proces i tym samym wprowadzić zmiany w życie:

service cron reload

Na serwerze z YunoHost pozostaje nam jeszcze włączyć logowanie przy użyciu kluczy SSH, bo bez tego ciężko będzie nam połączyć się z poziomu serwera do backup’ów. Jak to zrobić opisałem tutaj.

To wszystko co mamy tutaj do zrobienia. Pora przejść na maszynę, która będzie naszą przestrzenią do przechowywania stworzonych kopii zapasowych.

Zadania do wykonania na serwerze do backup’ów

Teraz przełączamy się na serwer do backup’ów. W pierwszej kolejności ustawmy również i tutaj strefę czasową odpowiednią dla Polski:

timedatectl set-timezone Europe/Warsaw

Skonfigurujmy teraz połączenie przez SSH do serwera z YunoHost. W tym celu w folderze /home/$USER/.ssh/ stwórzmy plik yunohost i wkleić do niego prywatny klucz SSH do serwera z YunoHost:

nano /home/$USER/.ssh/yunohost

Plik zapisujemy i wychodzimy z niego. Nadajmy mu odpowiednie uprawnienia:

chmod 600 /home/$USER/.ssh/yunohost

Dodajmy ten klucz prywatny do naszego “pęku” kluczy:

ssh-add /home/$USER/.ssh/yunohost

Od tego momentu powinniśmy być w stanie z poziomu serwera do backup’ów połączyć się przez SSH do serwera z YunoHost, więc sprawdźmy to używając poniższego polecenia sformatowanego odpowiednio do swoich potrzeb:

ssh <nazwa_admina>@<ip_serwera_z_yunohost>

Jeżeli wszystko zrobiliśmy prawidłowo to nie powinniśmy zostać poproszeni o hasło i bez problemu uzyskać dostęp do powłoki serwera z YunoHost. Przerwijmy połączenie SSH i wróćmy z powrotem na serwer do backup’ów używając polecenia:

exit

Do pobierania kopii zapasowych z serwera z YunoHost i przerzucania ich na serwer do backup’ów użyjemy narzędzia scp, którego rozwinięcie nazwy to Secure Copy (z ang. bezpieczne kopiowanie). Pozwala ono na proste i bezpieczne przenoszenie danych pomiędzy serwerami. Składnia scp dla naszego zastosowania jest następująca:

scp <nazwa_admina>@<ip_serwera_z_yunohost>:<co_skopiować> <gdzie_skopiować>

Znamy już mechanizm pozyskiwania plików z jednego serwera na drugi. Teraz trzeba zastanowić się nad strategią jak zamierzamy to robić. Przypomnijmy sobie, że na serwerze z YunoHost mamy uruchomione zadanie tworzenia kopii zapasowej każdego dnia o godzinie 5:00 i 15:00. Tworzenie kopii zajmuje raczej mniej niż minutę, ale wraz ze wzrostem naszego środowiska YunoHost ten czas może ulec wydłużeniu, a więc dla bezpieczeństwa przyjmijmy, że kopię zapasową będziemy pobierać godzinę po jej wykonaniu, czyli o 6:00 i 16:00.

Należy teraz zrozumieć jak YunoHost zarządza kopiami zapasowymi. Do tworzenia kopii z poziomu terminala twórcy udostępnili gotowe polecenie:

yunohost backup create

Polecenie to musi zostać wykonane przez uprawnieniami administratora, a więc albo bezpośrednio z poziomu użytkownika root albo poprzedzone frazą sudo. Taka składnia polecenia sprawi, że zostaną użyte domyślne ustawienia tego narzędzia, a więc zostanie stworzona kopia wszystkiego (konfiguracja systemu, dane użytkowników, aplikacje…), która zostanie zapisana w folderze:

/home/yunohost.backup/archives/

Nazwa pod jaką zostanie zapisana dana kopia ma następujący format:

<rok><miesiąc><dzień><godzina><minuta><sekunda>.tar

Zatem jeżeli kopia powstanie 8 lipca 2023 o godzinie 12:34:56 to będzie miała ona nazwę 20230708-123456.tar. Dlaczego skupiam się na tym tak bardzo? Jest to istotne w kontekście tego jak będziemy określać, który plik ma zostać pobrany, a więc która kopia jest najnowszą i powinna zostać pozyskana, aby zająć miejsce obok już wcześniej pobranych kopii na serwer do backup’ów. Zauważ, że robiąc dwie kopie dziennie będę każdego dnia miał dwa pliki, których część nazwy przed myślnikiem będzie taka sama, bo to data. W takim razie można je rozróżnić tylko po drugiej części nazwy (tej po myślniku), czyli na podstawie godziny utworzenia. Zauważ, że celowo robię dwie kopie, z których pierwsza jest z 5:00, a więc po myślniku w nazwie będzie miała 0 (zero), a druga jest z 15:00, a więc po myślniku w nazwie będzie miała 1 (jedynkę). W ten sposób kopia o nazwie 20230708-0* jest kopią poranną zrobioną 8 lipca 2023, a kopia o nazwie 20230708-1* jest kopią popołudniową. Użycie znaku * w bash’u oznacza, że pozostała część nazwy może być dowolna.

Skoro mamy już wszystko zaplanowane to w takim razie przystąpmy do działania. Zacznijmy od utworzenia na serwerze do backup’ów miejsca (folderu), w którym będziemy przechowywać pobrane kopie zapasowe.

mkdir /home/$USER/yunohost_backups

Teraz otwórzmy (lub utwórzmy jeżeli jeszcze nie istnieje) tablicę zadań Cron na tym serwerze:

crontab -e

Na końcu otwartego pliku tekstowego wstawmy takie dwie linijki:

0 6 * * * scp admin@AAA.BBB.CCC.DDD:/home/yunohost.backup/archives/$(date +"%Y%m%d")-0* /home/$USER/yunohost_backups/
0 16 * * * scp admin@AAA.BBB.CCC.DDD:/home/yunohost.backup/archives/$(date +"%Y%m%d")-1* /home/$USER/yunohost_backups/

Pamiętaj tylko, aby frazę admin zamienić na nazwę swojego administratora YunoHost, a frazę AAA.BBB.CCC.DDD na adres serwera z YunoHost. Plik zapisujemy i wychodzimy z niego. Powyższe dwie linijki wykonują prawie to samo tylko odpalają się o dwóch różnych porach (codziennie o 6:00 i 16:00). W przypadku obu następuje połączenie przez scp z serwerem z YunoHost, znalezienie pliku, którego nazwa zaczyna się od dzisiejszej daty, następnie myślnika i w przypadku pierwszej linijki (odpalenie o 6:00) dalej mamy 0* (zero i dowolne inne znaki), a w przypadku drugiej linijki (odpalenie o 16:00) dalej mamy 1* (jedynka i dowolne inne znaki). Na końcu każdej z linijek jest jeszcze wskazanie ścieżki do folderu z kopiami zapasowymi na serwerze do backup’ów.

Tak samo jak wcześniej musimy po modyfikacji zadań Cron przeładować tą usługę:

service cron reload

Jak zwykle czasem coś nie działa…

W moim przypadku jako serwer do backup’ów wybrałem Mikrusa i natrafiłem na ciekawy problem. Po jakimś czasie Mikrus całkowicie zapomina mój klucz prywatny do serwera z YunoHost. I żeby tego było mało to jeszcze, gdy chciałem dodać go ponownie poleceniem ssh-add to otrzymywałem komunikat:

Could not open a connection to your authentication agent.

To znany problem, gdy próbuje się użyć ssh-add, gdy ssh-agent nie działa jako proces. Wychodzi na to, że proces ssh-agent jest z jakiegoś powodu ubijany po pewnym czasie przez mój serwer… Czy jest to problem nie do rozwiązania? Ależ skąd! Trzeba jednak nieco zmodyfikować przedstawione przeze mnie działania.

W pierwszej kolejności muszę napisać dwa skrypty, które zastąpią mi te dwa zadania z tablicy zadań Crona. Te skrypty będą:

  1. uruchamiały ssh-agent’a,
  2. dodawały mój klucz prywatny do serwera z Yunohost do pęku kluczy,
  3. wykonywały polecenie kopiujące plik z kopią zapasową przy użyciu scp tak jak to było wcześniej.

Najpierw tworzymy pierwszy skrypt, który będzie cyklicznie uruchamiany o 6:00:

nano /home/$USER/yunohost_backup1.sh

Wklejmy do niego następującą treść (pamiętaj oczywiście, aby zmodyfikować odpowiednio pod siebie frazy admin i AAA.BBB.CCC.DDD):

#!/bin/bash
eval "$(ssh-agent)"
ssh-add /home/$USER/.ssh/yunohost
scp admin@AAA.BBB.CCC.DDD:/home/yunohost.backup/archives/$(date +"%Y%m%d")-0* /home/$USER/yunohost_backups/

Następnie tworzymy drugi skrypt:

nano /home/$USER/yunohost_backup2.sh

Wklejmy do niego następującą treść (pamiętaj oczywiście, aby zmodyfikować odpowiednio pod siebie frazy admin i AAA.BBB.CCC.DDD):

#!/bin/bash
eval "$(ssh-agent)"
ssh-add /home/$USER/.ssh/yunohost
scp admin@AAA.BBB.CCC.DDD:/home/yunohost.backup/archives/$(date +"%Y%m%d")-1* /home/$USER/yunohost_backups/

Teraz musimy uczynić oba skrypty wykonywalnymi (nadać im uprawnienia do wykonywania się):

sudo chmod +x /home/$USER/yunohost_backup1.sh /home/$USER/yunohost_backup2.sh

Na koniec musimy zmodyfikować jeszcze tablicę zadań Cron:

crontab -e

Zamiast wcześniej ustawionych dwóch linijek wklejamy takie:

0 6 * * * /home/$USER/yunohost_backup1.sh
0 16 * * * /home/$USER/yunohost_backup2.sh

Tak zmodyfikowany sposób działania rozwiązuje problem z ssh-agent’em.

Alternatywne rozwiązania

Trzeba przyznać, że przedstawione przeze mnie rozwiązanie na pewno nie należy do najbardziej wykwintnych. Pokazuje ono jednak, że istnieje wiele sposobów jakimi można dojść do tego samego efektu. Jeżeli ktoś szuka innego sposobu to YunoHost w swojej dokumentacji wspomina o trzech aplikacjach, z których można skorzystać: BorgBackup, Restic i Archivist. Próbowałem skorzystać z tej ostatniej, ale zdaje się, że aktualnie jest ona uszkodzona i po prostu nie działa… Międzyinnymi dlatego postanowiłem wszystko ustawić od początku do końca po swojemu, bez polegania na aplikacjach zewnętrznych. Polecam jednak zapoznać się z dokumentacją YunoHost i samemu zdecydować, która opcja dla Ciebie, drogi Czytelniku, wydaje się najlepsza.


Jeżeli podobał Ci się ten wpis to możesz mnie wesprzeć! 🙂

Tomasz Dunia

🇵🇱 Z wykształcenia Mechatronik. Z zawodu Główny Konstruktor w PAK-PCE Polski Autobus Wodorowy (Neso Bus). Po pracy Ojciec Roku. W nocy Wannabe Programista. Wszystko to daje przepis na zwykłego nerda :) 🇬🇧 Mechatronics by education. By profession Chief Constructor in PAK-PCE Polish Hydrogen Bus (Neso Bus). After work Father of the Year. At night Wannabe Programmer. All this gives a recipe for an ordinary nerd :)

svg

Co myślisz?

Pokaż komentarze / Napisz komentarz

5 komentarzy

  • Chłop Marcin :fediverse:

    10 maja, 2023 / at 12:57 pm

    @to3k Robisz naprawdę świetną robotę tymi swoimi poradnikami! Dziękuję! 👌

  • Grzegorz Cichocki

    10 maja, 2023 / at 2:44 pm

    @to3k@blog.tomaszdunia.pl @to3k@tomaszdunia.pl a co ze starymi backupami? Zapewne kilka ostatnich ma wartość, a reszta może trafić spokojnie do kosza. Tym bardziej przy dwóch backupach dziennie pamięć zarówno na jednej, jak i drugiej maszynie zapcha się i to szybko, więc trzeba te stare archiwa usuwać. Problem ten rozwiązałem u siebie: https://github.com/cichy1173/yh-backup usuwając starsze backupy oraz symlinki do nich w /home/yunohost.backup/archives. 1/2

  • MorganMLG

    10 maja, 2023 / at 3:45 pm

    @to3k Nie chcę się za bardzo czepiać, ale widzę, że pominąłeś w swoim wpisie kilka dosyć istotnych elementów. Ustawianie na sztywno czasu, po którym backup ma zostać przekopiowany na drugi serwer to bardzo prosta i szybka droga, żeby w momencie, gdy będziemy potrzebować odzyskać backup zwyczajnie go nie mieć. Już tłumaczę. Twoje rozwiązanie zadziała, ale ma poważną wadę, gdy już skonfigurujemy tworzenie i kopiowanie backupów, to wszystko się ładnie utworzy i przekopiuje o wyznaczonym czasie. Użytkownik szczęśliwy ze swojego sukcesu jeszcze może sprawdzi po dniu, dwóch, tygodniu czy backupy są tworzone, a później o tym zapomni. Gdy danych na serwerze będzie przybywać, czas wykonania backupu będzie co raz większy. Gdy czas wykonania backupu będzie dłuższy niż 1 godzina, wtedy skrypt kopiujący backup na drugi serwer, prawdopodobnie skopiuje uszkodzone archiwum tar, albo nie skopiuje nic (nie mam jak teraz sprawdzić jak zachowa się scp). Kolejne kopie backupów, jeżeli czas backupu będzie większy niż 1 godzina, zwyczajnie będą do wyrzucenia. Obecnie posiadam dwa serwery i czas tworzenia backupów na jednym z nich to około 45 minut , a na drugim już grubo ponad 1 godzina. Nie używam YH ale skoro, backupy są zapisywane w formacie "<rok><miesiąc><dzień>–<godzina><minuta><sekunda>.tar" to wystarczy zwykłe "ls | tail -1", żeby pobrać ostatnio utworzony backup. Wtedy wystarczy zwykły "lsof | grep <to co zwróci ls>" żeby sprawdzić czy plik jest aktualnie otwarty. Jeżeli nie jest to śmiało możemy go kopiować na drugi serwer. Dodać do tego sprawdzenie czy taki plik już istnieje na drugim serwerze i wtedy czas uruchomienia kopiowania backupów nie ma żadnego znaczenia i może być uruchamiany spokojnie co godzinę.

    • Tomasz Dunia

      10 maja, 2023 / at 4:05 pmsvgOdpowiedz

      @morganmlg O dzięki za podpowiedzi! Są dla mnie bardzo cenne, bo nie będę udawał, że jestem ekspertem, a jedynie hobbistycznie zajmuję się takimi rzeczami i jak się czegoś nauczę to wtedy o tym publikuję 😉 Zbadam i przemyślę temat i wprowadzę modyfikacje we wpisie lub utworzę zupełnie nowy 😉

Odpowiedz

svg
Szybka nawigacja
  • 01

    YunoHost – kopia zapasowa