ดิสก์: GPT → LUKS2 → btrfs → subvolume
สร้าง “ที่อยู่” ของ hop 2 (ESP) และ hop 3–4 (root ที่เข้ารหัส)
Partitioning, full-disk encryption and btrfs subvolume layout
ใช้ทำอะไร (Purpose)
จาก ext4 ที่คุ้นเคย เพิ่มแค่ 2 ชั้น
ext4: nvme0n1p2 ─────────────────────────► ext4 ─► /
ใหม่: nvme0n1p2 ─► [LUKS] ─► /dev/mapper/cryptroot ─► btrfs ─► [subvolume] ─► mount หลายจุด| ชั้น | เปรียบกับ network |
|---|---|
LUKS → /dev/mapper/cryptroot | VPN: eth0 เห็นแต่ข้อมูลเข้ารหัส / tun0 เห็นข้อมูลปกติ |
| btrfs subvolume | VLAN: switch ตัวเดียว หลายเครือข่ายแยกกัน ใช้ backplane ร่วม |
mount -o subvol=@home | เลือก VLAN tag |
ขั้นตอน (Setup)
1. เงื่อนไขก่อนแตะดิสก์
cat /sys/firmware/efi/fw_platform_size # ต้องได้ 64 (UEFI) — systemd-boot ใช้ได้แค่ UEFI
timedatectl # System clock synchronized: yes — ลายเซ็นแพ็กเกจต้องการเวลาถูก2. ดูสิ่งที่จะลบเป็นครั้งสุดท้าย แล้วล้าง
lsblk -o NAME,SIZE,FSTYPE,LABEL /dev/nvme0n1
blkdiscard /dev/nvme0n1 # ถูกปฏิเสธเพราะเจอ GPT = ระบบป้องกันทำงาน
blkdiscard -f /dev/nvme0n1 # ล้างจริง (TRIM ทั้งดิสก์ ไม่เขียนข้อมูล ไม่เปลืองอายุ SSD)
wipefs /dev/nvme0n1 # อ่านลายเซ็นจากดิสก์จริง: เงียบ = สะอาด⚠️ ตรวจด้วย wipefs ไม่ใช่ lsblk — lsblk อ่านจาก cache ของ kernel (เหมือน ARP cache)
3. ตาราง GPT
sgdisk -o /dev/nvme0n1
sgdisk -n 1:0:+1G -t 1:ef00 -c 1:ESP /dev/nvme0n1
sgdisk -n 2:0:0 -t 2:8309 -c 2:LUKS /dev/nvme0n1
sgdisk -p /dev/nvme0n1
lsblk /dev/nvme0n1 # ยืนยันว่า kernel เห็น partition ใหม่| ค่า | ทำไม |
|---|---|
| ESP 1 GiB | เก็บ kernel 2 ตัว + initramfs (NVIDIA ทำให้ใหญ่) |
| เริ่ม sector 2048 | จัดแนวกับหน่วยภายใน SSD (เหมือน MTU ไม่ตรง → แตก packet) |
8309 | ป้ายบอกว่าเข้ารหัส (ช่วย triage ดิสก์ในงานสืบ) |
ชื่อ LUKS ≠ cryptroot | กันสับสนว่าพูดถึงชั้นไหน |
ตรวจด้วยเลขคณิต: 1 GiB ÷ 512 = 2,097,152 sector → p1 จบ 2,099,199 / p2 เริ่ม 2,099,200 ✓
GPT มีสารบัญ 2 ชุด (หัว + ท้ายดิสก์) = redundancy ถ้าตัวหน้าเสีย ดูท้ายดิสก์
4. ESP
mkfs.fat -F 32 -n ESP /dev/nvme0n1p1 # UEFI ต้องอ่าน FAT ได้ตามมาตรฐาน5. LUKS2
cryptsetup luksFormat --verbose /dev/nvme0n1p2 # พิมพ์ YES ตัวใหญ่
cryptsetup open --allow-discards --persistent /dev/nvme0n1p2 cryptroot
cryptsetup status cryptroot- รหัสใช้ตัวอักษรบนแป้น US เท่านั้น (หน้าถามรหัสตอนบูตยังไม่มีภาษาไทย)
- ลืมรหัส = ข้อมูลหายถาวร
--persistent= เขียนค่า discards ลง header ไม่ต้องใส่ kernel parameter- TRIM ผ่าน LUKS: รั่วแค่ “แผนที่พื้นที่ว่าง” ไม่รั่วเนื้อหา
ตรวจด้วยเลขคณิต: 998,115,983 − 32,768 (header 16 MiB) = 998,083,215 ✓ ตรงกับ size
6. btrfs + subvolume
mkfs.btrfs -L ARCH /dev/mapper/cryptroot # ⚠️ ที่ mapper ไม่ใช่ p2 (ไม่งั้นทับ LUKS)
mount /dev/mapper/cryptroot /mnt # top-level (ID 5)
btrfs subvolume create /mnt/@ /mnt/@home /mnt/@snapshots /mnt/@log /mnt/@pkg
btrfs subvolume list /mnt # ทุกตัว top level 5 = พี่น้อง (flat layout)
umount /mnt| subvolume | rollback | เหตุผล |
|---|---|---|
| @ | ย้อน | ตัวระบบ |
| @home | ไม่ย้อน | ไฟล์งาน |
| @log | ไม่ย้อน | หลักฐาน ว่าอะไรทำให้พัง |
| @pkg | ไม่ย้อน | cache |
| @snapshots | ไม่ย้อน | ไม่ให้ snapshot ถ่ายซ้อนตัวเอง |
7. Mount ทุกอย่าง
mount -o noatime,compress=zstd:1,subvol=@ /dev/mapper/cryptroot /mnt
mkdir -p /mnt/{home,.snapshots,var/log,var/cache/pacman/pkg,boot}
mount -o noatime,compress=zstd:1,subvol=@home /dev/mapper/cryptroot /mnt/home
mount -o noatime,compress=zstd:1,subvol=@snapshots /dev/mapper/cryptroot /mnt/.snapshots
mount -o noatime,compress=zstd:1,subvol=@log /dev/mapper/cryptroot /mnt/var/log
mount -o noatime,compress=zstd:1,subvol=@pkg /dev/mapper/cryptroot /mnt/var/cache/pacman/pkg
mount -o fmask=0077,dmask=0077 /dev/nvme0n1p1 /mnt/boot
findmnt -R /mnt- ต้อง mount
@ก่อน (จำลองสภาพตอนบูตจริง ไม่งั้น genfstab บันทึกผิด) noatime: ไม่บันทึกเวลาอ่าน (ใน forensic atime มีค่ามาก แต่บนเครื่องเราไม่จำเป็น)fmask/dmask=0077: FAT ไม่มีสิทธิ์แบบ Linux → ตั้งให้ root เท่านั้น (กันคำเตือน random-seed)
ทดสอบว่าใช้ได้ (Verification)
| ตรวจ | หลักฐาน |
|---|---|
| TRIM ผ่าน LUKS จริง | flags: discards + mkfs.btrfs ขึ้น “Performing full device TRIM” |
| subvolume ถูกตัว | findmnt แสดง [/@home] ฯลฯ |
| ESP | vfat + fmask=0077,dmask=0077 |
| discard ปลายทาง | discard=async ปรากฏเองใน options |
UUID 3 ตัว (จุดพลาดคลาสสิก)
<LUKS-UUID>-... LUKS (nvme0n1p2) → kernel parameter rd.luks.name=
<BTRFS-UUID>-... btrfs (cryptroot) → /etc/fstab
1A5F-40FD FAT (nvme0n1p1) → /etc/fstabสลับ LUKS กับ btrfs = บูตไม่ขึ้น
ปัญหาที่เคยเจอ & สิ่งที่ทายผิด (Troubleshooting)
| เหตุการณ์ | บทเรียน |
|---|---|
ทายว่า sgdisk พิมพ์ Setting name! / partNum is 0 | รุ่นใหม่ตัดข้อความภายในออกแล้ว — ตรวจด้วย sgdisk -p แทนการเชื่อข้อความ |
| ทายวันที่ผิด (29 vs 1 ต.ค.) | ข้อมูลจากเครื่องถูกเสมอ |
| ลำดับ partition minor 259:3, 259:4 | kernel แจกเลขต่อจากตาราง Windows เดิม = ร่องรอยประวัติ |
คำถามชวนคิด
- ถ้าเผลอรัน
mkfs.btrfs /dev/nvme0n1p2แทน mapper ข้อมูลอะไรหายไป และยังกู้อะไรได้บ้าง (เบาะแส: header สำรอง) - ทำไม subvolume แบบ “พี่น้อง” (flat) จึง rollback ได้ง่ายกว่าแบบ “ซ้อนใน @” ลองวาดภาพตอนสลับ @ ทั้งก้อน
- TRIM ผ่าน LUKS ทำให้ผู้ตรวจพิสูจน์รู้อะไรเกี่ยวกับดิสก์ได้บ้าง ถ้าคุณเป็นฝ่ายตรวจดิสก์ของผู้ต้องสงสัย ข้อมูลนี้มีค่าแค่ไหน