mcpField
W
windows-vm

windows-vm

github.com/obraクラウド・DevOps434274 回インストール21 週間前に更新
リポジトリ

windows-vm について

windows-vmは、DockerとKVMでヘッドレスのWindows 11 VMを実行・管理するスキルです。SSHで利用できるWindows環境が必要な開発者向けに、VMの操作や画面のデバッグを扱います。

主な機能

  1. 01DockerでヘッドレスWindows 11 VMを作成
  2. 02SSH経由でVMに接続
  3. 03VMの起動、停止、再起動、状態確認
  4. 04デバッグ用のVM画面キャプチャ
  5. 05再作成時に備えたISOのキャッシュ

活用シーン

  1. 01分離されたWindowsコマンドライン環境の提供
  2. 02SSH経由でのWindows VM管理
  3. 03VMの起動画面のデバッグ
  4. 04ISOの再利用による再ダウンロード回避

インストール

コマンドをコピーしてターミナルで実行します。

$npx skills add https://github.com/obra/superpowers-lab --skill windows-vm

インストール後、Claude Code で/windows-vmを入力して読み込まれたか確認します。

詳細

ヘッドレス Windows 11 VM

KVM アクセラレーション付きの Docker 上で実行される dockur/windows のヘッドレス Windows 11 VM を管理します。VM には SSH のみでアクセスでき、RDP や GUI は必要ありません。

ホストの前提条件

  • Docker
  • KVM のサポート(/dev/kvm が存在する必要があります。ls /dev/kvm で確認してください)
  • sshpass(sudo apt install sshpass)
  • imagemagick(任意。スクリーンショットのデバッグ用:sudo apt install imagemagick)

構成

  • コンテナー名:windows11
  • VM ディレクトリ:$HOME/windows-vm/
    • storage/ — VM ディスクイメージ(dockur が管理し、再作成時に消去されます)
    • iso/win11x64.iso — キャッシュ済み Windows ISO(7.3GB。再作成後も保持されます)
    • oem/install.bat — インストール後スクリプト(OpenSSH Server をインストール)
  • 認証情報:user / password
  • SSH:localhost:2222(127.0.0.1 のみでバインド)
  • RDP:localhost:3389(127.0.0.1 のみでバインド。フォールバック用)
  • Web コンソール:localhost:8006(ブラウザー内の VNC。デバッグ用)
  • リソース:RAM 8GB、CPU 4 コア、ディスク 64GB

操作

