10 KiB
NenjimHub: Alpine, valgfri rå swap og OpenZFS
Designet bruger en klassisk MBR-partitionstabel:
- partition 1: FAT32 til Alpine diskless, APKoVL og APK-cache
- partition 2: valgfri rå Linux-swap
- partition 3: resten af kortet som OpenZFS-poolen
rpool
ZFS er altid partition 3. Hvis den rå swapstørrelse er 0, oprettes partition
2 ikke; partitionsnummer 2 står blot tomt. Det gør layoutet entydigt for alle
profiler.
flash.sh skriver kun til partition 1. Partition 2 og 3 ændres ikke, så en
senere Alpine-opdatering ikke overskriver swap eller ZFS-data.
Filer i samme mappe
alpine-rpi-3.24.1-aarch64.img
flash.sh
headless.apkovl.tar.gz
installZeroTier.sh
NenjimHub.conf
prepare-storage.sh
unattended.sh
wpa_supplicant.conf
zerotier-one-1.16.2-linux-musl-aarch64-sso0 # valgfri
zulu25.36.205-ca-jre25.0.4.1-linux_musl_aarch64.tar.gz
prepare-storage.sh downloader som udgangspunkt det officielle statiske
zrepl-linux-arm64-program fra zrepl v0.7.0 og kontrollerer SHA-256-værdien fra
GitHub. Det kan i stedet placeres lokalt ved siden af scriptet med navnet
zrepl-linux-arm64.
Fælles konfiguration
Ret kun NenjimHub.conf; både prepare-storage.sh, flash.sh og første boot
bruger den samme fil. DEVICE skal være hele SD-kortet, eksempelvis /dev/sdc,
og aldrig en partition som /dev/sdc1.
Standardprofilen til Raspberry Pi Zero 2W er:
DEVICE="/dev/sdc"
NENJIMHUB_HOSTNAME="alpine-nenjim"
CONSOLE_KEYMAP_LAYOUT="dk"
CONSOLE_KEYMAP_VARIANT="dk"
SYSTEM_LOCALE="C.UTF-8"
VIRT_ZVOL_SIZE_MIB="4096"
SWAP_SIZE_MIB_PART="2048"
SWAP_SIZE_MIB_ZFS="0"
SWAP_SIZE_PCT_ZRAM="25"
SWAP_PRI_ZRAM="300"
SWAP_PRI_ZFS="200"
SWAP_PRI_PART="100"
ZEROTIER_ENABLE_SSO="0"
ZEROTIER_VERSION="1.16.2"
Sæt NENJIMHUB_HOSTNAME til et unikt navn for hvert apparat, eksempelvis
nenjimhub-01. Værdien må være ét hostname-led på 1-63 bogstaver, tal eller
bindestreger og må ikke begynde eller slutte med en bindestreg.
CONSOLE_KEYMAP_LAYOUT="dk" og CONSOLE_KEYMAP_VARIANT="dk" vælger det
almindelige danske PC-tastatur på Linux-konsollen. Første boot kontrollerer
keymap-navnet før setup-alpine, så en stavefejl stopper med en tydelig fejl i
stedet for at åbne en interaktiv menu.
SYSTEM_LOCALE="C.UTF-8" giver et neutralt UTF-8-loginmiljø uden at vælge
engelske eller danske dato- og talformater. Installationen aktiverer samtidig
Unicode på Linux-konsollen.
En swaptype slås fra ved at sætte dens størrelse eller procent til 0.
Prioritet 0 er derimod en gyldig Linux-swapprioritet og slår ikke noget fra.
PC'en skal have OpenZFS 2.4.3, ZFS-kernemodulet indlæst, FAT/ext4-værktøjer, Python 3 og enten Podman eller Docker. Minimumskapaciteten beregnes ud fra konfigurationen; standardprofilen er beregnet til et SD-kort solgt som 16 GB.
Trin 1: klargør hele kortet
sudo ./prepare-storage.sh
Dette trin sletter hele SD-kortet. Det opretter de valgte partitioner,
rpool, datasets rpool/home, rpool/software og rpool/sysop samt det
ext4-formaterede zvol rpool/virt. Java og zrepl lægges på
rpool/software.
Størrelsen på rpool/virt styres særskilt af VIRT_ZVOL_SIZE_MIB; den har
ingen forbindelse til ZFS-swapstørrelsen.
Trin 2: installer eller opdater Alpine
sudo ./flash.sh
Dette trin erstatter kun partition 1. Det bygger på PC'en en matchende Alpine
Raspberry Pi-kernel/modloop med zfs-rpi og lægger first-boot-filerne ind.
Som sikkerhed skal du skrive NENJIMHUB, når scriptet beder om bekræftelse.
Scriptet gemmer også PC'ens aktuelle UTC-tid på kortet, så Pi'en uden RTC kan
validere HTTPS-certifikater, inden netværkstiden er synkroniseret. Vent på
slutteksten Alpine partition 1 is ready.
Ved en senere Alpine-opdatering køres kun trin 2. flash.sh bevarer /sysop
fra det gamle APKoVL, mens alle ZFS-data ligger urørt på partition 3.
Første boot
Pi'en gør følgende automatisk:
- aktiverer den rå swap-partition, hvis den er konfigureret
- aktiverer midlertidig ZRAM til installationen, hvis ZRAM er konfigureret
- importerer
rpoolfra partition 3 - opretter og aktiverer
rpool/swap, hvis dens størrelse er større end0 - installerer pakker og genbruger en prekompileret ZeroTier-binærfil eller bygger ZeroTier med ét compile-job, hvis filen ikke findes
- skriver den endelige ZRAM-størrelse, opretter APKoVL og genstarter
rpool/swap oprettes på Pi'en, så volblocksize kan følge den faktiske værdi
fra getconf PAGESIZE. ZeroTier-kontrollen summerer al aktiv swap; den er ikke
afhængig af, om pladsen kommer fra partition, ZRAM eller ZFS.
På Pi Zero 2W er ZEROTIER_ENABLE_SSO="0" standard. Det udelader den meget
store Rust/Cargo-toolchain og bygger ZeroTier med GCC og ét job. Sæt værdien til
1, hvis hubben senere skal kunne bruge ZeroTier-netværk, som kræver SSO; det
gør førstegangsinstallationen væsentligt tungere.
Genbrug den færdigbyggede ZeroTier-fil
Når en Pi har bygget ZeroTier færdig, kopieres binærfilen til PC'en fra den
persistente ZFS-placering. Kør dette på PC'en i mappen med scripts og erstat
PI-ADRESSE med Pi'ens IP-adresse:
scp sysop@PI-ADRESSE:/usr/local/software/zerotier/current/zerotier-one \
./zerotier-one-1.16.2-linux-musl-aarch64-sso0
chmod 0755 ./zerotier-one-1.16.2-linux-musl-aarch64-sso0
Ved næste kørsel kopierer flash.sh automatisk filen til kortet. Første boot
installerer den direkte og testkører den på Pi'en; både arkitektur og den
forventede version skal passe. Filnavnet indeholder også SSO-profilen, så et
SSO-build ikke forveksles med standardbuildet uden SSO.
Hvis den navngivne fil ikke findes ved siden af flash.sh, falder installationen
automatisk tilbage til lokal kompilering på Pi'en. Det er derfor nok at slette
eller flytte filen på PC'en, før et nyt SD-kort klargøres, for at fremtvinge en
ny kompilering.
tmux, htop og btop installeres i den tidlige pakkegruppe. Pakken
kitty-terminfo gør, at de kan bruges direkte fra Kitty med
TERM=xterm-kitty, og musl-locales plus SYSTEM_LOCALE giver UTF-8 til
tekstbaserede programmer. Installationen kan
følges lokalt sådan:
tmux new-session -s install
tail -f /media/mmcblk0p1/NenjimHub-Install.log
Når brugeren nenjim er oprettet, findes samme log her:
tail -f /var/log/NenjimHub-Install.log
Den sidste linje før genstart viser den samlede tid fra start af unattended
installation til reboot, målt monotont og vist som HH:MM:SS.
På normale boots venter nenjim-wifi-ready op til 60 sekunder på wlan0, før
Wi-Fi og networking startes. Tilsvarende venter nenjim-virt på det asynkront
oprettede /dev/zvol/rpool/virt-link, før ext4 kontrolleres og Docker samt
containerd får adgang til deres datalager. Begge ventetider er afgrænsede, så
en hardware- eller udev-fejl ikke kan blokere boot uendeligt.
Loginprompten på HDMI-konsollens tty1 startes af BusyBox init via
/etc/inittab, ikke som en OpenRC-service. Installationen sikrer og gemmer
denne entry, så sysop kan logge ind lokalt efter boot.
Inden det endelige APKoVL oprettes, køres en fuld apk cache sync. Det er
vigtigt i diskless mode, fordi også pakker som eudev, der blev installeret
før den persistente cache blev aktiveret, skal ligge som APK-filer på
bootpartitionen. De egne storage- og Wi-Fi-services bruger udev-settle som
valgfri rækkefølge og ikke som en hård afhængighed.
apk cache sync er den autoritative cachekontrol. Tomme metadatapakker som
udev-init-scripts kræver ikke nødvendigvis en separat payloadfil med samme
navn; installationen kontrollerer derfor de leverede udev-services frem for
at gætte cachefilnavne.
Konti efter installation:
sysop / sysop administrator via password-beskyttet doas og Docker-gruppen
nenjim / nenjim almindelig bruger uden wheel, doas og Docker-adgang
Medlemskab af Docker-gruppen er i praksis root-adgang. Det gives derfor kun
til sysop; nenjim fjernes eksplicit fra både wheel og docker.
Direkte root-login er låst på både normal konsol og SSH. Skift de to standard-passwords, før maskinen placeres på et netværk, som andre har adgang til.
Persistente placeringer
/etc/NenjimHub.conf kopi af den anvendte provisioningprofil
/home rpool/home
/usr/local/software rpool/software
/media/sysop rpool/sysop
/media/virt ext4 på rpool/virt
/var/lib/docker -> /media/virt/docker
/var/lib/containerd -> /media/virt/containerd
/sysop/zerotier -> /media/sysop/zerotier
/sysop/zrepl -> /media/sysop/zrepl
/etc/zrepl/zrepl.yml -> /sysop/zrepl/zrepl.yml
Selve /sysop ligger i Alpine/APKoVL, så sysop stadig kan logge ind, hvis ZFS
ikke kan importeres. De vigtige ZeroTier- og zrepl-data ligger på ZFS.
zrepl starter med den gyldige no-op-konfiguration jobs: []. Efter redigering
kan konfigurationen kontrolleres og servicen genstartes sådan:
doas zrepl configcheck
doas rc-service zrepl restart
Swap-profiler og prioriteter
Linux foretrækker det højeste prioritetsnummer. Scripts accepterer enhver selvstændig prioritet fra 0 til 32767. Derfor kan ZFS-swap godt gives højere prioritet end partitions-swap. Første boot skriver en advarsel, hvis dette valg bruges, men afviser det ikke.
En profil til en Pi med mere RAM kan eksempelvis være:
SWAP_SIZE_MIB_PART="1024"
SWAP_SIZE_MIB_ZFS="4096"
SWAP_SIZE_PCT_ZRAM="75"
SWAP_PRI_ZRAM="300"
SWAP_PRI_ZFS="200"
SWAP_PRI_PART="100"
ZRAM-størrelsen beregnes ved hver normal opstart ud fra MemTotal; pladsen
bruges kun efter behov. Under førstegangsinstallationen anvendes midlertidigt
100 % logisk ZRAM-størrelse, hvorefter den ønskede procent gemmes til næste
boot. Sættes SWAP_SIZE_PCT_ZRAM="0", oprettes og aktiveres ZRAM slet ikke.
Swap på et ZFS-zvol kan under ekstremt hukommelsespres skabe en uheldig
afhængighed mellem ZFS og swap. Den rå partition er derfor den sikreste høje
belastningsbuffer på Pi Zero 2W. På en større Pi kan ZFS-swap prioriteres højere,
hvis det er det ønskede kompromis. ZFS ARC begrænses separat via
ZFS_ARC_MAX_MIB.