Rocky Linux 10 + TPM 自動解鎖完整標準流程(從裸機開始)

🔹 第一階段:BIOS 設定

進入 BIOS:

✅ 開啟:

  • TPM 2.0
  • Secure Boot(建議開啟)
  • UEFI 模式(不要 Legacy)

儲存離開。


🔹 第二階段:安裝 Rocky Linux 10(含 LUKS2)

用 Rocky Linux 10 ISO 開機。

在安裝畫面:

1️⃣ 選擇語言 → Installation Destination

2️⃣ Storage Configuration

選:

Custom

Automatic (然後勾選 Encrypt my data)

✅ 必須勾選:

Encrypt my data

3️⃣ 設定 LUKS 密碼

系統會要求設定:

👉 這個密碼非常重要
👉 這就是日後主機壞掉時的救援密碼

請妥善保存。


4️⃣ 建議分割方式(標準企業配置)

/boot        (1GB, 不加密)
EFI          (600MB)
/            (加密)

✅ root 分割區必須加密


5️⃣ 完成安裝並重開機

此時開機會:

👉 要求輸入 LUKS 密碼
(這是正常的)


🔹 第三階段:啟用 TPM 自動解鎖


登入 root。


✅ Step 1:安裝套件

dnf install -y clevis clevis-luks clevis-dracut clevis-systemd tpm2-tools

✅ Step 2:確認 TPM 存在

ls /dev/tpm*

應看到:

/dev/tpm0
/dev/tpmrm0

✅ Step 3:確認 LUKS 位置

lsblk -f

找到:

rl-root

然後確認版本:

cryptsetup luksDump /dev/mapper/rl-root | grep Version

必須是:

Version: 2

✅ Step 4:將 TPM 綁定到 LUKS

執行:

clevis luks bind -d /dev/mapper/rl-root tpm2 '{}'

會要求輸入:

👉 您安裝時的 LUKS 密碼

成功會顯示:

Successfully bound

✅ Step 5:重建 initramfs(非常重要)

dracut -f

這一步會把 clevis 打包進開機映像。



🔹 第四階段:測試


重新開機:

reboot

如果成功:

✅ 不會要求輸入密碼
✅ 自動開機



🔹 第五階段:測試備援


進 BIOS:

👉 暫時關閉 TPM

開機:

✅ 應要求輸入密碼
✅ 輸入後可進入系統

再重新開啟 TPM。



🔹 如果主機壞掉


把硬碟接到另一台 Linux:

cryptsetup luksOpen /dev/sdX rescue

輸入原本密碼即可。

TPM slot 會失效,但密碼 slot 還在 ✅


🔹最終安全架構

LUKS2
 ├─ Slot 0 → 密碼(備援)
 ├─ Slot 1 → TPM2 自動解鎖

🔹 安全等級說明

情境結果
硬碟被偷無法解鎖 ✅
主機被偷可開機 ⚠
主機壞掉可用密碼救援 ✅

🔹 進階強化(企業級)

如果您是(金融相關)

建議下一步:

  • 加入 PCR 綁定
  • 限制 Secure Boot 狀態變更即鎖死
  • 設定 TPM policy
  • 設定自動 recovery SOP

🔹您現在的狀況總結

✔ 已成功安裝
✔ 已啟用 LUKS2
✔ 結構正確
✔ 可以直接做 TPM 綁定

Rocky Linux 安裝多版本 PHP 及切換 CLI PHP 教學

本文示範如何在 Rocky Linux 9 / 10 上:

  • ✅ 安裝多個 PHP 版本(7.4 / 8.1 / 8.2)
  • ✅ 同時並存
  • ✅ 切換 CLI PHP 預設版本
  • ✅ 啟用不同版本的 PHP-FPM

一、安裝 Remi Repository

Rocky Linux 預設只提供單一 PHP 版本,因此需要使用 Remi repo 來安裝多版本 PHP。

1️⃣ 安裝 Remi 與 EPEL