create — 初回セットアップまたは完全な再作成
  1. ディレクトリが存在することを確認します:

    mkdir -p "$HOME/windows-vm/oem" "$HOME/windows-vm/storage" "$HOME/windows-vm/iso"
    
  2. $HOME/windows-vm/oem/install.bat に OpenSSH のセットアップが記述されていることを確認します:

    @echo off
    echo Installing OpenSSH Server...
    powershell -Command "Add-WindowsCapability -Online -Name OpenSSH.Server~~~~0.0.1.0" 2>nul
    powershell -Command "Get-WindowsCapability -Online -Name OpenSSH.Server* | Add-WindowsCapability -Online" 2>nul
    dism /Online /Add-Capability /CapabilityName:OpenSSH.Server~~~~0.0.1.0 2>nul
    powershell -Command "Start-Service sshd" 2>nul
    powershell -Command "Set-Service -Name sshd -StartupType Automatic"
    powershell -Command "New-ItemProperty -Path 'HKLM:\SOFTWARE\OpenSSH' -Name DefaultShell -Value 'C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe' -PropertyType String -Force"
    powershell -Command "New-NetFirewallRule -Name 'OpenSSH-Server' -DisplayName 'OpenSSH Server' -Enabled True -Direction Inbound -Protocol TCP -Action Allow -LocalPort 22"
    powershell -Command "Get-Service sshd" 2>nul
    echo Done.
    
  3. 再作成する場合は、古いコンテナーとディスクを削除します:

    docker stop windows11 && docker rm windows11
    rm -f "$HOME/windows-vm/storage/data.img"
    
  4. コンテナーを起動します。以下の 2 つのケースがあります:

    キャッシュ済み ISO がある場合($HOME/windows-vm/iso/win11x64.iso):

    docker run -d \
      --name windows11 \
      -p 127.0.0.1:3389:3389 \
      -p 127.0.0.1:2222:22 \
      -p 127.0.0.1:8006:8006 \
      -e RAM_SIZE="8G" \
      -e CPU_CORES="4" \
      -e DISK_SIZE="64G" \
      -e USERNAME="user" \
      -e PASSWORD="password" \
      --cap-add NET_ADMIN \
      --device /dev/kvm \
      -v "$HOME/windows-vm/storage:/storage" \
      -v "$HOME/windows-vm/oem:/oem" \
      -v "$HOME/windows-vm/iso/win11x64.iso:/boot.iso" \
      dockurr/windows
    

    初回(キャッシュ済み ISO がない場合) — /boot.iso のマウントを省略し、VERSION を追加します:

    docker run -d \
      --name windows11 \
      -p 127.0.0.1:3389:3389 \
      -p 127.0.0.1:2222:22 \
      -p 127.0.0.1:8006:8006 \
      -e RAM_SIZE="8G" \
      -e CPU_CORES="4" \
      -e DISK_SIZE="64G" \
      -e VERSION="win11" \
      -e USERNAME="user" \
      -e PASSWORD="password" \
      --cap-add NET_ADMIN \
      --device /dev/kvm \
      -v "$HOME/windows-vm/storage:/storage" \
      -v "$HOME/windows-vm/oem:/oem" \
      dockurr/windows
    

    ISO のダウンロードが完了して Windows が起動したら、コンテナーを停止する前に、すぐに ISO をコピーします(dockur は再作成時に /storage を消去します):

    cp "$HOME/windows-vm/storage/win11x64.iso" "$HOME/windows-vm/iso/win11x64.iso"
    
  5. Windows のインストールと OpenSSH のセットアップが完了するまで待ちます。新規インストールでは 20〜30 分かかります(OEM の install.bat は Windows OOBE の最後に実行され、Microsoft から OpenSSH をダウンロードしますが、これには時間がかかります)。次のコマンドで状況を確認できます:

    docker logs -f windows11
    

    http://localhost:8006 の Web コンソールから VM の画面を見ることもできます。

    SSH が起動したかどうかを確認するには:

    sshpass -p 'password' ssh -o StrictHostKeyChecking=no -o ConnectTimeout=5 -p 2222 user@localhost "whoami"
    
  6. SSH 経由での PowerShell のエスケープ処理を避けるため、標準入力からセットアップスクリプトを渡して Node.js と Claude Code をインストールします:

    cat << 'PS' | sshpass -p 'password' ssh -o StrictHostKeyChecking=no -p 2222 user@localhost "powershell -ExecutionPolicy Bypass -Command -"
    # Download and install Node.js silently
    Invoke-WebRequest -Uri 'https://nodejs.org/dist/v22.14.0/node-v22.14.0-x64.msi' -OutFile 'C:\Users\user\node-install.msi'
    Start-Process msiexec.exe -ArgumentList '/i C:\Users\user\node-install.msi /qn /norestart' -Wait -Verb RunAs
    Write-Host "Node.js installed"
    
    # Install Claude Code globally
    & 'C:\Program Files\nodejs\npm.cmd' install -g @anthropic-ai/claude-code
    Write-Host "Claude Code installed"
    
    # Add npm global bin to SYSTEM PATH (user PATH is not read by sshd)
    $systemPath = [Environment]::GetEnvironmentVariable('Path', 'Machine')
    $additions = @()
    if ($systemPath -notlike '*AppData*npm*') { $additions += 'C:\Users\user\AppData\Roaming\npm' }
    if ($systemPath -notlike '*Git\cmd*') { $additions += 'C:\Program Files\Git\cmd' }
    if ($additions.Count -gt 0) {
        [Environment]::SetEnvironmentVariable('Path', $systemPath + ';' + ($additions -join ';'), 'Machine')
        Write-Host "Added to system PATH: $($additions -join ', ')"
    }
    
    # Set execution policy machine-wide (required for claude.ps1)
    Set-ExecutionPolicy RemoteSigned -Scope LocalMachine -Force -ErrorAction SilentlyContinue
    
    # Create system-wide PowerShell profile that rebuilds PATH from registry on login.
    # Without this, interactive SSH sessions don't pick up the full system PATH.
    $profileDir = Split-Path $PROFILE.AllUsersAllHosts
    if (-not (Test-Path $profileDir)) { New-Item -ItemType Directory -Path $profileDir -Force }
    @'
    $machinePath = [Environment]::GetEnvironmentVariable('Path', 'Machine')
    $userPath = [Environment]::GetEnvironmentVariable('Path', 'User')
    $env:Path = "$machinePath;$userPath"
    '@ | Set-Content -Path $PROFILE.AllUsersAllHosts -Force
    Write-Host "PowerShell profile created"
    
    # Restart sshd so it picks up the new PATH
    Restart-Service sshd -Force
    PS
    

    注:sshd の再起動時に接続が切れますが、これは想定どおりです。

  7. 古いホストキーを削除します(新しい VM ではホストキーも新しくなります)。その後、動作を確認します:

    ssh-keygen -f ~/.ssh/known_hosts -R '[localhost]:2222'
    sshpass -p 'password' ssh -o StrictHostKeyChecking=no -p 2222 user@localhost "claude --version"
    
