透過 Cloudflare SSH 隧道使用 EAG Proxmox
Proxmox VE 9.2 伺服器托管 disposable 測試 VM。在此環境中,主機為 eric-pve-ssh.eag.tools。代理程式會複製範本、執行測試,然後在刪除任何東西前詢問使用者。
範本、複製步驟和 guest 登入方式與 LAN 環境相同。不同的只是路徑:雲端代理程式透過 Cloudflare Access 連線到主機,並透過該主機跳轉連線到每個 guest。
存取
環境啟動腳本會從 PVE_SSH_PRIVATE_B64 和 PVE_SSH_PUBLIC_KEY 建立金鑰對:
| 檔案 | 模式 | 用途 |
|---|---|---|
~/.ssh/pve_ssh | 600 | 私鑰。用於 Proxmox 主機、Windows Administrator、Ubuntu erolleman。 |
~/.ssh/pve_ssh.pub | 644 | 對應的公鑰。 |
/etc/ssh/ssh_config.d/eric-pve-ssh.conf 已為 eric-pve-ssh.eag.tools 設定 User root、IdentityFile ~/.ssh/pve_ssh、IdentitiesOnly yes 和 ProxyCommand /usr/local/bin/cloudflared access ssh --hostname %h。請使用該主機別名。保留系統檔案不變。
KEY="$HOME/.ssh/pve_ssh"
test -r "$KEY" || { echo "缺少 $KEY;啟動腳本會從 PVE_SSH_PRIVATE_B64 建立它" >&2; exit 1; }
PVE="ssh -o StrictHostKeyChecking=accept-new eric-pve-ssh.eag.tools"
$PVE 'qm list'
Guest SSH,同時適用於 10.115.64.x (vmbr0) 和 10.20.0.x (nat0):
JUMP='ssh -o StrictHostKeyChecking=accept-new -W %h:%p eric-pve-ssh.eag.tools'
VMSSH="ssh -i $KEY -o IdentitiesOnly=yes -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null -o ConnectTimeout=5 -o ProxyCommand=\"$JUMP\" USER@$IP"
在展開 VMSSH 之前,將 USER 設為 Administrator 或 erolleman,並將 IP 設為 guest 位址。
- Windows VM 登入:
Administrator/Change_me,或使用~/.ssh/pve_ssh。 - Ubuntu VM 登入:使用
~/.ssh/pve_ssh以erolleman身分登入。sudo無需密碼。docker需要sudo。 - Proxmox Web UI 在 LAN 上監聽於
https://10.115.64.44:8006。此隧道僅限 SSH。請透過$PVE使用qm和pvesh管理主機。 - 請將金鑰資料保留在上述檔案中。不要將
~/.ssh/pve_ssh或PVE_SSH_PRIVATE_B64的內容讀入命令、日誌或回覆中。不要產生替代金鑰。
透過 SSH 的 PowerShell 遠端使用相同的跳轉主機。將以下內容加入 ~/.ssh/config(僅 guest 的 Host 區塊;系統檔案已涵蓋隧道主機):
Host 10.115.64.* 10.20.0.*
IdentityFile ~/.ssh/pve_ssh
IdentitiesOnly yes
StrictHostKeyChecking no
UserKnownHostsFile /dev/null
ProxyCommand ssh -o StrictHostKeyChecking=accept-new -W %h:%p eric-pve-ssh.eag.tools
Enter-PSSession -HostName <ip> -UserName Administrator -KeyFilePath "$HOME/.ssh/pve_ssh"
嚴格規範
- 絕對不要啟動、修改、覆蓋複製或刪除 VM 100(
ubuntu-2404)或 VM 101(ws2025-template)。兩者皆為範本。 - 除非使用者明確要求,否則不要變更主機設定(儲存、網路、SDN、套件)。
- 不要在複製體上重新執行 sysprep、
windows-template/Copy-SysprepFiles.ps1或ubuntu-template/cloud-init-prepare.sh。這些腳本用於準備範本,且存放在工作站上。它們不在這個環境中。 - 為您建立的每個 VM 加上
ai-test標籤。 - 測試完成後,詢問使用者是否要銷毀您建立的 VM。未經使用者回答,絕不銷毀任何 VM。
- 不要直接開啟 SSH 連線到
10.115.64.44、10.115.64.x或10.20.0.x。這些網路不會路由到雲端代理程式。主機命令必須透過eric-pve-ssh.eag.tools。Guest 命令使用上述的ProxyCommand跳轉。
主機資訊
此主機是一個 Hyper-V 虛擬機器。已啟用巢狀 VT-x。在 LAN 上,其位址為 10.115.64.44。
| 項目 | 值 |
|---|---|
| 硬體 | Intel Xeon Gold 6234(8 核心 / 16 執行緒),94 GB RAM。請據此分配 VM 資源。 |
vmbr0 | LAN 橋接器,DHCP。主機位址 10.115.64.44/24,閘道和 DNS 10.115.64.1,搜尋網域 eag.lan。兩個範本的 NIC 都在此橋接器上。Guest 位址為 10.115.64.x。從此環境透過 eric-pve-ssh.eag.tools 跳轉以 SSH 連線到它們。 |
nat0 | SDN VNet(簡單區域 nat),10.20.0.0/24。閘道 10.20.0.1。DHCP 範圍 10.20.0.100–10.20.0.200(12 小時)由主機上的 dnsmasq 提供,DNS 10.20.0.1。SNAT 出口為 vmbr0,位址 10.115.64.44。Proxmox 主機可以連線到此子網路。從此環境,SSH 到 10.20.0.x 使用相同的跳轉主機。 |
local-data | VG vmdata 上的 LVM-thin,約 671 GB。存放 VM 磁碟、EFI、TPM 和 cloud-init 驅動。 |
local-lvm | 小型 PVE 系統 VG 上的 LVM-thin,約 23 GB,為空。請勿使用。 |
local | 根檔案系統上的目錄。備份、容器範本、匯入。 |
isos | 目錄 /mnt/isos。僅存放安裝 ISO。 |
選用範本
| 需求 | 複製來源 |
|---|---|
| Windows、RDP 或 Windows PowerShell | 101 ws2025-template |
Linux、Docker、pwsh 或 Nushell | 100 ubuntu-2404 |
如果使用者未指定作業系統,請在複製前詢問。
Windows 複製體會在 guest 內部啟用 RDP。Cloudflare 隧道僅傳送 SSH。請使用 SSH 或 PowerShell 遠端連線到 guest。
範本:ws2025-template(VMID 101)
Windows Server 2025 Datacenter Evaluation。4 vCPU(host)、4 GB RAM、UEFI + Secure Boot + TPM 2.0、64 GB VirtIO SCSI 磁碟(位於 local-data)、VirtIO NIC(位於 vmbr0,4 佇列)、已安裝 VirtIO 驅動和 QEMU guest agent。
首次開機時,每個複製體會自動:
- 取得隨機電腦名稱、太平洋時區、en-US 地區設定,以及 Administrator 密碼
Change_me。 - 自動登入一次並執行
Initialize-WindowsServer.ps1,該腳本會從 GitHub 安裝最新的 PowerShell 7、啟用 OpenSSH 伺服器並包含powershell子系統(透過 SSH 進行 PS 遠端)、將 SSH 金鑰加入administrators_authorized_keys、啟用 RDP、將公用網路設為私人網路,並移除 Ctrl+Alt+Del 需求。 - 移除自動登入密碼和回應檔案,寫入
C:\ProgramData\TemplateSetup\setup-complete,然後重新啟動。
首次開機需要幾分鐘時間,且需要網際網路連線(下載 PowerShell 7)。記錄檔:C:\ProgramData\TemplateSetup\Initialize-WindowsServer.log。
範本:ubuntu-2404(VMID 100)
Ubuntu 24.04.5 LTS。2 vCPU(x86-64-v2-AES)、4 GB RAM、UEFI(未註冊 Secure Boot 金鑰)、無 TPM、32 GB VirtIO SCSI 磁碟(位於 local-data)、VirtIO NIC(位於 vmbr0)。已安裝 QEMU guest agent、OpenSSH、PowerShell 7(pwsh)、Nushell(nu 位於 /usr/local/bin)和 Docker。未安裝 Podman。時區為 UTC。
Cloud-init 已被清理並限制為僅使用 NoCloud 和 ConfigDrive 資料來源。磁碟上沒有 netplan,因此在 Proxmox cloud-init 執行之前,複製體將沒有網路。帳戶 erolleman 已在 sudo 群組中,並已包含專案公鑰。SSH 是 socket-activated 的。Guest agent 在 virtio 連接埠出現時由 udev 啟動。
Proxmox 產生的 user-data 也會建立一個已鎖定且沒有 SSH 金鑰的 ubuntu 帳戶。請以 erolleman 身分登入。
工作流程:建立測試 VM
- [ ] 1. 確認來源 VM 是範本
- [ ] 2. 複製、設定、標籤、啟動
- [ ] 3. 從 guest agent 取得 IP
- [ ] 4. 等待首次開機完成
- [ ] 5. 執行測試
- [ ] 6. 詢問使用者是否要銷毀 VM
1. 確認範本。 如果此命令沒有任何輸出,請停止並通知使用者。不要複製非範本的 VM。
$PVE 'qm config 101 | grep ^template' # Windows
$PVE 'qm config 100 | grep ^template' # Ubuntu
2. 複製、設定、標籤、啟動。 預設為連結複製。僅當 VM 必須比範本更長壽時,才加上 --full --storage local-data。
複製體會繼承 4 vCPU / 4 GB(Windows)或 2 vCPU / 4 GB(Ubuntu)。當測試需要更多資源時,請在啟動前使用 qm set 設定複製體。保持範本不變。
Windows:
ID=$($PVE 'pvesh get /cluster/nextid')
$PVE "qm clone 101 $ID --name test-<用途> && qm set $ID --tags ai-test && qm start $ID"
Ubuntu:在首次啟動前掛載 cloud-init 磁碟。範本上的 ide2 是一個空的 CD;請取代它。--ciupgrade 0 會跳過預設的完整套件升級。如果沒有 --ipconfig0 ip=dhcp,複製體將永遠無法取得位址。
ID=$($PVE 'pvesh get /cluster/nextid')
$PVE "qm clone 100 $ID --name test-<用途> && qm set $ID --tags ai-test --ide2 local-data:cloudinit --citype nocloud --ipconfig0 ip=dhcp --ciupgrade 0 --boot order=scsi0 && qm start $ID"
隔離網路,任何作業系統:在啟動前,將 NIC 設為 nat0。僅當使用者希望 VM 脫離 LAN 時才保留此設定。Guest 位址將是 10.20.0.x。從此環境的 SSH 仍然使用「存取」一節中的跳轉主機;Proxmox 主機是能夠連線到 nat0 的唯一節點。
$PVE "qm set $ID --net0 virtio,bridge=nat0"
# 僅限 Ubuntu。Windows 會自行 DHCP。將 Ubuntu 的 DNS 指向 NAT 閘道上的 dnsmasq。
$PVE "qm set $ID --ipconfig0 ip=dhcp --nameserver 10.20.0.1"
3. 取得 IP。 作業系統啟動後,guest agent 會回應。大約每 15 秒重試一次。對於 vmbr0 NIC,使用 10.115.64.x 位址;對於 nat0,使用 10.20.0.x 位址。
$PVE "qm guest cmd $ID network-get-interfaces" \
| jq -r '.[]."ip-addresses"[]? | select(."ip-address-type"=="ipv4") | ."ip-address"' \
| grep -vE '^(127\.|169\.254\.)'
4. 等待首次開機。 複製體會取得新的主機金鑰,且位址會被重複使用,因此 guest SSH 會跳過主機金鑰檢查。跳轉主機金鑰已使用 accept-new 儲存。
Windows:SSH 在設定期間上線,腳本在設定完成後會重新啟動 VM。一旦 setup-complete 存在且 Windows 在寫入該檔案後再次啟動,VM 即準備就緒。
VMSSH="ssh -i $KEY -o IdentitiesOnly=yes -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null -o ConnectTimeout=5 -o ProxyCommand=\"$JUMP\" Administrator@$IP"
# -EncodedCommand (base64 UTF-16LE) 可避免巢狀的 bash/cmd/PowerShell 引號問題。
PS_CHECK=$(cat <<'EOF'
$m = Get-Item C:\ProgramData\TemplateSetup\setup-complete -ErrorAction SilentlyContinue
if ($m -and (Get-CimInstance Win32_OperatingSystem).LastBootUpTime -gt $m.LastWriteTime) { 'READY ' + (Get-Content $m.FullName) } else { 'WAITING' }
EOF
)
CHECK="powershell -NoProfile -EncodedCommand $(printf %s "$PS_CHECK" | iconv -t UTF-16LE | base64 -w0)"
until STATUS=$($VMSSH "$CHECK" 2>/dev/null | tr -d '\r'); [[ $STATUS == READY* ]]; do sleep 15; done
echo "$STATUS"
READY succeeded 表示設定已完成且 VM 已重新啟動。如果顯示 READY failed,請閱讀記錄檔並回報:
$VMSSH 'powershell -NoProfile -Command "Get-Content C:\ProgramData\TemplateSetup\Initialize-WindowsServer.log -Tail 30"'
Ubuntu:等待 cloud-init 回報 status: done。status: error 表示應停止並閱讀 /var/log/cloud-init-output.log。
VMSSH="ssh -i $KEY -o IdentitiesOnly=yes -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null -o ConnectTimeout=5 -o ProxyCommand=\"$JUMP\" erolleman@$IP"
until STATUS=$($VMSSH 'cloud-init status 2>/dev/null' | tr -d '\r'); [[ $STATUS == status:\ done || $STATUS == status:\ error ]]; do sleep 10; done
echo "$STATUS"
5. 執行測試。
Windows:預設的 SSH shell 是 cmd.exe。
$VMSSH 'pwsh -NoProfile -Command "Get-ComputerInfo | Select-Object OsName, CsName"'
透過 SSH 的 PowerShell 遠端(從雲端代理程式的 pwsh 執行)使用「存取」一節中的 ~/.ssh/config guest 區塊:
Enter-PSSession -HostName <ip> -UserName Administrator -KeyFilePath "$HOME/.ssh/pve_ssh"
Ubuntu:
$VMSSH 'pwsh -NoLogo -Command "$PSVersionTable.PSVersion.ToString()"'
$VMSSH 'sudo docker info --format "{{.ServerVersion}}"'
6. 清理前先詢問。 回報測試結果,列出您建立的 VM(VMID、名稱、IP),並詢問使用者是否要銷毀它們。在可用時使用 AskQuestion 工具,選項包括「銷毀」、「保持執行」和「關機但保留」(如果您建立了多個 VM,則加上每個 VM 的選擇)。
如果使用者選擇銷毀:
$PVE "qm stop $ID && qm destroy $ID --purge"
如果使用者選擇保留但關機:
$PVE "qm shutdown $ID --timeout 120 || qm stop $ID"
當 VM 被保留時,告知使用者其 VMID,以便日後可以找到它們(它們會保留 ai-test 標籤)。
快照
兩個範本的磁碟都位於 LVM-thin 上,因此複製體支援快照:
$PVE "qm snapshot $ID before-test"
$PVE "qm rollback $ID before-test"
$PVE "qm delsnapshot $ID before-test"
清理與庫存
$PVE 'pvesh get /cluster/resources --type vm --output-format json' \
| jq -r '.[] | select((.tags // "") | split(";") | index("ai-test")) | "\(.vmid)\t\(.name)\t\(.status)"'
除非使用者要求更廣泛的清理,否則僅提議銷毀您在此工作階段中建立的 ai-test VM。務必先取得使用者的確認。
注意事項
- Windows 是 Evaluation 版本,具有 180 天授權。僅適用於短期 VM。
- 如果 Ubuntu 複製體在沒有 cloud-init 磁碟的情況下啟動一次,它將在沒有網路的情況下啟動,且 cloud-init 不會乾淨地重試。請銷毀它並重新複製。
- 不要在 Windows 複製體上執行
sysprep,也不要將任一範本的複製體轉換為範本。 - 主機位址是 DHCP 租約。
nat0SNAT 固定為10.115.64.44。如果該位址變更,請告知;除非使用者要求,否則不要編輯 SDN。 cloudflared由系統 SSH 設定檔以/usr/local/bin/cloudflared的方式呼叫。缺少金鑰檔案表示啟動腳本未執行;請保留密鑰不變並回報此情況。- 每次複製時,guest 主機金鑰都會變更。
UserKnownHostsFile=/dev/null適用於 guest 工作階段。隧道主機金鑰會保留在~/.ssh/known_hosts中。