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ディストリビューションなどの公式ドキュメントも併せてご参照ください。
まずは、ホストOSのVSCodeからゲストOSのLinux環境へSSHで接続できるように設定します。
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サーバーが待ち受ける標準ポートです。
次に、ゲスト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
ゲストOSでファイアウォール(UFW: Uncomplicated Firewall)が有効になっている場合、SSH接続を許可する設定が必要です。
- SSHが使用するポート(デフォルトは22)への接続を許可します。
Guest OS
- 設定をリロード(再読み込み)します。
Guest OS
- ファイアウォールの状態とルールを確認します。
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 で有効化してください。
ホストOS(Windows)のターミナル(コマンドプロンプトやPowerShell)から、ゲストOSへSSH接続できるか確認します。
Host OSssh your_guest_username@localhost -p 22222
your_guest_username はゲストOSのユーザー名に置き換えてください。
-p 22222 は、VirtualBoxのポートフォワーディングで設定したホストポートです。
初回接続時にはフィンガープリントの確認を求められるので yes と入力し、その後ゲストOSのユーザーパスワードを入力します。ログインできれば成功です。
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/configHost 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のものを直接利用できるようになりました。
ここまでの設定での課題点:
- 毎回SSH接続時にパスワード入力が必要(これはSSHキー認証で改善可能ですが、この記事では扱いません)。
- VSCodeで特定の開発プロファイル(拡張機能のセットなど)を使って接続したい場合、一手間かかることがある。
- ゲストOSをVirtualBoxマネージャーから手動で起動する必要があり、GUIウィンドウが表示される。
次のセクションでは、これらの課題を解決するための自動化手順に進みます。
目標は、デスクトップのショートカットをワンクリックするだけで、以下の処理を自動で行うことです。
- VirtualBoxのゲストOSをヘッドレスモード(GUIなし)で起動。
- ゲストOSのSSHサーバーが起動するまで待機。
- 指定したVSCodeプロファイルとワークスペースで、ゲストOSへSSH接続した状態でVSCodeを起動。
VirtualBoxをコマンドラインから操作するために、VBoxManage.exe へのパスを通します。
- Windowsの「設定」→「システム」→「バージョン情報」と進み、「システムの詳細設定」をクリックします。
- 「環境変数」ボタンをクリックします。
- 「システム環境変数」の「Path」を選択し、「編集」をクリックします。
- 「新規」をクリックし、VirtualBoxのインストールディレクトリ(通常は
C:\Program Files\Oracle\VirtualBox)を追加します。
- OKを押して全てのダイアログを閉じ、設定を反映させるためにPCを再起動するか、新しいコマンドプロンプト/PowerShellウィンドウを開きます。
- コマンドプロンプトまたはPowerShellで
VBoxManage --version を実行し、バージョン情報が表示されればパスが通っています。
- 自動化スクリプトで使用するVMの名前を確認しておきます。
Host OS
表示されたリストから、対象のVMの名前(例: "Linux Mint 22" や "MyLinuxVM"など、引用符も含めて)を控えておきます。以降、このVM名を Your_VM_Name とします。
ゲストOSが起動しSSH接続の準備が整ったことをホストOSに伝える仕組みを構築します。これにはVirtualBoxのGuest Properties機能を利用します。
-
対象の仮想マシンを起動します。
-
ゲストOS側: SSH準備完了通知スクリプトの作成
ゲストOSのホームディレクトリなどに、SSHサービスの起動を確認してGuest Propertyを設定するスクリプトを作成します。例えば、~/bin/set-ssh-ready.sh として以下の内容で作成します。~/bin ディレクトリがない場合は作成してください。
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のユーザー名に置き換えてください。
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 OSVBoxManage guestproperty get "Your_VM_Name" "/guestinfo/ssh.ready"
# Expected output: Value: true
特定のプロジェクトフォルダをVSCodeで開くように、ワークスペースファイルを作成しておくと便利です。これはSSH接続後に開きたいゲストOS上のフォルダを指定します。
- ホストOSの任意の場所(例:
C:\Users\[ユーザー名]\Documents\VSCodeWorkspaces)に、 .code-workspace という拡張子でファイルを作成します(例: my-linux-project.code-workspace)。
- ファイルに以下のJSON形式で内容を記述します。
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側のコマンドとして実行される点に注意してください。
VMの起動、SSH準備待機、VSCodeの起動を連続して行うPowerShellスクリプトを作成します。
-
ホストOSの任意の場所(例: C:\Users\[ユーザー名]\Scripts)に、 .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開発環境起動)を付けて「完了」します。
- 作成したデスクトップショートカットをダブルクリックして実行します。
- 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のワークスペースファイルで定義したタスク)を選択する。
- または、後述のシャットダウン用ショートカットを利用する。
-
SSHキー認証の設定:
毎回のパスワード入力を省略するために、SSHキー認証を設定することを強く推奨します。ホストOSでSSHキーペアを作成し、公開鍵をゲストOSの ~/.ssh/authorized_keys に登録します。
-
開発用サーバー起動タスクのカスタマイズ (.vscode/tasks.json):
プロジェクトフォルダのルートに .vscode/tasks.json ファイルを作成することで、VSCodeから複数の開発サーバー起動などを一括で行うタスクを定義できます。
例えば、フロントエンドとバックエンドのサーバーを同時に起動するタスクは以下のように記述できます。(内容はプロジェクトに合わせて変更してください)
.vscode/tasks.json (ゲストOSのプロジェクトフォルダ内に配置){
"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 で実行できます。
- 「デスクトップで右クリック」→「新規作成」→「ショートカット」
- 「項目の場所を入力してください」に以下のように入力します (
Your_VM_Name は実際のVM名に置き換えてください)。
"C:\Program Files\Oracle\VirtualBox\VBoxManage.exe" controlvm "Your_VM_Name" poweroff
- 「次へ」をクリックし、ショートカットに任意の名前(例:
VMシャットダウン)を付けて「完了」します。
-
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) で明示的にパスを指定する必要がある場合もあります。
この記事は、私の環境における自動化の解答の一例です。
あなたの環境に合わせて、より良い方法を見つけて、よりよい開発ライフをお送りください!