Proxmox memoárok: AdGuard Home és Unbound költöztetés

Proxmox memoárokFolytatom a "saját" bejegyzések generálását. A jegyzettömbél jobb és hátha másnak is segít...

Ramdisk: OpenWRT és AGH

Rövid kitérő az Openwrt-re is, tényleg csak pár mondatban. Nemrég váltottam le az Opnsense tűzfalat OpenWRT-re. Más a két rendszer, itthonra az Opnsense overkill és az OpenWRT Smart Queue Management-re szükségem van a mobilnet miatt. Nem elhanyagolható, hogy az OpenWRT minimális erőforrásal beéri. Mérete is szerény, alap telepítéssel 124 MB és még frissíteni is tudja a csomagokat.
OK, a Tailscale elsőre megakadt a torkán a 65 MB-os "ápgréddel" (erre is van több megoldás, de nem térek el a témától...ugye?).

Proxmoxon a korábbi cikkben leírt módon hozzunk létre egy Immutable (nem módosítható) mappát:
mkdir /mnt/ramdisk
chmod 777 /mnt/ramdisk/
chown nobody:nogroup /mnt/ramdisk/
chattr +i /mnt/ramdisk/
lsattr -d /mnt/ramdisk/

----i---------e------- /mnt/ramdisk/ - ha ezt látjuk, akkor jó.

A mappa alap esetben nem írható, csak akkor, ha csatolunk bele valamit (ami írható...).
Ehhez az FSTAB-ot használjuk:
nano /etc/fstab
A végére ugráljunk le és szúrjuk be ezt a két sort:
# RAMDISK
tmpfs /mnt/ramdisk tmpfs defaults,noatime,nosuid,nodev,size=500M 0 0

Hirdetés

Kb. ez az egyetlen rész a jelen írásban, ahol maradandó kárt tudunk tenni a rendszerünkben,
ezért itt az "egysoros" parancs, ami az fstab végére bepattintja a ramdisk-et:
echo -e "\n# RAMDISK\ntmpfs /mnt/ramdisk tmpfs defaults,noatime,nosuid,nodev,size=500M 0 0" | sudo tee -a /etc/fstab

Mentés és systemctl daemon-reload kell, hogy a PVE lássa is a módosítást, majd egy mount -a parancs és elvileg kész is a ramdisk, teszteljük:
mkdir /mnt/ramdisk/teszt
cd /mnt/ramdisk/teszt

Ez létrehozott egy mappát a ramdisken. Ha nem volt hiba és mindent jól csináltunk,
akkor törölhetjük a teszt mappánkat:
cd /root
rm -r /mnt/ramdisk/teszt

Mindjárt itt a vége, még pár ezer parancs és kész, nyugi!
A következő hőstett a Proxmox webUI-n a Datacenter, storage menüben lesz:

Add directory a lenyílóban és adjuk meg a ramdisk mappa elérését (/mnt/ramdisk), adjunk neki valami fancy nevet, lehet pl. ramdisk. A content (tartalom) résznél válasszuk ki a disk image-t és container-t. Kész.

Ugorjunk vissza a node-ra (PVE nálam), jelöljük ki az LXC-t és állítsuk le. A resources résznél kattintsunk
a root disk-re, ami a konténerünk "merevlemeze". Felette így aktív lesz a volume action legördülő menü, amiben válasszuk a move storage (tároló átmozgatása) lehetőséget:

Innen már egyenes az út, target storage a ramdisk, delete source (forrás törlése) jelölőbe egy pipa és kész. Indulhat az LXC, most már a ramdiskről. Az OpenWRT esetében is hasonló az eljárás, annyi eltéréssel,
hogy itt volume action helyett disk action a fenti menüpont neve. Kész...

Majdnem kész... :) A ramdisknek hátránya, hogy ha a gép leáll, akkor a tartalma az hussss... és annyi. Ha az (áram) hálózat nem stabil, akkor UPS ajánlott (igazán minden PC-nél az...). A változások is a ramdiskbe mentődnek, pl. ha frissítjük az openWRT-t, egy Proxmox reboot után ismét frissítenünk kellene...