dnf install -y https://rpms.remirepo.net/enterprise/remi-release-$(rpm -E %rhel).rpm
dnf install -y epel-release
dnf update -y

2️⃣ 重設系統 PHP module

dnf module reset php -y

⚠️ 注意:不要使用 dnf module enable php:remi-xx
否則會變成單一 system PHP。


二、安裝多個 PHP 版本(並存模式)

我們使用 Remi 的 平行安裝版本(remi-safe)


✅ 安裝 PHP 7.4

dnf install -y php74 php74-php-cli php74-php-fpm php74-php-mysqlnd php74-php-gd php74-php-mbstring php74-php-xml php74-php-curl php74-php-zip

安裝完成後可用:

/usr/bin/php74

✅ 安裝 PHP 8.1

dnf install -y php81 php81-php-cli php81-php-fpm php81-php-mysqlnd php81-php-gd php81-php-mbstring php81-php-xml php81-php-curl php81-php-zip

✅ 安裝 PHP 8.2

dnf install -y php82 php82-php-cli php82-php-fpm php82-php-mysqlnd php82-php-gd php82-php-mbstring php82-php-xml php82-php-curl php82-php-zip

三、查看已安裝 PHP 版本

ls /usr/bin/php*

或:

alternatives --list | grep php

四、切換 CLI PHP 版本(推薦方法)

建議使用 alternatives 系統機制 切換 CLI PHP。


1️⃣ 註冊不同版本到 alternatives

如果尚未註冊:

alternatives --install /usr/bin/php php /usr/bin/php74 74
alternatives --install /usr/bin/php php /usr/bin/php81 81
alternatives --install /usr/bin/php php /usr/bin/php82 82

2️⃣ 選擇預設 CLI PHP

alternatives --config php

系統會顯示:

1   /usr/bin/php74
2   /usr/bin/php81
3   /usr/bin/php82

輸入對應號碼即可切換。


3️⃣ 確認切換成功

php -v

應顯示所選版本。


五、臨時使用指定版本(不切換系統)

如果只想執行某個版本,不需更改預設:

php74 -v
php81 -v
php82 -v

或執行腳本:

php81 script.php

六、啟用不同版本 PHP-FPM

多版本 FPM 可以同時存在。

例如啟動 PHP 7.4 FPM:

systemctl enable php74-php-fpm
systemctl start php74-php-fpm

查看狀態:

systemctl status php74-php-fpm

同樣方法可啟動 8.1 或 8.2。


七、檢查目前 CLI PHP 位置

which php
php -v

應顯示:

/usr/bin/php

八、總結

✅ 使用 Remi repo 安裝多版本 PHP
✅ 使用 remi-safe 平行安裝
✅ 使用 alternatives 切換 CLI
✅ FPM 可同時並存
✅ 不建議使用 module enable(除非只需要單一版本)

🛡 Mail Platform Disaster Recovery Drill Runbook

(Mailcow Multi‑Node Architecture)


1️⃣ 文件目的

本文件定義公司郵件平台(Mailcow 架構)的:

  • 災難復原流程
  • 定期演習標準
  • 目標恢復時間(RTO)
  • 操作步驟
  • 成功驗證標準

目標:

✅ 任何受訓工程師可在 45–60 分鐘內重建一台 mailcow 節點


2️⃣ 系統架構概覽

2.1 架構摘要

  • 4–5 台 Email Gateway(按 domain 分流)
  • 多台獨立 Mailcow Server
  • S3 Object Storage Snapshot 備份
  • Restic Snapshot
  • Rsync 冗餘備份
  • DB 同步機制

2.2 設計原則

  • Domain Sharding(每個 domain 固定歸屬)
  • 無 Shared Storage
  • 無跨節點強依賴
  • 可獨立重建

3️⃣ Recovery 目標定義

指標目標
RTO≤ 60 分鐘
RPO≤ 5 分鐘
MTTR每季統計

4️⃣ 演習類型分類


✅ Level 1:單節點完全損毀(每月)

