自宅サーバー構築譚：Xubuntu 22.04 LTS on ZFS in ノートパソコン(UEFI+wifi)

# 能書き

[自宅サーバー構築譚：基本構想](https://qiita.com/katz_engineer/items/cb592be44daa28a51d9b)に基づく自宅サーバー構築、[Ubuntu22.04LTSインストールその2](https://qiita.com/katz_engineer/items/033471b69143bf76650e)の続き。

[Hyper-V に Xubuntu 22.04 LTS をインストールして成功した](https://qiita.com/katz_engineer/items/f02604adc8b523c5d645)訳ですが、それを踏まえて実機にインストールします。

# 参考文献

- [自宅サーバー構築譚：Xubuntu 22.04 LTS on ZFS in Hyper-V（第2世代） - Qiita](https://qiita.com/katz_engineer/items/f02604adc8b523c5d645)
- [俺様サーバー構築記 - ZFS の上に Arch Linux と無線LANをインストール; やり直し(Linux-LTS)@ノートパソコン(UEFI+wifi) - Qiita](https://qiita.com/katz_engineer/items/128364a91633f83fd412)

# 環境

[以前扱った、かつて悪評高かったマシン](https://qiita.com/katz_engineer/items/128364a91633f83fd412#%E5%89%8D%E6%9B%B8%E3%81%8D%E3%83%9E%E3%82%B7%E3%83%B3%E3%82%B9%E3%83%9A%E3%83%83%E3%82%AF)になります。そのスペックを再掲します。

- 機種：HP Pavilion TouchSmart 10-e013AU
- 型番: F6C99PA#ABJ
- CPU: AMD A4-1200 APU with Radeon(TM) HD Graphics
- クロック: 1.00GHz
- メモリ: 2GB
- HDD: 320GB

これに Xubuntu で ZFS というとパワー不足感が溢れ出しそうですが。まぁ、頑張ってみます。

# インストール環境の整備

暗号化はしない方針です。家庭用なので。

## デスクトップインストーラーを起動しsshの環境整備

[デスクトップマシンへインストールした時に作成したUSBメモリ](https://qiita.com/katz_engineer/items/033471b69143bf76650e#%E3%83%87%E3%82%B9%E3%82%AF%E3%83%88%E3%83%83%E3%83%97%E3%82%A4%E3%83%B3%E3%82%B9%E3%83%88%E3%83%BC%E3%83%A9%E3%83%BC%E3%82%92%E8%B5%B7%E5%8B%95%E3%81%97ssh%E3%81%AE%E7%92%B0%E5%A2%83%E6%95%B4%E5%82%99)を再利用します。

内容はデスクトップ版のisoです。Ubuntuのサイトからダウンロードして、USBメモリに焼いた物です。私は普段使いのWin10マシンで[Rufus](https://forest.watch.impress.co.jp/library/software/rufus/)というツールを使ってみましたが、ここはお好みで。

このUSBメモリをインストール対象マシンに挿入して、ここから起動。

GUI インストーラーが立ち上がって Welcome という画面が表示されたら、 TAB キーを押して Try Ubuntu ボタンにフォーカスを移動して（ボタンにオレンジの枠がつきます） Enter キーを押します。

ウィンドウ環境に切り替わったら、まず最初にWi-Fiを設定して通信環境を確保します。わかりやすいGUIがありますので、画面上で確認しながらマウス操作します。

それからターミナルを起動しますが、マウス操作またはショートカットキー Ctrl+Alt+T でどうぞ。

主な作業はsshで接続して行いたいので、そのように準備します。sshで接続するのはコマンドをコピペできるから。

ターミナルで下記のコマンドを実行。

```console
sudo apt update
```

OpenSSHサーバーと、フルのvimをインストール。

```console
sudo apt install --yes openssh-server vim
```

ssh接続用にユーザー ubuntu のパスワードを設定。

```console
passwd
```

ssh接続先のIPアドレスを確認します。

```console
ip a
```

## 別のマシンから対象のマシンにsshしてインストール作業を続行

sshはほとんどのOSで利用可能でしょう。Windows10でもコマンドプロンプトからsshコマンドを実行できます。

```console
ssh ubuntu@接続先のIPアドレス
```

インストール作業を同じマシンでやり直してたりすると、ここでエラーが出る事があります。そんな時には ```.ssh\known_hosts``` を削除してから、sshコマンドを実行します。

```console
del %USERPROFILE%\.ssh\known_hosts
```

rootユーザーになります。

```console
sudo -i
```

debootstrapとZFSを Live CD 環境にインストールします。

```console
apt install --yes debootstrap gdisk zfsutils-linux
```

```console
systemctl stop zed
```

# ディスクのフォーマット

フォーマット対象ディスクを確認します。

```console
lsblk
```

今回は下記のように表示されます。[以前 ArchLinux on ZFS でインストールしたマシン](https://qiita.com/katz_engineer/items/128364a91633f83fd412)なので、その名残が見えます。

```console
root@ubuntu:~# lsblk
NAME   MAJ:MIN RM   SIZE RO TYPE MOUNTPOINTS
loop0    7:0    0   2.1G  1 loop /rofs
loop1    7:1    0     4K  1 loop /snap/bare/5
loop2    7:2    0    62M  1 loop /snap/core20/1587
loop3    7:3    0 400.8M  1 loop /snap/gnome-3-38-2004/112
loop4    7:4    0 163.3M  1 loop /snap/firefox/1635
loop5    7:5    0  45.9M  1 loop /snap/snap-store/582
loop6    7:6    0  91.7M  1 loop /snap/gtk-common-themes/1535
loop7    7:7    0    47M  1 loop /snap/snapd/16292
loop8    7:8    0   284K  1 loop /snap/snapd-desktop-integration/14
sda      8:0    0 298.1G  0 disk
└─sda4   8:4    0 298.1G  0 part
sdb      8:16   1   7.5G  0 disk
├─sdb1   8:17   1   512M  0 part
└─sdb3   8:19   1     2G  0 part
sdc      8:32   1  58.2G  0 disk
└─sdc1   8:33   1  58.2G  0 part /cdrom
```

`loop0`～`loop8`はインストーラによる設定でしょうか。
`sda`が内蔵HDDです。
`sdb`が、起動用に利用するUSBメモリになります。
`sdc`はインストーラです。

ディスクの指定にはIDを使います。

```console
ls -l /dev/disk/by-id
```

これを変数に設定するのがubuntu流らしいですが、ここは私の流儀で取得する事にします。

```console
BOOTDISK=$(cd /dev/disk/by-id; ls ata-* usb-* | while read d; do if [ "$(readlink -f $d)" = "/dev/sdb" ]; then echo "/dev/disk/by-id/$d"; fi; done)
```

```console
DISK=$(cd /dev/disk/by-id; ls ata-* usb-* | while read d; do if [ "$(readlink -f $d)" = "/dev/sda" ]; then echo "/dev/disk/by-id/$d"; fi; done)
```

スワップパーティションが使用されていない事を確認します。

```console
swapoff --all
```

USBメモリのパーティションを全削除します。

```console
wipefs -a $BOOTDISK
```

パーティションテーブルをクリアします。

```console
sgdisk --zap-all $BOOTDISK
```

ブートローダー パーティションを作成します。

```console
sgdisk -n1::+512M -t1:EF00 $BOOTDISK
```

ブートプールパーティションも、USBメモリ上に用意してみます。起動が遅くなるようでしたら考え直すかも知れません。

```console
sgdisk -n2::+4G -t2:BE00 $BOOTDISK
```

残りは適当に確保しておきます。

```console
sgdisk -n3:: $BOOTDISK
```

確認。

```console
sgdisk -p $BOOTDISK
```

結果は下記のようになります。

```console
# sgdisk -p $BOOTDISK
Disk /dev/disk/by-id/usb-SanDisk__Cruzer_Fit_4C530000111203116363-0:0: 15630336 sectors, 7.5 GiB
Sector size (logical/physical): 512/512 bytes
Disk identifier (GUID): 36D7086B-6EE7-4A91-B095-9E974346DF16
Partition table holds up to 128 entries
Main partition table begins at sector 2 and ends at sector 33
First usable sector is 34, last usable sector is 15630302
Partitions will be aligned on 2048-sector boundaries
Total free space is 2014 sectors (1007.0 KiB)

Number  Start (sector)    End (sector)  Size       Code  Name
   1            2048         1050623   512.0 MiB   EF00
   2         1050624         9439231   4.0 GiB     BE00
   3         9439232        15630302   3.0 GiB     8300
```

そしてメインのHDD。そのパーティションを全削除します。

```console
wipefs -a $DISK
```

パーティションテーブルをクリアします。

```console
sgdisk --zap-all $DISK
```

スワップについて。[参考文献](https://openzfs.github.io/openzfs-docs/Getting%20Started/Ubuntu/Ubuntu%2022.04%20Root%20on%20ZFS.html#step-2-disk-formatting)によると、zvolにスワップを置くとデッドロックの危険性があるので非推奨だそうです。バグレポートが上がっているらしい。
しかし Linux ではスワップを有効にした方が、メモリ管理の都合上、良いらしいです。今回はメモリが不足しているという意味もあります。

```console
sgdisk -n1:0:+4G -t1:8200 $DISK
```

ルートプールパーティションを作成します。

```console
sgdisk -n2:0:0 -t2:BF00 $DISK
```

設定を確認するコマンドは下記になります。

```console
sgdisk -p $DISK
```

確認の結果。

```console
# sgdisk -p $DISK
Disk /dev/disk/by-id/ata-ST320LT012-1DG14C_S3P11L17: 625142448 sectors, 298.1 GiB
Sector size (logical/physical): 512/4096 bytes
Disk identifier (GUID): 57F67CC9-3CC3-452E-B299-BA132A25058C
Partition table holds up to 128 entries
Main partition table begins at sector 2 and ends at sector 33
First usable sector is 34, last usable sector is 625142414
Partitions will be aligned on 2048-sector boundaries
Total free space is 2014 sectors (1007.0 KiB)

Number  Start (sector)    End (sector)  Size       Code  Name
   1            2048         8390655   4.0 GiB     8200
   2         8390656       625142414   294.1 GiB   BF00
```

いよいよzfsフォーマットします。ここが今回最大のコピペポイント！これをコピペする為にssh経由で接続していると言っても過言ではありません。

因みにこのzpool名は```bpool```固定らしい。変更したい場合は```update-grub```後に```/etc/grub.d/10_linux_zfs```を修正すればいいらしいのですが、試していません。

※なおインストール2回目以降でエラーが出る際には、コマンドの末尾かどこかに ```-f``` オプションを付加します。

```console
zpool create \
    -o ashift=12 \
    -o autotrim=on \
    -o cachefile=/etc/zfs/zpool.cache \
    -o compatibility=grub2 \
    -o feature@livelist=enabled \
    -o feature@zpool_checkpoint=enabled \
    -O devices=off \
    -O acltype=posixacl -O xattr=sa \
    -O compression=lz4 \
    -O normalization=formD \
    -O relatime=on \
    -O canmount=off -O mountpoint=/boot -R /mnt \
    bpool ${BOOTDISK}-part2
```

エラー「not in specified 'compatibility' feature set.」（指定された「互換性」機能セットにない）は無視します。

そしてルートプールを作成します。こちらのzpool名は何でも良いそうです。zfsの伝統に則って```tank```にしてみました。

```console
zpool create \
    -o ashift=12 \
    -o autotrim=on \
    -O acltype=posixacl \
    -O xattr=sa -O dnodesize=auto \
    -O compression=lz4 \
    -O normalization=formD \
    -O relatime=on \
    -O canmount=off -O mountpoint=/ -R /mnt \
    tank ${DISK}-part2
```

作成したプール一覧の確認は下記。このコマンドはコピペではなくて ```zpool list``` ```zpool status```と手打ちでお願いします。別に良いよねこの位は。

```console
# zpool list
NAME    SIZE  ALLOC   FREE  CKPOINT  EXPANDSZ   FRAG    CAP  DEDUP    HEALTH  ALTROOT
bpool  1.88G   612K  1.87G        -         -     0%     0%  1.00x    ONLINE  /mnt
tank    294G   504K   294G        -         -     0%     0%  1.00x    ONLINE  /mnt
# zpool status
  pool: bpool
 state: ONLINE
status: One or more features are enabled on the pool despite not being
        requested by the 'compatibility' property.
action: Consider setting 'compatibility' to an appropriate value, or
        adding needed features to the relevant file in
        /etc/zfs/compatibility.d or /usr/share/zfs/compatibility.d.
config:

        NAME                                                      STATE     READ WRITE CKSUM
        bpool                                                     ONLINE       0     0     0
          usb-SanDisk__Cruzer_Fit_4C530000111203116363-0:0-part2  ONLINE       0     0     0

errors: No known data errors

  pool: tank
 state: ONLINE
config:

        NAME                                    STATE     READ WRITE CKSUM
        tank                                    ONLINE       0     0     0
          ata-ST320LT012-1DG14C_S3P11L17-part2  ONLINE       0     0     0

errors: No known data errors
```

最後に、USBメモリの余りパーティション。万が一に備えてFAT32でフォーマットしておきます。それならWindowsマシンでも読み書きできるので、何かあった際には緊急で利用できるでしょう。

```console
mkdosfs -F32 ${BOOTDISK}-part3
```

# システムのインストール

## ディレクトリ構造に合わせたデータセット作成

Linuxのディレクトリ構造については、[大昔にちょっと調べただけ](https://qiita.com/katz_engineer/items/3c4bafd3aeb32aa2eaf0)で実はあんまり良く分かっていません。その為なるべく[参考文献](https://openzfs.github.io/openzfs-docs/Getting%20Started/Ubuntu/Ubuntu%2022.04%20Root%20on%20ZFS.html)通りにしています。

コンテナとして機能するファイルシステムデータセットを作成します。

```console
zfs create -o canmount=off -o mountpoint=none tank/ROOT
zfs create -o canmount=off -o mountpoint=none bpool/BOOT
```

ルートおよびブート ファイル システムのファイル システム データセットを作成します。

[参考文献](https://openzfs.github.io/openzfs-docs/Getting%20Started/Ubuntu/Ubuntu%2022.04%20Root%20on%20ZFS.html)はUUID（っぽいランダムな6文字）を付加したデータセット名にしていますが、これをやると後々とっても扱いづらくなります。ubuntu以外はインストールしないし、複数インストールもしない予定なので、UUIDは無しの方向にしました。

```console
zfs create -o mountpoint=/ \
    -o com.ubuntu.zsys:bootfs=yes \
    -o com.ubuntu.zsys:last-used=$(date +%s) tank/ROOT/ubuntu

zfs create -o mountpoint=/boot bpool/BOOT/ubuntu
```

データセットを作成します。

```console
zfs create -o com.ubuntu.zsys:bootfs=no -o canmount=off tank/ROOT/ubuntu/usr
zfs create -o com.ubuntu.zsys:bootfs=no -o canmount=off tank/ROOT/ubuntu/var
zfs create tank/ROOT/ubuntu/var/lib
zfs create tank/ROOT/ubuntu/var/log
zfs create tank/ROOT/ubuntu/var/spool

zfs create -o canmount=off -o mountpoint=/ tank/USERDATA
zfs create -o com.ubuntu.zsys:bootfs-datasets=tank/ROOT/ubuntu \
    -o canmount=on -o mountpoint=/root tank/USERDATA/root
chmod 700 /mnt/root
```

[参考文献](https://openzfs.github.io/openzfs-docs/Getting%20Started/Ubuntu/Ubuntu%2022.04%20Root%20on%20ZFS.html#step-3-system-installation)から、今回必要なデータセットのオプションを選んで設定します。

```console
zfs create tank/ROOT/ubuntu/var/lib/apt
zfs create tank/ROOT/ubuntu/var/lib/dpkg
zfs create -o com.ubuntu.zsys:bootfs=no tank/ROOT/ubuntu/srv
zfs create tank/ROOT/ubuntu/var/lib/AccountsService
zfs create tank/ROOT/ubuntu/var/lib/NetworkManager
zfs create tank/ROOT/ubuntu/usr/local
```

LXDをインストールする為のsnapというパッケージ管理システムは、下記ディレクトリを使用します。

参考文献：[snapパッケージの関連ディレクトリ - 第714回 Firefoxを含むsnapパッケージとの付き合い方 - gihyo.jp](https://gihyo.jp/admin/serial/01/ubuntu-recipe/0714#sec4)

```console
zfs create tank/ROOT/ubuntu/snap
zfs create tank/ROOT/ubuntu/var/snap
zfs create tank/ROOT/ubuntu/var/lib/snapd
```

Dockerの為には下記ディレクトリを用意します。

```console
zfs create tank/ROOT/ubuntu/var/lib/docker
zfs create tank/ROOT/ubuntu/var/lib/containerd
```

```/run```に tmpfs をマウントします。

```console
mkdir /mnt/run
mount -t tmpfs tmpfs /mnt/run
mkdir /mnt/run/lock
```

なお```/home```はユーザー追加時に作成します。

## debootstrap

Ubuntu 22.04 LTS 通称 jammy をインストール。

```console
debootstrap jammy /mnt
```

終わったら以下のコマンドを実行します。

```console
mkdir /mnt/etc/zfs
cp /etc/zfs/zpool.cache /mnt/etc/zfs/
```

# システム構成

## マシン名

まずはホスト名を決めます。

```console
hostname ホスト名
```

```console
hostname >/mnt/etc/hostname
```

## ネットワーク関連

hostsファイルを修正。

```console
sed -i -e"/^127.0.0.1/a 127.0.1.1\t$(hostname)" /mnt/etc/hosts
```

netplanのネットワーク設定ファイル`/mnt/etc/netplan/01-netcfg.yaml`を作成します。まずはネットワークインターフェイス名を確認。イーサネットが`eno1`、wifiが`wlo1`のようです。

```console
# ip addr show
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
    inet 127.0.0.1/8 scope host lo
       valid_lft forever preferred_lft forever
    inet6 ::1/128 scope host
       valid_lft forever preferred_lft forever
2: eno1: <NO-CARRIER,BROADCAST,MULTICAST,UP> mtu 1500 qdisc fq_codel state DOWN group default qlen 1000
    link/ether a0:1d:48:e4:b4:b2 brd ff:ff:ff:ff:ff:ff
    altname enp5s0
3: wlo1: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc mq state UP group default qlen 1000
    link/ether 54:35:30:9b:f8:c5 brd ff:ff:ff:ff:ff:ff
    altname wlp1s0f0
    inet 192.168.0.104/24 brd 192.168.0.255 scope global dynamic noprefixroute wlo1
       valid_lft 83235sec preferred_lft 83235sec
    inet6 fe80::43bf:ae32:f816:8da8/64 scope link noprefixroute
       valid_lft forever preferred_lft forever
```

[以前の記事](https://qiita.com/katz_engineer/items/04396d58add14cb63573#%E3%83%87%E3%82%B9%E3%82%AF%E3%83%88%E3%83%83%E3%83%97%E3%83%91%E3%82%BD%E3%82%B3%E3%83%B3)の通りにIPアドレスを割り振ります。今回はDHCPにします。

参考文献：[固定IPアドレスの割当(IPv4、IPv6) - Netplanの使い方 - komeの備忘録](https://www.komee.org/entry/2018/06/12/181400#%E5%9B%BA%E5%AE%9AIP%E3%82%A2%E3%83%89%E3%83%AC%E3%82%B9%E3%81%AE%E5%89%B2%E5%BD%93IPv4IPv6)

更に、wifiの設定を追加します。パスワードは平文で書かずに暗号化してみます。

```console
WIFI_SSID=我が家のSSID
WIFI_PWD=パスワード
```

```console
cat > /mnt/etc/netplan/01-netcfg.yaml <<___
network:
  version: 2
  ethernets:
    eno0:
      dhcp4: true
  wifis:
    wlo1:
      access-points:
        "$WIFI_SSID":
          password: $(wpa_passphrase $WIFI_SSID $WIFI_PWD | grep "^[[:space:]]*psk=" | cut -d= -f2)
      dhcp4: true
___
```

## パッケージソース
```console
cat >/mnt/etc/apt/sources.list <<___
deb http://archive.ubuntu.com/ubuntu jammy main restricted universe multiverse
deb http://archive.ubuntu.com/ubuntu jammy-updates main restricted universe multiverse
deb http://archive.ubuntu.com/ubuntu jammy-backports main restricted universe multiverse
deb http://security.ubuntu.com/ubuntu jammy-security main restricted universe multiverse
___
```

## chroot

Live CD 環境の仮想ファイルシステムをバインドマウントして、上記でセットアップした環境に chroot します（ --bind ではなく --rbind を使っていることに注意）。

```console
mount --make-private --rbind /dev  /mnt/dev
mount --make-private --rbind /proc /mnt/proc
mount --make-private --rbind /sys  /mnt/sys
```

```console
chroot /mnt /usr/bin/env BOOTDISK=$BOOTDISK DISK=$DISK bash --login
```

chroot環境内のaptのインデクスを更新します。

```console
apt update
```

## ロケール

en_US.UTF-8 と ja_JP.UTF-8 と、後は個人的な好みで。私は ja_JP.EUC-JP を入れます。

```console
locale-gen --purge en_US.UTF-8 ja_JP.UTF-8 ja_JP.EUC-JP
```

## エディタ

個人的な好みで vi です。

```console
apt install --yes vim
```

## タイムゾーン

[参考文献](https://openzfs.github.io/openzfs-docs/Getting%20Started/Ubuntu/Ubuntu%2022.04%20Root%20on%20ZFS.html)には書かれていませんが、タイムゾーンを設定します。
日本なら Asia/Tokyo です。

```console
ln -sf /usr/share/zoneinfo/Asia/Tokyo /etc/localtime
```

```console
dpkg-reconfigure -f noninteractive tzdata
```

## EFIファイルシステム

EFIファイルシステムを作成します。

```console
apt install --yes dosfstools
```

```console
mkdosfs -F 32 -s 1 -n EFI ${BOOTDISK}-part1
mkdir /boot/efi
echo /dev/disk/by-uuid/$(blkid -s UUID -o value ${BOOTDISK}-part1) /boot/efi vfat defaults 0 0 >> /etc/fstab
```

```/etc/fstab```を設定したらすぐに```mount```したい所ですが、連続して実行するとなぜかエラーが発生します。一瞬の間が必要なようです。理由は不明。
と言う訳で下記```mount```コマンドは分けておきます。

```console
mount /boot/efi
```

```/boot/grub```を設定します。

```console
mkdir /boot/efi/grub /boot/grub
echo /boot/efi/grub /boot/grub none defaults,bind 0 0 >> /etc/fstab
mount /boot/grub
```

## カーネルイメージなど

LinuxのカーネルイメージとZFSをchroot環境にインストールします。wifiを扱う為のwpasupplicantパッケージもインストールします。

```console
apt install --yes grub-efi-amd64 grub-efi-amd64-signed linux-image-generic shim-signed zfs-initramfs zsys wpasupplicant
```

Windowsなど他のOSを入れる予定は無いので、os-proberを削除します。

```console
apt purge --yes os-prober
```

ここで下記のエラーが出ますが、これは無視して良さそうです。多分。

```console
ERROR couldn't connect to zsys daemon: connection error: desc = "transport: Error while dialing dial unix /run/zsysd.sock: connect: no such file or directory"
```

## rootパスワード

パスワードを設定します。

```console
passwd
```

## スワップを構成

下記コマンドを実行します。

```console
mkswap -f ${DISK}-part1
```

```console
echo /dev/disk/by-uuid/$(blkid -s UUID -o value ${DISK}-part1) none swap discard 0 0 >> /etc/fstab
```

```console
swapon -a
```

## tmpfs

次回起動時にtmpfsを`/tmp`にマウントするようにします。

```console
cp /usr/share/systemd/tmp.mount /etc/systemd/system/
systemctl enable tmp.mount
```

## システムグループ

無くてもいいかなと思ったけれど、一応Ubuntuなので、念の為に作成しておきます。

```console
addgroup --system lpadmin
addgroup --system lxd
addgroup --system sambashare
```

## SSH

SSHをインストールします。

```console
apt install --yes openssh-server
```

ここでも下記のエラーが出ますな。無視。

```console
ERROR couldn't connect to zsys daemon: connection error: desc = "transport: Error while dialing dial unix /run/zsysd.sock: connect: no such file or directory"
```

rootログインできるように設定。

```console
sed -i -e"/^#PermitRootLogin /a PermitRootLogin yes" /etc/ssh/sshd_config
```


# GRUB のインストール

## ZFSの認識

ZFSのブートファイルシステムが認識されていることを確認します。`zfs`と出力されればOKです。

```console
grub-probe /boot
```

## initrd更新

initrdファイルを更新します。

```console
update-initramfs -c -k all
```

## 設定ファイル

メモリのゼロ化を無効にします。

```console
sed -i -e'/^GRUB_CMDLINE_LINUX_DEFAULT=/s/"$/ init_on_alloc=0"/' /etc/default/grub
```

ブート構成を更新します。
```console
update-grub
```

## ブートローダーをインストール

UEFI用にGRUBをインストールします。

```console
grub-install --target=x86_64-efi --efi-directory=/boot/efi --bootloader-id=ubuntu --recheck --no-floppy
```

ZFSのモジュールがインストールされていることを確認します。

```console
ls /boot/grub/*/zfs.mod
```

`grub-initrd-fallback.service`を無効にします。

```console
systemctl mask grub-initrd-fallback.service
```

## ファイルシステムのマウント順序を修正

`zfs-mount-generator`を有効にする必要があります。これによりsystemdは個別のマウントポイントを認識します。これは`/var/log`や`/var/tmp`などにとって重要です。また、`rsyslog.service`は`local-fs.target`を介して`var-log.mount`に依存し、systemdの`PrivateTmp`機能を使用するサービスは自動的に`After=var-tmp.mount`を使うようになります。
……との事。なるほど、わからん！

```console
mkdir /etc/zfs/zfs-list.cache
touch /etc/zfs/zfs-list.cache/bpool
touch /etc/zfs/zfs-list.cache/tank
zed -F &
```

これらが空でない事をチェックして、キャッシュが更新された事を確認します。
空だった場合の対応は[参考文献](https://openzfs.github.io/openzfs-docs/Getting%20Started/Ubuntu/Ubuntu%2022.04%20Root%20on%20ZFS.html)を参照。

```console
cat /etc/zfs/zfs-list.cache/bpool
```

```console
cat /etc/zfs/zfs-list.cache/tank
```

キャッシュにデータが含まれたら`zed`を停止します。

```console
fg
(Ctrl-C)
```

パス`/mnt`を除去するように修正します。

```console
sed -Ei "s|/mnt/?|/|" /etc/zfs/zfs-list.cache/*
```

## chroot終了

chroot環境を終了して LiveCD 環境に戻ります。

```console
exit
```

## 初回のブート

LiveCD 環境で次のコマンドを実行して、すべてのファイルシステムをアンマウントします。

```console
mount | grep -v zfs | tac | awk '/\/mnt/ {print $3}' | xargs -n 1 -r umount -lf
```

```console
zpool export -a
```

なぜかエラーが出ます。原因不明。仕方が無いので放置します。

```console
# zpool export -a
cannot export 'tank': pool is busy
```

そのままシャットダウン。

```console
shutdown -h now
```

その後、インストールメディアを取り出して、それからマシンの電源を入れます。

## grub

案の定、grubでエラーが出ます。
ここで慌てず騒がず、grubのプロンプトで普通にzpoolをimportします。

```console
zpool import -f tank
exit
```

今度はちゃんと起動します。

## rootログイン

rootユーザーでパスワードを入力してログインします。それから`ip a`コマンドで IP アドレスを確認。

```console
# ip a
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
    inet 127.0.0.1/8 scope host lo
       valid_lft forever preferred_lft forever
    inet6 ::1/128 scope host
       valid_lft forever preferred_lft forever
2: eno1: <BROADCAST,MULTICAST> mtu 1500 qdisc noop state DOWN group default qlen 1000
    link/ether a0:b1:c2:d3:e4:f5 brd ff:ff:ff:ff:ff:ff
    altname enp5s0
3: wlo1: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc mq state UP group default qlen 1000
    link/ether a1:b2:c3:d4:e5:f6 brd ff:ff:ff:ff:ff:ff
    altname wlp1s0f0
    inet 192.168.0.104/24 metric 600 brd 192.168.0.255 scope global dynamic wlo1
       valid_lft 85056sec preferred_lft 85056sec
    inet6 fe80::5635:30ff:fe9b:f8c5/64 scope link
       valid_lft forever preferred_lft forever
```

SSHサーバを入れたので`ssh`で接続できます。取得したIPアドレスにssh接続、rootユーザーでパスワードを入力してログインします。

```console
del %USERPROFILE%\.ssh\known_hosts
ssh root@192.168.0.104
```

## ユーザーアカウントの作成

最初のユーザー、管理者アカウントを作成します。

```console
username=ユーザー名
```

```console
zfs create -o com.ubuntu.zsys:bootfs-datasets=tank/ROOT/ubuntu -o canmount=on -o mountpoint=/home/$username tank/USERDATA/$username
adduser $username
```

```console
cp -a /etc/skel/. /home/$username
chown -R $username:$username /home/$username
usermod -a -G adm,cdrom,dip,lpadmin,lxd,plugdev,sambashare,sudo $username
```

# フルのソフトウェアインストール

ミニマムインストールをアップグレードします。

```console
apt dist-upgrade --yes
```

デスクトップ用としてGUI環境をインストールします。今回もXubuntuにしてみます。

```console
apt install --yes xubuntu-desktop
```

Xubuntuインストールの途中でgdm3かlightdmかどちらにするかの選択画面が表示されます。軽さの点ではlightdmの方が上のようですな。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/107218/f1d1fe0f-e02a-94cd-756f-b5d4b3d6bf44.png)

GUI環境をインストールする場合はNetworkManagerを使用してのネットワーク管理が推奨されています。Xubuntuも同じでいいよね、多分。

```console
rm /etc/netplan/01-netcfg.yaml
cat >/etc/netplan/01-network-manager-all.yaml <<___
network:
  version: 2
  renderer: NetworkManager
___
```

## 日本語キーボード配列

サーバーのコンソールで記号を打ってみるとわかりますが、英語配列になっています。日本語配列に変更する手順は以下の参考文献を参照。バージョンは古いですが、画面キャプチャがあるのでわかりやすいです。

参考文献：[Ubuntuでキーボードレイアウト変更 - Ragnite Blue](https://thejuraku.com/pc/ubuntu%E3%81%A7%E3%82%AD%E3%83%BC%E3%83%9C%E3%83%BC%E3%83%89%E3%83%AC%E3%82%A4%E3%82%A2%E3%82%A6%E3%83%88%E5%A4%89%E6%9B%B4/)

コマンドは下記。

```console
dpkg-reconfigure keyboard-configuration
```

設定後、次のコマンドを打つ必要があるようです。

```console
setupcon
```

# 再起動して確認

```console
reboot
```

GUI画面でログインします。それからwifiを再設定。XubuntuのGUI画面上で、wifiを設定し直します。

そして確認。

- キーボードが日本の配列になっている事。アットマーク @ を打ってみて確認。
- ネットワ－クが有効になっている事。次のようなコマンドを試してみればわかります。
※ example.com はドメインの例示の際に使うべしとRFC2606で定められています。何か適当なサーバーを選んで下さい。

```console
ping -c2 example.com
```

# root無効化

引き続きGUI画面で作業するか、あるいはssh接続。
そしてrootパスワードを無効にします。

```console
sudo usermod -p '*' root
```

rootでのSSHログインを無効（というか禁止）にします。

```console
sudo sed -i -e"/^PermitRootLogin /s/yes/no/" /etc/ssh/sshd_config
```

一度ログアウトして、rootではログインできない事を確認します。

# Xubuntuの日本語設定

Xubuntuの日本語化を設定します。

メインメニュー > Settings > Language Support

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/107218/62f97185-5c70-2232-4e20-0dbc584fdeb2.png)

Language Support ダイアログ > Install / Remove Languages... ボタン

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/107218/f88fac4a-99f7-b20c-8b92-87414791b7fc.png)

Installed Languages ダイアログで Japanese をチェックして Apply ボタンをクリック。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/107218/6fdd464b-37b6-f600-778d-4b0ed86e0fde.png)

パスワードを要求されますので入力します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/107218/43fb1431-2820-92a5-5916-fab52280b14d.png)

待つ事しばし。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/107218/2eedf4fb-623f-a572-4dbc-400032dbfea5.png)

日本語が追加されますが、未選択状態です。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/107218/b9cc932d-749e-a8f1-4e0e-4a192d338c4b.png)

未選択のままダイアログを閉じます。そして一度ログアウトします。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/107218/bed80f61-c517-f220-e666-0d3fd7cf438f.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/107218/739b84ac-a0f9-3274-ac6a-46670381aa10.png)

ログイン画面において、画面上部の「en」の箇所をクリック。
ドロップダウンメニューが出るので「Japanese - Japan」を選択します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/107218/65068487-6228-e755-d2c0-9a06aaade575.png)

「en」だった箇所が「ja_JP」に変わります。そして普通にログイン。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/107218/e5640712-2cb4-e2e9-3121-215a2c67eb67.png)

「標準フォルダーの名前を現在の言語に合わせて更新しますか？」という問い合わせが表示されます。個人的な好みでどちらでもいいのですが、フォルダー名を全角にしてしまうと何かと問題が起き易いです。古い名前のままがよろしいでしょう。
ついでに「次回から表示しない」にします。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/107218/60129034-35c9-d384-d816-fde3f5c040c3.png)

画面上部のタスクバー(?)の右の方、キーボードアイコンを右クリックします。
するとポップアップメニューが出るので「設定」を選択。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/107218/e943a190-d7c8-9b6e-0a49-e8cec2629e8e.png)

IBus の設定ダイアログ > 入力メソッドタブ > 追加ボタン

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/107218/b12681c1-510c-30df-5a61-4b5ee20d7a2e.png)

入力メソッドの選択ダイアログが表示されるので「日本語」を選択。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/107218/c765b3d8-316b-7e68-baad-98d90241e1e8.png)

日本語の入力メソッドが表示されます。「Mozc」を選択して「追加」ボタン。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/107218/045880af-0c49-7ec9-2c86-a77bf3393f08.png)

IBusの設定ダイアログに戻るので閉じます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/107218/1ab00fa9-5aad-2f27-5dab-76a1b5e1ec57.png)

これで Mozc を使えるようになりました。
確認の為に LibreOffice Writer を起動します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/107218/f074a2e5-01df-3fc8-05f6-f00009afed07.png)

今日のヒント、鬱陶しいですね。非表示にしてOK。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/107218/94e0b777-f2a6-66b5-41cf-4c7b6f33eda2.png)

