Canonical infra facts (projects, buckets, VM inventory, regions, the compute budget) live in infrastructure.md. This doc is the daily VM/SSH how-to.
Development workflow: VSCode Remote-SSH connected to gpu-vm-l4. All code editing, running, and debugging happens on the VM. Your local Windows machine is just a thin client — no local Python environment needed.
Two tools, two jobs:
vmup.ps1(PowerShell script): Start a VM and auto-update its IP in your SSH config. One command per day.- VSCode Remote-SSH: Develop on the running VM (edit files, run scripts, use terminal).
| VM Name | Zone | GPU | Use Case |
|---|---|---|---|
| gpu-vm-l4 | us-west1-a | NVIDIA L4 (23 GB) | Development, testing, lighter workloads |
| ml-training-vm | us-west1-b | NVIDIA A100 | Production training |
Persistent storage: /mnt/argo_filestore (1TB shared)
In PowerShell (or double-click the desktop shortcut if you made one):
& "C:\Users\Yili Yang\vmup.ps1"For the A100:
& "C:\Users\Yili Yang\vmup.ps1" -VM ml-training-vm -Zone us-west1-bThe script starts the VM and automatically writes the new external IP into your SSH config. Output should end with VM up. IP: <something>.
- Ctrl+Shift+P → "Remote-SSH: Connect to Host"
- Select gpu-vm-l4 (or ml-training-vm)
- Bottom-left should show SSH: gpu-vm-l4 in blue
- Open a terminal (Ctrl+
) and runnvidia-smi` to confirm GPU access
In the VSCode terminal:
source ~/ml-env/bin/activate
cd ~/RTSmappingDL- L4: Run scripts directly for quick feedback
- A100: Wrap long jobs in
screen -S trainingso they survive disconnects (Ctrl+A then D to detach;screen -r trainingto reconnect)
In Google Cloud SDK Shell (or any PowerShell with gcloud configured):
gcloud compute instances stop gpu-vm-l4 --zone=us-west1-a
Or for the A100:
gcloud compute instances stop ml-training-vm --zone=us-west1-b
Cost reminder: L4 ~$0.35/hr idle; A100 ~$4.50/hr idle. Always stop VMs when done.
- L4: Code editing, debugging,
check_data.py, quick sanity checks - A100: Full training runs, pan-arctic inference (only after confirming readiness on L4)
This section sets up the script that Part 1 depends on. Do this once.
Open PowerShell as Administrator and run once:
Set-ExecutionPolicy -Scope CurrentUser RemoteSignedConfirm with Y.
Create the file C:\Users\Yili Yang\vmup.ps1 with this content:
param([string]$VM = "gpu-vm-l4", [string]$Zone = "us-west1-a")
Write-Host "Starting $VM in $Zone..."
gcloud compute instances start $VM --zone=$Zone | Out-Null
$ip = gcloud compute instances describe $VM --zone=$Zone `
--format='get(networkInterfaces[0].accessConfigs[0].natIP)'
$ip = $ip.Trim()
if (-not $ip) {
Write-Host "Failed to get IP. Check VM status." -ForegroundColor Red
exit 1
}
$configPath = "$HOME\.ssh\config"
$config = Get-Content $configPath -Raw
# Update HostName line under "Host <VM>" block (handles both LF and CRLF)
$pattern = "(Host\s+$VM\s*[\r\n]+\s*HostName\s+)\S+"
$config = $config -replace $pattern, "`${1}$ip"
Set-Content $configPath -Value $config -NoNewline
Write-Host "VM up. IP: $ip" -ForegroundColor Green
Write-Host "VSCode: Remote-SSH -> $VM" -ForegroundColor CyanImportant: the script depends on Part 3.3 — it edits the Host gpu-vm-l4 and Host ml-training-vm blocks in your SSH config. Those blocks must exist before the script can update them.
For one-click VM start:
- Right-click on Desktop → New → Shortcut
- Location:
powershell.exe -ExecutionPolicy Bypass -File "C:\Users\Yili Yang\vmup.ps1" - Name: Start GPU L4
For the A100, repeat with this location:
powershell.exe -ExecutionPolicy Bypass -File "C:\Users\Yili Yang\vmup.ps1" -VM ml-training-vm -Zone us-west1-b
- Zone fallback — if
us-west1-ahas no capacity, the script fails. Manually start in another zone (see Appendix A.1) and edit the IP in your SSH config that one time. - Stopping VMs — intentional, so the stop command is explicit and not accidentally automated.
- First-time SSH key/config/permissions setup — covered in Part 3.
Skip this part if your VSCode Remote-SSH already connects successfully. Only needed on a new machine or after a reinstall.
In VSCode: Extensions panel (Ctrl+Shift+X) → search "Remote - SSH" → Install.
Open Google Cloud SDK Shell and SSH into the VM once. This creates the SSH key pair automatically:
gcloud config set project pdg-project-406720
gcloud compute instances start gpu-vm-l4 --zone=us-west1-a
gcloud compute ssh gpu-vm-l4 --zone=us-west1-a
Once connected, note two things:
- The external IP shown during connection (e.g.,
136.109.212.78) - Your VM username — run
whoami(e.g.,ext_rtsmapping_woodwellclimate_o)
Type exit to disconnect.
Create or edit C:\Users\Yili Yang\.ssh\config (no file extension) with a plain text editor. Contents:
Host gpu-vm-l4
HostName 136.109.212.78
User ext_rtsmapping_woodwellclimate_o
IdentityFile "C:\Users\Yili Yang\.ssh\google_compute_engine"
Host ml-training-vm
HostName 0.0.0.0
User ext_rtsmapping_woodwellclimate_o
IdentityFile "C:\Users\Yili Yang\.ssh\google_compute_engine"
Important:
- Replace
136.109.212.78with the L4's current external IP. The A100'sHostName 0.0.0.0is a placeholder —vmup.ps1will fill in the real IP the first time you start it. - Use quotes around the
IdentityFilepath since it contains a space. - The file must be named exactly
config— notconfig.txt. Turn on "File name extensions" in File Explorer (View → Show → File name extensions) to verify.
Windows SSH requires strict permissions on both the config file and the private key. Without this, SSH fails with "bad permissions" errors.
For each of these two files in C:\Users\Yili Yang\.ssh\:
configgoogle_compute_engine(the private key, no extension)
Do the following:
- Right-click → Properties → Security tab → Advanced
- Click Disable inheritance → choose "Remove all inherited permissions from this object"
- Click Add → Select a principal → type your Windows username → Check Names → OK
- Grant Full control → OK
- Ensure only your user appears in the permissions list — remove all others (especially "OWNER RIGHTS")
- Apply → OK
Open a regular PowerShell (not Cloud SDK Shell) and run:
ssh gpu-vm-l4
When prompted "Are you sure you want to continue connecting?", type yes. This saves the VM's fingerprint to known_hosts. Then exit.
Repeat for ml-training-vm after starting it the first time.
Now do Part 2 above (vmup.ps1 setup). Test it:
& "C:\Users\Yili Yang\vmup.ps1"
ssh gpu-vm-l4Should connect cleanly with no prompts.
- Ctrl+Shift+P → "Remote-SSH: Connect to Host" → gpu-vm-l4
- If asked for platform, select Linux
- VSCode installs its server on the VM (takes ~1 min the first time) and connects
Verify: Bottom-left shows "SSH: gpu-vm-l4". Open a terminal and run nvidia-smi.
In the VSCode integrated terminal:
Clone the repo:
git clone https://github.com/whrc/RTSmappingDL.git
cd RTSmappingDLCreate the venv:
python3 -m venv ~/ml-env
source ~/ml-env/bin/activate
pip install --upgrade pipInstall PyTorch with CUDA:
pip install torch torchvision torchaudio --index-url https://download.pytorch.org/whl/cu121Install project dependencies:
pip install -r requirements.txtVerify CUDA:
python -c "import torch; print(f'CUDA available: {torch.cuda.is_available()}'); print(f'Device: {torch.cuda.get_device_name(0)}')"ls /mnt/argo_filestore/
mkdir -p /mnt/argo_filestore/yiligsutil cp gs://abrupt_thaw/path/to/file ~/data/
gsutil -m cp -r gs://abrupt_thaw/folder ~/data/ # recursive, parallelFrom Google Cloud SDK Shell (not the VM):
gcloud compute scp "C:\path\to\local\file" gpu-vm-l4:~/file --zone=us-west1-a
gcloud compute scp --recurse "C:\path\to\folder" gpu-vm-l4:~/folder --zone=us-west1-a
- Always stop VMs when done — L4 costs ~$0.35/hr idle; A100 costs ~$4.50/hr idle
- Develop on L4, use A100 only for full training runs (after confirming readiness on L4)
- Data lives in GCS — use gcsfuse or
gsutil, never upload full datasets to VM local disk - Pan-arctic inference — coordinate with Luigi/Todd (PDG workflow VMs)
If the default zone has no capacity, try alternatives in order. In Google Cloud SDK Shell:
gcloud compute instances start gpu-vm-l4 --zone=us-west1-c
gcloud compute instances start gpu-vm-l4 --zone=us-west2-a
gcloud compute instances start gpu-vm-l4 --zone=us-west2-b
gcloud compute instances start gpu-vm-l4 --zone=us-central1-a
Same pattern for ml-training-vm. After a successful start in a non-default zone, manually edit the HostName line in your SSH config that one time, since vmup.ps1 assumes the default zone.
Get your current IP:
curl -4 ifconfig.me
Then update the cluster authorized networks (replace YOUR_IP):
gcloud container clusters update autopilot-cluster-1 --region us-west1 --enable-master-authorized-networks --master-authorized-networks YOUR_IP/32
gcloud compute instances list
| Problem | Cause | Fix |
|---|---|---|
resource not found when starting VM |
Typo: gpu-vm-14 (number) vs gpu-vm-l4 (letter L) |
Use lowercase L |
Bad permissions on config or key file |
Windows file permissions too open | Redo Part 3.4 |
Permission denied (publickey) |
Key file permissions or wrong IdentityFile path | Fix key permissions; verify path in SSH config has quotes |
extra arguments at end of line |
Unquoted path with space in IdentityFile |
Wrap path in double quotes |
authenticity of host can't be established |
First-time connection to this IP | Type yes to accept and save the fingerprint |
| Connection fails after VM restart | External IP changed | Run vmup.ps1 — it refreshes the IP in your config |
vmup.ps1 not recognized |
Wrong working directory | Use full path: & "C:\Users\Yili Yang\vmup.ps1" |
vmup.ps1 cannot be loaded (execution policy) |
First-time PowerShell setup not done | Redo Part 2.1 |
Attempting gcloud compute start-iap-tunnel returns error 4033: 'not authorized'. This is expected — IAP isn't configured for your account on this project, and fixing it requires admin permissions. Stick with the direct-IP workflow via vmup.ps1.
| Problem | Cause | Fix |
|---|---|---|
| CUDA out of memory | Batch size too large | Reduce batch size, enable mixed precision (AMP) |
| Disconnected during training | SSH dropped | If using screen/tmux, reconnect; if using nohup, check logs |
| Files missing after restart | VM boot disk reset | Use /mnt/argo_filestore/ or GCS for persistent storage |