ThinkPad X240 に ArchLinux をインストールして作業環境を構築

# 最初に
開発とかで使用しているメインの作業環境に、リモートからVPNで接続できる環境を作りたかった。でもお金はかけたくなかった。
なので、中古の ThinkPad 購入して、ArchLinux インストールしたら解決じゃね？って思ったので実際にやってみた。そのメモ書き。

# ThinkPad の入手
ThinkPad の中古品専門店の [Be-Stock](https://www.be-stock.com/shop/) から手頃なものを選ぶ。
このときは掲題の ThinkPad X240 が 3 万円いかないくらいで入手できた。

# USB メモリで ArchLinux のインストール用メディアを作成
[ここ](https://wiki.archlinux.org/index.php/USB_flash_installation_media)を参照

# インストール
- 作成したインストールメディアで ThinkPad を起動後、以下の手順を実行していく。

## ThinkPad で SSH 起動
```console
# loadkeys jp106
# wifi-menu  // Wifi AP に接続
# ip addr
# passwd  // 適当なパスワードを設定
# systemctl start sshd  // 別の作業用PCから ssh ログインするため
```

## パーティション作成＆Diskフォーマット
- ここからの手順は別の作業用PCから ssh ログインの上実施する。

```
$ ssh root@xxx.xxx.xxx.xxx    // ThinkPad に割り振られた IP アドレスを指定
```

### Disk フォーマット (非暗号化の場合)
```
- パーティション作成
# lsblk
# cgdisk /dev/sda  // GUI メニューが起動する。下記の構成でパーティション作成する。
  efi  - EFI System 512 MiB
  /    - Linux filesystem -

- root("/") と boot パーティションのフォーマット＆マウント
# mkfs.vfat -v -F 32 /dev/sda1
# mkfs.ext4 /dev/sda2

# mount /dev/sda2 /mnt
# mkdir /mnt/boot
# mount /dev/sda1 /mnt/boot
```

### Disk フォーマット (暗号化(dm-crypt)を実施する場合)
```
- Disk を初期化する
# dd if=/dev/urandom of=/dev/sda bs=4096

- パーティション作成
# lsblk
# cgdisk /dev/sda
  efi  - EFI System 512 MiB
  /    - Linux filesystem -

- root パーティション("/")の暗号化、フォーマット＆マウント
# cryptsetup -y -v luksFormat /dev/sda2
# cryptsetup open /dev/sda2 cryptroot
# mkfs.ext4 /dev/mapper/cryptroot
# mount /dev/mapper/cryptroot /mnt

- boot パーティションのフォーマット＆マウント
# mkfs.vfat -v -F 32 /dev/sda1
# mkdir /mnt/boot
# mount /dev/sda1 /mnt/boot
```

## インストール

```console
- システムクロックの更新
# timedatectl set-ntp true
# timedatectl status

- Package Install
# mv /etc/pacman.d/mirrorlist ./
# grep Japan -A 1 mirrorlist > /etc/pacman.d/mirrorlist
# vi /etc/pacman.d/mirrorlist
// jaist を使用する。経験則的にこちらの方が安定している気がする。
// 不要行('--')を削除すること。

# pacstrap /mnt base base-devel

- システム設定
# genfstab -U -p /mnt >> /mnt/etc/fstab
# arch-chroot /mnt /bin/bash
# ln -sf /usr/share/zoneinfo/Asia/Tokyo /etc/localtime
# hwclock --systohc

# vi /etc/locale.gen
// 以下の 2 行をコメントアウトを外す。
en_US.UTF-8 UTF-8
ja_JP.UTF-8 UTF-8
# locale-gen
# echo LANG=ja_JP.UTF-8 > /etc/locale.conf

# echo KEYMAP=jp106 > /etc/vconsole.conf
# echo "任意のホスト名" > /etc/hostname
# vi /etc/hosts
---
127.0.0.1	localhost
::1		localhost
127.0.1.1	任意のホスト名.localdomain	任意のホスト名
---

- 無線周りの NW 設定
# pacman -S iw wpa_supplicant wpa_actiond dialog
# systemctl enable netctl-auto@wlp3s0
# systemctl enable dhcpcd.service

- Initramfs
// mkinitcpio.conf の編集は Disk を暗号化しない場合は実施する必要なし
# vi /etc/mkinitcpio.conf
keyboard, keymap, encrypt フックを mkinitcpio.conf 内の filesystems の前に追加
ex.)
HOOKS=(base udev autodetect modconf keyboard keymap block encrypt filesystems fsck)

# mkinitcpio -p linux

- Root Password の設定
# passwd
```

## ブートローダの設定(systemd-boot)

```console
# pacman -S vim
# bootctl --path=/boot install
# vim /boot/loader/loader.conf
  // 設定例を下記に示す。
---
timeout 3   // コメントアウト解除
#console-mode keep
default xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx-*   // 既に設定されているため変更不要
editor 0    // 追記
---

# blkid -s PARTUUID -o value /dev/sda2
# blkid -s UUID -o value /dev/mapper/cryptroot
// Disk の暗号化を実施しない場合は、 UUID の確認は不要
# vim /boot/loader/entries/arch.conf
// 設定例を下記に示す。なお、 options の設定は Disk の暗号化と非暗号化のケースで異なる。
// options の PARTUUID / UUID は blkid で確認したものを設定すること。
---
title          Arch Linux
linux          /vmlinuz-linux
initrd         /initramfs-linux.img
// Disk の暗号化を行う場合は options は下記の通りとすること。
options        cryptdevice=PARTUUID=xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx:cryptroot root=UUID=xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx rw
// Disk の暗号化を行わない場合は options は下記の通りとすること。
options        root=PARTUUID=xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx rw
---
```

## ユーザの追加＆リブート
```console
- 一般ユーザ(sudo権限あり)の追加
# useradd -m -g wheel xxxxx
# passwd xxxxx
# visudo
// 以下 2 行のコメントアウトを外す
Defaults env_keep += "HOME"
%wheel ALL=(ALL) NOPASSWD: ALL

- リブート
// リブート後、USBのインストールメディアを PC から抜いておくこと。
# exit
# umount -R /mnt
# reboot
```

## GUI環境(LightDM/X-fce)のインストール
```console
- 再起動後、コンソールから root でログインし、下記の手順を実施
# export LANG=C
# wifi-menu
# pacman -S openssh wget
# systemctl enable sshd.service

- 作業用PCから再度、sshでログイン
$ ssh xxxxx@xxx.xxx.xxx.xxx

- 時刻同期の設定
# timedatectl set-ntp true
# timedatectl status
// System clock synchronized が「yes」となっていること
// NTP service が「active」となっていること

- AUR ヘルパー(yay) のインストール (一般ユーザで実施)
// AUR ヘルパーのメンテナンス状況は Arch Wiki でチェックすること
// - https://wiki.archlinux.jp/index.php/AUR_%E3%83%98%E3%83%AB%E3%83%91%E3%83%BC
# wget https://aur.archlinux.org/cgit/aur.git/snapshot/yay.tar.gz
# makepkg -sri
// yay.tar.gz を展開し、下記コマンドを実行

- 日本語フォント(Ricty)のインストール (一般ユーザで実施)
// Ricty 以外のフォントがいい人は適宜選択すること。
# yay -S ttf-ricty 

- mlocate (updatedb/locate)
// 無いと困りますよね？？
# sudo pacman -S mlocate

- 省電力(tlp) のインストール
# sudo pacman -S tlp
# sudo systemctl enable tlp

- X.org のインストール
# sudo pacman -S xorg-server xorg-apps xorg-xinit xorg-xclock xterm
// 2回ほど質問されるが、defaultを選択しておけばよいと思う。
# sudo pacman -S xf86-video-intel

- ディスプレイマネージャ(LightDM) のインストール
# sudo pacman -S lightdm lightdm-gtk-greeter lightdm-gtk-greeter-settings
# sudo systemctl enable lightdm.service

- Desktop(X-fce) 環境のインストール
# sudo pacman -S xfce4 xfce4-goodies gamin
# sudo shutdown -r now
// これで X-fce の GUI 環境でのログインが可能になるはず。
```

## その他色々な設定

```console
- 日本語入力環境の構築
# GUI のメニューより : アプリケーション -> 設定 -> キーボード -> レイアウト
  -> キーボードレイアウトを日本語に変更。
  -> システムデフォルトを使用する のチェックを外す
# sudo pacman -S fcitx-mozc fcitx-configtool
# vim ~/.xprofile
// 下記の設定を行うこと。
---
export XMODIFIERS=@im=fcitx
export QT_IM_MODULE=fcitx
export GTK_IM_MODULE=fcitx
---

- サウンドカードの設定
$ yay -S xfce4-volumed
$ sudo pacman -S alsa-utils
$ sudo vim /etc/asound.conf
// 下記の設定を行うこと。
// 音量設定は Xfce パネルに PulseAudio プラグインを追加するのがいいと思う。
---
defaults.ctl.card 1
defaults.pcm.card 1
defaults.timer.card 1
---

- NetworkManager のインストール
// GUI で Wifi の接続や状況確認等をやりやすくするもの。必須ではない。
$ sudo pacman -S network-manager-applet
$ sudo systemctl disable netctl-auto@wlp3s0.service
$ sudo systemctl stop netctl-auto@wlp3s0.service

- キーボードのCTRLキーとCapsLockキーの入れ替え
// CTRLキーの位置が気になる人向け。設定は必須ではない。
# vim /etc/X11/xorg.conf.d/00-keyboard.conf
---
Section "InputClass"
        Identifier "system-keyboard"
        MatchIsKeyboard "on"
        Option "XkbOptions" "ctrl:swapcaps"
EndSection
---

- monitor 設定
// 僕の持ってるセカンドモニタはこの設定をしないとなんだか、解像度がちゃんと設定できなかった。設定は必須ではない。
# vim /etc/X11/xorg.conf.d/10-monitor.conf
---
Section "Monitor"
    Identifier "DP2"
    Modeline "1920x1080_60.00"  173.00  1920 2048 2248 2576  1080 1083 1088 1120 -hsync +vsync
    Option "PreferredMode" "1920x1080_60.00"
EndSection

Section "Screen"
    Identifier "Screen0"
    Monitor "DP2"
    DefaultDepth 24
    SubSection "Display"
        Modes "1920x1080_60.00"
    EndSubSection
EndSection

Section "Device"
    Identifier "Device0"
    Driver "intel"
EndSection
---

- リブート
$ sudo shutdown -r now
```

## L2TP/IPsec VPN の設定
基本的には[ここ](https://wiki.archlinux.org/index.php/Openswan_L2TP/IPsec_VPN_client_setup)の手順を踏襲すればいける。インターネット接続がNAT環境の場合、設定の考慮が必要だったのでメモを残しておく。なお、接続先の VPN サーバは既に準備されていることが前提となる。

### インストール
Arch Wiki にある通り、 openswan と xl2tpd をインストールする。

```console
- パッケージインストール
$ yay -S openswan
$ yay -S xl2tpd
$ yay -S python2  // あとで実行する ipsec verify は python2 が必要

- kernel パラメータ設定
$ sudo -E vim /etc/sysctl.d/10-sysctl_ipsec.conf
---
net.ipv4.ip_forward = 1
net.ipv4.conf.all.accept_redirects = 0
net.ipv4.conf.all.send_redirects = 0
net.ipv4.conf.default.accept_redirects = 0
net.ipv4.conf.default.send_redirects = 0
net.ipv4.conf.wlp3s0.accept_redirects = 0
net.ipv4.conf.wlp3s0.send_redirects = 0
net.ipv4.conf.lo.accept_redirects = 0
net.ipv4.conf.lo.send_redirects = 0
---
$ sudo shutdown -r now
//リブートにより kernel パラメータ変更を反映する

- ipsec verify 実行
$ sudo systemctl start openswan
$ ipsec verify
// ERROR や FAILED などの表示がないことを確認する。
```

### 設定
IPsec と L2TP の設定をそれぞれ記述していく。

```console
- /etc/ipsec.conf
$ sudo -E vim /etc/ipsec.conf
---
# /etc/ipsec.conf - Openswan IPsec configuration file

# This file:  /usr/share/doc/openswan/ipsec.conf-sample
#
# Manual:     ipsec.conf.5


version	2.0	# conforms to second version of ipsec.conf specification

# basic configuration
config setup
	dumpdir=/var/run/pluto/
	nat_traversal=yes
	virtual_private=%v4:10.0.0.0/8,%v4:192.168.0.0/16,%v4:172.16.0.0/12
	oe=off
	protostack=netkey
	plutoopts="--interface=wlp3s0"  // NWに接続する NIC を指定

conn L2TP-PSK
	authby=secret
	pfs=no
	auto=add
	keyingtries=3
	rekey=yes
	dpddelay=30
	dpdtimeout=120
	dpdaction=clear
	ikelifetime=8h
	keylife=8h              // デフォルトは 1h だった。用途に応じて適切な時間を設定すること。短いと ipsec がすぐ切れる。
	type=transport

	left=xxx.xxx.xxx.xxx    // 自PCのIPアドレス
	leftprotoport=17/1701

	right=yyy.yyy.yyy.yyy   // 接続先のVPNサーバ。ドメイン名指定も可。
	rightid=yyy.yyy.yyy.yyy // 接続先のVPNサーバ。ドメイン名指定も可。これがないと NAT 環境だと接続できなかった。
	rightprotoport=17/1701
---

- /etc/ipsec.secrets
$ sudo -E vim /etc/ipsec.secrets
---
: RSA	{
    ... snip
	}
# do not change the indenting of that "}"
%any yyy.yyy.yyy.yyy : PSK "xxxxxxxxxxxxxxxx"  // 事前鍵共有方式を想定。VPNサーバ側で規定されている PreSharedKey を記載
---

- /etc/xl2tpd/xl2tpd.conf
$ sudo -E vim /etc/xl2tpd/xl2tpd.conf
---
[global]
access control = no
auth file = /etc/ppp/chap-secrets
debug avp = no
debug network = no
debug packet = no
debug state = no
debug tunnel = no

[lac vpn-connection]
lns = yyy.yyy.yyy.yyy  // 接続先の VPN サーバ
redial = yes
redial timeout = 5
require chap = no
require authentication = yes
ppp debug = yes
pppoptfile = /etc/ppp/peers/options.l2tpd.client
require pap = no
autodial = yes
length bit = yes
---

- /etc/ppp/peers/options.l2tpd.client
$ sudo -E vim /etc/ppp/peers/options.l2tpd.client
---
ipcp-accept-local
ipcp-accept-remote
refuse-eap
require-mschap-v2
noccp
noauth
idle 1800
mtu 1410
mru 1410
defaultroute
usepeerdns
debug
connect-delay 5000
name xxxxxxxxx  // VPN サーバから払い出されているアカウントを設定
password xxxxxxxxxxxxxxxx  // アカウントのパスワードを設定
---
```

### 接続/切断スクリプトの準備
VPN 接続手順としては以下の通り。
1. openswan の起動
2. IPsec 接続開始
3. xl2tpd の起動
4. VPN 接続用のルーティングテーブル設定

切断時はこれの逆をやればよい。
1. VPN 接続用のルーティングテーブル削除
2. IPsec の接続終了
3. xl2tpd の停止
4. openswan の停止

これを毎度、手作業で打ち込むのも辛いので、スクリプト化しておく。内容は以下の通り。
sleep を良い感じの間隔で入れておかないと、うまく接続できない。

#### /usr/local/bin/vpn-connect.sh
```bash
#!/bin/bash
set -eu

## connecting IPsec(openswan)
echo "Starting openswan ..."
systemctl start openswan
sleep 2 #delay to ensure that IPsec is started before overlaying L2TP

echo "Starting IPsec interface for L2TP-PSK ..."
/usr/sbin/ipsec auto --up  L2TP-PSK                        
sleep 10 #delay to ensure that IPsec is started before overlaying L2TP

## connecting L2TP
echo "Starting xl2tpd ..."
systemctl start xl2tpd
sleep 3
echo "c vpn-connection" > /var/run/xl2tpd/l2tp-control     
sleep 3

## adding routing table for internal ip addresses
echo "Adding routing table for L2TP/IPsec ..."
ip route add xxx.xxx.xxx.xxx/xx dev ppp0

echo "L2TP/IPsec starting process have completed."
```

#### /usr/local/bin/vpn-shutdown.sh
```bash
#!/bin/bash
set -u

## deleting routing table for internal ip addresses
echo "Deleting routing table for L2TP/IPsec ..."
ip route del xxx.xxx.xxx.xxx/xx dev ppp0

## shutting down IPsec/L2TP
echo "Shutting down IPsec interface for L2TP-PSK ..."
/usr/sbin/ipsec auto --down L2TP-PSK
sleep 5

echo "Shutting down xl2pd and openswan ..."
echo "d vpn-connection" > /var/run/xl2tpd/l2tp-control
sleep 2
systemctl stop xl2tpd
systemctl stop openswan

echo "L2TP/IPsec shutdown process have completed."
```

### 接続/切断手順

```console
- 接続
$ sudo vpn-connect.sh

- 切断
$ sudo vpn-shutdown.sh
```

# 参考にしたサイト
ほとんどが Arch Wiki を見ればなんとかなった。さすが ArchLinux
  - [X220にArch Linuxを入れた時の覚書](http://eleclog.quitsq.com/2014/10/arch-on-x220.html)
  - https://wiki.archlinux.org/index.php/Installation_guide
  - https://wiki.archlinux.jp/index.php/Dm-crypt
  - https://wiki.archlinux.org/index.php/Openswan_L2TP/IPsec_VPN_client_setup
  - https://wiki.archlinux.jp/index.php/Lenovo_ThinkPad_X240