
2026/06/17 5:17
アルパイン・イニトラミス NAS「Frood」(2024)
RSS: https://news.ycombinator.com/rss
要約▶
Japanese Translation:
本記事では、Alpine Linux を使用した簡素化されたネットワーク接続ストレージ(NAS)のセットアップについて詳述している。システム全体をメモリに格納された単一の初期化ファイルから動作させ、UEFI ファームウェアによって直接読み込まれる単一ファイルの統一カーネルイメージを活用することで、複雑なビルドシステムや独立したルートファイルシステムの複雑さを排除し、運用オーバーヘッドを大幅に削減している。著者は、Alpine の従来の「ディスクレスモード」が複雑でありブート失敗を引き起こすため回避し、代わりに
alpine-make-rootfs を用いて chroot ベースのイメージを組み立て、物理ストレージは専用 ZFS プールのために保持しつつ、OS レイヤーは一時的なものにしている。
設定は、曖昧なドメイン固有言語ではなく Git リポジトリを介して宣言的に管理されており、各ブートでシステム状態がリセットされることで蓄積エラーを防ぎ、RHEL などの分布型で一般的な脆弱なアップグレード手順を回避している。特定の
setup.sh スクリプトが OpenRC のランレベルを設定し、必要なサービス(Tailscale および SSH など)を有効化し、QEMU ワンライナーによる即座のテストを可能にしている。このモデルは単一ファイルシステムイメージの導入を簡素化する、信頼性が高くオープンソースな解決策を提供する。今後の計画としては、ZFS の安全な解放のためのパスキーの実装と、Secure Boot への統合の検討があり、シンプル性と効率性を優先した現代の埋め込み Linux デプロイメント向けの堅牢な枠組みを提供する。本文
特殊な構成を持つ NAS「frood」:単一ファイル initramfs で完結する Alpine Linux システム
私の NAS「frood」は非常に特殊な構成を持っています。単一の巨大な initramfs イメージ内に、Alpine Linux の全体システムがパッケージ化されているのです。これらは心地良く動作しており、なぜこれが一般的でないのか分かりません。
ファームウェアとの親和性と更新の簡単さ
ファームウェアがこのイメージを検出できれば、システムは常にクリーンに起動します。
- 新バージョン導入: 単なるファイルのコピーで済み、複雑な手順を必要としません。
- 設定の宣言性: システムの定義は複雑な DSL(ドメイン固有言語)ではなく、initramfs を構築する git リポジトリ内に宣言的に行われています。
にファイルを配置したい場合、ルートディレクトリの/etc/example.conf
に置くだけで済み、残りの設定は数百行のスクリプトが担います(これらのスクリプトは私が実際に読めるようになっています)。root/etc/example.conf
- テスト: 次のバージョン導入も、qemuでのワンライナーでテスト可能です。動いている要素が極めてわずかです。
注記: 私はこの記事を更新しており、2025 年以降の環境向けです。最新構成では 64 コア搭載の Ampere Altraに切り替え、ブートローダーを撤廃し、代わりに単一ファイルの **UKI(Unified Kernel Image)**を使用しています。
なぜこの構成なのか?:メモリ上から起動する理由
私はシステムをメモリ上から起動することを常に喜爱してきました。
- 高速性: 起動が瞬時に行えます。
- 耐久性: 安価な不揃いな SD カードに書き込まれることでディスクの消耗を防ぎます(良好なストレージデバイスは ZFS プール専用になっているため)。
直面する課題:設定変更の永続化
メモリ上からの起動では、設定変更を永続化させる必要があります。これには二つの大きな問題点があります。
-
apkovl アプローチの問題点
- アルプインへの答えは「ディスクレスモード」であり、全てのカスタマイズをオーバーレイファイル (
) に保持します。*.apkovl - 起動後に標準システムが
ファイルを探し、適用し、不足する apk パッケージをインストールします。*.apkovl - 複雑さの課題:
ツールを使って apkovl を生成・管理することは優れていますが、以下のプロセスにより多くの動く要素があります:lbu(1)- apkovl の発見と適用
- 新しい fstab でのマウントポイント設定
- 未インストールパッケージの再インストール
- 起動手順の再開
- これが多岐にわたって失敗します(ファイルシステムが見つからなくなる場合や、apk がインストールされない場合など)。起動プロセスがパッケージマネージャーに依存している点が脆さの原因です。
- アルプインへの答えは「ディスクレスモード」であり、全てのカスタマイズをオーバーレイファイル (
-
状態の蓄積と「あ、しまった」ステップ
- 時間経過とともに、ルートパーティション上に状態が蓄積されます(
,/etc
など)。/var - これらはサービス起動プロセスにおける未文書化または順序がずれたステップを表します。
- 「はい、myapp-init を実行する」(些細な設定を忘れる)
- 「ca-certificates を…にダウンロードして問題を修正する」(即時的な補修)
- 「/etc/ipsec.secrets を touch および l2tp チューネルが作動しない」
- 過去の RHEL アップグレードでの失敗と同様に、これらの一時的な補修作業は最終的にシステムを不安定にします。
- 時間経過とともに、ルートパーティション上に状態が蓄積されます(
代替手段の検討
かつて Ansible を活用して解決しましたが、マルチレイヤーになり管理コストが増大しました。他の選択肢として以下がありますが、私はAlpine Linuxが最も気に入っています:
- NixOS: あまり面白くない(と感じる)。
- Gokrazy: ZFS 対応がまだ準備完了していない。
- Buildroot / U-root: 組み込みツールチェーンではあるが、軽すぎる。
Alpine Linux はシンプルで軽量な GNU なしディストリビューションですが、init と永続化メカニズムについてはこれ以上求めず、単一ファイルの initramfs で完結させることを目指しました。
仕組み:システム構築の詳細
システムが起動すると、Linux は**「initramfs」イメージ**を期待します。これは起動時の最初のルートファイルシステムを構成するファイルたちの単なる cpio アーカイブです。
- 通常は本物のルートファイルシステムをマウントし、モジュールをロードするのが役割ですが、ここでは全体システムを収容しています。
initramfs の構築:alpine-make-rootfs
出発点は
です。これはコンテナイメージを構築するための短い(約 500 行)スクリプトで、我々が求めるものの約 90% を構成しています。alpine-make-rootfs
以下は主要なビルドスクリプトの一部です:
#!/bin/sh set -e # 公式スクリプトのダウンロードと検証 wget https://raw.githubusercontent.com/alpinelinux/alpine-make-rootfs/v0.7.0/alpine-make-rootfs \ && echo '91ceb95b020260832417b01e45ce02c3a250c4527835d1bdf486bf44f80287dc alpine-make-rootfs' | sha256sum -c && \ chmod +x alpine-make-rootfs # 一時的なルートディレクトリの作成 ROOTFS_DEST=$(mktemp -d) # mkinitfs のトリガーを無効化(apk インストール中に自動起動させない) mkdir -p "$ROOTFS_DEST/etc/mkinitfs" echo "disable_trigger=yes" > "$ROOTFS_DEST/etc/mkinitfs/mkinitfs.conf" # 環境変数の設定 export ALPINE_BRANCH=edge export SCRIPT_CHROOT=yes export FS_SKEL_DIR=root export FS_SKEL_CHOWN=root:root PACKAGES="$(cat packages)" export PACKAGES ./alpine-make-rootfs "$ROOTFS_DEST" setup.sh # ロールアウト:ルートディレクトリからファイルをコピーし、パッケージをインストール # chroot 内で setup.sh を実行した後、boot ディレクトリを除くものを initramfs アーカイブ化 cd "$ROOTFS_DEST" find . -path "./boot" -prune -o -print | cpio -o -H newc | gzip > "$ROOTFS_DEST/boot/initramfs-lts"
これだけでほぼ完了です!Alpine Linux がこれをほとんどハックなしで行うことができることは、本当に感嘆的です。
インストールされるパッケージ
サーバーで通常導入するものを採用しています。特に注目すべきは以下の 3 つです:
- alpine-base:
,apk
,busybox
および数つの設定ファイルをインストールするメタパッケージ。openrc - linux-lts: カーネルおよびそのモジュール。不要なモジュールを削って数百 MB を節約しましたが、結局ハックになるだけであります(modloop は存在せず、モジュールは常に利用可能です)。
- linux-firmware-none: 通常
をインストールしますが、これは数百メガバイトのファームウェアを追加します。これを避けるためにlinux-firmware-any
オプションを使用しています。-none
設定スクリプト (setup.sh)
このスクリプトも特段ことはありませんが、ランレベルとルートパスワードを設定します。
#!/sbin/sh set -e # システム初期化サービスの追加 rc-update add devfs sysinit rc-update add dmesg sysinit # ブート時のサービス(ハードウェア管理、ネッティング、ロギングなど) rc-update add hwclock boot rc-update add modules boot rc-update add sysctl boot rc-update add hostname boot rc-update add bootmisc boot rc-update add syslog boot rc-update add klogd boot rc-update add networking boot rc-update add seedrng boot # シャットダウン時のサービス rc-update add mount-ro shutdown rc-update add killprocs shutdown # デフォルトで起動するサービス(監視やアクセス管理) rc-update add acpid default rc-update add crond default rc-update add local default rc-update add openntpd default rc-update add sshd default rc-update add tailscale default # ルートパスワードの設定(ハッシュ付き) chpasswd -e <<'EOF' root:$6$twsDxnP.TG2M8J4l$7lte7E/ImK4UwoursD7qQCC7XMUothIDb9FTH1MncxYbGQDUQPkC/9pxleTwPxEs3nbatApszxuwc4yj6ucdX1 EOF
これは単に宣言的にシステム構成方法を示す場所です。実際にはさらにいくつかのサービスを設定していますが、最小限で動作させるためには不要な部分もあります。
ルートスカルプトン (root/init.d 等)
ルートスケルプンも同様にシステム固有であり、イメージの中にファイルを配置するだけで追加できるのが素敵です。
- 起動時の実行:
にファイルを追加するだけです。root/etc/local.d/ - inittab 設定:
::sysinit:/sbin/openrc sysinit ::sysinit:/sbin/openrc boot ::wait:/sbin/openrc default ::shutdown:/sbin/openrc shutdown tty1::respawn:/sbin/getty 38400 tty1 ttyAMA0::respawn:/sbin/getty -L 115200 ttyAMA0 vt100
は busybox の init が参照し、OpenRC ランレベルを実行、tty コンソールに getty を respawn します。root/etc/inittab - ネットワーク設定:
,root/etc/network/interfaces
,root/etc/hostname
で機能させます。root/etc/hosts - SSH キーと永続化:
とroot/etc/ssh/ssh_host_ed25519_key*
で SSH を確保します。root/root/.ssh/authorized_keys
とsshd_disable_keygen=yes
で、非 Ed25519 ホスト鍵の生成を防ぎます。root/etc/conf.d/sshd
- Tailscale の永続化: UUID 厳密にマウントして状態を保持します。
UUID=B61B-19E7 /media/usb vfat noatime,rw,fmask=177 0 0 root/etc/fstab seed_dir=/media/usb/persist/seedrng # Random number generator の永続化 root/etc/conf.d/seedrng TAILSCALED_OPTS="-state /media/usb/persist/tailscaled.state" root/etc/conf.d/tailscale
UEFI ブートローダーと UKI
2024 年の変更により、リムーバブルメディアのデフォルトパスである
EFI/BOOT/BOOTAA64.EFI から、ukify でアッセンブリされた Unified Kernel Image (UKI) をUEFI が直接ロードするようになりました。
apk add --no-cache systemd-efistub ukify # コマンドラインオプションの定義 CMDLINE="rdinit=/sbin/init console=tty1 console=ttyAMA0" # UKI の構築 ukify build --output "$1" --cmdline "$CMDLINE" \ --linux "$ROOTFS_DEST/boot/vmlinuz-lts" \ --initrd "$ROOTFS_DEST/boot/initramfs-lts" \ --os-release "@$ROOTFS_DEST/etc/frood-release" # デプロイ(イメージを USB メディアクリックにコピー) rsync images/$image root@frood:/media/usb/EFI/BOOT/BOOTAA64.EFI
QEMU テストによる検証
この構成の魅力の一つは、UKI イメージを指定するだけで、意味のある方法で qemu でテストできることです。
qemu-system-aarch64 -M virt -cpu cortex-a72 -m 4G -nographic \ -bios QEMU_EFI.fd -kernel "images/$image" \ -drive file=usb_disk.img,if=virtio,format=raw
- 生産環境と同じ UUID でフォーマットされた永続化デバイスを含まれています。
- Tailscale 設定も含まれており、qemu イメージは異なる Tailscale デバイスとして起動し、個別に SSH 接続することも可能です。
シンプルなステータスサービス
システムのステータスを一目で把握するためのシンプルなサービスが必要でした。私は小さな Go サーバーを書くことにしました。
- 構築方法:
の呼び出し前に、ローカルモジュール内のすべての Go バイナリをalpine-make-rootfs
に構築します。/usr/local/bin/go env -w GOTOOLCHAIN=auto go build -o "$ROOTFS_DEST/usr/local/bin/" ./cmd/... - サービス登録:
を作成し、root/etc/init.d/srvmonitor
で起動します。rc-update add srvmonitor default - 機能: Go サーバーは Tailscale IP のポート 80 でリスニングし、
に置いたスクリプトの出力を提供します。/etc/monitor.d/
#!/sbin/openrc-run description="Serve scripts from /etc/monitor.d" command=/usr/local/bin/srvmonitor command_background=true pidfile="/run/${RC_SVCNAME}.pid" depend() { need net localmount after firewall }
frood のオープンソース化と今後の展望
全体の構成はオープンソースで、私の主に無害なリポジトリにあります。ZFS インポートの仕組みは上記ではカバーされていませんが、興味深いかもしれません。
現在の課題:シークレットの注入方法
まだ解決していない問題として、ZFS のアンロック方法があります。現時点ではパスワードで解除していますが、将来的には以下のような方法を検討しています:
- YubiKey:
で復号化し、age-plugin-yubikey
でホスト鍵を取得。yubikey-agent - TPM: ボードの TPM を活用して完全な Secure Boot チェーンを行い、TPM キーでアンロック。
それらは非常に面白いですね。詳しくは Bluesky の
@filippo.abyssdomain.expert または Mastodon の @filippo@abyssdomain.expert で追跡できます。
画像について:ポルトモニズ
記事に添付された写真は、マデイラ島にある自然のプール群「ポルトモニズ」です。
- 特徴: 公共アクセス可能で、火山岩で作られており、大海からの波が spectacular に激突しています。
- 場所の雰囲気: マデイラ島は本当に涼しい場所です。ここは 3 または最も困難なクロスウィンド着陸の一つでもあります。
支援とスポンサー
私の保守作業は awesome Geomys クライアント(Interchain, Smallstep, Ava Labs, Teleport, SandboxAQ, Charm, Tailscale, Sentry)によって資金提供されています。これらとの定期契約を通じて、オープンソースの保守作業の持続可能性と信頼性を確保し、私自身および他の Geomys メイテイナーへの専門知識への直接ラインを提供しています。
各スポンサーからのメッセージ:
- Teleport: 過去 5 ヵ年で脅威は従来のマルウェアから社会的工学へとシフトしています。Teleport Identity はアクセス監視による弱いたちのパターンの排除、アクセスリクエストによる攻撃表面の最小化、および必須のアクセスレビューによる未使用権限の削除を設計されています。
- Ava Labs: 私たちは AvalancheGo を維持しており、ブロックチェーン技術の広範な採用にはオープンソース暗号プロトコルの持続可能な保守と開発が不可欠であると信じています。
- SandboxAQ: AQtive Guard は、機密データを保護し、当局および顧客との準拠を支援するための統合暗号管理ソフトウェアプラットフォームです。AQtive Guard は自動的に暗号セキュリティ状態およびポリシー管理を分析・報告し、コードを書き換えずに新しいプロトコル(量子耐性暗号を含む)を実装および執行することを可能にします。
- Charm: 端末愛好者ならぜひ加入してください。Charm はコマンドライン向けツールとライブラリを構築しており、CLI および TUI ベースのアプリを提供しています。