Ezért a rendszeres mentések mellett kell egy mentés a Proxmox leállításakor is. Másik probléma a boot: a ramdisk létrejön, csatolja és... üres. Erre is kell egy script, ami helyreállítja a legfrissebb mentést a ramdisk-re és elindítja azt.

Claude és Qwen3 AI-al készítettük el, az adatokat és a feltételeket én adtam, a két scriptet és a két systemd service-t "cross reference" és "Peer Review Loop" a két AI legózta össze.

Ha pontosan megadjuk mi a terv, mi és hol található, akkor hibátlanul megírja az ilyen és hasonló scripteket bármelyik AI. Legalábbis azt hiszi mindegyik. De amint másik AI-al is összevetjük, kiderülnek apró hibák, amik jó esetben csak ezt a scriptet kaszálják el. Ezért érdemes másod vagy akár harmad véleményt is kérni. CGPT (free) itt is elhasalt, Gemini gondolkodót is inkább nem script jellegű feladatra tartom jobbnak.

Sokat próbálgattuk a "szabványos" utat: leálláskor VM/LXC stop, backup. Induláskor legutolsó mentést megkeres, helyreállít... Nehézkes. A leállásnál már sok szolgáltatást lelő a PVE, mire a mentést kezdené.
A szabályos mentés is viszonylag sok idő, a kis méret ellenére.

Ezért inkább csalunk. ;)
Leállításkor -a lehető legkorábban- a ramdisken lévő VM/LXC megállítjuk, rsync egy SSD-re és ennyi. A visszatöltése is sokkal egyszerűbb, gyorsabb. A lényeg, hogy még az előtt a helyükre kerüljenek a mappák és a lemezek, mielőtt a PVE a guest rendszereket indítaná.

Első, hogy Proxmox újraindításakor a legfrissebb mentéseket töltse a ramdiskbe.
nano /usr/local/bin/ramdisk-restore.sh
Ez egy új file, másoljuk bele ezt (Neked át kellhet írni itt-ott természetesen, ha mások voltak a csatolási pontok vagy a VM ID-k):

#!/bin/bash
export PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin

RAMDISK="/mnt/ramdisk/images"
CACHE_DIR="/mnt/ssd/ramdisk_cache"
LOG="/root/ramdisk.log"
ERR="/root/ramdisk.error.log"

log() {
local msg="[$(date '+%Y-%m-%d %H:%M:%S')] RESTORE: $*"
echo "$msg" >> "$LOG"
}
err() {
local msg="[$(date '+%Y-%m-%d %H:%M:%S')] ERROR: $*"
echo "$msg" >> "$ERR"
echo "$msg" >> "$LOG"
}

log "=== Visszaállítás indítása (Boot) ==="

# 1. Mount ellenőrzés
for mnt in "/mnt/ssd" "/mnt/ramdisk"; do
if ! mountpoint -q "$mnt"; then
err "$mnt nincs csatolva. Kilépés."
exit 1
fi
done

# Storage aktiválás ha szükséges
if ! pvesm status 2>/dev/null | grep -q "^ramdisk"; then
log "Ramdisk storage aktiválása..."
pvesm set ramdisk --disable 0 >> "$LOG" 2>> "$ERR"
fi

# 2. Ramdisk célmappa biztosítása
mkdir -p "$RAMDISK"

# 3. Adatok visszatöltése az SSD-ről
if [ -d "$CACHE_DIR" ] && [ "$(ls -A "$CACHE_DIR" 2>/dev/null)" ]; then
log "Gyorsítótár megtalálva, visszatöltés..."
if rsync -a --sparse "$CACHE_DIR/" "$RAMDISK/" >> "$LOG" 2>> "$ERR"; then
log "Adatok visszamásolva a RAM-ba."
else
err "Rsync SIKERTELEN."
exit 1
fi
else
err "Nincs adat az SSD gyorsítótárban ($CACHE_DIR) – első indítás?"
exit 1
fi

log "=== Visszaállítás kész, pve-guests indítja a guest-eket ==="

A script ellenőrzi, hogy az fstab csatolások létrejöttek-e, illetve ha nem aktív a tárhely, akkor bekapcsolja. Ezután az rsync mentéseket megkeresi, ha talál, akkor helyreállítja a ramdisk-re.

