はじめに
Windows上でVirtualBoxを使いLinux環境で開発を行っている皆さん、こんなお悩みはありませんか?
- 「VMを起動して、VSCodeを開いて、SSH接続して…毎回の準備が面倒!」
- 「VSCodeでせっかく開発プロファイルを作ったのに、SSH接続するとデフォルトで開いてしまう…」
- 「VMのGUIは使わないのに、リソースもウィンドウも無駄に感じる…」
この記事では、そんなお悩みを解決し、開発フローを大幅に効率化する方法をご紹介します。ホストOSのVSCode系エディタからゲストOS(Linux Mint想定ですが、他のLinuxディストリビューションでも応用可能)にスムーズに接続し、最終的にはデスクトップのショートカット一つでVMの起動(ヘッドレス)、SSH接続、VSCodeの起動までを自動化することを目指します。
📌 前提条件
- ホストOS:Windows 11
- ゲストOS:VirtualBox上のLinux(記事内ではLinux Mint 22を例としますが、Ubuntuなど他のDebian系ディストリビューションでも同様の手順で設定可能です)
- エディタ(ホストOS):VSCodeまたはその派生エディタ(以下、VSCodeと表記)
- VirtualBox Guest AdditionsがゲストOSにインストール済みであること。
⚠️ 免責事項
- 本記事の内容は、特定の検証環境(研究室の開発環境)に基づいており、お使いの環境では同様に動作しない可能性があります。
- 作業を実施する際は、万が一に備え、仮想マシンのスナップショット作成やファイルのバックアップなど、各自の環境に応じた安全対策を行ってください。
- 記事内の情報は執筆時点のものです。各種ツールやソフトウェアのバージョンアップにより、内容が古くなったり手順が変更されたりする可能性があります。
- 必要に応じて、VirtualBox、VSCode、SSH、お使いのLinuxディストリビューションなどの公式ドキュメントも併せてご参照ください。
☁️ 1. VSCodeからゲストOSへSSH接続する準備
まずは、ホストOSのVSCodeからゲストOSのLinux環境へSSHで接続できるように設定します。
1.1. VirtualBox ネットワーク設定の変更
SSH接続を受け付けるために、VirtualBoxのネットワーク設定でポートフォワーディングを設定します。
- VirtualBox マネージャーを開き、対象の仮想マシン(例:Linux Mint)を選択し、シャットダウンします。
- 仮想マシンの「設定」を開き、「ネットワーク」セクションへ進みます。
- 「アダプター1」(または利用するアダプター)で以下のように設定します。
- 割り当て:
NAT
- NATを選択することで、ゲストOSはホストOSのIPアドレスを共有して外部ネットワークに接続しつつ、ポートフォワーディングでホストOSからゲストOSへの特定の通信を許可できます。
- 「高度」を展開し、「ポートフォワーディング」ボタンをクリックします。
- ルールを新規追加(右側の
+
ボタン)し、以下のように設定します(ゲストIPは空欄でも構いません)。名前 プロトコル ホストIP ホストポート ゲストIP ゲストポート SSH TCP 2222
22
- ホストポート
2222
: ホストOS側でSSH接続を待ち受けるポートです。他のサービスと重複しない任意の番号に変更可能です。 - ゲストポート
22
: ゲストOSのSSHサーバーが待ち受ける標準ポートです。
- ホストポート
- 割り当て:
1.2. ゲストOSでのSSHサーバーの構築と自動起動設定
次に、ゲストOS(Linux Mint)にSSHサーバーをインストールし、起動と自動起動の設定を行います。
- 対象の仮想マシンを起動します。
- ゲストOSのターミナルを開き、以下のコマンドを実行してOpenSSHサーバーをインストールします。
Guest OS $ sudo apt update $ sudo apt install openssh-server
- SSHサービスを起動し、OS起動時に自動で起動するように設定します。
Guest OS $ sudo systemctl start ssh $ sudo systemctl enable ssh
- SSHサービスのステータスを確認します。
active (running)
と表示されていれば正常です。Guest OS $ sudo systemctl status ssh
- 自動起動が有効になっているか確認します。
enabled
と表示されていればOKです。Guest OS $ systemctl is-enabled ssh enabled
1.3. ゲストOSのファイアウォール設定 (UFW)
ゲストOSでファイアウォール(UFW: Uncomplicated Firewall)が有効になっている場合、SSH接続を許可する設定が必要です。
-
SSHが使用するポート(デフォルトは22)への接続を許可します。
Guest OS $ sudo ufw allow 22
-
設定をリロード(再読み込み)します。
Guest OS $ sudo ufw reload
-
ファイアウォールの状態とルールを確認します。
22/tcp
(または22
) がALLOW IN Anywhere
となっていればOKです。Guest OS $ sudo ufw status 状態: アクティブ To Action From -- ------ ---- 22/tcp ALLOW Anywhere 22/tcp (v6) ALLOW Anywhere (v6)
- もし
ufw
がインストールされていない場合は、sudo apt install ufw
でインストール後、sudo ufw enable
で有効化してください。
- もし
1.4. SSH接続の確認 (ホストOSから)
ホストOS(Windows)のターミナル(コマンドプロンプトやPowerShell)から、ゲストOSへSSH接続できるか確認します。
ssh your_guest_username@localhost -p 22222
your_guest_username
はゲストOSのユーザー名に置き換えてください。-p 22222
は、VirtualBoxのポートフォワーディングで設定したホストポートです。- 初回接続時にはフィンガープリントの確認を求められるので
yes
と入力し、その後ゲストOSのユーザーパスワードを入力します。ログインできれば成功です。
1.5. VSCodeでのSSH接続設定
VSCodeから簡単にSSH接続できるように設定します。
-
ホストOSのVSCodeを起動します。
-
Remote - SSH拡張機能のインストール: もしインストールしていなければ、VSCodeの拡張機能マーケットプレイスから「Remote - SSH」(ms-vscode-remote.remote-ssh)を検索してインストールします。
-
SSH Configファイルの設定: SSH接続の設定をSSH Configファイルに記述します。このファイルは通常、ホストOSのユーザーディレクトリ配下の
.ssh
フォルダ(例:C:\Users\[ユーザー名]\.ssh\config
)にあります。ファイルがない場合は新規作成してください。 以下の内容を追記または新規作成します。.ssh/config Host your_ssh_alias HostName localhost User your_guest_username Port 22222
your_ssh_alias
: 任意の接続名(例:vbox-mint
)。VSCodeの接続先一覧に表示されます。your_guest_username
: ゲストOSのユーザー名。Port 22222
: VirtualBoxのポートフォワーディングで設定したホストポート。
-
VSCodeからSSH接続:
- VSCodeの左下にある緑色の「リモートウィンドウを開きます」アイコン(通常
><
のような形)をクリックします。 - ドロップダウンメニューから「ホストに接続する (Connect to Host...)」を選択します。
- 先ほどSSH Configファイルで設定した
your_ssh_alias
が表示されるので、それを選択します。 - 初回接続時は接続先のOSの種類を聞かれる場合があります。「Linux」を選択してください。
- 新しいVSCodeウィンドウが開き、ゲストOSのユーザーパスワードの入力を求められます。パスワードを入力して接続できれば成功です。ウィンドウの左下に
SSH: your_ssh_alias
と表示されます。
これで、ホストOSのVSCodeからゲストOSのファイルシステムにアクセスし、ターミナルもゲストOSのものを直接利用できるようになりました。
- VSCodeの左下にある緑色の「リモートウィンドウを開きます」アイコン(通常
ここまでの設定での課題点:
- 毎回SSH接続時にパスワード入力が必要(これはSSHキー認証で改善可能ですが、この記事では扱いません)。
- VSCodeで特定の開発プロファイル(拡張機能のセットなど)を使って接続したい場合、一手間かかることがある。
- ゲストOSをVirtualBoxマネージャーから手動で起動する必要があり、GUIウィンドウが表示される。
次のセクションでは、これらの課題を解決するための自動化手順に進みます。
🤖 2. 起動と接続の自動化
目標は、デスクトップのショートカットをワンクリックするだけで、以下の処理を自動で行うことです。
- VirtualBoxのゲストOSをヘッドレスモード(GUIなし)で起動。
- ゲストOSのSSHサーバーが起動するまで待機。
- 指定したVSCodeプロファイルとワークスペースで、ゲストOSへSSH接続した状態でVSCodeを起動。
2.1. VBoxManage コマンドラインツールの利用準備
VirtualBoxをコマンドラインから操作するために、VBoxManage.exe
へのパスを通します。
- Windowsの「設定」→「システム」→「バージョン情報」と進み、「システムの詳細設定」をクリックします。
- 「環境変数」ボタンをクリックします。
- 「システム環境変数」の「Path」を選択し、「編集」をクリックします。
- 「新規」をクリックし、VirtualBoxのインストールディレクトリ(通常は
C:\Program Files\Oracle\VirtualBox
)を追加します。 - OKを押して全てのダイアログを閉じ、設定を反映させるためにPCを再起動するか、新しいコマンドプロンプト/PowerShellウィンドウを開きます。
- コマンドプロンプトまたはPowerShellで
VBoxManage --version
を実行し、バージョン情報が表示されればパスが通っています。 - 自動化スクリプトで使用するVMの名前を確認しておきます。
表示されたリストから、対象のVMの名前(例:Host OS VBoxManage list vms
"Linux Mint 22"
や"MyLinuxVM"
など、引用符も含めて)を控えておきます。以降、このVM名をYour_VM_Name
とします。
2.2. ゲストOSのSSH準備完了通知の設定
ゲストOSが起動しSSH接続の準備が整ったことをホストOSに伝える仕組みを構築します。これにはVirtualBoxのGuest Properties機能を利用します。
-
対象の仮想マシンを起動します。
-
ゲストOS側: SSH準備完了通知スクリプトの作成 ゲストOSのホームディレクトリなどに、SSHサービスの起動を確認してGuest Propertyを設定するスクリプトを作成します。例えば、
~/bin/set-ssh-ready.sh
として以下の内容で作成します。~/bin
ディレクトリがない場合は作成してください。-
set-ssh-ready.sh
set-ssh-ready.sh #!/bin/bash # SSH サービス (sshd または ssh) がアクティブか確認 if systemctl is-active --quiet ssh || systemctl is-active --quiet sshd; then # VBoxControl コマンドが存在するか確認 (Guest Additions の一部) if command -v VBoxControl >/dev/null 2>&1; then /usr/bin/VBoxControl guestproperty set "/guestinfo/ssh.ready" "true" else echo "VBoxControl not found. Make sure Guest Additions are installed." >&2 fi fi
-
スクリプトに実行権限を付与します。
Guest OS $ mkdir -p ~/bin $ chmod +x ~/bin/set-ssh-ready.sh
-
-
ゲストOS側: systemdサービスファイルの作成 上記スクリプトを、ネットワークとSSHサービスが起動した後に実行するためのsystemdサービスユニットファイルを作成します。
sudo nano /etc/systemd/system/set-ssh-ready.service
などでエディタを開き、以下の内容を記述します。your_guest_username
は実際のゲストOSのユーザー名に置き換えてください。-
set-ssh-ready.service
Guest OS [Unit] Description=Set SSH Ready guest property for VirtualBox After=network.target ssh.service sshd.service [Service] User=your_guest_username Group=your_guest_username ExecStart=/home/your_guest_username/bin/set-ssh-ready.sh Type=oneshot [Install] WantedBy=multi-user.target
- 重要:
ExecStart
のパスは、実際のスクリプトの場所とユーザー名に合わせてください。 After
ディレクティブにsshd.service
も追加しておくと、ディストリビューションによってSSHデーモンのサービス名が異なる場合に対応しやすくなります。
- 重要:
-
-
ゲストOS側: systemdサービス有効化と確認
-
systemdに新しいサービスファイルを認識させ、自動起動を有効にします。
Guest OS $ sudo systemctl daemon-reload $ sudo systemctl enable set-ssh-ready.service
-
ゲストOSを再起動します:
sudo reboot
-
再起動後、サービスが一度実行されたか(
inactive (dead)
でstatus=0/SUCCESS
ならOK)、Guest Propertyが設定されたかを確認します。Guest OS $ systemctl status set-ssh-ready.service # ● set-ssh-ready.service - Set SSH Ready guest property for VirtualBox # Loaded: loaded (/etc/systemd/system/set-ssh-ready.service; enabled; ...) # Active: inactive (dead) since ... # Process: ... ExecStart=/home/your_guest_username/bin/set-ssh-ready.sh (code=exited, status=0/SUCCESS) # Main PID: ... (code=exited, status=0/SUCCESS) $ VBoxControl guestproperty get "/guestinfo/ssh.ready" # Value: true
- もし緑色で
active (running)
になっていなかったり、Value: true
が表示されない場合は、スクリプトのパス、実行権限、サービスファイルの内容、Guest Additionsのインストール状態などを確認してください。
- もし緑色で
-
-
ホストOS側: Guest Propertyの確認 ホストOSのコマンドプロンプトやPowerShellから、ゲストOSのプロパティが正しく設定されているか確認します。
Your_VM_Name
は実際のVM名に置き換えてください。Host OS VBoxManage guestproperty get "Your_VM_Name" "/guestinfo/ssh.ready" # Expected output: Value: true
2.3. ホストOS側: VSCodeワークスペースファイルの作成 (任意)
特定のプロジェクトフォルダをVSCodeで開くように、ワークスペースファイルを作成しておくと便利です。これはSSH接続後に開きたいゲストOS上のフォルダを指定します。
-
ホストOSの任意の場所(例:
C:\Users\[ユーザー名]\Documents\VSCodeWorkspaces
)に、.code-workspace
という拡張子でファイルを作成します(例:my-linux-project.code-workspace
)。 -
ファイルに以下のJSON形式で内容を記述します。
my-linux-project.code-workspace
my-linux-project.code-workspace { "folders": [ { // "your_ssh_alias" は 1.5 で設定したSSHホスト名 // "your_guest_username" はゲストOSのユーザー名 // "your_project_folder" はゲストOS内のプロジェクトフォルダ名 "uri": "vscode-remote://ssh-remote+your_ssh_alias/home/your_guest_username/your_project_folder" } ], "remoteAuthority": "ssh-remote+your_ssh_alias", // SSHホスト名を指定 "settings": { // ワークスペース固有の設定があれば記述 }, "tasks": { // このワークスペースで利用するタスク (例: VMシャットダウン) "version": "2.0.0", "tasks": [ { "label": "Shutdown Guest VM", "type": "shell", "command": "VBoxManage controlvm \"Your_VM_Name\" poweroff", // ホストOSで実行されるコマンド "problemMatcher": [], "group": "build", "presentation": { "reveal": "always", "close": true } } ] } }
uri
のパスやremoteAuthority
は、ご自身の環境に合わせて正確に設定してください。tasks
内のVMシャットダウンタスクは、VSCodeのコマンドパレット (Ctrl+Shift+P
) からTasks: Run Task
を選択し、Shutdown Guest VM
を実行することで、VMをシャットダウンできます。これはホストOS側のコマンドとして実行される点に注意してください。
2.4. ホストOS側: 自動起動用PowerShellスクリプトの作成
VMの起動、SSH準備待機、VSCodeの起動を連続して行うPowerShellスクリプトを作成します。
-
ホストOSの任意の場所(例:
C:\Users\[ユーザー名]\Scripts
)に、.ps1
という拡張子でスクリプトファイルを作成します(例:launch-linux-dev-env.ps1
)。 -
以下のスクリプトを参考に、ファイルに内容を記述します。
<...>
のプレースホルダー部分はご自身の環境に合わせて必ず変更してください。-
launch-linux-dev-env.ps1
launch-linux-dev-env.ps1 <# .SYNOPSIS VirtualBox VMをヘッドレスで起動し、SSH接続準備が整うまで待機後、 VSCodeを指定のプロファイルとワークスペースで起動します。 .DESCRIPTION 1. 指定されたVMが実行中でなければヘッドレスモードで起動します。 2. VMが起動し、Guest Property "/guestinfo/ssh.ready" が "true" になるまで待機します。 3. 指定されたVSCodeの実行パス、プロファイル名、ワークスペースファイルでVSCodeを起動します。 .NOTES Author: Riku-Mono Last Updated: 2025-06-07 Requires: VirtualBox command line tools (VBoxManage) in PATH. Guest OS configured to set "/guestinfo/ssh.ready" property. #> [CmdletBinding()] param() #====================================================================== # 🔧 設定 (ここを環境に合わせて変更してください) #====================================================================== # VirtualBox 関連設定 $VMName = "<Your_VM_Name>" # 例: "Linux Mint 22" (VBoxManage list vms で確認した名前) # VSCode 関連設定 # VSCodeの実行ファイルのパス。通常は以下のいずれか。 # $EditorPath = "$env:LOCALAPPDATA\Programs\Microsoft VS Code\Code.exe" # User Installer $EditorPath = "$env:ProgramFiles\Microsoft VS Code\Code.exe" # System Installer (適宜コメント解除) # $EditorPath = "<Path_To_Your_VSCode_Executable>" # 上記以外の場合 $EditorProfile = "<your_vscode_profile_name>" # 例: "dev-linux" (VSCodeで使うプロファイル名。存在しない場合は新規作成される) $WorkspacePath = "<Path_To_Your_code-workspace_File>" # 例: "C:\Users\YourUser\Documents\VSCodeWorkspaces\my-linux-project.code-workspace" (2.3で作成したファイル) # タイムアウト設定(秒): VM起動とSSH準備の待機時間。スペックに合わせて調整してください。 $VMStartTimeoutSec = 120 $SSHReadyTimeoutSec = 120 #====================================================================== # 🧯 共通関数 #====================================================================== function Write-Log { param( [Parameter(Mandatory=$true)] [string]$Message, [ValidateSet("Info", "Success", "Waiting", "Warning", "Error")] [string]$Severity = "Info" ) $Timestamp = Get-Date -Format "yyyy-MM-dd HH:mm:ss" $Prefix = switch ($Severity) { "Info" { "ℹ️ [INFO]" } "Success" { "✅ [SUCCESS]" } "Waiting" { "⏳ [WAITING]" } "Warning" { "⚠️ [WARNING]" } "Error" { "🛑 [ERROR]" } default { " [LOG]" } } Write-Host "$Timestamp $Prefix $Message" } function Exit-Script { param ( [string]$Message = "スクリプトを終了します。" ) Write-Log $Message -Severity Error Start-Sleep -Seconds 5 # メッセージを読む時間 exit 1 } function Test-VBoxInstalled { try { & VBoxManage --version | Out-Null return $true } catch { Write-Log "VirtualBox (VBoxManage) がインストールされていないか、パスが通っていません。" -Severity Error return $false } } function Get-VMState { param ( [Parameter(Mandatory=$true)] [string]$TargetVMName ) try { $VMInfo = VBoxManage showvminfo $TargetVMName --machinereadable | Select-String -Pattern "^VMState=" if ($VMInfo) { return ($VMInfo -split "=")[1].Trim('"') } return "notfound" # VMが見つからない場合 } catch { Write-Log "VM '$TargetVMName' の状態取得に失敗: $($_.Exception.Message)" -Severity Error return "error" } } #====================================================================== # 🚀 VM起動処理 #====================================================================== function Start-VMHeadless { param( [Parameter(Mandatory=$true)] [string]$TargetVMName ) Write-Log "VM '$TargetVMName' をヘッドレスモードで起動します..." try { # SSH準備完了フラグをリセット (念のため) VBoxManage guestproperty set $TargetVMName "/guestinfo/ssh.ready" "" | Out-Null $Result = & VBoxManage startvm $TargetVMName --type headless 2>&1 if ($LASTEXITCODE -ne 0) { Write-Log "VM '$TargetVMName' の起動に失敗しました: $Result" -Severity Error return $false } Write-Log "VM '$TargetVMName' の起動コマンドを送信しました。" -Severity Info return $true } catch { Write-Log "VM '$TargetVMName' の起動中にエラーが発生しました: $($_.Exception.Message)" -Severity Error return $false } } #====================================================================== # ⏳ VM起動およびSSH準備完了待機処理 #====================================================================== function WaitFor-VMStateAndSSHReady { param( [Parameter(Mandatory=$true)] [string]$TargetVMName, [Parameter(Mandatory=$true)] [string]$DesiredState, # 例: "running" [int]$VMTimeout, [int]$SSHTimeout ) Write-Log "VM '$TargetVMName' が '$DesiredState' 状態になるのを待機中... (タイムアウト: ${VMTimeout}秒)" $Stopwatch = [System.Diagnostics.Stopwatch]::StartNew() while ($Stopwatch.Elapsed.TotalSeconds -lt $VMTimeout) { $CurrentState = Get-VMState -TargetVMName $TargetVMName if ($CurrentState -eq $DesiredState) { Write-Log "VM '$TargetVMName' が '$DesiredState' 状態になりました。($($Stopwatch.Elapsed.ToString('hh\:mm\:ss')) 経過)" -Severity Success $Stopwatch.Stop() break } Write-Log "現在のVM状態: '$CurrentState'... ($($Stopwatch.Elapsed.ToString('hh\:mm\:ss')) 経過)" -Severity Waiting Start-Sleep -Seconds 2 } if ($Stopwatch.IsRunning) { # タイムアウトした場合 $Stopwatch.Stop() Write-Log "タイムアウト: VM '$TargetVMName' が '$DesiredState' 状態になりませんでした。" -Severity Error return $false } Write-Log "ゲストOSのSSH接続準備を待機中... (タイムアウト: ${SSHTimeout}秒)" $Stopwatch.Restart() while ($Stopwatch.Elapsed.TotalSeconds -lt $SSHTimeout) { try { $Result = VBoxManage guestproperty get $TargetVMName "/guestinfo/ssh.ready" if ($Result -match "Value: true") { Write-Log "SSH接続準備が完了しました。($($Stopwatch.Elapsed.ToString('hh\:mm\:ss')) 経過)" -Severity Success return $true } Write-Log "SSH準備状態確認中... ($($Stopwatch.Elapsed.ToString('hh\:mm\:ss')) 経過): $Result" -Severity Waiting } catch { Write-Log "Guest Propertyの取得に失敗しました。VMが完全に起動していない可能性があります。 ($($Stopwatch.Elapsed.ToString('hh\:mm\:ss')) 経過)" -Severity Warning } Start-Sleep -Seconds 5 } Write-Log "タイムアウト: SSH接続準備が完了しませんでした。" -Severity Error Write-Log "VM '$TargetVMName' をシャットダウンします。" -Severity Warning try { VBoxManage controlvm $TargetVMName poweroff | Out-Null } catch { Write-Log "VM '$TargetVMName' のシャットダウン中にエラーが発生しました: $($_.Exception.Message)" -Severity Error } return $false } #====================================================================== # 🖥️ VSCode起動処理 #====================================================================== function Start-VSCode { param( [Parameter(Mandatory=$true)] [string]$EditorExecPath, [string]$TargetProfile, [string]$TargetWorkspacePath ) Write-Log "VSCodeを起動します..." Write-Log " 実行パス: $EditorExecPath" Write-Log " プロファイル: $TargetProfile" Write-Log " ワークスペース: $TargetWorkspacePath" if (-not (Test-Path $EditorExecPath -PathType Leaf)) { Write-Log "指定されたVSCodeの実行パスが見つかりません: $EditorExecPath" -Severity Error return $false } if (-not (Test-Path $TargetWorkspacePath -PathType Leaf) -and $TargetWorkspacePath) { Write-Log "指定されたワークスペースファイルが見つかりません: $TargetWorkspacePath" -Severity Warning Write-Log "ワークスペースなしで続行します。" $TargetWorkspacePath = $null # ワークスペースなしで起動 } $Arguments = New-Object System.Collections.Generic.List[string] if ($TargetProfile) { $Arguments.Add("--profile") $Arguments.Add "$TargetProfile" } if ($TargetWorkspacePath) { $Arguments.Add "`"$TargetWorkspacePath`"" # パスは引用符で囲む } try { Start-Process -FilePath $EditorExecPath -ArgumentList $Arguments Write-Log "VSCodeの起動コマンドを送信しました。" -Severity Info return $true } catch { Write-Log "VSCodeの起動に失敗しました: $($_.Exception.Message)" -Severity Error return $false } } #====================================================================== # ⭐ メイン処理 #====================================================================== Write-Log "開発環境起動スクリプトを開始します。" # 0. VirtualBoxが利用可能か確認 if (-not (Test-VBoxInstalled)) { Exit-Script "VirtualBox (VBoxManage) の準備ができていません。" } # 1. VMの状態確認と起動処理 $CurrentVMState = Get-VMState -TargetVMName $VMName if ($CurrentVMState -eq "running") { Write-Log "VM '$VMName' は既に実行中です。" -Severity Info } elseif ($CurrentVMState -eq "poweroff" -or $CurrentVMState -eq "aborted" -or $CurrentVMState -eq "saved") { Write-Log "VM '$VMName' は現在 '$CurrentVMState' 状態です。起動します。" if (-not (Start-VMHeadless -TargetVMName $VMName)) { Exit-Script "VM '$VMName' の起動に失敗しました。" } } elseif ($CurrentVMState -eq "notfound") { Exit-Script "VM '$VMName' が見つかりません。VM名を確認してください。" } else { Exit-Script "VM '$VMName' は予期せぬ状態 ($CurrentVMState) です。手動で確認してください。" } # 2. VMの起動完了とSSH準備完了を待機 if (-not (WaitFor-VMStateAndSSHReady -TargetVMName $VMName -DesiredState "running" -VMTimeout $VMStartTimeoutSec -SSHTimeout $SSHReadyTimeoutSec)) { Exit-Script "VMの準備がタイムアウトしました。" } # 3. VSCodeを起動 if (-not (Start-VSCode -EditorExecPath $EditorPath -TargetProfile $EditorProfile -TargetWorkspacePath $WorkspacePath)) { Exit-Script "VSCodeの起動に失敗しました。" } Write-Log "開発環境の起動処理が完了しました。" -Severity Success Start-Sleep -Seconds 3 # 完了メッセージ表示用
-
-
デスクトップにショートカットを作成:
- デスクトップで右クリックし、「新規作成」→「ショートカット」を選択します。
- 「項目の場所を入力してください」の欄に以下のように入力します。
<Path_To_Your_Script_File.ps1>
は上記で作成したPowerShellスクリプトのフルパスに置き換えてください。 例:powershell.exe -ExecutionPolicy Bypass -File "<Path_To_Your_Script_File.ps1>"
powershell.exe -ExecutionPolicy Bypass -File "C:\Users\YourUser\Scripts\launch-linux-dev-env.ps1"
- 「次へ」をクリックし、ショートカットに任意の名前(例:
Linux開発環境起動
)を付けて「完了」します。
2.5. 起動テストと確認
- 作成したデスクトップショートカットをダブルクリックして実行します。
- PowerShellのウィンドウが開き、ログメッセージが表示されながら処理が進みます。
- VMが起動(ヘッドレスなのでVirtualBoxのGUIは表示されません)。
- SSH準備完了の待機。
- VSCodeが起動。
- VSCodeが起動し、指定したプロファイルで、かつゲストOSへSSH接続された状態(左下に
SSH: your_ssh_alias
と表示)で、指定したワークスペースが開かれれば成功です。初回接続やプロファイルが新しい場合は、パスワード入力や確認ダイアログが表示されることがあります。
正常に動作しない場合の確認ポイント:
- PowerShellスクリプト内の各パス(VM名、VSCode実行パス、ワークスペースパス)が正しいか。
- PowerShellスクリプトの実行ポリシー(
-ExecutionPolicy Bypass
で一時的に許可していますが、恒久的な設定はSet-ExecutionPolicy
コマンドで調べてください)。 - VBoxManageコマンドがパスを通して正しく実行できるか。
- ゲストOS側の
set-ssh-ready.sh
スクリプトとset-ssh-ready.service
の設定、パーミッション、パスが正しいか。 - ゲストOSのGuest Additionsが正しくインストールされ動作しているか。
- VirtualBoxのネットワーク設定(ポートフォワーディング)が正しいか。
- ゲストOSのファイアウォール設定が正しいか。
- VSCodeのSSH Configファイルの内容が正しいか。
- PowerShellウィンドウに表示されるエラーメッセージを確認する。
💬 最後に
ここまでの設定で、デスクトップのショートカット一つで開発環境が整うようになりました。
開発フローの改善例
- 作成したショートカットを実行。
- VSCodeが起動し、ゲストOSへのSSH接続が確立されます(初回やキー設定によってはパスワード入力)。
- VSCode内でコーディングを開始。
- VSCode内のターミナル(これはゲストOSのターミナルです)で開発サーバー(例:
npm run dev
,python manage.py runserver
など)を起動します。- 開発サーバーがゲストOSの特定のポート(例: 3000, 8000)でリッスンする場合、VSCodeのRemote-SSH機能が自動的にそのポートをホストOSのlocalhostの同ポートにフォワーディングしてくれることが多いです。「ポート」タブで確認・手動設定も可能です。
- ホストOSのブラウザから
http://localhost:3000
やhttp://localhost:8000
などでアクセスして動作確認。 - 開発終了後、VMをシャットダウンします。
- VSCodeのコマンドパレット (
Ctrl+Shift+P
) からTasks: Run Task
を実行し、Shutdown Guest VM
(2.3のワークスペースファイルで定義したタスク)を選択する。 - または、後述のシャットダウン用ショートカットを利用する。
- VSCodeのコマンドパレット (
追加すると便利なTIPS
-
SSHキー認証の設定: 毎回のパスワード入力を省略するために、SSHキー認証を設定することを強く推奨します。ホストOSでSSHキーペアを作成し、公開鍵をゲストOSの
~/.ssh/authorized_keys
に登録します。 -
開発用サーバー起動タスクのカスタマイズ (.vscode/tasks.json): プロジェクトフォルダのルートに
.vscode/tasks.json
ファイルを作成することで、VSCodeから複数の開発サーバー起動などを一括で行うタスクを定義できます。 例えば、フロントエンドとバックエンドのサーバーを同時に起動するタスクは以下のように記述できます。(内容はプロジェクトに合わせて変更してください)-
.vscode/tasks.json
(ゲストOSのプロジェクトフォルダ内に配置).vscode/tasks.json { "version": "2.0.0", "tasks": [ { "label": "Dev Server: Frontend", "type": "shell", "command": "npm run dev", // フロントエンドの起動コマンド "options": { "cwd": "${workspaceFolder}/frontend" // フロントエンドのディレクトリ }, "problemMatcher": [], "isBackground": true // バックグラウンドで実行 }, { "label": "Dev Server: Backend", "type": "shell", // バックエンドの起動コマンド (仮想環境有効化、環境変数設定などを含む例) "command": "source ~/venvs/myproject_venv/bin/activate && export DB_USER='<db_user>' && python manage.py runserver 0.0.0.0:8000", "options": { "cwd": "${workspaceFolder}/backend" // バックエンドのディレクトリ }, "problemMatcher": [], "isBackground": true }, { "label": "Start All Dev Servers", "dependsOn": ["Dev Server: Frontend", "Dev Server: Backend"], "dependsOrder": "parallel", // 並列実行 "group": { "kind": "build", "isDefault": true // ビルドタスクのデフォルトにする }, "problemMatcher": [] } ] }
コマンドパレットから
Tasks: Run Task
→Start All Dev Servers
で実行できます。
-
-
VMシャットダウン用ショートカット: VMを素早くシャットダウンするための専用ショートカットをデスクトップに作成します。
- 「デスクトップで右クリック」→「新規作成」→「ショートカット」
- 「項目の場所を入力してください」に以下のように入力します (
Your_VM_Name
は実際のVM名に置き換えてください)。"C:\Program Files\Oracle\VirtualBox\VBoxManage.exe" controlvm "Your_VM_Name" poweroff
- 「次へ」をクリックし、ショートカットに任意の名前(例:
VMシャットダウン
)を付けて「完了」します。
Q&A
-
Q: VSCodeでRemote-SSH接続後、一部の拡張機能が動作しません。
A: Remote-SSHでは、拡張機能は「UI拡張機能(ローカルで動作)」と「ワークスペース拡張機能(リモートのSSHサーバーで動作)」に分類されます。必要な拡張機能がリモート側(ゲストOS)にインストールされているか確認してください。拡張機能のサイドバーで、各拡張機能がどこにインストールされているか確認し、必要に応じて「SSH:
your_ssh_alias
にインストール」を選択してください。 -
Q: ゲストOS上のPythonインタープリターやNode.jsなどがVSCodeに認識されません。
A: VSCodeのウィンドウがリモートサーバーに接続されていることを確認してください(左下に
SSH: your_ssh_alias
)。その上で、VSCodeのコマンドパレットから例えばPython: Select Interpreter
や、Node.jsの場合はnvm
やnodenv
等でバージョンが正しく選択されているか、ゲストOSのターミナルで確認してください。VSCodeの設定 (settings.json) で明示的にパスを指定する必要がある場合もあります。
この記事は、私の環境における自動化の解答の一例です。 あなたの環境に合わせて、より良い方法を見つけて、よりよい開発ライフをお送りください!