ホームラボで遊ぼう。TerraformとlibvirtでFreeBSD 15.0-RELEASE環境を構築してみる。

ホームラボで遊ぼう。TerraformとlibvirtでFreeBSD 15.0-RELEASE環境を構築してみる。

AIによるこの記事の要約
RHEL 10 をホストとし、Terraform と libvirt を用いて FreeBSD 15.0-RELEASE の仮想環境を構築しました。Cockpit による GUI 管理と Terraform による IaC を組み合わせた「Home Lab」ならではの柔軟な運用に加え、Google Cloud とのコスト比較、MacPorts を通じた BSD 文化への親和性、そして Packer によるイメージ管理への展望についてまとめています。

はじめに

最近MacBook Proを買い替えたこともあり、macOSの環境をよりBSDに寄せてみました。
自身のBSD経験については、大学時代に少しだけFreeBSDを触ったことがあり、最近はmacOSでもMacPortsを使い始めています。DarwinベースのmacOSの奥底にはBSDの血が流れていることもあり、改めて学習の一環としてホームラボでFreeBSDを触ってみることにしました。

今回は仮想環境を立てるにあたり、Terraformとlibvirtを使って、再現性のある形でVMを作っています。

構成

今回の構成は以下の通りです。

  • Red Hat Enterprise Linux (以降RHEL) 10(ホストOS / 自宅サーバ redhat.local
  • libvirt / KVM(仮想化基盤)
    • FreeBSD 15.0-RELEASE VM(検証環境)
  • Terraform(IaC / 手元の作業PCから実行)

なぜこの構成か

RHEL

Home Lab用途として、長期間安定して動かしやすいため採用しています。また、仕事でも触れる機会の多いRHELにより深く習熟したいという意図もあります。個人利用であればRed Hat Developer Program経由で利用できる点も魅力です。

libvirt / KVM

Linux標準寄りの仮想化構成であり、比較的シンプルに扱えるため採用しました。軽量で扱いやすく、Home Lab用途とも相性が良いです。

Terraform

VM構成をコード化し、壊してもすぐ再現できるようにしたかったためです。「試して壊す」を気軽にできる環境を目指しました。

図1.Terraformのライフサイクル

図1.Terraformのライフサイクル

FreeBSD

久しぶりにBSD系OSを触って学習をしようと思いました。最近macOS上でもMacPortsを使い始め、改めてBSD系の思想や文化に興味が出てきています。

構築してみた

セットアップ

まずはRHEL側に必要なパッケージを導入します。

sudo dnf install -y libvirt qemu-kvm virt-install xorriso cockpit cockpit-machines
sudo systemctl enable --now libvirtd cockpit.socket

RHELにはブラウザから管理できる Cockpit を導入しており、cockpit-machines プラグインを入れることで、Terraformで作成したVMの稼働状況をGUIでも直感的に確認・操作できるようにしています。
以下は「仮想マシン」の項目が追加された、導入直後のCockpitの画面になります。

図2.Cockpit画面(仮想マシン初期画面)

図2.Cockpit画面(仮想マシン初期画面)

TerraformでVM作成

設定は管理しやすくするため、プロバイダー定義(provider.tf)とメインのリソース定義(main.tf)を分けて記述しました。また、Google Cloud(GCP)の n2d-standard-2 インスタンス(2 vCPU / 8GB RAM)と同等のスペックを目指しました。

Google Cloudで運用した場合のコスト比較

Google Cloud で同様の構成(n2d-standard-2)を運用すると、月額で以下のコストが見込まれます。

  • VM インスタンス: JPY 11,312/月(2 vCPU + 8GB RAM)
  • 標準 Persistent Disk: JPY 151/月(20 GB)
  • 継続利用割引: ▲JPY 3,394/月
  • 月間推定合計額: 約 JPY 8,069/月

※ OSライセンス料は無料ですが、Home Labならこれがまるごと浮く計算になります。

1. provider.tf

手元のMacからリモートのRHELへSSH経由で接続するように設定します。

provider "libvirt" {
  uri = "qemu+ssh://username@redhat.local/system"
}

2. main.tf

イメージはCloud-Initに対応した最新の FreeBSD 15.0-RELEASE を使用します。

resource "libvirt_volume" "os_image" {
  name   = "freebsd15_0_os_image.qcow2"
  source = "/path/to/local/FreeBSD-15.0-RELEASE-amd64-BASIC-CLOUDINIT-ufs.qcow2"
  format = "qcow2"
}

resource "libvirt_cloudinit_disk" "commoninit" {
  name      = "commoninit.iso"
  user_data = templatefile("${path.module}/cloud_init.cfg", {
    ssh_public_key = var.ssh_public_key
  })
}

resource "libvirt_domain" "vm" {
  name      = "freebsd-15"
  memory    = "8192"
  vcpu      = 2
  cloudinit = libvirt_cloudinit_disk.commoninit.id

  network_interface {
    network_name = "default"
    wait_for_lease = true
  }

  disk {
    volume_id = libvirt_volume.os_image.id
  }

  console {
    type        = "pty"
    target_port = "0"
    target_type = "serial"
  }
}

図3.Cockpit画面(作成された仮想マシンの画面)

図3.Cockpit画面(作成された仮想マシンの画面)

遭遇したトラブル

遭遇したトラブル1:Mac側にmkisofsがない!

Terraformの libvirt_cloudinit_disk は、内部的に ISO イメージを作成するために mkisofs コマンドを使用します。しかし、macOSには標準でインストールされていません。

これを解決するため、MacPortsを使用して cdrtools をインストールしました。

sudo port install cdrtools

これで無事に mkisofs コマンドがパスに通り、terraform apply が成功するようになりました。

遭遇したトラブル2:No bootable device(イメージの圧縮)

VMは作成されたものの、コンソールに No bootable device と表示されて起動しない問題が発生しました。指定していた公式イメージのURLが .xz で圧縮されていたため、libvirt側で直接ブートデバイスとして認識できなかったのが原因です。

一旦手元のMacでダウンロード・展開してからアップロードする構成に変更することで解決しました。

unxz FreeBSD-15.0-RELEASE-amd64-BASIC-CLOUDINIT-ufs.qcow2.xz

遭遇したトラブル3:root権限になれない(FreeBSDの作法)

ようやくログインできたものの、sudo コマンドが見つからず、管理者権限に昇格できない壁にぶつかりました(やっぱりrootになりたい!)
FreeBSD は Linux と異なり、ベースシステムに sudo は含まれておらず、さらに wheel グループに属していないと su で root になれないという伝統的な作法があります。 これを解決するため、cloud_init.cfgsudo の自動インストールを指定し、ユーザーを wheel グループに追加しました。

# cloud_init.cfg
users:
  - name: username
    groups: [wheel]
    sudo: ALL=(ALL) NOPASSWD:ALL
    ssh_authorized_keys:
      - ${ssh_public_key}

packages:
  - sudo

これで、ログイン後に sudo su - でスッと root になれる、完璧な検証環境が整いました。

SSHで快適に接続する

libvirt の内部ネットワークへ Mac から直接接続できないため、RHELホストを ProxyJump として経由します。~/.ssh/config に以下を追記することで、ssh freebsd-15 だけで接続できるようになりました。

Host freebsd-15
    HostName 192.168.x.x # VM毎に払い出されるIP
    User username
    IdentityFile ~/.ssh/username_rsa
    ProxyJump rhel # 踏み台設定 (rhelは別途定義済みとする)

図4.ターミナル画面(SSH)

図4.ターミナル画面(SSH)

少し触ってみた感想

Linuxとかなり似ていますが、設定周りや思想にBSDらしさを感じます。特に以下の点が印象的でした。

  • ドキュメントが丁寧: ハンドブックが非常に充実しており、迷うことが少ない。
  • システム全体として統一感がある: カーネルと基本ツールが同じレポジトリで管理されていることによる一貫性。
  • 「安定性を重視する文化」を感じる: 変化は慎重だが、一度決まった仕組みの堅牢さが高い。

また、今回 MacPorts で cdrtools を入れた際に改めて気づきましたが、MacPortsはGNU系のツールを g プレフィックス(lsgls など)で管理したり、Pythonのバージョンを port select で切り替えたりと、非常に理理整然とした管理思想を持っています。

Darwin(macOS)の上で、MacPortsを通じてBSD的なツール管理に触れ、さらにその先にある本家FreeBSDをTerraformで構築する。この「つながり」を意識しながら環境を作るのは、エンジニアとしての知的好奇心をくすぐる非常に楽しい体験でした。

まとめ

Terraform + libvirt を使うことで、FreeBSD検証環境を簡単に再現できるようになりました。壊してもすぐ作り直せるため、気軽にBSD系OSを試せるのがかなり良いです。

今後は以下も触ってみたいと思っています。

  • ZFS: FreeBSDといえばZFS、その真髄を味わいたい。
  • Packer: Cloud-Init だけでなく、ゴールデンイメージ作成の自動化も試したい。
  • ports / pkg: システム管理の思想をより深く知りたい。
@urchin_hat
Written by
@urchin_hat

とある領域のSaaSサービスでSREとして活動中。現在はインフラの正常化とAIを活用した運用効率化(AIOps)に注力しています。

Back to Memo