模擬:

mailcow-3 完全不可用

目標:

  • 在新 VM 上重建 mailcow
  • 恢復資料
  • Gateway 切換
  • 完成收發測試

✅ Level 2:Gateway 故障(每季度)

模擬:

gateway-2 關閉

測試:

  • MX fallback
  • Queue retention
  • 是否有 mail drop

✅ Level 3:無預警 Chaos Drill(半年)

  • 隨機關閉一台 mailcow
  • 不通知工程師
  • 記錄反應時間

5️⃣ Level 1 演習完整流程(標準版)

以下為「單 mailcow 節點完全重建」標準操作流程。


✅ Step 1:宣告演習開始

  • 指定演習節點
  • 指定計時開始
  • 指定負責工程師
  • 指定觀察員

開始計時。


✅ Step 2:模擬節點失效

操作:

  • 關閉 VM
  • Block network

確認:

  • 無法 SSH
  • Gateway 出現 delivery defer

✅ Step 3:建立新 VM

標準規格:

  • CPU: ___
  • RAM: ___
  • Disk: ___
  • OS: Ubuntu ___

驗證:

ssh 正常

✅ Step 4:基礎環境準備

apt update
apt install docker docker-compose

Clone mailcow:

git clone https://github.com/mailcow/mailcow-dockerized

✅ Step 5:還原資料

5.1 還原 mail data volume

使用 restic:

restic restore latest --target /restore

或使用 S3 snapshot:

aws s3 sync ...

將:

/var/lib/docker/volumes/mailcowdockerized_vmail-vol-1/_data

恢復。


5.2 還原資料庫

方式:

  • restore SQL dump
  • 啟用 DB replication

確認:

mysql -u root -p
show databases;

✅ Step 6:啟動 mailcow

docker-compose up -d

確認:

docker ps

所有 container 正常。


✅ Step 7:健康檢查

檢查:

  • Postfix
  • Dovecot
  • Rspamd
  • Nginx

測試:

✅ IMAP login
✅ SMTP auth
✅ Webmail
✅ 外部寄信


✅ Step 8:Gateway 切換

在 gateway:

  • 更新 routing IP
  • 修改 upstream

Reload postfix。


✅ Step 9:功能驗證

發送測試信:

  • 外部 → 內部
  • 內部 → Gmail
  • 內部 → 同 server

確認:

  • 無 queue 堆積
  • DKIM 正常
  • SPF pass
  • TLS 正常

✅ Step 10:記錄時間

記錄:

  • 開始時間
  • 完成時間
  • 卡住時間點
  • 改進建議

停止計時。


6️⃣ 演習後檢討會議

每次演習必須:

  • 討論瓶頸
  • 是否文件不清晰
  • 是否需要自動化
  • 是否某步驟過慢

7️⃣ 自動化改進方向

✅ 建立:

  • 一鍵 restore script
  • 基礎 VM provisioning script
  • 自動 DB restore
  • 自動 health check script

目標:

人只需要輸入 domain 名稱
系統自動完成 80% 重建


8️⃣ 成功標準

演習成功必須符合:

  • 60 分鐘內恢復
  • 無資料遺失
  • 收發正常
  • 用戶無感

9️⃣ 進階目標(未來)

  • Immutable mailcow node
  • Blue/Green 切換
  • 完全自動 rebuild
  • 15 分鐘 RTO

🔟 核心文化

可靠性 ≠ 有備份
可靠性 = 定期還原


✅ 最終目標

當新人加入公司:

  • 給他這份文件
  • 不協助
  • 他能 45–60 分鐘內完成

你嘅郵件平台就真正成熟。

一個中型 Mailcow Server 的備份反思與重建之路

前言

這篇文章不是教學文。

我不打算講操作步驟,也不會列出指令。

我想記錄的,是一段關於失敗、責任、重建,以及備份理念轉變的過程。