Super キー + Space キーで Mozc が起動します。Super キーは Windows の場合は Win キーです。

最初は直接入力になっています。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/107218/117cb193-2534-443a-66f4-d09daa202e5f.png)

かなキーを押すとひらがな入力になります。適当に入力して確認。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/107218/f76da53f-98f5-5308-d572-7b0b44798c6f.png)

Xubuntuは設定が比較的素直ですね。助かりました。

# 家庭内DNS

[以前のサーバー設定でUnboundを立ち上げています](https://qiita.com/katz_engineer/items/4e29b954e0290621c1ab)。家庭内ルーターのDHCPなどで上手く設定できていれば問題ありませんが、我が家のルーターでは設定できませんでした。

仕方が無いので、クライアントマシンの[名前解決の設定を弄ります](https://qiita.com/katz_engineer/items/4e29b954e0290621c1ab#systemd-resolved-%E3%81%AE%E8%A8%AD%E5%AE%9A%E3%82%92%E5%A4%89%E6%9B%B4)。

ターミナルを起動して下記を実行。なお 172.16.1.3 は[我が家のサーバーのIPアドレス](https://qiita.com/katz_engineer/items/4e29b954e0290621c1ab#systemd-resolved-%E3%81%AE%E8%A8%AD%E5%AE%9A%E3%82%92%E5%A4%89%E6%9B%B4)です。

```console
sudo sed -i -e"/^#DNS=/c DNS=172.16.1.3" -e"/^#Domains=/c Domains=home" /etc/systemd/resolved.conf
sudo systemctl restart systemd-resolved
```

# スナップショット

初回インストールのスナップショットを作成しておきます。こういう事をしたいが為にZFSを使うのです。

```console
sudo zfs snapshot -r tank@$(date +%Y%m%d_%H%M%S)_install
```

スナップショットの一覧を表示して確認します。

```console
zfs list -t snapshot
```

ただ、どうも、自動的にsnapshotを撮られているようです。apt-getのタイミングなんでしょうかね。自分で手動snapshotした分を表示するには下記コマンドが良さそうです。

```console
zfs list -t snapshot | grep -v autozsys
```

# 仕舞い

これで最小限のXubuntuデスクトップをZFSの上にセットアップできました。
この後は下記の記事に従って整備します。

- [自宅サーバー構築譚：Subversionをインストールして /etc をバージョン管理・Ubuntu 22.04](https://qiita.com/katz_engineer/items/92d0b58677b8783e1fe5)
- [自宅サーバー構築譚：NTPクライアント](https://qiita.com/katz_engineer/items/fa46454a85d93e6e671b)
- [自宅サーバー構築譚：LDAPサーバー OpenLDAP・SSSD を利用したログイン・Xubuntu 22.04 LTS](https://qiita.com/katz_engineer/items/e51104d04549dcf2842c)。

ひとまずはこれでUbuntuデスクトップ環境(Xubuntu)は一区切り。やったね:thumbsup_tone1: