Remote Development via SSH: The Productivity Workflow
AI generated
$
/etc
Linux · SSH · Remote Development
Remote Development via SSH
The workflow that merges local and remote work

When development environments, databases and Docker containers live on a remote server, the quality of the SSH connection decides whether the work feels local or like a constant compromise. With a clean SSH config, VS Code Remote-SSH and targeted port forwarding, the remote server becomes a seamless extension of your own development environment.

19 min read SSH Config · VS Code · Port Forwarding · File Sync Linux · Remote Servers · Developer Workflow

1. Why remote development over SSH is standard today

Many development projects, especially in the Magento and PHP world, need resources that barely fit on a single laptop anymore: several Docker containers, a large database, Elasticsearch and a full web server stack running at the same time. Remote development over SSH solves this by shifting the actual computing load to a powerful server, while the local machine serves only as a thin client window. The result is a consistent environment for the whole team, independent of local hardware.

The second major benefit of remote development lies in the consistency of the environment itself. Instead of every developer maintaining a slightly different local PHP version, different Node module versions, or diverging system libraries, everyone works on the same server with identical configuration. This drastically reduces the classic "it works on my machine" problem, because development and production can share the same system environment.

SSH here is not just a transport mechanism for a terminal session, but the entire foundation of modern remote development tooling. VS Code Remote-SSH, JetBrains Gateway and similar solutions tunnel their complete communication over exactly the same SSH connection that is also used for a simple terminal session. Anyone who masters the basics of SSH configuration benefits from it equally in every one of these tools.

2. The SSH config as the foundation for productive connections

The file ~/.ssh/config is the central building block for efficient remote development, yet it is surprisingly often ignored. Instead of manually specifying host, username, port and key file on every connection, you define a descriptive alias once, through which the server can afterwards be reached with a single short command. This not only saves typing, it also reduces errors, for example accidentally connecting to the wrong server when hostnames look similar.

Particularly valuable for remote development is the ability to also store options for connection stability and speed in the SSH config. The option ServerAliveInterval sends regular keep alive packets so the connection is not dropped by a firewall due to inactivity, while ControlMaster and ControlPersist reuse subsequent connections over an already established channel instead of performing a completely new handshake every time.


# ~/.ssh/config - reusable host aliases for remote development

Host devserver
  HostName 203.0.113.42
  User deploy
  Port 22
  IdentityFile ~/.ssh/id_ed25519_devserver
  ServerAliveInterval 30
  ServerAliveCountMax 3
  # Reuse an existing connection instead of a fresh handshake every time
  ControlMaster auto
  ControlPath ~/.ssh/sockets/%r@%h-%p
  ControlPersist 10m

Host staging
  HostName staging.internal.example.com
  User www-deploy
  Port 2222
  IdentityFile ~/.ssh/id_ed25519_staging
  # Jump through a bastion host before reaching the internal server
  ProxyJump bastion.example.com

Host bastion.example.com
  User jumpuser
  IdentityFile ~/.ssh/id_ed25519_bastion

# One command replaces host, user, port and key file:
# ssh devserver

A frequently overlooked detail is the folder ~/.ssh/sockets/, which must already exist for ControlPath, otherwise connection multiplexing silently fails and every connection performs a fresh handshake again. Anyone managing several projects in parallel should create a clearly named host entry for each target system, instead of memorizing IP addresses or ports. This makes daily remote development noticeably faster and less error prone.

3. VS Code Remote-SSH: the editor runs local, the code runs remote

The Remote-SSH extension for VS Code is the entry point into structured remote development for many teams. The principle: the graphical interface of the editor keeps running locally, while a small server process is installed on the target machine that directly executes file access, language servers, terminal sessions and debugging requests on the remote system. The result feels like local work to the developer, even though all the code, all dependencies and the entire build process run remotely.

An important practical advantage of this model is that resource intensive operations, such as indexing a large codebase or compiling assets, happen on the powerful server, not on the often weaker laptop. The extension uses the same SSH connection also used for a normal terminal session, which is why a correctly configured ~/.ssh/config appears directly in VS Code as a connection target, without additional configuration inside the editor.

For Magento projects this approach is especially practical, because the full local Docker environment with PHP-FPM, Elasticsearch, Redis and MySQL no longer needs to be replicated on every single developer laptop. A single, well equipped development server is enough for the entire team, while each developer uses their own isolated working copy in the same server file system via Remote-SSH.

