セキュリティ関連のテーマを扱う者として,医者の不養生みたいなことはしてはいけないと思い,持ち歩くデバイスには最大限の対策をしている(ほんまか?).
その一環として,ラップトップではディスク暗号化とSecure Bootを有効にしている.
元はArch Linuxでこれらをやっていたが,NixOS以降後も同様の環境を再現できたので,その方法を記録しておく.
(既に半年以上前にやっていたものですが,最近修理から返ってきたマシンに再設定したのでこの機会に文字に起こしました)
概要
- NixOSをLUKS暗号化ディスクにインストールし,Secure BootとTPM2.0による自動アンロックまで導入する
- Windows 11とのデュアルブート構成も同時に行う
- そのため真面目に使うなら少なくともSecure Bootは必須
- 同一ドライブ上に導入する想定
Prerequisites
- Windows 11がインストール済み
- Bitlockerは一旦解除しておいた方が良い.回復キーを何度か入れる羽目になるので.
- Secure Bootは一時的に無効化しておく
- NixOSはクリーンインストール
- そもそも後からFull Disk Encryptionをするのは厳しいので
パーティションの調整
各自の好みのサイズをNixOS用に確保しておけば良いが,ESP(EFI System Partition)は1-2GiB程度まで拡張しておくことを推奨.
NixOSでは/boot
以下にESPをマウントするのが基本構成で,/boot/efi/nixos
以下に,存在するgenerationでin-usedなカーネルとinitrdを保持する.多くの場合initrdは100MiBを超えるサイズとなるため,複数のkernelとinitrdが存在するとESPが圧迫されてすぐ領域不足となる.
パーティション拡張は色々方法があると思うので割愛.Windowsだと怪しいソフトがよく出てきますが,推奨はしません(一応使ったことはあります).
NixOSのRootFSは未使用領域としてパーティションのみ切っておく.
NixOSのインストール
GUIインストーラでは設定可能な項目に限りがあるので,CLIでのマニュアルインストールを行う.GUI付きLive USBでも別にマニュアルインストールを行うことはできる.
Live環境を起動し,sudo -i
等でroot
のシェルに入る.
パーティションのフォーマット・マウント
LUKSをセットアップする.ここでは,ターゲットパーティションが/dev/nvme0n1p5
と仮定.
# LUKS partitionの作成
cryptsetup luksFormat -y --label="NixOS-LUKS" /dev/nvme0n1p5
# LUKS partitonをアンロック
# /dev/mapper/luks にマップされる
cryptsetup luksOpen /dev/nvme0n1p5 luks
OpenしたLUKS partitionをフォーマットする.
ここではRootFSにbtrfs
を使用するが,各自の好みのFilesystemでもよい.
サブボリュームを使用したbtrfs
特有の構成をするので,他のFSを使う場合は読み飛ばしてOK.
# btrfsでフォーマット
mkfs.btrfs -L "NixOS-ROOT" /dev/mapper/luks
# subvolumeを切るために一時的にマウント
mount /dev/mapper/luks /mnt
# subvolumeを作成
btrfs subvolume create /mnt/root
btrfs subvolume create /mnt/home
btrfs subvolume create /mnt/nix
btrfs subvolume create /mnt/swap
# マウント解除
umount /mnt
# 実際の運用構成でマウント
mount -o compress=ztsd,subvol=root /dev/mapper/luks /mnt
mkdir -p /mnt/{home,nix,swap}
mount -o compress=zstd,subvol=home /dev/mapper/luks /mnt/home
mount -o compress=zstd,noatime,subvol=nix /dev/mapper/luks /mnt/nix
mount -o noatime,subvol=swap /dev/mapper/luks /mnt/swap
# Swap作成
btrfs filesystem mkswapfile --size 8g --uuid clear /mnt/swap/swapfile
swapon /mnt/swap/swapfile
Configuration生成・適用
この状態でconfiguration.nix
とhardware-configuration.nix
を生成する.生成後,最小限の変更を入れた上でインストールする.
一般ユーザーの作成程度はここでやっておくとよい.また,FSのマウントマップはby-uuid
で生成されているが,パーティションにlabelを振っているならby-label
での指定に変えておくと見た目が分かりやすい.
# configurationの生成
nixos-generate-config --root /mnt
vim /mnt/etc/nixos/configuration.nix
vim /mnt/etc/nixos/hardware-configuration.nix
# Just uncomment and change username
users.users.myuu = {
isNormalUser = true;
extraGroups = [ "wheel" ]; # Enable ‘sudo’ for the user.
};
# Modify to use /dev/disk/by-label/*
boot.initrd.luks.devices."luks".device = "/dev/disk/by-label/NixOS-LUKS";
fileSystems."/" = {
device = "/dev/disk/by-label/NixOS-ROOT";
fsType = "btrfs";
options = [ "subvol=root" ];
};
fileSystems."/home" = {
device = "/dev/disk/by-label/NixOS-ROOT";
fsType = "btrfs";
options = [ "subvol=home" ];
};
fileSystems."/nix" = {
device = "/dev/disk/by-label/NixOS-ROOT";
fsType = "btrfs";
options = [
"subvol=nix"
"noatime"
];
};
fileSystems."/swap" = {
device = "/dev/disk/by-label/NixOS-ROOT";
fsType = "btrfs";
options = [
"subvol=swap"
"noatime"
];
};
fileSystems."/boot" = {
device = "/dev/disk/by-label/SYSTEM";
fsType = "vfat";
options = [
"fmask=0077"
"dmask=0077"
];
};
# インストール
nixos-install
すべて完了したら,再起動してインストールしたNixOSを起動する.
正しくインストールできていれば,initプロセスの間にLUKSのPassphraseが聞かれる.
Secure Boot
NixOSでのSecure Bootには,Lanzabooteを利用する.Lanzabooteはドキュメントがしっかりしているので,ここで改めて書く必要もないが,掻い摘まんで書き起こしておく.
Secure Boot Keyの作成
sbctl
を使用してSecure Boot Keyを作成・管理する.
nix-shell -p sbctl
sudo sbctl create-keys
Lanzabooteの導入
Lanzabooteのドキュメントを参照.flakesかnivを使うことになる.flakesで導入するにはそもそもconfigurationをflakesで管理している必要があるが,この際にflakes管理にしてしまうとよい.
nixos-rebuild switch
して再起動した後,stubが署名されているか確認する.
sudo sbctl verify
Dual Boot環境だとESPに大量のstubがあるため大量に未署名のものがリストされるが,無視でよい.
とりあえず以下のものが署名されていれば問題無い.
BOOTX64.EFI
nixos-generation-*.efi
systemd-bootx64.efi
Secure Bootの有効化
このSecure Bootでは, 自身で作成した独自のSecure Boot Keyを用いる(俗に言うCustom Modeというやつ).
まずはBIOSにてSecure BootをSetup Modeにする.これにより,独自の鍵をインポート可能な状態になる.
やり方はマシンベンダーによって様々だが,大抵は Setup Mode や Reset, Delete Secure Boot Key などの文言が書かれている.
その後NixOSを起動し,事前に作成していたSecure Boot Keyをインポートする.
sudo sbctl enroll-keys --microsoft
ここで,--microsoft
を渡すことでMicrosoftのOEM Keyを一緒にenrollしている.BIOS側でMSのKeyを認めるオプションがない場合などは,ここでenrollしておかないとWindowsがSecure Boot Violationで起動不能となる(気がする).とりあえず何も考えずに付けておいて良いだろう.
enrollの際,efivarfsに書き込めずエラーとなるケースがある.その場合,エラーとなったファイルに対してchattr
でアトリビュートを設定することで対処可能.
# このようなエラーとなる
‼ File is immutable: /sys/firmware/efi/efivars/KEK-hoge...
‼ File is immutable: /sys/firmware/efi/efivars/db-fuga...
You need to chattr -i files in efivarfs
sudo chattr -i /sys/firmware/efi/efivars/KEK-hoge...
sudo chattr -i /sys/firmware/efi/efivars/db-fuga...
bootctl status
でSeucre Bootがenabledとなっていれば完了.
System:
Firmware: UEFI 2.70 (Dell 1.00)
Firmware Arch: x64
Secure Boot: enabled (deployed)
TPM2 Support: yes
Measured UKI: yes
Boot into FW: supported
Current Boot Loader:
Product: systemd-boot 257.6
Features: ✓ Boot counting
✓ Menu timeout control
✓ One-shot menu timeout control
✓ Default entry control
✓ One-shot entry control
✓ Support for XBOOTLDR partition
✓ Support for passing random seed to OS
✓ Load drop-in drivers
✓ Support Type #1 sort-key field
✓ Support @saved pseudo-entry
✓ Support Type #1 devicetree field
✓ Enroll SecureBoot keys
✓ Retain SHIM protocols
✓ Menu can be disabled
✓ Multi-Profile UKIs are supported
✓ Boot loader set partition information
Partition: /dev/disk/by-partuuid/85ceda52-3b90-47f9-b282-911d82317a29
Loader: └─/EFI/systemd/systemd-bootx64.efi
Current Entry: nixos-generation-69-476cyowt6jzex6bdmu5y2tk7xm7vjrcpiyieoxlbisblk777e2yq.efi
Current Stub:
Product: lanzastub 0.4.2
Features: ✓ Stub sets loader partition information
✗ Picks up credentials from boot partition
✗ Picks up system extension images from boot partition
✗ Picks up configuration extension images from boot partition
✗ Measures kernel+command line+sysexts
✗ Support for passing random seed to OS
✗ Pick up .cmdline from addons
✗ Pick up .cmdline from SMBIOS Type 11
✗ Pick up .dtb from addons
✗ Stub understands profile selector
✗ Stub sets stub partition information
✗ Stub loader set partition information
...
TPMを用いたLUKSのアンロック
ここまで全ての設定が問題なくできていれば,以下のコマンドのみで完了する.
sudo systemd-cryptenroll --tpm2-device=auto --tpm2-pcrs=0+4+7 /dev/nvme0n1p5
--tpm2-pcrs
で復号に使用するPCR Bankを指定している.どのBankを指定すべきかは想定する脅威によって異なるが,少なくともPCR[0]
(UEFI FW Code) とPCR[7]
(Secure Boot State) は指定しておくと良いだろう.各BankのUsageはArchWikiを参照するとよい.
再起動し,LUKSのPassphraseが要求されなければ設定完了.もしBootloaderのアップデートなどで状態が変化した場合は,再度同一のコマンドを実行すればOK.
Windows側の調整
NixOSでの全ての作業完了後,Windows側のセキュリティ設定を元に戻す.ここでは,WindowsをLanzabooteで導入したsystemd-boot
経由で起動する想定である.
TPMの状態が変わるため,BitLockerが有効なままインストールを行った場合は回復キーを要求される.一時的に解除していた場合はここで再度有効化する.
また,Windows Helloの認証情報もTPMの状態の変化により使用不可能となるため,再設定が要求される.
MSアカウントに紐付いている場合,MSアカウント経由でPINの再設定となる.
The END
これにて完了.
セキュリティで固めたマシンを使っていると謎に優越感に浸れます(???)