Fontos, hogy hiba esetén ne akadjon fel a rendszer, ezért a legrosszabb esetben csak kilép, helyreállítás nélkül. Ilyenkor manuálisan kell beavatkozni, pl. ha nem jött létre a ramdisk, akkor másik tárolóra kell helyreállítani. Igen, lehetett volna benne fallback restore az NVME tárhelyre is, de ehhhh... ne bonyolítsuk.
Ha nincs ramdisk, vagy más okból nem áll helyre, akkor ott mindenképp log olvasás lesz a vége. Ebben segít a root könyvtárba mentett ramdisk.log és a ramdisk.error.log fájl, nem kell journal-t is olvasgatni (jó esetben).

Ilyen kritikus hibánál érdemes a Proxmox által mentett VM-et és LXC-t visszaállítani inkább. Nálam napi VM+LXC mentés van, minden hajnalban (ajánlom másnak is). Ezért ha valami nem sikerül, akkor a helyreállítással maximum az aznapi frissítések és módosítások vesznek el. Egyik sem kritikus, frissítéseket leszedik újra, módosítani jó esetben ritkán kell a router beállításokon. Praktikus tanács, hogy nagyobb "beavatkozás" előtt és után is mentsük. És ennek semmi köze a ramdiskhez, csak hasznos szokás.

A következő script a Proxmox leállításakor menti a ramdiskből a virtuális gépek "merevlemezét". Itt is fontos, hogy ne legyen blokkoló hatása a leállításra. Nézzünk egy "worst case"-t: nem ment és a ramunk huss... Induláskor így egy korábbi lemez másolatot találhat, ami nem biztos, hogy friss*.

Másik lehetőség, hogy a VM/LXC nem áll le. A mentés ilyenkor is lefut, de lehet, hogy "dirty state" lesz a lemez eredménye. Ebből 99%-ban helyreáll és nem probléma, a fennmaradó 1%-ra ott a Proxmox napi mentés. A scriptbe nem került semmi ennek a kezelésére (pedig ötleteim vannak :) ), mert még nem fordult elő a már kb. két hetes használat alatt.

###
*Erre is van megoldás (opcionális, kihagyható): crontab és egy script, ami hajnalban a PVE által vezényelt snapshot előtt leállítja a ramdiskben futó gépeket, menti a ramdisket és újraindítja a gépeket. A holtidő kb egy perc, de ezzel akkor is lesz egy viszonylag friss mentés a ramdisk mentésekben, ha a leállításkor a mentés nem jön össze. Email értesítőt is be lehet állítani, ha sikertelen, akkor időben tudunk róla és lehet intézkedni.
Proxmox konzolba be és először az időzítést adjuk meg:
crontab -e
Majd a végére szúrjuk be (lentebb van ebből egy másik verzió is):
# RAMDISK napi mentése
30 3 * * * /usr/local/bin/ramdisk-daily.sh
Mentés. Ezzel minden hajnalban 3.30-kor végrehajt egy mentést.
Hozzuk is létre a scriptet:
nano /usr/local/bin/ramdisk-daily.sh
Új file, könnyű dolgunk lesz, mert csak meghívjuk a scriptet, ami leállításkor futna. Ha az végzett, akkor indítja őket és kész.
#!/bin/bash
# ramdisk-daily.sh
/usr/local/bin/ramdisk-backup.sh
# Ha a backup sikeres volt, indítjuk a gépeket
if [ $? -eq 0 ]; then
qm start 121 && log "VM 121 újraindítva."
pct start 113 && log "LXC 113 újraindítva."
else
log "Backup sikertelen, gépek nem indulnak."
fi

