Skip to the content.

Remote SSH Development Server with Zed

This guide sets up a Raspberry Pi as a lightweight remote development server for an IDE running on another computer.

The examples use Zed on Windows, but the same general arrangement can be used with other SSH-capable IDEs including VS Code, although this is not recommended.

Why use a Raspberry Pi as a development server?

A lightweight IDE such as Zed can keep its graphical interface and other desktop work on the main PC while moving the resource-intensive development work to the Raspberry Pi.

This splits the workload:

This is particularly useful with a modest computer where a full VS Code Remote-SSH installation can consume substantial CPU, RAM, swap and disk space.

Zed’s Remote Development architecture is specifically designed this way: Zed runs its UI locally while the remote machine runs the source code, terminal, tasks and language servers.

The result is a very lightweight client/server development environment: the PC handles the interface while the Pi does the development work.

Assumptions

This guide assumes you already have:

The important security principle is:

The private GitHub SSH key stays on the IDE PC. It is never copied to the Raspberry Pi.

The Pi will temporarily use the PC’s SSH agent through SSH agent forwarding.

The resulting architecture

flowchart TD
    PC["PC - Windows + Zed + browser  - Private SSH key - SSH agent"]

    IDE["Zed on PC"]

    PI["Raspberry Pi: (Zed remote server, Source files, Git, Python web server)"]

    DRIVE[("1 TB external drive - /mnt/1TB/code")]

    GH["GitHub, Git repositories"]

    BROWSER["Web browser on PC"]

    PC --> IDE
    PC --> BROWSER
    IDE -->|"SSH -A agent forwarding"| PI
    BROWSER -->|"SSH port forwarding"| PI
    PI --> DRIVE
    PI -->|"Git over SSH, forwarded key"| GH

The private key never leaves the IDE PC:

flowchart LR
    KEY["Private GitHub SSH key"] --> AGENT["SSH agent<br/>on IDE PC"]
    AGENT -->|"forwarded authentication"| PI["Raspberry Pi"]
    PI -->|"authentication request"| GH["GitHub"]
    KEY -. "never copied" .-> PI

The Pi can therefore authenticate to GitHub without possessing the private key.

Add the public key to GitHub

The SSH key used for GitHub should already exist on the IDE PC because you already use it to connect to the Pi.

Copy the public key in PowerShell or in a text editor:

Get-Content "$HOME\.ssh\name+2026@host.com.pub"

Copy the resulting complete line.

On GitHub:

Profile → Settings → SSH and GPG keys → New SSH key

Give the key a descriptive title, select Authentication Key, and paste the public key.

GitHub requires the public key to be added to your account before it can be used for Git operations over SSH.

Do not copy the corresponding private key to the Pi.

Allow SSH agent forwarding on the Pi

The SSH server must permit agent forwarding.

On the Pi, edit:

sudo nano /etc/ssh/sshd_config

Find:

AllowAgentForwarding

If it is commented out or absent, add:

AllowAgentForwarding yes

Save the file.

Before reloading the SSH server, check the configuration:

sudo sshd -t

If there is no output, the configuration is syntactically valid.

Then reload SSH:

sudo systemctl reload ssh

A full restart also works:

sudo systemctl restart ssh

You do not normally need to restart the Pi.

Connect to the Pi from Zed

Open Zed’s Remote Projects dialog.

Choose Connect New Server.

Enter the SSH command you normally use to connect to the Pi, but add -A:

ssh -A pi@raspberrypi

The -A option enables SSH agent forwarding.

Zed uses the system ssh executable for Remote Development and supports -A as an SSH connection option.

If you already have a suitable SSH configuration entry, you can instead use that host name and add -A to the connection options.

First connection

On the first connection Zed will install its remote server executable on the Pi.

This is normal.

Zed’s remote server is considerably more lightweight than the VS Code Server arrangement, and it is responsible for the remote development components while the Zed interface remains on the PC. Zed stores the remote server under ~/.zed_server on the remote machine.

After the server has been installed, choose the project directory you want to open.

For this setup, that will be somewhere under:

/mnt/1TB/code/

Test GitHub access from Zed

Open Zed’s integrated terminal.

The terminal is running on the Pi, not on the Windows PC.

Check that the forwarded agent is visible:

ssh-add -l

You should see the key that is loaded into the PC’s SSH agent.

Now test GitHub:

ssh -T git@github.com

The first time, SSH may ask you to confirm GitHub’s host key.

After successful authentication, GitHub should respond with a message identifying your account and noting that GitHub does not provide shell access. This is the normal successful result.

If you instead get:

Permission denied (publickey).

check, in order:

  1. The private key is loaded into the PC’s SSH agent.
  2. Zed connected using -A.
  3. AllowAgentForwarding yes is present on the Pi.
  4. You reloaded sshd after changing sshd_config.
  5. The corresponding public key is present in your GitHub account.

