Let's Note CF-SZ6 に Debian GNU/Linux をインストール・環境設定

本稿は、Let's Note CF-SZ6 に Debian GNU/Linux Stretch をインストールした時の備忘録です。

# Debian GNU/Linux のインストール

https://www.disk-partition.com/jp/articles/shrink-volume-beyond-half-its-size.html などの記述にしたがい、以下の手順で Windows10 がインストールされている領域を縮小。

1. システムの保護を無効に設定し、復元ポイントを全て削除
2. 仮想メモリページングファイル（`C:\Pagefile.sys`）を削除[^pagefile]
3. デフラグを実行
4. ディスクの管理ツールで、ボリュームの縮小を実行
5. 仮想メモリページングファイルとシステムの保護の設定を元に戻す

[^pagefile]: スタートメニュー→Windowsシステムツール→コントロールパネルと辿って、コントロールパネルを開く。次に、コントロールパネルから、システムとセキュリティ→システムと辿って、システムの詳細設定をクリックして、システムのプロパティを開く。次に、詳細設定タブ→パフォーマンスの設定→詳細設定タブ→仮想メモリの変更と辿って、「すべてのドライブのページングファイルを自動的に管理する」チェックボックスを外し、「ページングファイルなし」チェックボックスにチェックして、設定ボタンをクリックする。

Windows10 の領域を約 60GB まで縮小して、Debian をインストールする領域を用意した。

```
Device          Start        End    Sectors   Size Type
/dev/sda1        2048     534527     532480   260M EFI System
/dev/sda2      534528     567295      32768    16M Microsoft reserved
/dev/sda3      567296  125223588  124656293  59.5G Microsoft basic data
/dev/sda4   125224960  126896127    1671168   816M Windows recovery environment
/dev/sda5  1968951296 2000408575   31457280    15G unknown
/dev/sda6   126896128  127395839     499712   244M Linux filesystem
/dev/sda7   127395840 1937747967 1810352128 863.2G Linux filesystem
/dev/sda8  1937747968 1968951295   31203328  14.9G Linux swap
```

後は、PANASONIC のロゴが表示されている間に F2 キーを叩いて、BIOS メニューに入り、USB から起動すればインストーラが走る[^power-option]。普通にインストーラを実行していけば、UEFI が自動検出されて、以下のように自動的にマルチブートな設定でインストールされる。MBR よりも楽だなあと初めて思った。

[^power-option]: 高速起動が有効になっていると、F2 キーを叩いても無視されるらしい。Windows10 であれば、Windows キーを押しながら x を押してメニューを出し、電源オプションを選択。そこで高速起動を無効化すると、F2 キーが使えるようになる。

```shell-session
# efibootmgr 
BootCurrent: 0007
Timeout: 2 seconds
BootOrder: 0007,0000,0001,0004,0002,0003
Boot0000* Windows Boot Manager
Boot0001* Recovery Partition
Boot0002* UEFI: PXE IP4 Intel(R) Ethernet Connection (4) I219-LM
Boot0003* UEFI: PXE IP6 Intel(R) Ethernet Connection (4) I219-LM
Boot0004* Windows Recovery Environment
Boot0007* debian
```

同じ状態のはずの CF-SX3 を、Recovery Partition から起動して Windows7 専用機に復元しようとしたが、失敗した。リカバリデータが格納されている /dev/sda5 は変更していなかったはずなのだが。/dev/sda6〜8 を削除してから復元を試みる必要があった可能性がある。次回は注意すること。

# 各種設定

## ネットワーク

### 無線LAN

Intel のドライバは non-free で配布されているので、最初に non-free のパッケージを sources.list に追加．

```conf:/etc/apt/sources.list
deb http://ftp.jp.debian.org/debian/ stretch main contrib non-free
deb-src http://ftp.jp.debian.org/debian/ stretch main contrib non-free

deb http://security.debian.org/debian-security stretch/updates main contrib non-free
deb-src http://security.debian.org/debian-security stretch/updates main contrib non-free

# stretch-updates, previously known as 'volatile'
deb http://ftp.jp.debian.org/debian/ stretch-updates main contrib non-free
deb-src http://ftp.jp.debian.org/debian/ stretch-updates main contrib non-free
```

