archlinuxを構築してみた

# はじめに
私自身archlinuxを触ったのが初めてでしたが、なんとか導入・運用までできたので、その際の作業手順を備忘録を兼ねて記事にしました。（※仕事柄Linux自体は触るので、基本的なコマンド類は使える前提です。）
なおこの記事は「NASNEを自作してみた」内の作業詳細の解説も兼ねています。

# archlinuxとは
「Keep It Simple を標榜する、軽量で柔軟性に優れた Linux® ディストリビューション」らしい（[公式サイト](https://www.archlinux.jp/)より）。
私は「CUI」で「軽量」なLinuxを探していてたどり着きました（[軽量なLinuxをまとめているサイト](https://eng-entrance.com/linux-light#ArchLinux)）。導入は大変だったが、おかげでLinuxのスキルが上がった気がします。



# 導入作業
インストール作業は[ArchWikiのインストールガイド](https://wiki.archlinux.jp/index.php/%E3%82%A4%E3%83%B3%E3%82%B9%E3%83%88%E3%83%BC%E3%83%AB%E3%82%AC%E3%82%A4%E3%83%89)に従って作業を進めました。本記事ではその中で実行したコマンドを列挙しています。
※以下では`archlinuxを導入するPC`を`サーバーPC`、`作業に使用するPC`を`作業用PC`と呼ぶことにします。


## インストールイメージの用意、起動
インストールイメージをUSBに書き込み、起動時にUSBを読み込ませます。
- インストールイメージのダウンロード（[公式ページ](https://www.archlinux.jp/download/)）
- rufus等でUSBに書き込む（[公式ページ](https://rufus.ie/ja/)）
- `サーバーPC`のBIOSで、ブート優先順位にてUSBを最優先に設定する
- `サーバーPC`の電源を入れる


## ssh接続できる様にする
`作業用PC`から`サーバーPC`にssh接続をするために必要な設定・確認をします。（こうすると`作業用PC`で調べたコマンドをコピペして`サーバーPC`で実行できるため、非常に作業が捗ります。）

```sh:サーバーPCで実行
# サーバーPCのIPアドレスを確認する（筆者は有線LANで家のネットワークに繋いだ）
ip add show
数行出力され、以下の様な部分があるので、192.168.から始まるアドレスを確認する。
（アドレスは環境に依るので、適宜読み替えてください。）
inet 192.168.XXX.XXX/24 metric 100 brd 192.168.0.255 scope global dynamic enp2s0

（以降、作業PCのIPアドレスを192.168.XXX.XXXと表記します）

# sshdが上がっていることを確認する（デフォルトで上がっているはず）
systemctl status sshd
以下の出力があればOK。（ない場合はsshdの導入・起動が必要）
Active: active (running) since Sun 2022-05-22 03:26:35 UTC; 11min ago

# rootユーザーにパスワードを設定する（ssh接続をするのに必要）
# ※ここで設定するパスワードは一時的なもの → これから導入するOSのrootパスワードは後段の手順で設定する
passwd
（root用のパスワードを入力する。なんでもいい）
```

作業用PCからsshで接続できることを確認する。
```sh:作業用PCで実行
# 疎通確認
ping -c 3 192.168.XXX.XXX
以下の様な出力があればOK
64 bytes from 192.168.XXX.XXX: icmp_seq=0 ttl=64 time=22.906 ms

nmap -p 22 192.168.XXX.XXX
22/tcp open  ssh と出ればOK

# 古いホストのssh公開鍵を削除する（ssh接続試行時にホストの鍵が変わっていると出る場合は実行）
ssh-keygen -R 192.168.XXX.XXX

# ssh接続
ssh -l root 192.168.XXX.XXX
（さっき設定したrootのパスワードを入力する）
```

## OSインストール作業
ここで行うのは、`archlinuxのインストールメディア`から`PC`にarchlinuxを導入する作業です。[インストールガイド](https://wiki.archlinux.jp/index.php/%E3%82%A4%E3%83%B3%E3%82%B9%E3%83%88%E3%83%BC%E3%83%AB%E3%82%AC%E3%82%A4%E3%83%89)に従って半分思考停止で進めていきます。（特に説明のない部分はお察しください。）

### キーボードレイアウトの設定
キーボードのレイアウトなんて種類があるの？と思いましたが、あるらしいです。→[Dvorak配列](https://atmarkit.itmedia.co.jp/flinux/rensai/linuxtips/613notqwerty.html)（当初、先人のarchlinux導入記事をコピペしたところ、アルファベット配置すら違うものになってしまい、まともにコマンドが打てずに泣きそうになりました。。）
以下では普通の日本で使われているレイアウトに設定しています。
```sh:作業用PCで実行（サーバーPCにssh接続済）
ls /usr/share/kbd/keymaps/**/*.map.gz
loadkeys jp106
ls /sys/firmware/efi/efivars
```

### システムクロックの更新
```sh:作業用PCで実行（サーバーPCにssh接続済）
timedatectl set-ntp true
```

### パーティション作成
ストレージに対する設定です。
今回はPC内蔵のHDDにarchlinuxを導入するため、PC内蔵のHDDに対してパーティションの設定をしています。
（もし、USBストレージ等に導入したい場合、USBストレージに対してパーティション設定を行えばOKです。元々入っているWindowsを残したまま、同じPCでarchlinuxも動かしたい場合などに有効です。）
```sh:作業用PCで実行（サーバーPCにssh接続済）
# 現在のデバイスパーティションを確認する
fdisk -l
/dev/sda や/dev/sdb など今回OSをインストールするパーティションを確認する

※後続作業で間違えたパーティションを指定すると、そこのデータが消えてしまうので注意！
（以下では/dev/sda にOSを導入しています）

# 前のOSのパーティションが残っている場合以下のコマンドで削除する
wipefs -a /dev/sda

# デバイスパーティションを再確認
fdisk -l /dev/sda

# パーティションを作成する（gdiskコマンドは対話的に操作するタイプのコマンド）
gdisk /dev/sda
>>> gdiskの対話的操作 >>>
# ブートローダー用のパーティションを作成する（500Mくらい割り当てる）
n #新規作成
1 #パーティション番号
2048 #開始セクター
512M #終了セクター（パーティション1に割り当てるサイズを決めている感じっぽい）
EF00 #パーティションの種類?を指定するらしい

# OS領域用のパーティションを作成する（残り全部割り当てる）
n #新規作成
2 #パーティション番号
1050624 #開始セクター
195371534 #終了セクター（ついてるストレージ容量によって異なる）
8300 #パーティションの種類

w #上記の設定内容を保存する
Y #上書きますか？的なメッセージが出た場合Yes
<<< gdiskの対話的操作 <<<

# パーティションテーブルを即時有効化する
partprobe

# パーティションのフォーマット
mkfs.vfat -F 32 /dev/sda1
mkfs.ext4 /dev/sda2
Proceed anyway? (y,N)と出たら y と入力する

# パーティションの確認
fdisk -l /dev/sda
```

### マウント
作ったパーティションをマウントする。
```sh:作業用PCで実行（サーバーPCにssh接続済）
# OS領域（/）用のパーティション（=/dev/sda2）を/mntにマウント
mount /dev/sda2 /mnt

# ブート領域マウント用のディレクトリ作成
mkdir /mnt/boot

# ブート領域用のパーティションをマウント
mount /dev/sda1 /mnt/boot
```

### 必須パッケージのインストール
```sh:作業用PCで実行（サーバーPCにssh接続済）
pacstrap /mnt base base-devel linux linux-firmware vi vim dhcpcd intel-ucode
```

### システムの設定
ここから先の設定は、上で作ったパーティションに保存されていきます。
#### fstabの作成
上でマウントしましたが、今後OSが起動したら自動的に同様のマウントを行う様にするための設定です。
```sh:作業用PCで実行（サーバーPCにssh接続済）
# fstabの作成
genfstab -U /mnt >> /mnt/etc/fstab
```

#### chrootする
現在`/mnt`となっているディレクトリを`/`にする。（→ 一時的なルートディレクトリ`/`の変更）
```sh:作業用PCで実行（サーバーPCにssh接続済）
# chroot
arch-chroot /mnt
```

#### タイムゾーンの設定
タイムゾーンを日本に設定する。
```sh:作業用PCで実行（サーバーPCにssh接続済）
# タイムゾーン設定
ln -sf /usr/share/zoneinfo/Asia/Tokyo /etc/localtime

# ハードウェア・クロックを現在のシステム・クロックに合わせる
hwclock --systohc
```

#### ローカリゼーション
OSで日本語を扱える様にする。
```sh:作業用PCで実行（サーバーPCにssh接続済）
# 設定ファイルのバックアップを取る
cp -p /etc/locale.gen /etc/locale.gen.bkup

# 設定ファイル（locale.gen）を編集する
vim /etc/locale.gen
>>> vim 編集内容 >>>
# 以下のコメントアウトを外す
en_US.UTF-8 UTF-8
ja_JP.UTF-8 UTF-8
<<< vim 編集内容 <<<

# ロケールのインストールをする
locale-gen

# /etc/locale.conf を作成し、LANG変数の設定をする
echo LANG=en_US.UTF-8 > /etc/locale.conf

# 一応現在のコンソールにも設定する
export LANG=en_US.UTF-8
```

#### キーボードレイアウトとフォントの設定
キー配列とフォントの設定をする。
```sh:作業用PCで実行（サーバーPCにssh接続済）
# vconsole.conf を作成し、設定内容を書き込む
cat - << EOF > /etc/vconsole.conf
KEYMAP=jp106
FONT=Lat2-Terminus16
EOF
```

#### ホストネームファイルの作成
ホストネームを設定する
```sh:作業用PCで実行（サーバーPCにssh接続済）
# /etc/hostname を作成し、ホスト名を記入する（以下の archlinux の箇所はなんでもOK）
echo archlinux > /etc/hostname
```

#### インターネット接続の設定
```sh:作業用PCで実行（サーバーPCにssh接続済）
# DHCPのサービスがOS起動時に自動起動する様に設定する
systemctl enable dhcpcd
```

#### rootパスワードの設定
本記事冒頭でもrootのパスワードを設定しましたがあれは一時的なもので、ここので設定がOS領域に保存されて今後使用するものになります。
```sh:作業用PCで実行（サーバーPCにssh接続済）
# rootのパスワードの設定
passwd
（root用のパスワードを入力する。なんでもいい）
```

#### ブートローダの設定
OSが起動する際には、「BIOS → ブートローダ → OS」の順に起動されるため、OS導入ができてもブートローダが設定できていないとPC再起動時にOSが起動されない事態が発生します。（当初この辺りが分かっておらず、「ブートローダ？ま、なくてもいいっしょ！」→ 起動せず。。 という事態にハマっていました。。）
ということでブートローダを設定する。
```sh:作業用PCで実行（サーバーPCにssh接続済）
# ブートマネージャをインストールする
bootctl --path=/boot install

# 設定ファイルを作成する
## /dev/sda2 の箇所はルートディレクトリがマウントするパーティションを指定する
cat - << EOF > /boot/loader/entries/arch.conf
title Arch Linux
linux /vmlinuz-linux
initrd /intel-ucode.img
initrd /initramfs-linux.img
options root=PARTUUID=$(blkid -s PARTUUID -o value /dev/sda2) rw
EOF

# ローダーの設定ファイルに追記する
## default arch の設定の archの部分が↑ arch.confを参照するという意味になっている
cat - << EOF >> /boot/loader/loader.conf
editor no
default arch
EOF
```

#### 再起動
ここまでで一旦設定が完了したので、PCの再起動をする。
```sh:作業用PCで実行（サーバーPCにssh接続済）
# chrootしていたので一旦抜ける
exit

# 再起動
poweroff

# 起動用のUSBを抜く → サーバーPCの電源を入れる
```

## OSインストール後のセットアップ作業
PCが再起動されると`archlinux login:`の様なプロンプトが表示されるかと思います。（もしそうでない場合、インストールがうまくいっていないので頑張ってください。）
以下ではインストール後に私が行なったセットアップを記載しています。
（必ずやった方がいいのは[ssh接続をするための設定](#ssh接続をするための設定)くらいでしょうか。）

### archlinuxにログイン
```sh:サーバーPCで実行
# rootでログインする
archlinux login: root
（上手順で設定したルートのパスワードを入力）
```

### パッケージのインストール
archlinuxでは`pacman`というパッケージマネージャーを使う様です。（ちなみに、redhat系では`yum`、ubuntu系では`apt`）
`pacman`について詳しくは[こちらのQiita](https://qiita.com/MoriokaReimen/items/dbe1448ce6c0f80a6ac1)にまとまっています。
以下は最低限必要であろう使い方です。

```sh
# パッケージの検索
pacman -Ss 検索したいパッケージ名

# ローカルのパッケージの検索
pacman -Qi 検索したいパッケージ名

# パッケージのインストール（--noconfirm はYの入力を省くオプション）
pacman -S --noconfirm インストールしたいパッケージ名

# パッケージの更新
pacman -Syyu
```

> **pacmanでバージョンを指定してのライブラリをインストールする場合**
まず前提として、archlinuxには「パッケージは最新版を使う」という思想があるようで、pacmanではバージョン指定はできなさそうです。
とはいえ動かすソフトウェアのバージョン依存の関係で、古いバージョンのライブラリを入れる必要が生じることもあります。そういう時は、[downgrade](https://ebc-2in2crc.hatenablog.jp/entry/2021/07/20/233435)というコマンドを使うことで、任意のバージョンを使うことができます。
私もバージョンを落とす必要があり、downgradeでパッケージのバージョンを落としたのですが、そうすると他の部分で（最新版がなくなったため）依存関係が壊れてしまい結局うまく動かないという事態に遭遇してしまいました。回避策として、ライブラリ自体は最新版にして、古いバージョンのファイルだけを取っておき、リンクを貼ることでまるで複数バージョンが共存するような状態にしました。（詳しくは別記事に書きたいと思います。）


### ssh接続をするための設定
インストール作業の冒頭ではデフォルト状態でsshのデーモン（sshd）が起動していましたが、インストール直後のarchlinuxではsshdが入っていません。そのためパッケージのインストールから行う必要があります。
```sh:サーバーPCで実行
# sshdのインストール
pacman -S --noconfirm openssh

# sshdをOS起動時に自動起動する様に設定する
systemctl enable sshd

# sshdを起動する
systemctl start sshd

# 起動確認
systemctl status sshd
```

<br>
rootで直接ssh接続をするのはセキュリティ上良くなさそうなので、sshログイン用のユーザーを作成します。（ユーザー名は任意のものでOK。ユーザー名を変えた場合、手順中のユーザー名を読み替えて実行してください。）

```sh:サーバーPCで実行
# sshログイン用のユーザーを作成
useradd -m arch
passwd arch
archユーザーのパスワードを入力（なんでもいい）

# sudoersにwheelグループを追加する
visudo
>>> visudoの編集内容 >>>
# 以下をコメントアウト
%wheel ALL=(ALL:ALL) ALL
<<< visudoの編集内容 <<<

# archをwheelグループに追加する
usermod -aG wheel arch
```
<br>
設定ができたので作業用PCからssh接続してみます。

```sh:作業用PCで実行（サーバーPCにssh接続済）
# 疎通確認
ping -c 3 192.168.XXX.XXX
以下の様な出力があればOK
64 bytes from 192.168.XXX.XXX: icmp_seq=0 ttl=64 time=22.906 ms

nmap -p 22 192.168.XXX.XXX
22/tcp open  ssh と出ればOK

# 古いホストのssh公開鍵を削除する（ssh接続試行時にホストの鍵が変わっていると出る場合）
ssh-keygen -R 192.168.XXX.XXX

# ssh接続
ssh -l arch 192.168.XXX.XXX
（さっき設定したarchのパスワードを入力する）

# ルートユーザーにスイッチする
su -
（ルートユーザーのパスワードを入力する）
```

### PCを閉じてもスリープしない様にする
今回ノートPCにarchlinuxを導入してサーバー的に使いたいので、基本的にはPCを閉じておきたいです。しかし、デフォルト状態ではPCを閉じるとスリープ状態になってしまうので、その設定を変更します。
```sh:作業用PCで実行（サーバーPCにssh接続済）
# 設定ファイルのバックアップ
cp -p /etc/systemd/logind.conf /etc/systemd/logind.conf.bkup

# 設定ファイルの変更
vim /etc/systemd/logind.conf
>>> vim編集内容 >>>
# HandleLidSwitchExternalPower の suspend を ignoreに変更する
<変更前>
#HandleLidSwitchExternalPower=suspend
<変更後>
HandleLidSwitchExternalPower=ignore
<<< vim編集内容 <<<
```

### 時刻の同期をする
時刻同期に使われるNTP(Network Time Protocol) のサービスをインストールします。
```sh:作業用PCで実行（サーバーPCにssh接続済）
# ntpのパッケージのインストール
pacman -S --noconfirm ntp

# 設定ファイルのバックアップ
cp -p /etc/ntp.conf /etc/ntp.conf.bkup

# 設定の変更
vim /etc/ntp.conf
>>> vim編集内容 >>>
# Associate to Arch's NTP pool を変更する
server 0.jp.pool.ntp.org iburst
server 1.jp.pool.ntp.org iburst
server 2.jp.pool.ntp.org iburst
server 3.jp.pool.ntp.org iburst
<<< vim編集内容 <<<

# デーモンのリロード
systemctl daemon-reload

# OS起動時に自動起動する様に設定
systemctl enable ntpd

# ntpdを起動
systemctl start ntpd

# 起動確認
systemctl status ntpd
```

# おわりに
archlinuxの導入は思ったよりも大変でした。。が、苦労した分、愛着が湧いた気もします。
CUIなので普段使いするにはハードルが高いですが（Webブラウジングができないため）、自宅サーバーとして大事に使っていきたいと思います。

最後まで読んでくださり ありがとうございました。


# 関連記事
- [NASNEを自作してみた](https://qiita.com/hirmr/items/cde0baf51d82ca9de791)