
ホームラボで遊ぼう。Raspberry Pi × Fedora CoreOSで作る、未来志向の開発環境を構築してみる。
はじめに
なぜ、今さら「Fedora CoreOS」なのか
Immutable(不変)なOSというものに興味を持ち、学習がてら Raspberry Pi に入れて試してみた。かつて「CoreOS」という名前をよく聞いていたが、最近あまり聞かなくなったなぁ。というぼんやりした動機から、その後継である「今の Fedora CoreOS (FCOS) ってどうなっているんだろう?」と気になったのがきっかけだ。
かつてコンテナ専用OSとして一世を風靡した CoreOS Container Linux の精神を引き継ぎ、Red Hat の手によって生まれ変わった FCOS。久々にその名に触れてみると、そこには「Immutable」という、今の自分にとって非常に刺激的で、かつしっくりくる思想が詰まっていた。
コンテナに最適化された OS | Fedora CoreOS
自動アップデート機能を備えた、ミニマルな OS。スケーラブルでセキュア。コンテナ化されたワークロードを安全かつ大規模に実行することを可能にします。
“Trash Your Servers and Burn Your Code”(サーバーを修理するのではなく、燃やして新しく作り直せ) — Chad Fowler
Immutable Infrastructure(不変のインフラ)とは、一度デプロイしたサーバーには一切の変更を加えず、変更が必要な場合は新しいインスタンスを丸ごと作り直して入れ替えるという運用スタイルになります。