A fenti verzió csak log-ot ment. Az alábbi levelet is küld az eredményről. A gépek indítása után vár kicsit és pingel. Ha a ping nem hibával tér vissza, akkor elküldi a mail-t. Ha nincs net és lejár a próbálkozások száma, akkor log-ba írja a bánatát. Lehet a sleep nem a legprofibb, de itt jól működik.
#!/bin/bash
export PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
LOG="/root/ramdisk.log"
DAILY_LOG="/root/ramdisk-daily.log"
ERR="/root/ramdisk.error.log"
MAIL_STATUS="Sikeres"
log() {
local msg="[$(date '+%Y-%m-%d %H:%M:%S')] DAILY: $*"
echo "$msg" >> "$DAILY_LOG"
}
err() {
local msg="[$(date '+%Y-%m-%d %H:%M:%S')] ERROR: $*"
echo "$msg" >> "$ERR"
echo "$msg" >> "$DAILY_LOG"
MAIL_STATUS="SIKERTELEN"
}
log "=== Napi sync indítása ==="
# 1. Backup futtatása
/usr/local/bin/ramdisk-backup.sh
if [ $? -eq 0 ]; then
# 2. VM 121 indítása
log "VM 121 indítása..."
if qm start 121; then
log "VM 121 fut."
else
err "VM 121 indítása sikertelen."
fi
# 3. LXC 113 indítása
log "LXC 113 indítása..."
if pct start 113; then
log "LXC 113 fut."
else
err "LXC 113 indítása sikertelen."
fi
else
err "Backup sikertelen, gépek nem indulnak."
fi
log "=== Napi sync kész ==="
# 4. Várakozás hálózatra
log "Várakozás hálózatra..."
sleep 5
NETWORK=0
for i in $(seq 1 12); do
ping -c1 -W2 8.8.8.8 >/dev/null 2>&1 && NETWORK=1 && break
sleep 5
done
# 5. Email küldés
if [ "$NETWORK" -eq 0 ]; then
log "Hálózat nem érhető el, email nem küldhető."
else
mail_body="Ramdisk napi sync: ${MAIL_STATUS}
--- Log ---
$(tail -n 15 "$LOG")"
echo -e "Subject: Ramdisk napi sync: ${MAIL_STATUS}\n\n${mail_body}" | /usr/libexec/proxmox-mail-forward
log "Email elküldve."
fi

###

Jöjjön a lemezeket mentő script:
nano /usr/local/bin/ramdisk-backup.sh

Ez is új, másoljuk bele:
#!/bin/bash
export PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin

RAMDISK="/mnt/ramdisk/images"
CACHE_DIR="/mnt/ssd/ramdisk_cache"
LOG="/root/ramdisk.log"
ERR="/root/ramdisk.error.log"

log() {
local msg="[$(date '+%Y-%m-%d %H:%M:%S')] SAVE: $*"
echo "$msg" >> "$LOG"
}
err() {
local msg="[$(date '+%Y-%m-%d %H:%M:%S')] ERROR: $*"
echo "$msg" >> "$ERR"
echo "$msg" >> "$LOG"
}

log "=== Mentés indítása (Leállás) ==="

# 1. Szabad hely ellenőrzése az SSD-n (min. 2GB)
FREE_SSD=$(df -m /mnt/ssd | awk 'NR==2 {print $4}')
if [ "$FREE_SSD" -lt 2048 ]; then
err "Kevés a hely az SSD-n ($FREE_SSD MB). Mentés megszakítva!"
exit 1
fi

# 2. Vendéggépek leállítása (konzisztens fájlrendszer miatt)
log "VM 121 leállítása..."
if qm stop 121 --timeout 40; then
log "VM 121 leállt."
else
err "VM 121 leállítása sikertelen – rsync így is fut (dirty state)."
fi

log "LXC 113 leállítása..."
# pct stop nem támogatja a --timeout opciót, a timeout paranccsal oldjuk meg
if timeout 40 pct stop 113; then
log "LXC 113 leállt."
else
err "LXC 113 leállítása sikertelen – rsync így is fut (dirty state)."
fi

# 3. Célmappa létrehozása, ha még nem létezne
mkdir -p "$CACHE_DIR"

# 4. Adatok szinkronizálása
log "Rsync indítása: $RAMDISK -> $CACHE_DIR"
if rsync -a --sparse --delete "$RAMDISK/" "$CACHE_DIR/" >> "$LOG" 2>> "$ERR"; then
log "=== Mentés sikeresen befejeződött ==="
else
err "=== Rsync SIKERTELEN ==="
exit 1
fi

Már csak a systemd-nek kell megmondani, hogy a scripteket futtassa:
nano /etc/systemd/system/ramdisk-restore.service
Ez lesz a tartalma:
[Unit]
Description=Ramdisk restore - LXC 113 és VM 121
After=local-fs.target pve-cluster.service pvedaemon.service
Requires=pve-cluster.service pvedaemon.service
Before=pve-guests.service
[Service]
Type=oneshot
RemainAfterExit=yes
ExecStart=/usr/local/bin/ramdisk-restore.sh
[Install]
WantedBy=multi-user.target