Create a development directory on the external drive

I keep development files on the persistent 1 TB drive rather than the Pi’s SD card:

sudo mkdir -p /mnt/1TB/code

Give your normal user ownership:

sudo chown pi:pi /mnt/1TB/code

Check:

ls -ld /mnt/1TB/code

You should now be able to create files there as pi.

For example:

cd /mnt/1TB/code
mkdir test

Clone a GitHub repository

From Zed’s terminal connected to the Pi:

cd /mnt/1TB/code

Then clone using the GitHub SSH URL:

git clone git@github.com:USERNAME/REPOSITORY.git

For example:

git clone git@github.com:USERNAME/my-website.git

Git on the Pi connects to GitHub using SSH.

The authentication chain is:

sequenceDiagram
    participant Z as Zed (on PC)
    participant P as Raspberry Pi
    participant A as SSH Agent (on PC)
    participant G as GitHub

    Z->>P: SSH connection (-A)
    P->>A: Request authentication
    A-->>P: Sign authentication request
    P->>G: SSH authentication
    G-->>P: Authentication successful
    P-->>Z: Git operation succeeds

The private key itself remains on the PC throughout.

Once the repository has been cloned, Zed can open and edit the files directly on the Pi. Git operations such as:

git status
git pull
git add .
git commit
git push

also execute on the Pi.

Run a Python web server on the Pi

For simple HTML/JavaScript development, Python’s built-in HTTP server is sufficient.

From the project directory:

python3 -m http.server 8000

This serves the current directory on port 8000.

However, repeatedly navigating to the correct directory manually is inconvenient. Zed tasks can use information about the file currently being edited, including $ZED_DIRNAME, which is the directory containing the current file.

Create a Zed web-server task

For a project-specific task, create:

.zed/tasks.json

inside the repository.

Add:

[
    {
        "label": "Start Python web server",
        "command": "python3",
        "args": [
            "-m",
            "http.server",
            "8000"
        ],
        "cwd": "$ZED_DIRNAME",
        "use_new_terminal": true,
        "allow_concurrent_runs": false
    }
]

The important part is:

"cwd": "$ZED_DIRNAME"

Zed replaces $ZED_DIRNAME with the directory containing the file currently open in the editor.

Therefore, if you have:

/mnt/1TB/code/my-website/
├── index.html
├── css/
│   └── style.css
└── js/
    └── app.js

and index.html is the active file, the task starts:

python3 -m http.server 8000

with:

/mnt/1TB/code/my-website/

as its working directory.

If the currently open file is instead:

/mnt/1TB/code/my-website/test/index.html

the server will start in:

/mnt/1TB/code/my-website/test/

This can be useful when testing several independent HTML pages, but if you always want to serve the whole project, replace:

"cwd": "$ZED_DIRNAME"

with:

"cwd": "$ZED_WORKTREE_ROOT"

which starts the server at the root of the Git worktree.

Forward the web-server port to the IDE PC

The Python server is running on the Pi, so localhost:8000 on the Windows PC would normally mean the Windows PC, not the Pi.

Zed can forward a remote port to a local port over its SSH connection. This tunnels your local traffic securely through the SSH connection to the Pi, effectively bypassing firewall restrictions or network accessibility issues. By default, the forwarded port is available only on the IDE PC’s localhost.

On Windows, open Zed’s local settings file:

%APPDATA%\Zed\settings.json

You can open it from Zed using the zed: open settings file command, or edit the file directly.

Add a port_forwards entry to the SSH connection for the Pi.

For example:

{
    "ssh_connections": [
        {
            "host": "raspberrypi",
            "args": ["-A"],
            "port_forwards": [
                {
                    "local_port": 8000,
                    "remote_port": 8000
                }
            ]
        }
    ]
}

If you already have an ssh_connections entry for the Pi, add port_forwards to that existing entry rather than creating a second entry.

Likewise, retain any existing projects, username, port or other settings.

Test the website

With the Python task running on the Pi, open the browser on the IDE PC and go to http://localhost:8000.

graph TD
    A[IDE PC Browser] -->|localhost:8000| B[Zed SSH Tunnel]
    B -->|Encrypted SSH| C[Pi Port 8000]
    C --> D[Python HTTP Server]

The browser behaves as though the web server were running locally, even though the files and server are actually on the Pi.

Running the task

With the desired HTML file open in Zed:

  1. Open the command palette.
  2. Choose task: spawn.
  3. Select Start Python web server.
  4. Zed opens a terminal and runs the server on the Pi.

Zed’s tasks execute on the remote machine during a Remote Development session, so Python, the source files and the HTTP server all remain on the Pi.

Stop the server with:

Ctrl+C

in its terminal.

Final Note

In my testing, Zed remote development, Python Web Server, and BOINC can run concurrently without interfering with each other.