Immutable(不変)とは?(概念図)
ホームラボで試行錯誤していると、いつの間にか「自分でも何を設定したか忘れたサーバー」が出来上がってしまうことが多々ある。今回 FCOS を Raspberry Pi に入れてみたのは、そんな環境をコード(Butane/Ignition)で定義し、壊しても同じ状態に作り直せる「不変の環境」を、遊び心を持って構築・実験してみたかったからだ。
構成の全体像
今回の構築における各要素の役割は以下の通りです。
| 項目 | 内容 | 備考 |
|---|---|---|
| ホスト | Raspberry Pi 4B | どこの家にもある、眠っていた定番ボード |
| OS | Fedora CoreOS (Stable) | 今回の主役。Immutable OS |
| 設定定義 | Butane (Ignition) | 宣言的構成管理の要 |
| 管理ツール | SSH, Podman | コンテナベースの運用 |
導入手順
1. Butaneの設定定義 (config.bu)
FCOSの構成はすべてButane(YAML形式)で記述します。今回は検証なのでユーザー作成とSSH鍵の登録、そしてSSHをしやすくするためにNetworkManagerによる静的IPの設定を盛り込みました。
variant: fcos
version: 1.5.0
passwd:
users:
- name: core
ssh_authorized_keys:
- "ssh-ed25519 AAAAC3Nza... (your-ssh-public-key-1) ... user@macbook"
- "ssh-ed25519 AAAAC3Nza... (your-ssh-public-key-2) ... user@fedora"
storage:
files:
- path: /etc/NetworkManager/system-connections/static-ip.nmconnection
mode: 0600
contents:
inline: |
[connection]
id=static-ip
type=ethernet
[ipv4]
address1=192.168.1.152/24,192.168.1.1
dns=192.168.1.1;8.8.8.8;
method=manual
[ipv6]
method=disabled
2. OSの焼き込みと「儀式」(ブート設定)
ここからは、作成した設計図を物理メディアに定着させ、ラズパイを起動させるプロセスです。
coreos-installer を使って直接 SD カードへ書き込むところでつまずきました。今回は Fedora(Linux実機)を作業用PCとして用意し、そこから焼き込みを行っています。2-1. Ignitionファイルの生成
butane コマンドを使って、人間が読める YAML から、OS が理解できる Ignition JSON に変換します。
butane --pretty --strict -d . config.bu > config.ign
2-2. coreos-installer による焼き込み
ターゲットディスクを確認し、アーキテクチャとストリームを指定して実行します。
# ターゲットディスクを確認(例: /dev/sdX)
lsblk
# 焼き込み実行
sudo coreos-installer install -a aarch64 -s stable -i config.ign /dev/sdX
2-3. UEFI ファームウェアの配置
Raspberry Pi 4 で FCOS をブートさせるため、pftf/RPi4 UEFI Firmware を EFI パーティションに配置します。
# 1. EFIパーティション(通常は第2パーティション)をマウント
sudo mount /dev/sdX2 /mnt/efi
# 2. UEFIファームウェア(ダウンロード済み)をコピー
sudo cp -rv RPi4_UEFI_Firmware_v1.xx/* /mnt/efi/
# 3. 配置確認とアンマウント
ls -l /mnt/efi/RPI_EFI.fd /mnt/efi/config.txt
sync && sudo umount /mnt/efi
2-4. Raspberry Pi 4 での初回起動設定
ラズパイにSDカードを挿入して電源を入れ、以下の初期設定を行います。
- EEPROMの更新: 最新状態にアップデートされていることを前提とします。
- EDK2 (UEFI) メニュー: 起動時に
Escを連打してメニューに入ります。- RAM制限の解除:
Device Manager->Raspberry Pi Configuration->Advanced Configuration->Limit RAM to 3GBを Disabled に変更。 - DeviceTreeの有効化: GPIOを利用する場合は ACPI モードから
DeviceTreeモードに変更。
- RAM制限の解除:
動作確認と「Immutableの洗礼」
起動後、指定した固定IPに対してSSH接続ができることを確認しました。
ssh core@192.168.1.152
しかし、意気揚々とPodmanを動かそうとしたところで壁にぶつかりました。
core@localhost:~$ sysctl net.ipv4.ip_forward
net.ipv4.ip_forward = 0
カーネルパラメータが期待した状態になっていないため、コンテナネットワークが機能しません。ここで安易に sudo sysctl -w ... を叩いて終わりにせず、Butane という「設計図」に反映して再構築するのが、Immutable(不変)な運用思想に基づいたアプローチです。
Immutable な考えに基づいたポイント
今回の構築において、以下の習慣を徹底しました。
- 冪等性と再現性:
config.buを唯一の真実(Single Source of Truth)として管理することで、SDカードを何度焼き直しても数分で「完璧な状態」を再現できる。 - 徹底した検証: ファイル配置後の
sync、焼き込み前のlsblk、起動後のsysctl確認など、各ステップで期待値とのズレがないかを検証する。
遭遇したトラブル
遭遇したトラブル1:焼き直すたびにSSHホストキーが変わる
FCOSは通常の再起動で /etc や /var が毎回消えるわけではありません。ただし、検証中に SD カードを何度も焼き直していると、初回起動時に生成されるSSHホストキーもそのたびに変わります。その結果、Mac側で REMOTE HOST IDENTIFICATION HAS CHANGED! と怒られることになります。
解決策:
Butaneの storage.files 定義で、特定のSSHホストキー(秘密鍵・公開鍵)を直接注入しました。これでSDカードを焼き直しても「同じサーバー」として扱えるため、検証を繰り返すときのノイズを減らせます。
遭遇したトラブル2:Podmanのコンテナ通信ができない
SSH接続はできても、Podman上のコンテナが外部と通信できない問題が発生しました。調べてみると、カーネルのパケット転送設定が無効になっていました。
ここでの気づき:
普通ならここで sudo sysctl -w net.ipv4.ip_forward=1 と叩いて即座に解決したくなるところですが、私はあえてそれをしませんでした。なぜなら、稼働中のOSにその場限りの修正を加えることは、Immutableインフラの原則に反するからです。
たとえば Butane 側の既存の storage.files に以下のようなファイル定義を追加し、初回プロビジョニング時に /etc/sysctl.d/ へ配置する方針にします。
storage:
files:
- path: /etc/sysctl.d/99-container-network.conf
mode: 0644
contents:
inline: |
net.ipv4.ip_forward = 1
「手元の Butane(設計図)を修正し、最初から作り直して解決する」という規律こそが、管理された不変な環境を維持するための道です。不便さはありますが、この「手出しを我慢する」こと自体が、不変インフラを運用する上での重要なマインドセットだと実感しました。
遭遇したトラブル3:Immutable の洗礼(手作業で直したくなる!)
FCOS では /usr が OS イメージとして管理され、通常の運用中に直接書き換える場所ではありません。一方で /etc や /var は永続化されるため、vi で設定を直すこと自体はできます。
ただし、そこで手作業の変更を積み重ねてしまうと、せっかく Butane で作った設計図と実機の状態がずれていきます。FCOSを触り始めて最初に難しいと感じたのは、ファイルシステムの制約そのものよりも、「今すぐ直せる変更」をどこまで設計図に戻すかという運用の規律でした。
気づき: 「なるほど、重要な設定は Butane に寄せなければいけないのか」と、ここで初めて Immutable という概念の不自由さと、その裏にある強みを肌で理解しました。手軽に直せるからこそ設計図へ戻す。その積み重ねによって、「Butaneファイルさえあれば、数分で全く同じ環境が復元できる」という再現性が保証されるわけです。
技術的深掘り:データの生存と永続性
FCOSを運用する上で、どこに何が保存されるかの理解は必須です。
- Immutable(不変)領域:
/usr。OS本体は rpm-ostree によって管理され、通常の運用中は直接変更しない。 - Mutable / Persistent(変更可能・永続)領域:
/etc,/var,/var/home。設定、ログ、ユーザーデータなどはここに維持される。 - 運用上のポイント:
/etcが書けるからといって、手作業の変更を増やしすぎると再現性が落ちる。重要な設定は Butane に戻して、焼き直しても同じ状態になるようにしておく。
振り返りと今後の課題
コンテナの外部通信でつまずいたことで、エラーが出るたびにサーバーに入って手作業で直すのではなく、Butane(設計図)を修正して再構築することこそが、Immutable インフラの正しい運用プロセスだと実感できた。
タイムゾーンの設定、使い慣れたシェルのエイリアス、SSHホストキーの永続化……。これらはサーバーの中に蓄積されれば、いつしか誰にも再現できないブラックボックスな「秘伝のタレ」になってしまう。
しかし FCOS では、エラーが出たら Butane を直し、必要な設定があれば Butane に追記する。私が育てているのは、時間の経過とともに腐敗していく「秘伝のタレ」ではなく、いつでも同じ環境を寸分違わず再現できる「不変のレシピ」なのだ。こうやって設定ファイルを少しずつ磨き上げていく感覚は、なかなか楽しい。
アーキテクトとしての視点で言えば、「そんなの Kubernetes (k8s) でいいんじゃないか」といううっすらとした思いもあります。しかし、k8s という巨大なシステムを持ち出すまでもないエッジ環境において、OSそのものを「不変のパーツ」としてどう使い倒すか。そのユースケースを模索すること自体が、今の自分にとって非常に刺激的な学びになった。
GitOpsのような自動化の仕組みを入れるのは、この Butane ファイルが自分なりの「ベストプラクティス」として成熟してからでいい。まずは、この小さなラズパイの上で、自分にとって一番使い勝手の良いインフラの設計図を作っていこうと思う。
まとめ
今回、興味本位から始めた Raspberry Pi 4 × Fedora CoreOS の構築でしたが、終わってみれば「Immutable Infrastructure(不変のインフラ)」という概念を実体験として深く理解する良い機会になりました。
設定変更をその場限りの手作業で終わらせず、「重要なものは Butane という設計図に戻す」という運用ルールを守ることで、環境の再現性を保てます。現在はまだSDカードを抜き差しして焼き直す物理的な手間がありますが、ゆくゆくはPXE(ネットワークブート)を導入し、完全な「コードを置くだけでOSが立ち上がる環境」を目指したいと思います。
Raspberry Pi という小さな基板の上に構築した、Immutableな環境。この設計図を自分専用の「不変のレシピ」として育てていく未来が楽しみです。
雑記(ハードウェアの苦労)
インフラをコードで定義するだの Immutable だのとカッコいいことを書きましたが、いざラズパイを触ろうと思うと「LANケーブルどこだっけ?」「電源の取り回しどうしよう」「ケースを組まないと」といった、物理的なハードウェアの準備と予想外の出費に毎回結構な時間を取られます。手軽に試せるクラウドのありがたみを逆説的に感じる瞬間でした。
ちなみに、私がラズパイを重ねて運用する際によく使っているのは、タカチ電機の2段アクリルケースです。シンプルで省スペースなので、ホームラボにとても重宝しています。