4. Port forwarding: making remote dev servers reachable locally

A central building block of productive remote development is local port forwarding, which makes a service running on the remote server, for example a PHP development server or a Vite instance, reachable in the local browser under localhost. The command ssh -L 8080:localhost:8080 devserver builds a tunnel through which every request to local port 8080 is transparently forwarded to the same numbered port on the server, without ever having to publicly expose the server's port.

VS Code Remote-SSH even automates this step to a large extent: if the extension detects that a process on the server opens a new port, it automatically offers to forward that port locally. For manual situations, for example working directly in the terminal without editor integration, the explicit -L option remains indispensable, especially when several ports need to be forwarded at once.


# Forward a remote dev server to localhost (single port)
ssh -L 8080:localhost:8080 devserver

# Forward multiple ports at once (web server, database, Elasticsearch)
ssh -L 8080:localhost:8080 \
    -L 3306:localhost:3306 \
    -L 9200:localhost:9200 \
    devserver

# Run the forward in the background without opening an interactive shell
ssh -f -N -L 8080:localhost:8080 devserver

# Reverse forwarding: expose a local service to the remote server
# (useful for webhooks that must reach your local machine)
ssh -R 9000:localhost:9000 devserver

A subtle but important difference exists between local and remote forwarding. Local forwarding (-L) makes a remote service reachable locally, while remote forwarding (-R) goes the opposite way and makes a local service reachable on the remote server, for example for webhook testing where an external service needs to reach your own development machine. Both variants run over the same SSH connection and need no additional firewall opening.

5. File synchronization: rsync, sshfs and alternatives

Not every instance of remote development runs through a fully remote editor. Many developers still prefer their local IDE and synchronize files with the server only when needed. For this case, rsync is the most reliable tool because it only transfers changed file parts while correctly preserving permissions, timestamps and symbolic links. A typical watch workflow combines rsync with a file system watcher that syncs automatically on every change.

As an alternative, sshfs offers a way to mount a remote directory directly as a local file system. The advantage: the local IDE appears to work with local files, while all reads and writes actually go through SSH. The downside shows up on unstable connections or with operations touching very many small files, for example browsing a vendor directory, where the latency of every single file system operation becomes noticeable. For such cases, a remotely running editor like VS Code Remote-SSH is usually the significantly more performant choice.

6. SSH agent forwarding for git and deployment

Anyone who wants to run git operations against a private repository on the remote server, or start deployment scripts that themselves need to establish another SSH connection, faces a problem: the private key lives locally but is needed on the server. SSH agent forwarding solves this without ever copying the private key onto the server. With the option ForwardAgent yes in the SSH config, or the flag -A at connection time, the local SSH agent forwards signature requests over the existing tunnel, so the server can perform operations on the user's behalf without ever owning the key itself.

Important for security: agent forwarding should only be enabled for trusted servers, because root access on the target server could theoretically abuse the forwarded signature requests while the connection is active. For daily remote development with your own deployment server, the risk is usually acceptable, but on foreign or multi tenant servers you should be more restrictive and store project specific deploy keys directly on the server instead.

7. Connection multiplexing for faster connections

Every new SSH connection requires a full cryptographic handshake that costs noticeable time, especially with high latency between local machine and server. Connection multiplexing with ControlMaster solves this by keeping the first connection open, and every subsequent connection, for example for a new terminal window or an additional port forward, reuses the same already authenticated channel. The noticeable effect: instead of several seconds of waiting, a second connection opens practically instantly.

For remote development with many short commands, for example repeated rsync runs or git operations over SSH, this speed gain adds up noticeably. Configuration happens centrally in the SSH config with ControlPersist, which defines how long the connection stays open after the last use before it is automatically closed. A value of 10 minutes is a good compromise between speed and resource use on the server for most development sessions.

8. Common pitfalls in remote development

A common pitfall is excessive network latency between local machine and server, which shows up as sluggish input delay with a remotely running editor. VS Code Remote-SSH partially compensates through local buffering of input, but at latencies above roughly 150 milliseconds the work becomes noticeably unpleasant. In such cases, choosing a geographically closer server or switching to a local file synchronization workflow instead of a fully remote editor is worthwhile.

A second pitfall concerns resource contention on shared development servers. When several developers work simultaneously via VS Code Remote-SSH, a single resource hungry language server process, for example for a large TypeScript or PHP codebase, can noticeably slow down the server. Configuring per user resource limits, for example via cgroups or systemd slices, helps prevent a single process from slowing down the entire server.

