AlmaLinux 9 の仮想マシンを複数作成する際の、最小インストールからの変更箇所

この記事は自分用のメモです。

何かの練習や実験で Linux 仮想マシンを作成するとき、とくに複数の仮想マシンを作成してネットワークを構成する際に、OSインストール済みの仮想マシンを複製して必要な個数をそろえることがあります。このとき、複製後の仮想マシン同士で同一にしたいため複製前にしたい設定もあれば、競合しないように仮想マシンごとに変更すべき設定もあります。この記事はその作業一覧です。

## 環境

- 物理マシン: Windows 10
- 仮想化: Oracle VM VirtualBox 7.0.20
- 仮想マシンにインストールするOS: AlmaLinux 9

## 前提条件

### 仮想マシンの設定

- ネットワークアダプタは、「NAT」と「ホストオンリーアダプタ」
    - 仮想マシンからインターネットへのアクセス、仮想マシン同士の通信、ホストマシンから仮想マシンへの ssh 接続が可能な構成

### OSインストール時の設定

- AlmaLinux 9 を「最小インストール」でインストール済み
- root ユーザを使用可能、ただし ssh での root への直接ログインは不可
    - 使用不可でも問題なさそう
- 管理者ユーザとして se という名前のユーザを作成済
    - パスワードを設定済み
    - ssh で se へログインできることを確認済み
- ホスト名は tempalma
- ネットワークアダプタ (NAT) は、DHCPを使用 (デフォルトから変更なし)
- ネットワークアダプタ (ホストオンリーアダプタ) は IPv6 を無効にし、IPv4 は手動設定

## 仮想マシン複製前の設定変更箇所

作成する全ホストで共通の設定があれば、複製前に済ませておくと手順を省略できます。

### ユーザ・グループの作成

