This article complements:
- Headless dev server & SSH port forwarding: https://www.maksonlee.com/spin-up-a-kiwi-tcms-dev-environment-on-ubuntu-24-04-server-headless-and-access-it-via-ssh-port-forwarding/
- JetBrains Gateway (IntelliJ) alternative: https://www.maksonlee.com/develop-kiwi-tcms-remotely-on-ubuntu-24-04-headless-with-intellij-idea-ultimate-jetbrains-gateway-windows-11/
Develop on a headless Ubuntu 24.04 server from Windows 10/11 using VS Code Remote-SSH, no desktop required.
TL;DR
- Install Remote – SSH in VS Code.
- Create an OpenSSH key (not
.ppk
). - Copy your public key to the server (strip CRLF).
- Use the Remote-SSH wizard with your full SSH command to add/connect.
- Install needed extensions on the remote (e.g., Python).
- Run your dev loop with two concurrent terminals or a one-click Tasks setup.
Prerequisites
- Server: Ubuntu 24.04 reachable on TCP/22 with
openssh-server
; useradministrator@client.maksonlee.com
. - Client: Windows 10/11 + VS Code (Stable).
- Install Remote-SSH
VS Code → Extensions → install Remote – SSH (ID: ms-vscode-remote.remote-ssh
).

- Generate an OpenSSH key on Windows (ed25519)
VS Code uses Windows OpenSSH; PuTTY .ppk
keys are not supported.
ssh-keygen -t ed25519 -C "cdlee@cdlee-pc" -f $env:USERPROFILE\.ssh\id_ed25519
- Copy your public key to the server (avoid CRLF)
Pure PowerShell one-liner (removes \r
):
$pub = (Get-Content $env:USERPROFILE\.ssh\id_ed25519.pub -Raw).Replace("`r","")
ssh administrator@client.maksonlee.com "umask 077; mkdir -p ~/.ssh; printf '%s\n' '$pub' >> ~/.ssh/authorized_keys; chmod 700 ~/.ssh; chmod 600 ~/.ssh/authorized_keys"
Quick check on the server (optional):
sed -n '1,3p' ~/.ssh/authorized_keys
- Connect using Remote-SSH
- F1 → Remote-SSH: Add New SSH Host…
- Paste this exact command, then press Enter:
ssh administrator@client.maksonlee.com -i C:/Users/cdlee/.ssh/id_ed25519
Use forward slashes in the key path.
- When prompted Select SSH configuration file to update, choose C:\Users\cdlee\.ssh\config (User config).
- The extension writes a minimal entry—keep it as is:
Host client.maksonlee.com
HostName client.maksonlee.com
User administrator
IdentityFile C:/Users/cdlee/.ssh/id_ed25519
- Connect: F1 → Remote-SSH: Connect to Host… → select
client.maksonlee.com
.
On first connect VS Code will install VS Code Server on the host (normal).
- Open Folder & install remote extensions
- In the remote window, Open Folder (this is the server filesystem).
- Extensions → search Python → click Install in SSH: client.maksonlee.com.

Optional: point VS Code to your venv Python
F1 → Python: Select Interpreter → ~/kiwi-env/bin/python
- Run your dev loop (two at the same time)
- Manual: two terminals
Terminal A
source ~/kiwi-env/bin/activate
cd tcms
./node_modules/.bin/webpack watch
Terminal B
source ~/kiwi-env/bin/activate
./manage.py runserver 127.0.0.1:8000
The Ports tab should auto-forward 8000
. If it doesn’t, add it manually.
- One-click with Tasks (parallel, each in its own panel)
Create .vscode/tasks.json
in your repo:
{
"version": "2.0.0",
"tasks": [
{
"label": "webpack:watch",
"type": "shell",
"command": "source ~/kiwi-env/bin/activate && ./node_modules/.bin/webpack watch",
"options": {
"cwd": "${workspaceFolder}/tcms",
"shell": { "executable": "/bin/bash", "args": ["-lc"] }
},
"isBackground": true,
"presentation": { "reveal": "always", "panel": "dedicated" },
"problemMatcher": []
},
{
"label": "django:runserver",
"type": "shell",
"command": "source ~/kiwi-env/bin/activate && ./manage.py runserver 127.0.0.1:8000",
"options": {
"cwd": "${workspaceFolder}",
"shell": { "executable": "/bin/bash", "args": ["-lc"] }
},
"isBackground": true,
"presentation": { "reveal": "always", "panel": "dedicated" },
"problemMatcher": []
},
{
"label": "dev:all",
"dependsOn": ["webpack:watch", "django:runserver"],
"dependsOrder": "parallel",
"problemMatcher": []
}
]
}
When VS Code asks “Select for which kind of errors and warnings to scan the task output”, choose Never scan the task output for this task (or keep "problemMatcher": []
as above to avoid the prompt).

- Ports
- The Ports tab auto-forwards common ports you start on the server.
- Manual SSH equivalent (reference):
ssh -N -L 8000:127.0.0.1:8000 administrator@client.maksonlee.com