背景是一台中型規模的 Mailcow 郵件伺服器:

  • 約 400–800 個電子郵件帳戶
  • 約 1.5TB 郵件資料
  • 運行於 VPS 環境

這樣的規模,已經不能再用「簡單備份」去處理。


為什麼我對 Email 備份如此執著?

因為我曾經失敗過。

由於管理不善與判斷失誤,我曾經遺失客戶大約 70% 的郵件資料。

無論責任是否完全在我身上,我都不應該容許這件事發生。

那段時間,我每天承受客戶的質疑與投訴。
我失去了大部分客戶的信任。

那是我職業生涯中最大的污點。

從那一天開始,我對備份的理解徹底改變。

備份不再是技術流程。
而是一種責任。


第一個現實:傳統備份方式行不通

1.5TB 的郵件容量,在 VPS 環境下意味著:

  • 備份時間極長
  • I/O 壓力巨大
  • 官方 backup / restore 並不穩定
  • Restore 成本過高

更關鍵的是:

備份是否真的成功?

很多技術人員都經歷過這種情況——
真正需要備份的時候,才發現備份早已失敗。

而我使用的是自動化備份。
不是人手操作。

如果沒有驗證機制,「備份成功」只是心理安慰。


第二個問題:備份系統本身是否安全?

我曾經使用 NAS 作為備份伺服器。

但我開始問自己:

  • 公司自購硬體是否可靠?
  • RAID 是否等於安全?
  • NAS 本身會否成為單點故障?

如果主機與 NAS 同時出事,我還剩下什麼?

於是我決定把備份移往雲端。


Restic + S3:備份思維的第一次轉變

我開始研究 Restic,並將備份目標改為 S3 Object Storage。

Restic 的 Snapshot 機制令我非常欣賞:

  • 全程加密
  • 去重儲存
  • 支援 S3
  • 備份速度非常快

於是我產生一個重要想法:

我是否可以利用 Restic 這個機制,去建立一台可隨時重建的後備 Email Server?

這個想法的核心不是「不要後備伺服器」。

而是:

我是否可以不長期維持一台閒置後備機,而是在需要時,從雲端完整重建一台?

理論上流程是:

  1. 主伺服器使用 Restic 備份至 S3
  2. 發生災難
  3. 在新 VPS 上 Restore
  4. 重建 Mailcow 環境
  5. 重新上線

這是一種「可重建型備援」概念。

我為此寫了一整套 Backup / Restore Script,
一度覺得這是接近完美的方案。


第二次現實衝擊:Restore 的限制

Restic 備份非常快。

但 Restore 是完整還原。

這不是缺點,而是設計理念。

問題在於:

如果我希望後備機保持接近同步狀態,
就意味著頻繁 Restore。

大量、持續的完整還原,
會造成極高 SSD 寫入量。

長遠而言,硬碟壽命會急速消耗。

於是我明白:

Restic 非常適合作為 Disaster Recovery 工具
但不適合作為「高頻同步型備援」。


策略調整:分層備份思維

我保留 Restic + S3:

  • 每日一次完整備份
  • Restore 改為手動
  • 作為最終保險

即使主機、NAS、整個公司設備全部毀滅,
我仍然可以在雲端取回完整數據。

這給了我最基本的安全感。

但我仍然需要一種「高速同步型備援」。


回到基礎:rsync 的重新定位

我開始重新審視 rsync。

過去我避免使用它,因為:

  • Mailcow 結構複雜
  • 郵件為加密格式
  • 緩衝與暫存檔案混亂
  • 資料庫同步難度高

整體看起來幾乎無法處理。


AI 帶來的突破

這一次,我沒有單打獨鬥。

我開始利用 AI 協助我思考架構:

  • 如何處理憑證?
  • 如何安全同步 Maildir?
  • 如何排除不必要的緩衝檔?
  • 如何由主機觸發備份機自行恢復資料庫?
  • 如何確保資料一致性?

經過多次測試與調整,
整個流程終於穩定下來。

同步時間只需幾分鐘。
可高頻執行。
速度快。
可靠。