- 参考
    - [RedHat Documentation](https://docs.redhat.com/ja/documentation/red_hat_enterprise_linux/9/html/configuring_basic_system_settings/managing-users-from-the-command-line_managing-users-and-groups)

全ホスト共通のユーザが必要であれば、複製前に作成しておきます。手間を減らせることも理由の一つですが、うっかり各ホストの同名ユーザに異なるUIDを割り当ててしまうミスを防げるというメリットもあります。UID割り当てが同一であることは NAS 内のファイルのアクセス制御などで必要となります。

:::note info
複製後に個々の仮想ホストでユーザ・グループを作成する場合でも、UID・GIDを明示して作成することで、ホスト間の同名ユーザ・同名グループに同じUID・GIDを割り当てることは可能です。ここでは、あくまで、より少ない手間で実現するための方法として複製前のユーザ作成を勧めています。
:::

:::note info
仮想ホスト群の構築完了後に動的にユーザをいくつも増やしていく想定であれば、構築時の手間は増えますが LDAP によるログインなど統括的にユーザ情報を管理する仕組みの導入を検討してもよいかもしれません。
:::

以下の例では、新規ユーザ `user01` を作成します。

```console
$ sudo -s

# # UID やグループなどの指定があれば、オプション引数で指定する
# useradd user01

# # パスワードを設定する
# passwd user01

# # ユーザが作られたこと、ログインできることを確認する
# id user01
# exit
$ su - user01
```


### 公開鍵 (物理マシンからの SSH 接続用) の登録

- 参考
    - https://learn.microsoft.com/ja-jp/windows-server/administration/openssh/openssh_keymanagement

物理マシンから各ホストへ鍵認証でログインする場合、公開鍵を各ホストに登録する必要があります。通常はどのホストにも共通の鍵でログインすることになると思うので、複製前に登録しておくことで手間を省くことができます。

まず、物理マシン側で鍵ペアを作成します。方法は何でもよいですが、ここでは ssh-keygen を使用します。

```console:鍵生成 (PowerShell)
> ssh-keygen
```

生成された鍵ペアのうち公開鍵の方を、ログイン先のユーザの `authorized_keys` に追記します。今回の例ではユーザ名が `se` なので、`/home/se/.ssh/authorized_keys` に追記します。以下の例では、そのファイルを作るところから実行しています。

```console:ログイン中のユーザへ公開鍵を登録
$ # ファイルの存在を確認
$ ls -l ~/.ssh ~/.ssh/authorized_keys

$ # .ssh ディレクトリがない場合は作成する。パーミッションは 700
$ mkdir -m 700 ~/.ssh

$ # authorized_keys がない場合は作成する。パーミッションは 600
$ touch ~/.ssh/authorized_keys
$ chmod 600 ~/.ssh/authorized_keys

$ # 公開鍵の追記。
$ # 以下のコマンドでは、作った公開鍵を scp 等でこの仮想ホストに送ってあることを前提にしている。
$ # vim 等で追記してもよい
$ cat key.pub >> ~/.ssh/authorized_keys
```

### 公開鍵 (仮想ホスト間通信用) の登録

場合によっては、仮想ホスト同士での SSH 接続をする予定があるかもしれません。その場合、__鍵をホストごとに変える必要が無ければ__ 複製前に鍵を生成・登録しておくことで手間を減らすことができます。

ここでは、全ホスト間でユーザ se からユーザ se への鍵認証による SSH 接続が必要であることを前提に作業します。

まず、接続元ユーザ (se) で鍵ペアを作成します。

```console:鍵生成 (Linux)
$ ssh-keygen
```

次に、接続先ユーザへ鍵を登録します。今回のケースでは接続元と同じユーザなので、下記のような簡単な手順でできます。

```console:ログイン中のユーザへ公開鍵を登録
$ # ~/.ssh と ~/.ssh/authorized_keys の存在確認と作成の方法はすでに述べたので省略

$ # 公開鍵の追記。
$ # 以下のコマンドでは、先ほど作成した公開鍵のファイル名が id_rsa.pub であることを前提にしている。
$ # vim 等で追記してもよい
$ cat ~/.ssh/id_rsa.pub >> ~/.ssh/authorized_keys
```

### hosts の作成

仮想ホスト間で互いに名前解決できるようにしたい場合、その方法の一つとして hosts ファイルにIPアドレスとホスト名 (あるいはドメイン名) を記載する方法があります。この方法をとる場合、全仮想ホストの hosts に同じ内容を書き込むため、複製前に実施することで手間を省くことができます。

まず、これから作る予定の全仮想ホストのホスト名とIPアドレスを計画し決定します。例として、ここでは次のように計画したとします。

| ホスト名 | IPアドレス |
|:-----------|:--------------|
| node001    | 192.168.56.33 |
| node002    | 192.168.56.34 |
| node003    | 192.168.56.35 |


この内容を、次のようにコピー元ホストの `/etc/hosts` に記載します。

```conf:/etc/hosts
127.0.0.1   localhost localhost.localdomain localhost4 localhost4.localdomain4
::1         localhost localhost.localdomain localhost6 localhost6.localdomain6
# ↑ もともと書いてある内容は、理由が無ければそのまま残しておく

192.168.56.33  node001
192.168.56.34  node002
192.168.56.35  node003
```

### 必要なソフトウェア等のインストール

各仮想ホスト共通で必要なソフトウェアがわかっている場合、複製前にインストールしておくことで手間を減らすことができます。たとえば次のソフトウェアを検討します。

- 今回仮想ホストによるネットワークを作る主目的であるミドルウェアなど
- git
- docker-cli


## 各仮想マシンでの設定変更箇所

以下の手順を順に実行します。特別に記載がない場合、ホストマシンから ssh で仮想マシンのホストオンリーアダプタへ se ユーザとしてログインした状態で作業します。

### ホスト名

参考: [RedHat Documentation](https://docs.redhat.com/ja/documentation/red_hat_enterprise_linux/9/html/configuring_and_managing_networking/proc_changing-a-hostname-using-hostnamectl_assembly_changing-a-hostname#proc_changing-a-hostname-using-hostnamectl_assembly_changing-a-hostname)

主に `hostnamectl` を使用します。

まず、現在のホスト名を下記のコマンドで確認します。

```console
$ hostnamectl status --static
tempalma
```

ホスト名の変更は `hostnamectl set-hostname <new-name>` でできます。次の例ではホスト名を node001 に変更します。管理者権限が必要なため、ここでは `sudo` を使用します。

```console
$ sudo hostnamectl set-hostname node001
```

設定を有効にするため、下記のコマンドで再起動します。

```console
$ sudo reboot
```

再起動後、再度ログインしたらもう一度ホスト名を確認し、目的のホスト名に変わっていれば完了です。

### IP アドレス・フィンガープリント

- 参考
    - https://qiita.com/mtn_kt/items/633bd5e3e00732af564e
    - https://rurukblog.com/post/ssh-fingerprint/

ホストオンリーアダプタに手動設定した IP アドレスを変更します。主に `nmcli` を使用します。

まずネットワークアダプタのデバイス名を知るために `nmcli device` を使用します。

```console
$ nmcli device
DEVICE  TYPE      STATE            CONNECTION
enp0s3  ethernet  接続済み         enp0s3
enp0s8  ethernet  接続済み         enp0s8
lo      loopback  接続済み (外部)  lo
```

次にどのデバイスが目的のアダプタか、またそのアダプタの現在の設定を知るために `nmcli -f ipv4 con show <device>` を使用します。


```console
$ nmcli -f ipv4 con show enp0s8
ipv4.method:                            manual
ipv4.dns:                               192.168.56.1
ipv4.dns-search:                        --
ipv4.dns-options:                       --
ipv4.dns-priority:                      0
ipv4.addresses:                         192.168.56.10/24
ipv4.gateway:                           192.168.56.1
（略）
```

目的のデバイスを確認したら、`nmcli con mod <device> ipv4.addresses <address-with-musk-length>` を使用して IP アドレスの設定を変更します (反映はまだされません)。

```console
$ sudo nmcli con mod enp0s8 ipv4.addresses "192.168.56.33/24"
```

IPアドレスの反映の前に、ここではフィンガープリントもコピー元の仮想マシンと別のものになるよう変更します。そのためには、下記のコマンドで sshd が自動生成する鍵ペアを削除します (再生成はまだされません)。

```console
$ ls -l /etc/ssh/ssh_host_*_key /etc/ssh/ssh_host_*_key.pub
-rw-r--r--. 1 root root         82  5月 18 11:59 ssh_host_ed25519_key.pub
-rw-r-----. 1 root ssh_keys    387  5月 18 11:59 ssh_host_ed25519_key
-rw-r--r--. 1 root root        162  5月 18 11:59 ssh_host_ecdsa_key.pub
-rw-r-----. 1 root ssh_keys    492  5月 18 11:59 ssh_host_ecdsa_key
-rw-r--r--. 1 root root        554  5月 18 11:59 ssh_host_rsa_key.pub
-rw-r-----. 1 root ssh_keys   2578  5月 18 11:59 ssh_host_rsa_key
$ sudo rm -f /etc/ssh/ssh_host_*_key /etc/ssh/ssh_host_*_key.pub
```

:::note info
フィンガープリントの更新は、必ずしも必要ではありません。
:::

IP アドレスの反映と鍵ペアの再生成は、今回はマシンごと再起動することで実施します (ネットワークを down すると ssh 接続が切れてしまい再開もできないため)。

```console
$ sudo reboot
```

:::note info
ネットワーク回りの操作をする場合、ssh 接続ではなく直接操作するほうが良いかもしれません。そのようにしていれば、`service sshd restart` で鍵ペアを再生成したあと、 `nmcli con down <device>`, `nmcli con up <device>` で IP アドレスの変更を反映できます。
:::

再起動後は変更後の IP アドレスになっているはずなので、今後の ssh 接続では新しい IP アドレスを接続先として指定しましょう。