KVM + Cockpit on Ubuntu24.04 or Rocky9  構築メモ

## はじめに
自宅ラボ環境に **KVM + Cockpit** 構成での簡易 IaaS 環境を構築したので構築メモを記載する

もともとは [ESXi で自宅ラボサーバ (NUC)](https://qiita.com/suzuyui/items/4db04469de06b61791f7) を構築していたが、2024 年に無償版 ESXi の提供が終了となったため、切り替えを進めるために試している

インストール先は NUC (Intel 版と ASUS 版) と呼ばれるミニ PC

ホスト OS は **Rocky9** と **Ubuntu24.04 LTS** の両方で試した結果を記載している

OS インストールから実施しており、OS インストール後の設定方法は Ansible コードにしている

※ 導入後の画面。GUI でノードの仮想マシン・ネットワーク・ストレージなどを管理できる

![スクリーンショット 2025-02-22 23.51.32.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/326183/b637f8ff-cdd3-4236-9c8c-fff657945efe.png)


## Cockpit とは

[Cockpit](https://cockpit-project.org/) の開発元は RedHat 社がスポンサーとなっているフリーソフトウェアプロジェクトで、 [LGPL v2.1+](https://github.com/cockpit-project/cockpit/blob/main/COPYING) で開発されている

様々な機能を提供している ([公式サイト](https://cockpit-project.org/)より抜粋)

- ネットワーク設定の検査と変更
- ファイアウォールを設定する
- ストレージの管理（RAIDおよびLUKSパーティションを含む）
- **仮想マシンの作成と管理**
- コンテナをダウンロードして実行する
- システムログの閲覧と検索
- システムのハードウェアを検査する
- ソフトウェアのアップグレード
- パフォーマンスを監視する
- ユーザーアカウントを管理する
- systemdベースのサービスを検査し、操作する
- ローカルウェブブラウザでリモートサーバー上のターミナルを使用する
- 複数のコックピットサーバーを切り替える
- 増え続けるアプリやアドオンをインストールして、コックピットの機能を拡張します

### サポート OS

[サポート OS](https://cockpit-project.org/running.html) は以下の通り

- 利用可能 & テスト済み
    - Fedora, RHEL (RedHat Enterprise Linux), Fedora CoreOS, CentOS, Debian, archlinux, Ubuntu
- 利用可能
    - clearlinux, Tumbleweed, SUSE Linux Enterpise Micro


## 実行環境

### サーバ

本環境では、2つの OS 種別のインストール先として、下記 2サーバを用意して実行する

構築時のポートと複数ネットワーク収容 (VLAN Trunk) 用のポートを分けるために、USB NIC を追加で入れている

| 項目 | サーバ1 | サーバ2 |
|:-:|:-:|:-:|
| サーバ | NUC8i5BEH | NUC14RVHI7 |
| CPU | Intel Core i5-8259U <br> 4Core/8Thread | Intel Core Ultra 7 155H <br> 16Core(P6/E8/LPE2)/22Thread |
| Memory | 64GiB (DDR4-3200 32BiB x2) | 96GiB (DDR5-5600 48GiB x2) |
| Disk | 500GB PCIe Gen3 | 1TB PCIe Gen4 |
| 拡張 NIC | USB NIC 1G x1 <br> (LUA4-U3-AGTE-NBK) | USB NIC 1G x1 <br> (LUA5-U3-AGTE-NBK) |
| ホスト名 | nuc02 | nuc04 |
| Install OS | Rocky9.5 | Ubuntu24.04 LTS |


### 構成

概要図は下記の通り、詳細は書かないが Gateway となる Router とサーバを収容する Switch を分けて構築している
機器は他の記事でも使用している、EdgeRouter ER-X と [GS108T](https://www.netgear.com/jp/business/wired/switches/smart-cloud/gs108tv3/) を使用する

![スクリーンショット 2025-02-23 13.24.12.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/326183/99cd106f-4933-4414-bca4-fbe61db8f29a.png)


### 操作PC
OS インストール用の USB メモリ作成で使用する

MacBook Air 15インチ, M3, 2024, MacOS Sequoia 15.3（24D60）

## 構築

下記の順番で、準備・インストール・設定を実施する

1. インストール USB 作成
1. OS インストール
1. KVM + Cockpit 設定 (ansible)

### 1. インストール USB 作成

#### 1.1. ISO ファイルダウンロード

##### Ubuntu24.04
`Ubuntu Server 24.04 LTS` を [ubuntu.com](https://ubuntu.com/download/server
) からダウンロードする

※ 本記事では 24.04.1 LTS で記載しているが、書いている途中で 24.04.2 LTS がリリースされた

##### Rocky9

`Rocky Linux 9` の `Minimal ISO` を [rockylinux.org](https://rockylinux.org/ja-JP/download) からダウンロードする

※ 本記事では 2025.02.22 時点で最新の `v9.5` を使用する


#### 1.2. USB メモリをフォーマット

下記の流れで実施する

1. USBメモリをMacに挿入
1. `ディスクユーティリティ` 開く（Command + Space → 「ディスクユーティリティ」と入力）
1. 左のリストからUSBメモリを選択
1. `消去` をクリックし、`MS-DOS (FAT32)`でフォーマット
1. `消去` をクリックしてフォーマット

![スクリーンショット 2025-02-11 18.11.16.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/326183/be570f71-c959-ddee-2d70-b05831edfbbc.png)
![スクリーンショット 2025-02-11 18.12.07.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/326183/522aed25-10f6-08e5-5d3c-e41dca49eb8a.png)
![スクリーンショット 2025-02-11 18.12.41.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/326183/839bfaa7-e263-5186-598a-854d2b17c955.png)

#### 1.3. USB メモリに書き込み

USBデバイス名を下記コマンドで確認

```sh
diskutil list
```

```sh:出力例(抜粋.ここだと「/dev/disk4」がデバイス名)
% diskutil list
...
/dev/disk4 (external, physical):
   #:                       TYPE NAME                    SIZE       IDENTIFIER
   0:     FDisk_partition_scheme                        *31.0 GB    disk4
   1:                 DOS_FAT_32 NO NAME                 31.0 GB    disk4s1
```

USB メモリをアンマウントする

```sh
diskutil unmountDisk [USBメモリデバイス名]
```

```sh:出力例
% diskutil unmountDisk /dev/disk4
Unmount of all volumes on disk4 was successful
```

USB メモリへ ISO ファイルを書き込みを実施する

```sh:ubuntu24.04の場合
sudo dd if=[ダウンロードパス]/ubuntu-24.04.1-live-server-amd64.iso of=/dev/disk4 bs=1m status=progress
```

```sh:rocky9の場合
sudo dd if=[ダウンロードパス]/Rocky-9.5-x86_64-minimal.iso of=/dev/disk4 bs=1m status=progress
```

```sh:出力例
% sudo dd if=/Users/suzuyu/Downloads/ubuntu-24.04.1-live-server-amd64.iso of=/dev/disk4 bs=1m status=progress
  2762997760 bytes (2763 MB, 2635 MiB) transferred 201.560s, 14 MB/s
2645+1 records in
2645+1 records out
2773874688 bytes transferred in 201.772883 secs (13747510 bytes/sec)
```

USB メモリを取り出す

```sh
diskutil eject [USBメモリデバイス名]
```

```sh:出力例
% diskutil eject /dev/disk4
Disk /dev/disk4 ejected
```

### 2. OS インストール

必要に応じて Boot 順番を BIOS で USB メモリを優先するように設定して起動する。起動後は下記のページ対応で設定をしていく (特別なことはしてない)

#### 2.1. Ubuntu24.04 インストール

| ページ | 選択・設定例 |
|:-:|:-:|
| Welcom page | `English` |
| Installer update available | `Continue without updating` |
| Keyboard configuration | Layout: [`Japanese`], Variant: [`Japanese`], `[ Done ]` |
| Choose the type of installation | `(X) Ubuntu Server`, `[ Done ]` |
| Network configuration | 環境に応じた IP アドレス設定をする (本環境はルータ側の DHCP で実施しているので何もせずに進める), `[ Done ]` |
| Proxy configuration | `[ Done ]` |
| Ubuntu archive mirror configuration | `[ Done ]` |
| Guided storage configuration | `(X) Use an entire disk` |
| Storage configuration | `[ Done ]` -> Confirm destructive action -> `[ Continue ]` |
| Profile configuration | Your name: `自分のアカウント名`, Your servers name: `サーバー名, `Pick a username: `自分のアカウント名`, Choose a password: `パスワード`, Confirm your password: `パスワード`, `[ Done ]` |
| Upgrade to Ubuntu Pro | `(X) Skip for now`, `[ Continue ]` |
| Installing system | Installation complete! が出るまで待って、`[ Reboot Now ]` |
| Please remove th installation medium, then press ENTER: | USB メモリを抜いて、`Enter` を押す |

起動後は次の ansible での設定のみとなる


#### 2.2. Rocky9 インストール

| ページ or 項目 | 選択・設定例 |
|:-:|:-:|
| WELCOM TO ROCKY LINUX 9.5 | `Japanese` -> `続行(C)` |
| インストール先(D) | OSインストールするローカルドライブを指定する , ストレージの設定 `カスタム(C)`, `完了(D)` <br> 手動パーティション設定 不要な既存領域をクリックして`-`で削除する -> `ここをクリックすると自動作成します(C)` -> `/home` を `-` をクリック (homeに大きく割り当てがデフォルトされるため) -> `/`をクリックして`要求される容量:` に最大値を割り当てる -> `完了(D)` <br> `変更を許可する(A)` をクリック |
| ソフトウェアの選択 | `最小限のインストール`, `完了(D)` |
| ネットワークとホスト名(N) | メインで利用するインターフェースを左上のボックで `オン`変える, ホスト名(H): にホスト名を入力して `適用(A)` をクリック, 完了(D) |
| 時刻と日付(T) | 地域(R): アジア, 都市(C): 東京, 完了(D) |
| root パスワード(R): | root パスワード(R) : パスワード入力, 確認(C): 再度入力, 完了(D) |
| ユーザーの作成(U) | (F): ユーザ入力, ユーザー名(U): アカウント名入力 , [x] このユーザーを管理者にする(M), [x] このアカウントを使用する場合にパスワードを必要とする(R), パスワード(P) パスワード入力, パスワードの確認(C) 再度入力, 完了(D) |
| インストールの開始(B) | クリック |
| システムの再起動(R) | クリック  |

起動後は次の ansible での設定のみとなる

### 3. KVM + Cockpit 設定 (ansible)

OS インストール後から初期設定として下記をまとめた ansible playbook を下記に共有する。ansible 実行以外は何も設定しなくていいようにしている

- LVM 拡張
    - Ubuntu は初期設定が 100GB になっているので、残りのサイズでディスクサイズを拡張しておく
- upgrade & update
    - 最新化をする。必要に応じてリブートする
- KVM と Cockpit の導入
    - 必要な package のインストール
    - libvirtd, cockpit, NetworkManager の start と有効化(再起動対応)
    - 既存 Interface を Cockpit で管理できるように NetworkManager 管理に書き換えて適用
        - NetworkManager にすると systemd-networkd-wait-online.service がうまく動作しないので止める (Ubuntu)
    - libvirt, kvm グループに ansible_user もしくは ansible 実行ユーザを登録

```yaml:初期設定playbook
--- 
- name: Extend LVM and Resize Filesystem (Ubuntu Only)
  hosts: cockpithost
  become: yes
  tasks:
    - name: Check current LVM size
      command: lvs --noheadings -o lv_size --units G --nosuffix /dev/ubuntu-vg/ubuntu-lv
      register: current_lvm_size
      changed_when: false
      when:
       - ansible_distribution == 'Ubuntu'

    - name: Get available free space in volume group
      command: vgs --noheadings -o vg_free --units G --nosuffix ubuntu-vg
      register: vg_free_space
      changed_when: false
      when:
       - ansible_distribution == 'Ubuntu'

    - name: Extend LVM logical volume if there is free space
      command: lvextend -l +100%FREE /dev/ubuntu-vg/ubuntu-lv
      register: lvextend_result
      changed_when: "'successfully resized' in lvextend_result.stdout"
      when:
       - ansible_distribution == 'Ubuntu'
       - vg_free_space.stdout | float > 0

    - name: Resize filesystem
      command: resize2fs /dev/ubuntu-vg/ubuntu-lv
      when:
       - ansible_distribution == 'Ubuntu'
       - lvextend_result.changed

- name: Update
  hosts: cockpithost
  become: yes
  tasks:
    - name: Update and upgrade all packages (Ubuntu)
      apt:
        update_cache: yes
        upgrade: dist
      when:
       - ansible_distribution == 'Ubuntu'

    - name: Check if reboot is required (Ubuntu)
      stat:
        path: /var/run/reboot-required
      register: reboot_flag
      when:
       - ansible_distribution == 'Ubuntu'

    - name: Reboot if required (Ubuntu)
      reboot:
      when:
       - ansible_distribution == 'Ubuntu'
       - reboot_flag.stat.exists

    - name: Install dnf-utils (for needs-restarting) (Rocky)
      dnf:
        name: dnf-utils
        state: present
      when:
       - ansible_distribution == 'Rocky'

    - name: Update and upgrade all packages (Rocky)
      dnf:
        name: '*'
        state: latest
        update_cache: yes
      when:
       - ansible_distribution == 'Rocky'

    - name: Check if reboot is required (Rocky)
      command: needs-restarting -r
      register: reboot_flag
      failed_when: reboot_flag.rc not in [0,1]
      changed_when: reboot_flag.rc == 1
      when:
       - ansible_distribution == 'Rocky'

    - name: Reboot if required (Rocky)
      reboot:
      when:
       - ansible_distribution == 'Rocky'
       - reboot_flag.rc == 1

- name: Enable KVM and Install Cockpit
  hosts: cockpithost
  become: yes
  tasks:

    - name: Install KVM, Cockpit (Ubuntu)
      apt:
        name:
          - qemu-kvm
          - libvirt-daemon
          - libvirt-clients
          - bridge-utils
          - cockpit
          - cockpit-machines
          - cockpit-networkmanager
          - nfs-common
        state: present
        update_cache: yes
      when:
       - ansible_distribution == 'Ubuntu'

    - name: Install EPEL repository (Rocky)
      dnf:
        name: epel-release
        state: present
      when:
       - ansible_distribution == 'Rocky'

    - name: Install KVM, Cockpit (Rocky)
      dnf:
        name:
          - qemu-kvm
          - libvirt-daemon
          - libvirt-client
          - bridge-utils
          - cockpit
          - cockpit-machines
          - cockpit-networkmanager
          - nfs-utils
        state: present
        update_cache: yes
      when:
       - ansible_distribution == 'Rocky'

    - name: Check if CPU supports KVM
      command: kvm-ok
      register: kvm_support
      ignore_errors: yes
      changed_when: false
      when:
       - ansible_distribution == 'Ubuntu'

    - name: Enable and start libvirtd service
      systemd:
        name: libvirtd
        enabled: yes
        state: started
      when: ansible_distribution == 'Ubuntu' or ansible_distribution == 'Rocky'

    - name: Enable and start Cockpit service
      systemd:
        name: cockpit
        enabled: yes
        state: started
      when: ansible_distribution == 'Ubuntu' or ansible_distribution == 'Rocky'

    - name: Enable and start NetworkManager service
      systemd:
        name: NetworkManager
        enabled: yes
        state: started
      when: ansible_distribution == 'Ubuntu' or ansible_distribution == 'Rocky'

    - name: Add current user to libvirt and kvm groups
      user:
        name: "{{ ansible_user | default(lookup('env', 'USER')) }}"
        groups: libvirt,kvm
        append: yes
      when: ansible_distribution == 'Ubuntu' or ansible_distribution == 'Rocky'

    - name: Backup the current netplan configuration
      copy:
        src: /etc/netplan/50-cloud-init.yaml
        dest: /etc/netplan/50-cloud-init.yaml.bak
        remote_src: yes
      register: backup_result
      when:
       - ansible_distribution == 'Ubuntu'

    - name: Set renderer to NetworkManager in Netplan configuration if not set (Ubuntu)
      lineinfile:
        path: /etc/netplan/50-cloud-init.yaml
        regexp: '^renderer:'
        line: '    renderer: NetworkManager'
      register: netplan_change
      when:
       - ansible_distribution == 'Ubuntu'


    - name: Check if renderer is already NetworkManager (Ubuntu)
      debug:
        msg: "Netplan renderer is already set to NetworkManager"
      when:
       - ansible_distribution == 'Ubuntu'
       - netplan_change is not changed


    - name: Apply Netplan configuration if changed (Ubuntu)
      command: netplan apply
      become: yes
      when:
       - ansible_distribution == 'Ubuntu'
       - netplan_change.changed
```

下記はインベントリ例。KVM側のサーバユーザが ansibleユーザと違う場合は、`ansible_user`で設定しておく

```ini:inventry.ini
[all]
nuc02 ansible_host=192.168.129.2
nuc04 ansible_host=192.168.129.4
[cockpithost]
nuc02
nuc04
```

実行コマンド例は下記の通り

```sh
ansible-playbook -i inventry.ini playbook_kvm_cockpit_servers.yml -Kk
```

設定後にブラウザで `https://[サーバアドレス]:9090` にアクセスすると管理画面にアクセス可能

以上で構築完了

## 動作確認

管理画面にアクセスして下記操作を実施する

- 管理画面操作にログイン
- ネットワークでの `Bridge` 作成
- 仮想マシン作成

### 管理画面操作にログイン

ホストIP + ポート 9090 に https でアクセスするとログイン画面が出るので、OS インストール時に設定したユーザ名・パスワードでログインする

![スクリーンショット 2025-02-23 11.42.53.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/326183/340d6e4a-71c4-4fd6-a0ed-2abc67c56c03.png)

ログイン後の画面は下記の通り

![スクリーンショット 2025-02-22 23.51.32.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/326183/b637f8ff-cdd3-4236-9c8c-fff657945efe.png)

Rocky9 の場合は下記の通り

![スクリーンショット 2025-02-23 11.47.36.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/326183/6e415784-0230-4f76-9c36-5bb1a71c4a43.png)


![スクリーンショット 2025-02-23 11.46.59.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/326183/2b3a2620-27d4-49a5-b291-e0c8c47a86b2.png)

以降は操作方法がインターフェース名以外は同じになるので、Rocky9 の画面の例のみ記載する

### ネットワークでの `Bridge` 作成

`ネットワーキング` 画面で `Bridge` の作成を試す

![スクリーンショット 2025-02-23 11.49.00.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/326183/461eb0fd-3b53-41ec-bcd9-a3e8c74451f5.png)

#### Bridge0 (NIC1番目) の追加

`ブリッジの追加` をクリックすると、下記の画面が出るので、
上位ポート `eno1` を選択して `追加` をクリックする

![スクリーンショット 2025-02-23 11.50.50.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/326183/4538484c-a94c-4e44-b1fa-7b9f5c5413f0.png)

追加されると、`bridge0` が作成される

![スクリーンショット 2025-02-23 11.51.28.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/326183/e0a88bf7-d240-4d1e-b963-039ac1567a8b.png)

##### Ubuntu の場合の注意点
Ubuntu の場合は、Bridge の MAC アドレスが NIC の MAC アドレスを踏襲しないので、DHCP 環境だと別のアドレスがアサインされるため、Bridge の MAC アドレスで再度 DHCP サーバ側の払い出し設定が必要になる
外部アクセス環境で設定する場合は、別 NIC 側の設定後 (別 IP からもアクセスを可能にした後) に設定する方がよい


#### VLAN 識別ポート、Bridge1 (NIC2番目(USB-NIC箇所)) の追加

`VLAN の追加` をクリックすると、下記画面が出るので、
VLAN Trunk を収容しているポート (ここでは `enpOs2OfOu3`) を`親`にして、
`VLAN ID` を収容したい VLAN ID (ここでは `300`) に設定して、
名前をつけて(ここではデフォルト命名される名前) にして `追加` をクリックする

![スクリーンショット 2025-02-23 11.54.11.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/326183/1ce44091-60e1-41b1-9453-46b19679d047.png)

追加するとインターフェースが追加される

![スクリーンショット 2025-02-23 11.56.52.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/326183/dd82ab81-6687-4c13-8d28-4c676fdd98b2.png)

追加したインターフェースをもとにブリッジ追加をするために、`ブリッジの追加`をクリックする
ポートを追加したインターフェースを選択して `追加` をクリックする

![スクリーンショット 2025-02-23 11.58.09.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/326183/e6552d49-9095-4b52-a8aa-c50540e37751.png)

追加されると下記の画面となる

![スクリーンショット 2025-02-23 11.59.02.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/326183/cd488d8c-99a3-4420-a8c5-bc83db3d2400.png)

##### Ubuntu の場合の注意点
Ubuntu では USB-NIC のインターフェース名が長くなるので、名前の長さが VLAN ID つけると違反する場合があるので、その場合は適切な名前を付与する必要がある

### 仮想マシン作成

各サブネット向けに VM 作成を試して外部疎通が可能なことまで確認する

`仮想マシン` タブにアクセスする

![スクリーンショット 2025-02-23 12.01.30.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/326183/a107170a-4f4e-4a1d-8ad3-e35bdc4e5c1e.png)

`仮想マシンの作成` をクリックすると下記画面が出てくるので、
`OS をダウンロードします` にすると事前用意なくダウンロードして作成が可能で (Air Gap 環境でなければ)、
`オペレーティングシステム` で作成したい VM を選択するして作成できる
`作成して編集する` を選ぶと起動前に他の設定も可能なので、一度そちらをクリックする

![スクリーンショット 2025-02-23 12.04.59.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/326183/ec0be657-c4c6-4b88-a0c5-dedfe449a120.png)

![スクリーンショット 2025-02-23 12.03.19.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/326183/1f508ddf-7b92-44b1-87c5-acd621df3b15.png)

`作成して編集する` をクリック後は下記のような画面になる
ネットワークインターフェースで接続するブリッジの選択や、仮想 NIC の MAC アドレスが表示されるので環境内の DHCP 側に登録して Static に払い出す設定を事前にすることも可能
ここではそのまま `インストール` をクリックする

![スクリーンショット 2025-02-23 12.07.40.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/326183/e9ccc166-2fba-45cf-ad11-609f27916a2d.png)

しばらくするとインストーラが起動して`コンソール`箇所に仮想マシンのコンソールが表示され操作可能になる (`コンソール`ブロックの`展開[ ]`をクリックするとコンソールブロックのみの表示に拡大できる)

![スクリーンショット 2025-02-23 12.12.34.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/326183/ab716f50-3f90-47a8-a508-62a4d7758e60.png)

設定諸々してインストール完了するとログイン画面が表示されるので、アドレス確認して外部から SSH でログイン可能なことを確認できる

![スクリーンショット 2025-02-23 12.37.54.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/326183/6dddeaa6-23b4-4a1e-8585-7423080cbeec.png)

![スクリーンショット 2025-02-23 12.42.29.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/326183/c6b4a103-db66-4bde-aac0-368c4a6decaf.png)

2つ目の VM として別の IP サブネットで作成する。ネットワーク設定以外は上記と同じなので`作成して編集`まで進める

NIC の所属 Bridge を変更するために `ネットワークインターフェース` の対象 NIC の `編集` で変更する (2NIC目にする場合は `ネットワークインターフェースの追加`で追加も可能)

![スクリーンショット 2025-02-23 12.49.43.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/326183/d725dc70-a166-4e75-9c7c-71ee4df781d8.png)

`ソース`で対象の Bridge を設定して `保存`する

![スクリーンショット 2025-02-23 12.50.14.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/326183/224f223d-3937-41ce-a4c5-e03db2fb5195.png)

インストール後にアクセスすると別のサブネットで作成・疎通ができるところまで確認できた

![スクリーンショット 2025-02-23 13.13.15.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/326183/7e4b2cc7-242f-44ea-bda6-42905f201675.png)


## おわりに

Cockpit を使用することで、簡易的に仮想マシン環境を構築できることが確認できた

管理機能は他にもいろいろありそうなので、詳細は [Cockpit 公式ページ](https://cockpit-project.org/
)などを見て試すのが良さそう

## 参考

https://cockpit-project.org/


## Tips

Wake-on-LAN を有効化する方法 (Ubuntu で NIC が `enp86s0` の場合)

```sh
sudo ethtool -s enp86s0 wol g
```

```yaml
- name: Enable Wake-on-LAN
  hosts: cockpithost
  become: yes
  tasks:
    - name: Ensure netplan configuration supports WoL
      lineinfile:
        path: /etc/netplan/50-cloud-init.yaml
        insertafter: '^            dhcp4: true'
        line: '            wakeonlan: true'
      register: netplan_change
      when:
       - ansible_distribution == 'Ubuntu'

    - name: Apply Netplan configuration if changed (Ubuntu)
      command: netplan apply
      become: yes
      when:
       - ansible_distribution == 'Ubuntu'
       - netplan_change.changed
```