這才是真正符合我需求的方案。


最終架構:雙層設計

第一層:Restic + S3

  • 每日完整備份
  • 災難恢復
  • 可重建後備機

第二層:rsync 備援同步

  • 高頻同步
  • 快速切換
  • 低 SSD 壓力
  • 接近即時可用

這不是替代關係。

而是分層策略。


結語

我曾經失敗。

那段經歷讓我明白:

備份不是「技術是否正確」。
而是「當事情發生時,你是否對得起客戶」。

今天我最重要的改變,不是學會 Restic。
不是寫好 Script。
不是架好 S3。

而是我不再依賴運氣。
也不再依賴別人替我承擔責任。

備份,從來不是工具問題。

而是態度問題。

✅ Mailcow Restore 後郵件無法讀取

✅ 修復 Dovecot mail_crypt 加密金鑰步驟


📌 問題現象

在將 Mailcow 從 Server A 還原到 Server B 後出現:

  • SOGo 郵件列表空白
  • doveadm index 出現錯誤:
Decryption error: no private key available

📌 問題原因

Mailcow 預設啟用 Dovecot mail_crypt 功能。

郵件在寫入時會被加密(at-rest encryption)。

加密金鑰儲存在 Docker volume:

mailcowdockerized_crypt-vol-1

如果 restore 時沒有包含這個 volume:

郵件會存在
但無法解密
導致 SOGo 空白


✅ 解決方案總覽

Server A 的 crypt volume 複製到 Server B。


🟢 步驟一:在 Server A 打包 crypt volume

進入 mailcow 目錄:

bash

cd /opt/mailcow-dockerized

執行:

bash

docker run --rm \
  -v mailcowdockerized_crypt-vol-1:/data \
  -v $(pwd):/backup \
  busybox \
  tar czf /backup/crypt_backup.tar.gz -C /data .

確認檔案存在:

bash

ls -lh /opt/mailcow-dockerized/crypt_backup.tar.gz

🟢 步驟二:將備份檔傳送到 Server B

例如:

bash

scp /opt/mailcow-dockerized/crypt_backup.tar.gz root@ServerB:/root/

🟢 步驟三:在 Server B 停止 Dovecot

bash

cd /opt/mailcow-dockerized
docker compose stop dovecot-mailcow

🟢 步驟四:清空 Server B 原有 crypt volume

⚠️ 必須先清空,避免舊金鑰干擾

bash

docker run --rm \
  -v mailcowdockerized_crypt-vol-1:/data \
  busybox \
  rm -rf /data/*

🟢 步驟五:還原正確金鑰

bash

docker run --rm \
  -v mailcowdockerized_crypt-vol-1:/data \
  -v /root:/backup \
  busybox \
  tar xzf /backup/crypt_backup.tar.gz -C /data

🟢 步驟六:重新啟動服務

bash

docker compose start dovecot-mailcow
docker compose restart sogo-mailcow

🟢 (建議)重建 Index

為了避免使用者第一次登入很慢,建議執行:

bash

docker compose exec dovecot-mailcow doveadm index -A INBOX

✅ 驗證方式

確認不再出現:

Decryption error: no private key available

登入 SOGo 應可正常讀取郵件。


📌 重要備註

未來進行 Mailcow 備份時,必須包含以下 Docker volumes:

mailcowdockerized_vmail-vol-1
mailcowdockerized_vmail-index-vol-1
mailcowdockerized_crypt-vol-1   ✅ 必須包含

若缺少 crypt-vol-1

郵件將永久無法解密


✅ 技術補充

mail_crypt 使用:

  • 公鑰加密郵件
  • 私鑰解密郵件

若金鑰不匹配,即使 Maildir 完整:

郵件仍然無法讀取

✅ 結論

當 Mailcow restore 後出現:

Decryption error: no private key available

這不是郵件損壞問題,而是:

Dovecot mail_crypt 金鑰未同步

只需還原 crypt volume,即可完全修復。