start — 停止中の VM を起動
docker start windows11
stop — VM を停止
docker stop windows11
restart — VM を再起動
docker restart windows11
status — VM の状態を確認
docker ps -f name=windows11 --format "table {{.Status}}\t{{.Ports}}"
docker logs windows11 2>&1 | tail -5
ssh — VM に接続
ssh -p 2222 user@localhost
screenshot — VM の画面を確認(デバッグ用)
docker exec windows11 bash -c "echo 'screendump /tmp/screen.ppm' | nc -w 2 localhost 7100" > /dev/null 2>&1
sleep 1
docker cp windows11:/tmp/screen.ppm /tmp/screen.ppm
convert /tmp/screen.ppm /tmp/screen.png

重要な注意事項

  • ISO のキャッシュ:/storage ボリュームは dockur によって管理され、再作成時に消去されます。ISO は $HOME/windows-vm/iso/ に別途保存し、/boot.iso としてマウントすると、7.3GB のダウンロードを省略できます。
  • --cap-add NET_ADMIN はポートフォワーディングに必要です。指定しない場合、QEMU はユーザーモードネットワークにフォールバックし、ポートフォワーディングは通知なく失敗します。
  • --device /dev/kvm はハードウェアアクセラレーションに必要です。
  • 起動時間:新規インストールには 20〜30 分かかります(Windows のインストールと Microsoft からの OpenSSH のダウンロード)。既存の data.img からの 2 回目以降の起動は高速です(約 2 分)。
  • ポートは 127.0.0.1 のみでバインドされ、ネットワークには公開されません。
  • /boot.iso をマウントする場合は、-e VERSION="win11" を使用しないでください。バージョンは ISO から自動検出されます。

インストール後の注意点

  • Node.js は事前にインストールされていません — Claude Code のインストールスクリプト(irm https://claude.ai/install.ps1 | iex)は成功したと表示されますが、Node をインストールしないと claude は動作しません。まず MSI で Node.js をインストールしてください。
  • npm のグローバル bin が PATH に含まれていません — Node の MSI は C:\Program Files\nodejs を PATH に追加しますが、npm install -g でバイナリが配置される C:\Users\user\AppData\Roaming\npm は追加しません。OpenSSH の sshd はシステム PATH しか読み取らないため、ユーザー PATH ではなくシステム PATH に追加する必要があります。システム PATH を変更した後、sshd を再起動してください。
  • PowerShell の実行ポリシー — 既定のポリシーは Restricted で、claude.ps1 がブロックされます。SSH セッションで有効にするには、CurrentUser ではなく LocalMachine スコープで RemoteSigned に設定する必要があります。
  • エスケープの問題 — 入れ子の引用符を含む PowerShell コマンドを SSH 経由で実行すると、正常に動作しないことがあります。代わりに、powershell -ExecutionPolicy Bypass -Command - を使い、スクリプトを標準入力経由でパイプしてください。
  • 対話型 SSH セッションでは完全な PATH が設定されません — Windows OpenSSH の sshd は、システム PATH を対話型 PowerShell セッションに正しく引き継ぎません。対処法:システム全体に適用される PowerShell プロファイル($PROFILE.AllUsersAllHosts)を作成し、ログインのたびにレジストリから $env:Path を再構築してください。
  • winget が動作しない場合があります — VM では Microsoft Store の証明書が原因で失敗することがあります。代わりに MSI またはインストーラーを直接ダウンロードしてください。
  • ホストキーの変更 — VM を再作成するたびに、新しい SSH ホストキーが割り当てられます。ssh-keygen -R '[localhost]:2222' を実行して古いキーを削除してください。

コメント