====== Raspberry Pi 5 - domácí server ====== Dokumentovaná sestava se skládá z těchto komponent: * [[https://rpishop.cz/563516/raspberry-pi-5-16gb-ram/|Raspberry Pi 5 - 16GB RAM]] * [[https://rpishop.cz/chladice-pro-raspberry-pi-5/6496-raspberry-pi-5-active-cooler.html|Raspberry Pi 5 Active Cooler]] * [[https://rpishop.cz/560366/suptronics-x1005-2280-m-2-nvme-dual-shield/|Suptronics - X1005 2280 M.2 NVMe dual Shield pro Raspberry Pi 5]] * [[https://rpishop.cz/sprava-napajeni-a-ups/3102-suptronics-x728-ups-deska-pro-inteligentni-napajeni.html|Suptronics X728 v2.5 UPS deska pro inteligentní napájení]] * [[https://rpishop.cz/zdroje-s-25x55mm-kabelem/5048-cellevia-25x55-mm-5v4a-napajeci-zdroj-eu-cerny.html|Cellevia 2,5x5,5 mm 5V⎓4A napájecí zdroj, EU]] Napájecí zdroj je kvůli UPS desce, protože UPS deska dokáže přes jack konektor 2,5×5,5 mm dodat až 20W. To je maximum, které půjde do UPS desky dodat a zároveň pokud nebudu připojovat další náročné periferie, tak tento výkon utáhne NVMe disky. ===== Bootování z NVMe disku ====== Standardně Raspberry Pi 5 bootuje z microSD karty, ale je možné nakonfigurovat systém tak, aby bootoval přímo z NVMe SSD připojeného přes PCIe. Návod vychází z článku [[https://wiki.geekworm.com/NVMe_SSD_boot_with_the_Raspberry_Pi_5|https://wiki.geekworm.com/NVMe_SSD_boot_with_the_Raspberry_Pi_5]]. Tento postup zahrnuje několik kroků: === 1. Flashování NVMe SSD pomocí Raspberry Pi Imager === Pro instalaci operačního systému na NVMe SSD můžete použít nástroj **Raspberry Pi Imager** na Windows nebo macOS. K tomu budete potřebovat **USB → NVMe adaptér**. **Postup:** * Nainstalujte a spusťte **Raspberry Pi Imager**. * Připojte NVMe SSD k počítači pomocí **USB → NVMe adaptéru**. * Vyberte operační systém pro instalaci (např. Raspberry Pi OS). * Zvolte disk (NVMe SSD připojené přes adaptér). * Klikněte na **Write** a potvrďte zápis. * Po dokončení **NEODPOJUJTE NVMe SSD**, dokud neprovedete aktivaci PCIe. Tedy bod níže a jednoduchá editace config.txt na NVMe disku. Pak je možné z disku nabootovat a řešit už další kroky. === 2. Aktivace PCIe konektoru === Ve výchozím nastavení je PCIe port deaktivovaný a je nutné jej povolit. Otevřete konfigurační soubor: sudo nano /boot/firmware/config.txt Přidejte následující řádky na konec souboru: # Povolení PCIe externího konektoru dtparam=pciex1 # Alternativní zápis pro povolení NVMe portu dtparam=nvme Uložte změny a restartujte Raspberry Pi: sudo reboot === 3. Nastavení NVMe disku jako primárního bootovacího zařízení === Po povolení PCIe portu je třeba upravit pořadí bootování v bootloaderu. **Možnost 1: Použití raspi-config** Spusťte konfigurátor: sudo raspi-config Zvolte: * **6 Advanced Options → A4 Boot Order → B2 NVMe/USB Boot** * Potvrďte volbu **Yes** a restartujte: sudo reboot **Možnost 2: Ruční úprava bootovacího řetězce** Otevřete EEPROM konfiguraci: sudo rpi-eeprom-config --edit Najděte řádek `BOOT_ORDER` a upravte ho na: BOOT_ORDER=0xf416 Uložte změny a restartujte Raspberry Pi. ===== UPS X728 ====== UPS desku jsem kupoval ve verzi 2.5. Je důležité si uvědomit, že **UPS X728 není určena k automatickému spuštění Raspberry Pi po obnovení napájení**. Její hlavní funkcí je zajistit nepřerušený provoz **během výpadku**, dokud je baterie dostatečně nabitá. Jakmile baterie klesne na **kritickou úroveň**, Raspberry Pi by mělo být **řízeně vypnuto**, aby se zabránilo náhlé ztrátě dat nebo poškození systému. **UPS však Raspberry Pi znovu automaticky nenastartuje**, i když je baterie plně nabitá. Pokud po zapnutí tlačítka na UPS svítí **červená LED dioda** na Raspberry Pi, znamená to, že deska je pod napětím, ale Raspberry Pi se samo nespustilo. Skutečné spuštění a běh systému indikují **jiné LED diody** na Raspberry Pi. ==== Specifikace ==== * Napájení: * přes USB-C: 5Vdc, 3A * přes DC jack: 5Vdc ±5%, ≥4A * UPS výstup : 5.1V ±5% Max 8A * UPS nabíjecí proud: 2,3-3,2A * Terminální napětí baterie : 4,24V * Limit nabití : 4,1V ==== Dokumentace: ==== * https://wiki.geekworm.com/X728-script * https://github.com/geekworm-com/x728-script/tree/main {{:it:jednodeskove-pocitace:pasted:20250214-225625.jpeg}} ==== Zprovoznění software ==== Tento návod popisuje postup pro zprovoznění softwaru UPS X728 a jeho správné nastavení. === Aktivace I2C podpory === Nejprve zapněte podporu I2C pomocí `raspi-config`: sudo raspi-config Poté nainstalujte potřebné balíčky: apt-get install i2c-tools apt install python3-smbus Ověření připojení přes I2C: root@propasiv-server:~# i2cdetect -y 1 0 1 2 3 4 5 6 7 8 9 a b c d e f 00: -- -- -- -- -- -- -- -- 10: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 20: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 30: -- -- -- -- -- -- 36 -- -- -- -- -- -- -- -- -- 40: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 50: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 60: -- -- -- -- -- -- -- -- 68 -- -- -- -- -- -- -- 70: -- -- -- -- -- -- -- -- #36 - adresa chipu pro měření úrovně nabití baterie #68 - adresa RTC chipu === Instalace X728 ovladačů a skriptů === Nainstalujte potřebné nástroje: sudo apt install -y gpiod Stáhněte ovladače: git clone https://github.com/geekworm-com/x728-script Nastavte práva pro skripty: cd x728-script chmod +x *.sh === Konfigurace tlačítka pro fyzické vypnutí === Přesuňte potřebné soubory na správná místa: sudo cp -f ./xPWR.sh /usr/local/bin/ sudo cp -f x728-pwr.service /lib/systemd/system sudo systemctl daemon-reload sudo systemctl enable x728-pwr sudo systemctl start x728-pwr Tento postup umožní, aby fyzické tlačítko na UPS desce X728 fungovalo takto: * Stisknutí po dobu **1-2 sekund** – **restart** zařízení. * Stisknutí po dobu **3 sekund** – **bezpečné vypnutí** (safe shutdown). * Stisknutí po dobu **7-8 sekund** – **nucené vypnutí** (force shutdown). Tento postup **nedělá nic jiného** – pouze definuje chování tlačítka. === Softwarové vypnutí UPS (bez použití Linuxového `shutdown`) === Pro správné softwarové vypnutí je nutné nastavit vlastní alias: 1. Připravte skript `xSoft.sh`: sudo cp -f ./xSoft.sh /usr/local/bin/ 2. Vytvořte alias `x728off`, který bude bezpečně vypínat UPS: echo "alias x728off='sudo /usr/local/bin/xSoft.sh 0 '''26''' '" >> ~/.bashrc 3. Aktivujte změny v `.bashrc`: source ~/.bashrc 4. Nyní můžete bezpečně vypnout UPS příkazem: x728off **Pozor:** Nepoužívejte klasický Linuxový příkaz `shutdown`, jinak se UPS nevypne správně a může zůstat zapnutá. === Test bezpečného vypnutí === Softwarové bezpečné vypnutí: x728off **Nepoužívejte příkaz `shutdown` v Linuxu**, jinak se X728 nevypne správně. === Hardwarové bezpečné vypnutí === Pomocí fyzického tlačítka na UPS lze ověřit bezpečné vypnutí: * **1-2 sekundy** – restart zařízení. * **3 sekundy** – bezpečné vypnutí, LED diody pomalu zhasnou. * **7-8 sekund** – vynucené vypnutí, okamžité zhasnutí. Tímto postupem zajistíte, že UPS X728 bude správně fungovat a umožní bezpečné vypnutí jak softwarově, tak fyzickým tlačítkem. === Přehled dostupných skriptů pro další práci s UPS === Každý skript demonstruje jinou funkcionalitu UPS X728: * **x728-v2.x-bat.py** – Čtení napětí baterie a jejího nabití. * **x728-v2.x-pld.py** – Detekce výpadku napájení z AC adaptéru. * **x728-v2.x-asd.py** – Automatické vypnutí při poklesu napětí baterie pod nastavenou hodnotu. == Problém s knihovnou RPi.GPIO a řešení pomocí libgpiod == Starší ukázkové skripty používají knihovnu **RPi.GPIO**, která **není podporována v jádru Linuxu 6.6.x**. Pokud spustíte skript jako: sudo python3 sample/x728-v2.x-plsd.py může se objevit chyba kvůli nesprávnému **gpiochip** číslu. Doporučuje se přejít na knihovnu **libgpiod**, která je oficiálně doporučena a lépe podporována. UPS X728 poskytuje **jediný oficiální skript** využívající libgpiod: sudo python3 sample/x728-v2.x-plsd-gpiod.py U ostatních skriptů, které stále používají RPi.GPIO, je doporučeno přepsání na libgpiod nebo jejich převedení na shell skripty. Skript jsem si tedy přizpůsobil pro libgpiod: #!/usr/bin/env python import struct import smbus import time import gpiod import logging # Log interval LOG_INTERVAL = 300 # seconds last_power_state = None # Stores last power state last_log_time = 0 # Stores last log timestamp # Logging configuration logging.basicConfig(filename='/var/log/x728-battery.log', level=logging.INFO, format='%(asctime)s - %(message)s') # GPIO chip and line definitions #chipname = "gpiochip0" # Use "gpiochip4" for Raspberry Pi 4/3 chipname = "gpiochip4" # Use "gpiochip4" for Raspberry Pi 5 out_line_offset = 26 # Corresponds to GPIO26 pld_line_offset = 6 # Power loss detection pin buzzer_line_offset = 20 # Buzzer control pin # I2C address for battery monitoring I2C_ADDR = 0x36 # Initialize I2C bus bus = smbus.SMBus(1) # Open GPIO chip chip = gpiod.Chip(chipname) # Get the output lines out_line = chip.get_line(out_line_offset) out_line.request(consumer="battery_monitor", type=gpiod.LINE_REQ_DIR_OUT) buzzer_line = chip.get_line(buzzer_line_offset) buzzer_line.request(consumer="power_monitor", type=gpiod.LINE_REQ_DIR_OUT) # Get the input line for power loss detection pld_line = chip.get_line(pld_line_offset) pld_line.request(consumer="power_monitor", type=gpiod.LINE_REQ_EV_BOTH_EDGES) def readVoltage(bus): """Reads battery voltage from I2C bus.""" address = I2C_ADDR read = bus.read_word_data(address, 2) swapped = struct.unpack("H", read))[0] voltage = swapped * 1.25 / 1000 / 16 return voltage def readCapacity(bus): """Reads battery capacity from I2C bus.""" address = I2C_ADDR read = bus.read_word_data(address, 4) swapped = struct.unpack("H", read))[0] capacity = swapped / 256 if capacity > 100: capacity = 100 return capacity def print_power_status(): """Monitors power status and logs changes.""" global last_power_state, last_log_time state = pld_line.get_value() current_time = time.time() if state == 1: print("Power Supply A/C Lost") # First detection of power loss if last_power_state != 1: logging.warning("Power Supply A/C Lost") elif current_time - last_log_time > LOG_INTERVAL: # Subsequent logging at intervals logging.warning("Power Supply A/C Lost") last_log_time = current_time # Activate buzzer to indicate power loss for _ in range(3): # Buzzer alarm cycle buzzer_line.set_value(1) time.sleep(0.1) buzzer_line.set_value(0) time.sleep(0.1) else: print("AC Power OK") if last_power_state != 0: # First detection of power restoration logging.info("AC Power OK") elif current_time - last_log_time > LOG_INTERVAL: # Subsequent logging at intervals logging.info("AC Power OK") last_log_time = current_time buzzer_line.set_value(0) last_power_state = state return state try: while True: print("******************") voltage = readVoltage(bus) capacity = readCapacity(bus) print(f"Voltage: {voltage:.2f}V") print(f"Battery: {capacity:.0f}%") # Log battery voltage and capacity at intervals if time.time() - last_log_time > LOG_INTERVAL: logging.info(f"Voltage: {voltage:.2f}V, Battery: {capacity:.0f}%") last_log_time = time.time() # Monitor power loss detection power_status = print_power_status() if capacity == 100: print("Battery FULL") if capacity < 20: print("Battery Low") # This condition ensures shutdown only if the battery is below 99% and the power is disconnected. # This means that if the power is connected, the server will not shut down. # Everyone should evaluate whether this is safe and adjust the condition if necessary. if voltage < 3.00 and power_status == 1: print("Battery LOW!!!") logging.critical("Battery LOW! Shutdown in 10 seconds") print("Shutdown in 10 seconds") time.sleep(10) out_line.set_value(1) time.sleep(3) out_line.set_value(0) time.sleep(2) except KeyboardInterrupt: print("Exiting...") finally: chip.close() === Automatické spuštění po restartu === Pro zajištění automatického spuštění skriptu po restartu použijeme **systemd service**, což je spolehlivý způsob, jak zajistit, že skript poběží na pozadí. == Vytvoření systemd služby == Otevřete terminál a vytvořte soubor pro službu: sudo nano /etc/systemd/system/x728-battery.service Do souboru vložte následující obsah a uložte: [Unit] Description=X728 Battery Monitor After=multi-user.target [Service] Type=simple ExecStart=/usr/bin/python3 /etc/local-scripts/x728-script/sample/x728-v2.x-asd-gpiod.py Restart=always User=root StandardOutput=append:/var/log/x728-battery.log StandardError=append:/var/log/x728-battery.log [Install] WantedBy=multi-user.target == Aktivace služby při startu == Načtěte systemd a povolte službu při startu: sudo systemctl daemon-reload sudo systemctl enable x728-battery.service == Okamžité spuštění služby == Pro okamžité spuštění služby spusťte: sudo systemctl start x728-battery.service == Kontrola stavu služby == Pro ověření, zda služba běží správně, použijte: sudo systemctl status x728-battery.service === Použití logrotate pro rotaci logů na Raspberry Pi === Na Raspberry Pi mi aplikace vytvořila nový logový soubor `/var/log/x728-battery.log`. Abych zajistil jeho pravidelnou rotaci a zabránil nadměrnému růstu, rozhodl jsem se použít **logrotate**. Tento nástroj už byl v systému nainstalován. == Jak přidat pravidlo do logrotate == Nejprve jsem vytvořil nový konfigurační soubor v `/etc/logrotate.d/`: sudo nano /etc/logrotate.d/x728-battery Do souboru jsem přidal následující konfiguraci: /var/log/x728-battery.log { weekly rotate 4 compress missingok notifempty create 644 root root postrotate systemctl restart x728-battery.service endscript } Bylo nutné přidat `postrotate` sekci, která restartuje službu `x728-battery.service`, protože jinak aplikace nepokračovala v logování do nového souboru. == Otestování konfigurace == Pro kontrolu, zda logrotate soubor správně rozpoznává, jsem spustil: sudo logrotate -d /etc/logrotate.d/x728-battery (Debug mód `-d` pouze zobrazí, co by se stalo, ale skutečně rotaci neprovede.) Pokud konfigurace neobsahovala chyby, provedl jsem ruční rotaci: sudo logrotate -f /etc/logrotate.d/x728-battery Po této úpravě se logy správně rotují a starší soubory jsou automaticky komprimovány a spravovány. === Nastavení a čtení RTC času === Tento návod popisuje kompletní nastavení a použití RTC (Real Time Clock) na UPS X728. UPS využívá RTC modul pro udržení přesného času i po odpojení napájení. Tento postup byl testován na **Raspberry Pi OS**. == Povolení RTC modulu == 1. Otevřete konfigurační soubor `/boot/config.txt` a přidejte na konec nebo pod sekci `[all]` tento řádek: sudo nano /boot/config.txt Přidejte: dtoverlay=i2c-rtc,ds1307 Uložte změny stisknutím **Ctrl+O**, potvrďte **Enter**, a ukončete editor **Ctrl+X**. 2. Restartujte Raspberry Pi: sudo reboot == Zakázání falešného hwclocku == Raspberry Pi OS obsahuje **fake-hwclock**, který simuluje RTC a může způsobovat problémy s reálným RTC modulem. Proto je nutné ho odstranit: sudo apt-get -y remove fake-hwclock sudo update-rc.d -f fake-hwclock remove sudo systemctl disable fake-hwclock == Úprava udev pravidel == Pro správné fungování RTC je třeba upravit soubor `/lib/udev/hwclock-set` a zakomentovat řádky 7-12: sudo nano /lib/udev/hwclock-set Najděte následující část kódu: #!/bin/sh # Reset the System Clock to UTC if the hardware clock from which it # was copied by the kernel was in localtime. dev=$1 #if [ -e /run/systemd/system ] ; then # exit 0 #fi # #/sbin/hwclock --rtc=$dev --systz #/sbin/hwclock --rtc=$dev --hctosys Každý řádek označený `#` je zakomentován a nebude se vykonávat. Uložte změny a ukončete editor. == Ověření a nastavení času == Po dokončení výše uvedených kroků restartujte Raspberry Pi: sudo reboot Po restartu můžete ověřit aktuální systémový čas: date Pokud je čas nesprávný, nastavte ho ručně: date -s "5 MAR 2019 13:00:00" Uložte nastavený čas do RTC: sudo hwclock -w Pro ověření času uloženého v RTC modulu použijte: sudo hwclock -r **Poznámka:** Ujistěte se, že jsou v UPS X728 vloženy baterie, aby se uložený čas zachoval i po vypnutí zařízení. Po dokončení tohoto postupu bude při každém startu Raspberry Pi čas automaticky synchronizován z RTC modulu. === Možné problémy a jejich řešení === Tato sekce popisuje možné problémy při používání UPS X728 a jejich řešení. Informace čerpám z oficiální dokumentace výrobce: [Zdroj: Geekworm Wiki - X728 FAQ](https://wiki.geekworm.com/X728#FAQ) __Problém: Zobrazuje se hláška „This power supply is not capable of supplying 5A“ na Raspberry Pi 5__ UPS X728/X729 má dostatečnou kapacitu pro napájení **5A**, nicméně je potřeba provést následující nastavení: **Krok 1: Úprava konfigurace napájení (povinné)** Otevřete terminál v Raspberry Pi OS a spusťte příkaz: sudo rpi-eeprom-config -e Na konec souboru přidejte následující řádek: PSU_MAX_CURRENT=5000 Uložte změny stisknutím **Ctrl+O**, potvrďte klávesou **Enter**, a ukončete editor stisknutím **Ctrl+X**. **Krok 2: Zvýšení proudového limitu USB (volitelné, pokud používáte USB zařízení s vyšší spotřebou)** Otevřete konfigurační soubor: sudo nano /boot/firmware/config.txt Přidejte tento řádek: usb_max_current_enable=1 Uložte změny a zavřete editor stejným způsobem jako v předchozím kroku. **Restartujte Raspberry Pi, aby se změny projevily:** sudo reboot **Poznámka:** Pokud používáte jiný operační systém (například Ubuntu), je nutné nejprve nahrát Raspberry Pi OS, provést výše uvedené úpravy a teprve poté znovu nahrát požadovaný operační systém. === Softwarové řízení nabíjení pomocí GPIO16 === Od verze **X728 v2.5** je možné **softwarově řídit nabíjení baterie** pomocí **GPIO16**. Tato funkce je určena pouze pro **pokročilé uživatele**, kteří mají zkušenosti s Linuxem. Pokud si nejste jisti, doporučuje se ponechat jumper "CHG Ctrl" zkratovaný, což umožní **automatické nabíjení** při připojení napájecího adaptéru. **Možnosti nastavení "CHG Ctrl" jumperu:** - **Jumper zkratovaný** → Baterie se **automaticky nabíjí**, pokud je připojen napájecí adaptér. - **Jumper otevřený** → Nabíjení lze **ovládat přes GPIO16**: - **GPIO16 = HIGH** → Nabíjení povoleno. - **GPIO16 = LOW** → Nabíjení zakázáno. == Ovládání nabíjení pomocí GPIO16 == Pro ruční ovládání nabíjení je nutné nejprve zjistit odpovídající GPIO pin: GPIO=16 # Zjištění skutečného čísla GPIO pinu GPIO=$(cat /sys/kernel/debug/gpio | grep "GPIO$GPIO" | awk -F'gpio-' '{print $2}' | awk -F' ' '{print $1}') echo "$GPIO" > /sys/class/gpio/export echo "out" > /sys/class/gpio/gpio$GPIO/direction **Povolení nabíjení:** echo "1" > /sys/class/gpio/gpio$GPIO/value **Zakázání nabíjení:** echo "0" > /sys/class/gpio/gpio$GPIO/value **Poznámka:** Nakonec jsem tuto funkci **nevyužil**, ale uvádím ji pro **kompletní dokumentaci**, pokud by bylo v budoucnu potřeba řídit nabíjení softwarově. ===== Konfigurace softwarového RAIDu – zrcadlení ===== Při konfiguraci jsem vycházel z těchto návodů, přičemž ani jeden není dokonalý pro moji situaci a musel jsem si návody přízpůsobit. Uvádím je pro úplnost jako zdroj: * https://github.com/robertalexa/rpi-raid1-root-partition/blob/main/README.md * https://www.jeffgeerling.com/blog/2020/building-fastest-raspberry-pi-nas-sata-raid * https://gist.github.com/leandrofilipe/f9636be272f97d414652ce1f21e6b1f4 ==== Adresace disků ==== Používám **Suptronics X1005 2280 M.2 NVMe Dual Shield** pro **Raspberry Pi 5**, který umožňuje připojení dvou disků. Na desce jsou viditelně označeny dva sloty: * **SSD1** * **SSD2** Při připojení jednoho disku do **SSD1**, systém jej rozpozná jako **nvme0n1**: lsblk NAME MAJ:MIN RM SIZE RO TYPE MOUNTPOINTS nvme0n1 259:0 0 1,8T 0 disk ├─nvme0n1p1 259:1 0 512M 0 part /boot/firmware └─nvme0n1p2 259:2 0 1,8T 0 part / Po připojení druhého disku do **SSD2** došlo k nečekanému přeskupení číslování disků. Systém nyní rozpoznává: * Disk připojený v **SSD2** jako **nvme0n1** * Disk připojený v **SSD1** jako **nvme1n1** Výstup příkazu `lsblk` po připojení druhého disku: lsblk NAME MAJ:MIN RM SIZE RO TYPE MOUNTPOINTS nvme0n1 259:0 0 1,8T 0 disk nvme1n1 259:1 0 1,8T 0 disk ├─nvme1n1p1 259:2 0 512M 0 part /boot/firmware └─nvme1n1p2 259:3 0 1,8T 0 part / Toto chování jsem nečekal, ale beru ho jako fakt a budu s ním dále pracovat obezřetně. Abych si ušetřil problémy a následné zmatky, tak jsem raději disky prohodil. Tedy disk s operačním systémem jsem dal do slotu SSD2 a nový disk do slotu SSD1. Po změně zapojení vypadá výpis takto: NAME MAJ:MIN RM SIZE RO TYPE MOUNTPOINTS nvme0n1 259:0 0 1,8T 0 disk ├─nvme0n1p1 259:1 0 512M 0 part /boot/firmware └─nvme0n1p2 259:2 0 1,8T 0 part / nvme1n1 259:3 0 1,8T 0 disk ==== Vytvoření partition na novém disku před RAIDem ==== Před vytvořením softwarového RAIDu je doporučeno **ručně vytvořit odpovídající partitiony na novém disku** (**nvme0n1**), aby odpovídaly rozdělení stávajícího disku (**nvme1n1**). RAID se obvykle vytváří nad existujícími partitionami, nikoliv nad celým diskem (i když je to možné, ale méně běžné). === Jak vytvořit partitiony přesně podle původního disku? === K tomu použijeme příkaz **sfdisk**, který umožňuje zkopírovat tabulku oddílů ze **nvme1n1** na **nvme0n1**. === Krok 1: Záloha stávající partition tabulky === Než cokoliv změníme, je vhodné **uložit stávající partition tabulku**, pokud by bylo potřeba ji obnovit: sudo sfdisk -d /dev/nvme0n1 > partition_backup.txt Tím se uloží rozložení oddílů do souboru **partition_backup.txt**, což umožní jejich případnou obnovu. === Krok 2: Zkopírování partition schématu na nový disk === Zkopíruj stejnou partition tabulku ze **nvme1n1** na **nvme0n1**: sudo sfdisk /dev/nvme1n1 < partition_backup.txt Tento příkaz vytvoří na **nvme1n1** stejnou strukturu jako na **nvme0n1**. === Krok 3: Ověření správnosti nového rozdělení disku === Po provedení předchozího příkazu je vhodné **ověřit, zda jsou partitiony nyní identické**: lsblk fdisk -l /dev/nvme1n1 Pokud se vše shoduje, můžeme pokračovat v nastavování RAIDu. ==== Konfigurace RAID 1 pomocí mdadm ==== Pro konfiguraci softwarového RAIDu pro zrcadlení (RAID 1) použijeme **mdadm**. Nejprve nainstalujeme potřebný balíček: sudo apt install mdadm Vzhledem k tomu, že RAID nastavujeme na běžícím systému, vytvoříme RAID **v degradovaném režimu**, tedy pouze s jedním diskem. Druhý disk přidáme později. === Vytvoření RAID 1 v degradovaném režimu === Místo dvou disků v RAIDu vytvoříme pole pouze s novým diskem (**nvme1n1p1** a **nvme1n1p2**). Druhý disk zatím nebude připojen (`missing`), což RAID umožňuje: sudo mdadm --create --verbose /dev/md0 --level=1 --raid-devices=2 /dev/nvme1n1p1 missing --metadata=0.90 sudo mdadm --create --verbose /dev/md1 --level=1 --raid-devices=2 /dev/nvme1n1p2 missing ✅ **Vysvětlení:** * `missing` znamená, že druhý disk zatím není připojen, RAID poběží pouze s jedním diskem. * `--metadata=0.90` je doporučeno pro zaváděcí oddíly. Následujícím krokem je vytvoření souborového systému na nově vytvořeném RAIDu. === Vytvoření souborových systémů === Na nových RAID oddílech vytvoříme souborový systém: sudo mkfs.vfat /dev/md0 sudo mkfs.ext4 /dev/md1 Nyní připojíme RAID a přeneseme systémové soubory. === Přenos systémových souborů na RAID === Nejprve připojíme bootovací oddíl RAID: mkdir /mnt/raid_boot mount /dev/md0 /mnt/raid_boot rsync -axv /boot/firmware/ /mnt/raid_boot/ Poté připojíme hlavní oddíl a přeneseme systém: mkdir /mnt/raid_root mount /dev/md1 /mnt/raid_root rsync -axv / /mnt/raid_root --exclude=/mnt --exclude=/proc --exclude=/sys --exclude=/dev --exclude=/run --exclude=/tmp === Úprava fstab pro použití RAIDu === Otevřeme soubor **fstab** na novém RAIDu: nano /mnt/raid_root/etc/fstab Najdeme řádky obsahující `/dev/nvme0n1p1` a `/dev/nvme0n1p2` a upravíme je: /dev/md0 /boot/firmware vfat defaults 0 2 /dev/md1 / ext4 defaults,noatime,errors=remount-ro 0 1 Tím zajistíme, že systém při bootu použije RAID. === Aktualizace konfigurace mdadm === Zjistíme UUID RAID polí: mdadm --detail --scan Výstup bude podobný tomuto: ARRAY /dev/md0 metadata=0.90 UUID=e11e72e6:cfe13794:c15f4f5c:b4c7de4f ARRAY /dev/md1 metadata=1.2 name=server:1 UUID=6af6a5bd:b7fd9bcc:2cd91b19:bf09e0c3 Tento výstup zapíšeme na konec souboru: nano /mnt/raid_root/etc/mdadm/mdadm.conf === Úprava cmdline.txt pro bootování z RAIDu === Otevřeme soubor bootovací konfigurace: nano /mnt/raid_boot/cmdline.txt Najdeme řádek obsahující: root=PARTUUID=aa235387-02 A nahradíme jej: root=/dev/md1 rootfstype=ext4 fsck.repair=yes rootwait rootdelay=10 cfg80211.ieee80211_regdom=CZ ✅ **Vysvětlení:** * `root=/dev/md1` – říká jádru, že root filesystem je na RAIDu. * `rootwait rootdelay=10` – umožňuje systému počkat na sestavení RAIDu. * `fsck.repair=yes` – umožní automatickou opravu souborového systému při bootu. === Přidání RAID modulů do initramfs === Aby jádro vědělo, že používáme RAID již při bootu, přidáme moduly do **initramfs**: nano /mnt/raid_root/etc/initramfs-tools/modules Přidáme tyto řádky: raid1 md_mod ext4 Aktualizujeme initramfs: umount /mnt/raid_boot mount /dev/md0 /mnt/raid_root/boot/firmware/ mkdir -p /mnt/raid_root/dev /mnt/raid_root/proc /mnt/raid_root/sys /mnt/raid_root/run mount --bind /dev /mnt/raid_root/dev mount --bind /proc /mnt/raid_root/proc mount --bind /sys /mnt/raid_root/sys mount --bind /run /mnt/raid_root/run chroot /mnt/raid_root update-initramfs -u Tím jsme zajistili, že RAID bude dostupný již při startu systému. **Nyní jsem mohl Raspberry restartovat. Důležitá věc, musel jsem primární disk - tedy disk s RAID přesunout do slotu SSD2 na desce. Dokud jsem to neudělal, boot se nepodařil, systém byl zmatený. Tento krok je klíčový - prohodit disky ve slotech.** ==== Přidání disku do RAID ==== Po prohození disků ve slotech (disk s nastaveným RAIDem musí být ve slotu **SSD2**) a nabootování systému je možné přidat druhý disk zpět do RAID pole. Stejný postup se použije i v případě, že se nějaký disk odpojí a pole je **degradované**, tedy běží pouze s jedním diskem. ✅ **Klíčové pravidlo:** **Primární disk musí být ve slotu SSD2, aby systém správně nabootoval.** === Stav RAID pole po nabootování === Z výpisu je vidět, že v RAID poli je zatím pouze jeden disk: cat /proc/mdstat **Výstup:** Personalities : [raid1] [linear] [raid0] [raid6] [raid5] [raid4] [raid10] md0 : active raid1 nvme0n1p1[0] 524224 blocks [2/1] [U_] md1 : active raid1 nvme0n1p2[0] 1952854080 blocks super 1.2 [2/1] [U_] bitmap: 4/4 pages [64KB], 65536KB chunk Nově připojený disk **nvme1n1** zatím není součástí RAID pole. === Výpis připojených disků === Podíváme se na aktuální stav připojených disků: lsblk **Výstup:** NAME MAJ:MIN RM SIZE RO TYPE MOUNTPOINTS nvme0n1 259:0 0 1,8T 0 disk ├─nvme0n1p1 259:1 0 512M 0 part │ └─md0 9:0 0 511,9M 0 raid1 /boot/firmware └─nvme0n1p2 259:2 0 1,8T 0 part └─md1 9:1 0 1,8T 0 raid1 / nvme1n1 259:3 0 1,8T 0 disk ├─nvme1n1p1 259:4 0 512M 0 part └─nvme1n1p2 259:5 0 1,8T 0 part === Detaily RAID pole === Zkontrolujeme aktuální stav RAID pole: mdadm --detail /dev/md0 /dev/md0: Version : 0.90 Creation Time : Sat Feb 15 16:52:29 2025 Raid Level : raid1 Array Size : 524224 (511.94 MiB 536.81 MB) Used Dev Size : 524224 (511.94 MiB 536.81 MB) Raid Devices : 2 Total Devices : 1 Persistence : Superblock is persistent Update Time : Sat Feb 15 19:15:46 2025 State : clean, degraded Active Devices : 1 Working Devices : 1 Failed Devices : 0 Spare Devices : 0 Consistency Policy : resync Number Major Minor RaidDevice State 0 259 1 0 active sync /dev/nvme0n1p1 - 0 0 1 removed Stejným způsobem můžeme zkontrolovat i hlavní RAID oddíl: mdadm --detail /dev/md1 **Výstup ukazuje, že RAID pole je degradované – chybí druhý disk.** === Přidání nového disku do RAID pole === Nyní přidáme nový disk **nvme1n1** do RAID pole: mdadm --add /dev/md0 /dev/nvme1n1p1 mdadm --add /dev/md1 /dev/nvme1n1p2 Po přidání zkontrolujeme stav RAIDu: cat /proc/mdstat **Výstup ukazuje, že RAID začíná synchronizaci:** Personalities : [raid1] [linear] [raid0] [raid6] [raid5] [raid4] [raid10] md0 : active raid1 nvme1n1p1[1] nvme0n1p1[0] 524224 blocks [2/2] [UU] md1 : active raid1 nvme1n1p2[2] nvme0n1p2[0] 1952854080 blocks super 1.2 [2/1] [U_] [=>...................] recovery = 5.3% (104572928/1952854080) finish=149.1min speed=206517K/sec bitmap: 4/4 pages [64KB], 65536KB chunk === Sledování průběhu synchronizace === Pro sledování průběhu synchronizace RAID pole můžeme použít: watch -n 1 cat /proc/mdstat ✅ **RAID nyní probíhá synchronizace a disk bude plně zrcadlen po dokončení procesu.** === Priorita disků po odpojení a opětovném připojení === Pokud dojde k **odpojení jednoho disku** a následně jej znovu připojíme, systém rozhodne, **který disk bude v RAIDu upřednostněn**, a to na základě několika faktorů. Nezáleží na tom, **že je disk ve slotu SSD2**, protože po připojení obou disků systém automaticky **vybere ten, který běžel jako poslední aktivní po rozpojení RAIDu**. === Jak systém určuje, který disk bude upřednostněn? === Systém rozhoduje na základě **poslední aktualizace metadat RAIDu**. Každý disk v RAIDu obsahuje **metadata (superblock)**, která uchovávají informace o změnách v poli. **Klíčový parametr je tzv. Event Count**, což je čítač změn. ✅ **RAID vybere disk s nejvyšším Event Count jako platný.** Pokud má jeden disk vyšší Event Count než druhý, systém považuje tento disk za aktuální a použije jej jako primární. === Jak zjistit, který disk má vyšší Event Count? === Můžeš si ověřit, který disk má aktuálnější metadata pomocí příkazu: mdadm --examine /dev/nvme0n1p2 /dev/nvme1n1p2 **Výstup bude obsahovat řádky podobné tomuto:** /dev/nvme0n1p2: Events : 405 /dev/nvme1n1p2: Events : 392 ✅ **Disk s vyšším číslem „Events“ je považován za aktuální.** Pokud se **Event Count neshoduje**, mdadm automaticky označí **starší disk jako neaktuální** a vyřadí ho z RAID pole. === Co se stane při neaktuálním disku? === Pokud má jeden z disků nižší Event Count, systém jej při dalším spuštění považuje za **zastaralý** a označí jej jako neaktivní. RAID pak při připojení tohoto disku provede **resynchronizaci** dat. Proto je důležité po výpadku disku **zkontrolovat stav RAID