Third, firewall configuration is often neglected. Anyone using port forwarding for development purposes should ensure that the forwarded ports are not accidentally also directly reachable on the network from the server itself. Since SSH tunnels bind only to localhost by default, the risk is low, but an explicit check with ss -tlnp on the server adds extra safety.

9. Remote development approaches compared

Depending on the project and team size, different approaches to remote development suit different needs. The table below compares the most important options.

Approach Latency sensitivity Setup effort Best suited for
VS Code Remote-SSH Medium to high Low Large codebases, resource heavy builds
rsync watch sync Low Medium Preference for local IDE, unstable connections
sshfs mount High Very low Occasional file access, small projects
JetBrains Gateway Medium Medium PHPStorm teams sharing a server

For most Magento and PHP teams, VS Code Remote-SSH or JetBrains Gateway is the most productive solution, because resource intensive operations happen directly on the server. rsync based workflows remain the more robust choice on unstable connections, or when developers absolutely want to keep their familiar local IDE configuration.

Mironsoft

Remote development environments for Magento and PHP teams

A development server the whole team can use productively?

We set up remote development servers with SSH config, VS Code Remote-SSH and clean resource management, so your team works in a consistent environment independent of local hardware.

Server setup

Development servers with clean SSH configuration and access control

Team workflows

Consistent remote environments for several developers at once

Resource management

cgroups and limits against mutual slowdown within the team

10. Summary

Remote development via SSH is today the pragmatic answer to resource hungry projects and heterogeneous developer hardware. A well maintained SSH config with aliases, keep alive options and connection multiplexing forms the foundation on which VS Code Remote-SSH, JetBrains Gateway or classic rsync workflows build. Port forwarding makes remote services reachable locally, agent forwarding allows secure git operations without copying keys.

The choice between a fully remote editor and a local editor with file synchronization depends mainly on network latency and personal preference. In both cases, a well thought out server configuration matters, one that avoids resource contention between team members and keeps an eye on the security of forwarded connections. Once these building blocks are set up correctly, you benefit permanently from productive remote development that feels almost like local work.

For teams new to this topic, a step by step approach is advisable: first set up the SSH config with aliases and ControlMaster, then test VS Code Remote-SSH or JetBrains Gateway on the first projects, and only add extra building blocks such as agent forwarding or resource limits once genuinely needed. This gradual introduction avoids overwhelming a team with too many new concepts at once, and ensures each building block is actually understood and used before the next one is added.

Remote Development via SSH, the Essentials at a Glance

SSH config

Host aliases with ServerAliveInterval and ControlMaster save time and typing.

VS Code Remote-SSH

Editor local, compute load remote, ideal for large codebases and Docker stacks.

Port forwarding

ssh -L makes remote dev servers reachable locally without public exposure.

Agent forwarding

ForwardAgent allows git operations on the server without a copied private key.

11. FAQ: Remote Development via SSH

1Remote-SSH vs. file synchronization?
Remote-SSH runs all operations directly on the server. With file synchronization, the IDE works locally and only syncs periodically.
2Set up a reusable SSH alias?
Define a host block in ~/.ssh/config with HostName, User, Port and IdentityFile, then ssh aliasname is enough.
3What does ControlMaster do?
Keeps the first connection open, new connections reuse the same channel and become significantly faster.
4Make a remote dev server reachable locally?
With ssh -L 8080:localhost:8080 servername, which forwards local requests transparently to the server.
5sshfs instead of Remote-SSH?
Suitable for occasional access or small projects. For large codebases, a remotely running editor is more performant.
6Is agent forwarding safe?
Low risk on trusted servers. On foreign servers, use project specific deploy keys instead.
7Why does the work feel sluggish?
High network latency is the usual cause. Above roughly 150 milliseconds it becomes noticeably unpleasant.
8Prevent one developer slowing the server?
With per user resource limits via cgroups or systemd slices, CPU and memory can be constrained.
9Local vs. remote port forwarding?
-L makes a remote service reachable locally, -R makes a local service reachable for the server.
10Own firewall configuration needed?
SSH tunnels bind only to localhost by default. A check with ss -tlnp adds extra safety.

Last content review of this article: July 2026, example configurations tested with OpenSSH 9.x and VS Code Remote-SSH.