A service a fenti helyreállító scriptet indítja el, miután a csatolások létrejöttek, de mielőtt a Proxmox elkezdené a "start at boot - yes" (Proxmox indulásakor elindítandó) jelölésű VM-eket és LXC-ket indítani. Mivel az AGH és az OpenWRT a hálózat alapja, nem lenne szerencsés őket pl. a NAS után indítani. A Home Assistant meg olyan, mint én: nem túl boldog, ha ébredéskor nincs net...

Még egy service kell a mentésnek is... mindjárt vége...
nano /etc/systemd/system/ramdisk-backup.service
Ez lesz a tartalma:
[Unit]
Description=Ramdisk backup - LXC 113 és VM 121
DefaultDependencies=no
# Leálláskor a systemd megfordítja a sorrendet:
# Előbb leállítja ezt a service-t (ExecStop), és CSAK UTÁNA a listában lévőket.
After=local-fs.target pve-cluster.service pvedaemon.service pve-guests.service
# Biztosítjuk, hogy a tényleges kikapcsolás előtt végezzen
Before=umount.target shutdown.target reboot.target halt.target

[Service]
Type=oneshot
# Indításkor nem csinál semmit, csak "él"
ExecStart=/bin/true
# Itt történik a varázslat leálláskor
ExecStop=/usr/local/bin/ramdisk-backup.sh
# Ez a kulcs: a service "aktív" marad az indítás után
RemainAfterExit=yes
# Adjunk elég időt a mentésnek (5 perc)
TimeoutStopSec=300

[Install]
# Normál indításkor aktiválódjon
WantedBy=multi-user.target

Itt van egy kis timeout (várakozás). Érdemes tesztelni, hogy kb. hány másodperc a VM + LXC leállítás és a backup, azt az időt kicsit megnövelni és beírni timeout-nak. Ez amolyan "legrosszabb eset" jelenleg, még nem finomítgattam rajta. A service sorrendet itt is Claude és Qwen3 rakta össze közösen, mert nem mindegy, hogy mikor fut a script: pl. ha a mentésre használt tárhelyünk csatolása eltűnik, akkor nincs mentés és hasonló finomságok történhetnek.

Az új service-nek jogokat is kell adnunk és a futtatásukat engedélyezni kell:
chmod +x /usr/local/bin/ramdisk-restore.sh
chmod +x /usr/local/bin/ramdisk-daily.sh
chmod +x /usr/local/bin/ramdisk-backup.sh
systemctl daemon-reload
systemctl enable ramdisk-restore.service
systemctl enable ramdisk-backup.service

Teszteljük a napi mentést (vigyázat, a ramdiskben a gépeket leállíja!):
bash -x /usr/local/bin/ramdisk-daily.sh

Ha csak visszatölteni szeretnénk a ramdiskbe:
bash -x /usr/local/bin/ramdisk-restore.sh

Ha valamit később módosítunk, akkor újra kell tölteni a service-okat, hogy érvénybe lépjenek a módosítások:
systemctl daemon-reload && systemctl enable --now ramdisk-restore.service
systemctl daemon-reload && systemctl enable --now ramdisk-backup.service

Probléma esetén a /root könyvtárban vannak a logok, illetve a
journalctl -u ramdisk-restore.service -n 50 vagy journalctl -u ramdisk-backup.service -n 50
lehet az első diagnosztikai lépés. Ehhez kapcsolódik a logrotate: ha nem állítjuk be, akkor a log fájlunk csak növekszik... nem jó.
nano /etc/logrotate.d/ramdisk
Az utolsó három log elég szerintem, mail is jön, nem fogjuk nézegetni, ha nincs baj:
/root/ramdisk.log
/root/ramdisk-daily.log
/root/ramdisk.error.log {
daily
rotate 3
compress
missingok
notifempty
}

Mentés, bezárás. Innen a rendszer intézi már.

Azt hiszem ennyi volt. :)

A cikk még nem ért véget, kérlek, lapozz!