その上で、firmware-iwlwifi をインストール。

```shell-session
# apt update
# apt install firmware-iwlwifi
```

初回時のみ、iwlwifi を再ロードして初期化する（またはシステム全体を再起動する）。

```shell-session
# modprobe -r iwlwifi
# modprobe iwlwifi
firmware: failed to load iwlwifi-8265-26.ucode (-2)
Direct firmware load for iwlwifi-8265-26.ucode failed with error -2
firmware: failed to load iwlwifi-8265-25.ucode (-2)
Direct firmware load for iwlwifi-8265-25.ucode failed with error -2
firmware: failed to load iwlwifi-8265-24.ucode (-2)
Direct firmware load for iwlwifi-8265-24.ucode failed with error -2
firmware: failed to load iwlwifi-8265-23.ucode (-2)
Direct firmware load for iwlwifi-8265-23.ucode failed with error -2
firmware: direct-loading firmware iwlwifi-8265-22.ucode
loaded firmware version 22.361476.0 op_mode iwlmvm
```

上記のように failed というメッセージがかなり出てくるので少し心配になるが、最終的に iwlwifi-8265-22.ucode を読み込むことができていて、動作には支障ないようだ。

なお、CF-SV8 に搭載されている Cannon Point-LP CNVi という無線 LAN アダプタの場合は、Debian 10 (buster) で用意されている firmware-iwlwifi パッケージでは動かない。[backports.debian.org](https://backports.debian.org/Instructions/) のリポジトリを有効化して、buster-backports の firmware-iwlwifi パッケージをインストールする必要がある。

```shell-session
# apt -t buster-backports install firmware-iwlwifi
```

### 外部からの通信を全て拒否する

サーバ目的として使うマシンではないので、外部からの全てのパケットは拒否するよう設定しておく。iptables-persistent をインストール。

```shell-session
# apt install iptables-persistent
```

以下のような設定ファイル /etc/iptables/rules.v4 および /etc/iptables/rules.v6 を用意。なお、[v197 以後の systemd は NIC に対して、eth0 などの旧来の名前の代わりに、enp2s0 などの名前を割り当てる](https://www.freedesktop.org/wiki/Software/systemd/PredictableNetworkInterfaceNames/)ため、iptables で指定するインタフェース名も従来とは変化しているので、少々注意が必要。

```conf:/etc/iptables/rules.v4
*filter
:INPUT ACCEPT [0:0]
:FORWARD ACCEPT [0:0]
:OUTPUT ACCEPT [0:0]
-A INPUT -i enp+ -m state --state INVALID,NEW -j DROP
-A INPUT -i wlp+ -m state --state INVALID,NEW -j DROP
-A FORWARD -i enp+ -m state --state INVALID,NEW -j DROP
-A FORWARD -i wlp+ -m state --state INVALID,NEW -j DROP
COMMIT
```

設定ファイルを読み込ませる。

```shell-session
# service netfilter-persistent reload
```

### Bluetooth

buleman をインストールして、適当にペアリング。

```shell-session
# apt install blueman
```

### VPN over SSH

従来は vpnc を使っていたが設定が面倒だったので、[sshuttle](https://pypi.org/project/sshuttle/) に変更した。まず、sshuttle パッケージをインストール。

```shell-session
# apt install sshuttle
```

以下のようにコマンドを実行しておくと、指定されたサブネットの範囲については sshuttle を経由して接続するようになる。

```shell-session
$ sshuttle -D -r ユーザ名@サーバ名 AAA.BBB.CCC.DDD/XXX
```

先に iptables の設定をせずに sshuttle を使おうとすると、

```
ssh connection to server (pid 14783) exited with returncode 255
```

という謎のエラーで接続に失敗することがある。デバッグメッセージを出力させても、まったく手がかりが得られずに苦労したのだが、あきらめて先に iptables の設定をしたら接続できるようになった。

## 省電力設定

### ディスプレイを閉じた時にサスペンドするように変更

「アプリケーション」→「設定」→「電源管理」で設定できる。


### バッテリー充電管理

バッテリーの過充電を避けるために，[tlp](https://linrunner.de/tlp/) をインストールしておく．

```shell-session
# apt install tlp
# systemctl enable tlp
# systemctl start tlp
```

### CPU の周波数スケーリング

バッテリ稼働時間を延ばすには、負荷状況に応じて CPU の周波数を変更する設定が重要。従来は cpufreq デーモンのインストールなどが必要だったが、[Linux 3.4 以後はカーネルモジュールで自動的に行われる](https://wiki.archlinux.jp/index.php/CPU_%E5%91%A8%E6%B3%A2%E6%95%B0%E3%82%B9%E3%82%B1%E3%83%BC%E3%83%AA%E3%83%B3%E3%82%B0)ようだ。

```shell-session
# apt install linux-cpupower
# cpupower frequency-info
```

として、CPU の周波数制御が powersave モードで行われるようになっている点を確認しておく。

## デスクトップ設定

### CapsLock キーを Control キーとして動作するようにする

以下を記述して，CapsLock を完全に Control キーとして動作するようにする．

```conf:/etc/default/keyboard 
XKBMODEL="pc105"
XKBLAYOUT="jp"
XKBVARIANT=""
XKBOPTIONS="ctrl:nocaps"
```
### タッチパッドでタップした時に、クリックと同じ働きをするようにする

xserver-xorg-input-synaptics をインストールする。

```shell-session
# apt install xserver-xorg-input-synaptics
```

その上で、synclient コマンドを起動する度に呼び出すように設定する。各種の流儀があるが、XFCE を利用している場合は、以下のように XFCE 用の xinitrc を書き換えておくのが楽だろう。

```conf:~/.config/xfce4/xinitrc
#!/bin/sh

if [ -z "${DISPLAY}" ]; then
    prog=xinit
else
    prog=/bin/sh
fi

# Enable tap actions on a touchpad.
if ( grep -q synaptics /var/log/Xorg.0.log ); then
    if [ -x /usr/bin/synclient ]; then
        /usr/bin/synclient TapButton1=1 LBCornerButton=2 RBCornerButton=3 MaxTapTime=140 \
                           SingleTapTimeout=140 MaxDoubleTapTime=140 VertEdgeScroll=1
    fi
fi

exec ${prog} /etc/xdg/xfce4/xinitrc $*
```

### ビープ音が鳴らないようにする

https://wiki.ubuntulinux.jp/UbuntuTips/Hardware/StopBeepSound

### 日本語入力

emacs-mozc mozc-fcitx をインストール。

Let's Note 本体のキーボードは日本語配列なので、Happy Hacking Keyboard などの英語配列の USB 外付けキーボード使う場合などは、キー配列を切り替えて使う必要が生じる。[fcitx-imlist](https://www.clear-code.com/blog/2015/6/6.html) コマンドを使うと、簡単に切り替えられるようになる。

```shell-session
;; インストール済みのキーボード配列を調べる
$ fcitx-imlist -l
fcitx-keyboard-us (キーボード - 英語 (US)) [enabled]
fcitx-keyboard-jp (キーボード - 日本語) [enabled]
mozc (Mozc) [enabled]
;; 英語配列を優先する
$ fcitx-imlist -s us
;; 日本語配列を優先する
$ fcitx-imlist -s jp
```

## その他

### etckeeper

```shell-session
# apt install etckeeper
```
### git-lfs

https://gist.github.com/tsuchm/4cb3fd65927fe49ea77c256352a8915e

### nextcloud-client

リポジトリを追加．

```conf:/etc/apt/sources.d/nextcloud-client.list
deb http://ppa.launchpad.net/nextcloud-devs/client/ubuntu zesty main
```

リポジトリ署名の公開鍵を追加，nextcloud-client をインストール．

```shell-session
# apt-key adv --recv-key --keyserver keyserver.ubuntu.com AD3DD469
# apt update
# apt install nextcloud-client
```

[2022/06/13追記] Debian bullseyeでは、本家パッケージリポジトリに`nextcloud-desktop`が入ったので、上記設定は不要。単に以下のようにすれば良い。

```shell-session
# apt install nextcloud-desktop
```

### 他のマシンと同一のパッケージ構成にする

元のマシンで以下のコマンドを実行すると、インストール済みパッケージ一覧が得られるので、このパッケージ一覧を使って、新しいマシンに一気に同じパッケージをインストールすれば良い。

```shell-session
$ dpkg --get-selections
```

しかし、元のマシンと、新しいマシンとで Debian のバージョンが異なっていたりすると、単にパッケージ一覧を使っても「そんなパッケージは存在しないよ」というエラーでインストールできない。

そのような場合は、[not_depeneded_packages.pl](https://gist.github.com/tsuchm/8cf7dfeefbf236b484e97d2ab1ebb4ee) を使って、他のパッケージによって依存されていないパッケージの一覧を作成し、その一覧に含まれるパッケージのインストールを試みると楽。

### 時刻合わせ

[2022/06/13追記] Debian bullseyeでは、従来の `ntpd` の代わりに `systemd-timesyncd` が利用できる。

まず、ハードウェアCMOSクロックの設定を確認するために `timedatectl` コマンドを実行する。

```shell-session
# timedatectl status
               Local time: 月 2022-06-13 22:12:48 JST
           Universal time: 月 2022-06-13 13:12:48 UTC
                 RTC time: 月 2022-06-13 22:12:48
                Time zone: Asia/Tokyo (JST, +0900)
System clock synchronized: no
              NTP service: n/a
          RTC in local TZ: yes

Warning: The system is configured to read the RTC time in the local time zone.
         This mode cannot be fully supported. It will create various problems
         with time zone changes and daylight saving time adjustments. The RTC
         time is never updated, it relies on external facilities to maintain it.
         If at all possible, use RTC in UTC by calling
         'timedatectl set-local-rtc 0'.
```

警告にしたがって、ハードウェアCMOSクロックにはUTCを設定するように設定を変更する。

```shell-session
# timedatectl set-local-rtc 0
# timedatectl status
               Local time: 月 2022-06-13 22:13:23 JST
           Universal time: 月 2022-06-13 13:13:23 UTC
                 RTC time: 月 2022-06-13 13:13:23
                Time zone: Asia/Tokyo (JST, +0900)
System clock synchronized: no
              NTP service: n/a
          RTC in local TZ: no
```

次に `systemd-timesyncd` をインストールする。

```shell-session
# apt install systemd-timesyncd
```

`/etc/systemd/timesyncd.conf` の `NTP=` の行を編集して `ntp.nict.jp` を参照するように設定しておく．

```diff
diff --git a/systemd/timesyncd.conf b/systemd/timesyncd.conf
index e74c0f6..a8b93d9 100644
--- a/systemd/timesyncd.conf
+++ b/systemd/timesyncd.conf
@@ -12,7 +12,7 @@
 # See timesyncd.conf(5) for details.
 
 [Time]
-#NTP=
+NTP=ntp.nict.jp
 #FallbackNTP=0.debian.pool.ntp.org 1.debian.pool.ntp.org 2.debian.pool.ntp.org 3.debian.pool.ntp.org
 #RootDistanceMaxSec=5
 #PollIntervalMinSec=32
```

`systemd-timesyncd` を再起動後に、以下のような結果が得られれば、正常に動作（時刻同期）している。

```
# systemctl restart systemd-timesyncd
# timedatectl status
               Local time: 月 2022-06-13 22:39:05 JST
           Universal time: 月 2022-06-13 13:39:05 UTC
                 RTC time: 月 2022-06-13 22:39:05
                Time zone: Asia/Tokyo (JST, +0900)
System clock synchronized: yes
              NTP service: active
          RTC in local TZ: no
# timedatectl timesync-status 
       Server: 2001:df0:232:eea0::fff4 (ntp.nict.jp)
Poll interval: 8min 32s (min: 32s; max 34min 8s)
         Leap: normal
      Version: 4
      Stratum: 1
    Reference: NICT
    Precision: 1us (-20)
Root distance: 0 (max: 5s)
       Offset: +62.526ms
        Delay: 17.242ms
       Jitter: 35.790ms
 Packet count: 7
    Frequency: -48.092ppm
```

## TODO

* 残設定
  * ICカード
  * [MultiArch](https://wiki.debian.org/Multiarch/HOWTO)
* 暗号化ボリューム
  * 最初に、空の領域全体を暗号化ボリュームに設定する。
  * 次に、論理ボリューム（LVM）の設定を行う。先に作成した暗号化ボリューム全体を、ボリュームグループに登録する。そのボリュームグループから、/ 用の論理ボリュームと、スワップ用の論理ボリュームを切り出す。
  * このように設定すると、起動時の暗号化パスフレーズの入力が1回で済むようになる。
  * 「ディスク全体を使って暗号化ボリュームの設定を行う」を選べば、同じような手順になるのだが、そうするとWindowsの回復領域などが破壊されてしまうので、手作業で設定する必要がある。
* secure boot
  * CF-SV8 では UEFI の secure boot が有効になっているので，所有者の個人鍵（Machine Owner Key; MOK）を登録して，MOK を使って kernel module に署名してやる必要がある（署名しないと、kernel module が load できず、例えば virtualbox の利用時に問題になる）。手順は、 https://stegard.net/2016/10/virtualbox-secure-boot-ubuntu-fail/ を参照。
  * CF-SR4では、なぜか secure boot に失敗し、BIOS 設定で secure boot を無効化する必要があった。https://gihyo.jp/admin/serial/01/ubuntu-recipe/0444 で解説されている通り、shim ブートローダが挟まっているのだが。

## Windows専用マシンへのリカバリ手順

まず、UEFIのブート情報を確認する。

```
# efibootmgr 
BootCurrent: 0007
Timeout: 1 seconds
BootOrder: 0007,0001,0002,0000,0003,0004
Boot0000* Recovery Partition
Boot0001* Windows Boot Manager
Boot0002* Windows Recovery Environment
Boot0003* UEFI: PXE IP4 Intel(R) Ethernet Connection (6) I219-LM
Boot0004* UEFI: PXE IP6 Intel(R) Ethernet Connection (6) I219-LM
Boot0007* debian
```

この状態から、Debianのブートローダ登録情報を削除する。ここで、7番目のブートローダがDebian用のブートローダであるから、以下のコマンドでブートローダを削除する。

```
# efibootmgr -b 7 -B
```

この状態で再起動すると、通常のWindowsが立ち上がるはずである。

次に、Debianが利用していたパーティションを削除する。通常のインストール用USBメモリを用意して、rescue modeで起動する。rescue modeに入ったら、`parted` コマンドでDebianが利用していたパーティションを削除する。

```
Device              Start        End    Sectors  Size Type
/dev/nvme0n1p1       2048     534527     532480  260M EFI System
/dev/nvme0n1p2     534528     567295      32768   16M Microsoft reserved
/dev/nvme0n1p3     567296  118007807  117440512   56G Microsoft basic data
/dev/nvme0n1p4 1967968256 1968951295     983040  480M Windows recovery environme
/dev/nvme0n1p5 1968951296 2000408575   31457280   15G unknown
/dev/nvme0n1p6  118007808  118456319     448512  219M Linux filesystem
/dev/nvme0n1p7  118456320 1936619519 1818163200  867G Linux filesystem
/dev/nvme0n1p8 1936619520 1967968255   31348736 14.9G Linux swap
```

という状態だったので、6・7・8の3つのパーティションのみを削除し、他には手を触れない。

この後、一旦シャットダウン（再起動では、パーティションテーブルが更新されない）してから、Windowsを起動する。ディスクの管理ツールで、ボリュームの拡張を実行すると、解放したパーティションがWindowsで使える状態に戻る。