Cloudflare SSH トンネル経由の EAG Proxmox
Proxmox VE 9.2 サーバーは、使い捨てテスト VM をホストします。この環境から、ホストは eric-pve-ssh.eag.tools です。エージェントはテンプレートのクローンを作成し、テストを実行してから、削除する前にユーザーに確認します。
テンプレート、クローン手順、およびゲストログインは LAN 環境と同じです。変更点はパスです。クラウドエージェントは Cloudflare Access を経由してホストに到達し、そのホストを経由してすべてのゲストに到達します。
アクセス
環境開始スクリプトは、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 "missing $KEY; the start script creates it from PVE_SSH_PRIVATE_B64" >&2; exit 1; }
PVE="ssh -o StrictHostKeyChecking=accept-new eric-pve-ssh.eag.tools"
$PVE 'qm list'
ゲスト 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 をゲストアドレスに設定します。
- 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 にこれを追加します(ゲスト 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 を破棄しないでください。
10.115.64.44、10.115.64.x、または10.20.0.xへの直接 SSH セッションを開かないでください。これらのネットワークはクラウドエージェントにルーティングされていません。ホストコマンドはeric-pve-ssh.eag.toolsを経由します。ゲストコマンドは上記の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 はこのブリッジ上にあります。ゲストアドレスは 10.115.64.x です。この環境から、それらへの SSH は eric-pve-ssh.eag.tools を経由してジャンプします。 |
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 ホストはこのサブネットに到達できます。この環境から、10.20.0.x への SSH は同じジャンプを使用します。 |
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 |
ユーザーが OS を指定しない場合は、クローンを作成する前に確認します。
Windows クローンは、ゲスト内で RDP を有効にします。Cloudflare トンネルは SSH を伝送します。SSH または PowerShell リモーティングを使用してゲストに接続します。
テンプレート: ws2025-template(VMID 101)
Windows Server 2025 Datacenter Evaluation。4 vCPU(host)、4 GB RAM、UEFI + セキュアブート + TPM 2.0、local-data 上の 64 GB VirtIO SCSI ディスク、vmbr0 上の VirtIO NIC(4 キュー)、VirtIO ドライバーと QEMU ゲストエージェントがインストール済み。
初回起動時に、すべてのクローンは自動的に:
- ランダムなコンピューター名、太平洋時間帯、en-US ロケール、および Administrator パスワード
Change_meを取得します。 - 自動ログオンを 1 回実行し、
Initialize-WindowsServer.ps1を実行します。このスクリプトは、GitHub から最新の PowerShell 7 をインストールし、powershellサブシステム(SSH 経由の PS リモーティング)を使用して OpenSSH サーバーを有効にし、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(セキュアブートキー未登録)、TPM なし、local-data 上の 32 GB VirtIO SCSI ディスク、vmbr0 上の VirtIO NIC。QEMU ゲストエージェント、OpenSSH、PowerShell 7(pwsh)、Nushell(/usr/local/bin 上の nu)、および Docker がインストールされています。Podman はインストールされていません。タイムゾーンは UTC です。
Cloud-init はクリーンアップされ、NoCloud および ConfigDrive データソースに制限されています。ディスクには netplan がないため、Proxmox cloud-init が実行されるまで、クローンにはネットワークがありません。アカウント erolleman は既に sudo グループに属し、プロジェクトの公開鍵を持っています。SSH はソケットアクティベーションされています。ゲストエージェントは、virtio ポートが表示されたときに udev から起動します。
Proxmox によって生成された user-data は、ロックされた ubuntu アカウントを SSH キーなしで作成します。erolleman としてログインします。
ワークフロー: テスト VM を作成する
- [ ] 1. ソース VM がテンプレートであることを確認する
- [ ] 2. クローンを作成し、設定し、タグを付け、起動する
- [ ] 3. ゲストエージェントから 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-<purpose> && 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-<purpose> && qm set $ID --tags ai-test --ide2 local-data:cloudinit --citype nocloud --ipconfig0 ip=dhcp --ciupgrade 0 --boot order=scsi0 && qm start $ID"
分離ネットワーク、どちらの OS でも: 起動前に NIC を nat0 に配置します。これは、ユーザーが VM を LAN からオフにしたい場合のみ保持します。ゲストアドレスは 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 を取得する。 ゲストエージェントは、OS が起動すると応答します。約 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. 初回起動を待機する。 クローンは新しいホストキーを取得し、アドレスは再利用されるため、ゲスト 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 シェルは cmd.exe です。
$VMSSH 'pwsh -NoProfile -Command "Get-ComputerInfo | Select-Object OsName, CsName"'
SSH 経由の PowerShell リモーティング(クラウドエージェント上の pwsh から)は、アクセスの ~/.ssh/config ゲストブロックを使用します:
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 ツールを使用し、オプション「Destroy」、「Keep running」、「Shut down but keep」(複数作成した場合は 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 は 180 日間ライセンスの評価版です。短期間の VM に使用します。
- cloud-init ドライブなしで一度起動した Ubuntu クローンは、ネットワークなしで起動し、cloud-init は正常に再試行しません。それを破棄して、再度クローンを作成します。
- Windows クローンで
sysprepを実行したり、どちらかのテンプレートのクローンをテンプレートに変換したりしないでください。 - ホストアドレスは DHCP リースです。
nat0SNAT は10.115.64.44に固定されています。そのアドレスが変更された場合は、そのように伝えてください。ユーザーが要求しない限り、SDN を編集しないでください。 cloudflaredは、システム SSH 設定によって/usr/local/bin/cloudflaredとして呼び出されます。キーファイルが見つからない場合は、開始スクリプトが実行されなかったことを意味します。シークレットには触れず、そのことを報告してください。- ゲストホストキーはクローンごとに変更されます。
UserKnownHostsFile=/dev/nullはゲストセッションに適用されます。トンネルホストキーは~/.ssh/known_hostsに残ります。