managing twingate

Remote Development with Twingate SSH

Run your IDE on your laptop. Run your code on a remote VM. No VPN. No exposed ports. No SSH keys.

This guide walks you through remote development workflows using VS Code Remote SSH, JetBrains Gateway, and Cursor with Twingate SSH. You connect to remote development environments using standard IDE tools, authenticated through your identity provider, with every session recorded.

How remote development with Twingate works

In a typical remote development setup, your IDE runs locally while the codebase, build tools, and runtime environment live on a remote Linux VM. The IDE opens an SSH session to the remote host, transfers files, and executes commands remotely. You edit in the IDE on your laptop; the code runs on a VM with more CPU, memory, or GPU than your local machine.

Twingate secures this workflow through your existing identity provider. The SSH server on your development VM stays in a private network with no public IP. The Twingate Gateway handles authentication and proxying. When you connect through VS Code or JetBrains, you authenticate via your SSO provider — no SSH keys, no VPN, no bastion host.

[ IDE on laptop ] ── Twingate Client ── Connector ──> [ SSH Gateway ] ──> [ Dev VM ]
<====== Twingate Auth & Certificate ======>

The Gateway issues a short-lived SSH certificate tied to your identity. The SSH server on the dev VM trusts certificates from Twingate’s SSH CA. No private keys live on your laptop. Access revocation is instant — remove a user from a group, and their IDE can’t connect.

Every SSH session is captured in asciicast format and tied to your identity. File transfers work transparently: scp, rsync, and SFTP are all supported.

Enable SSH config sync

Twingate Client can automatically populate your SSH client configuration with entries for every SSH Resource you have access to. This makes remote hosts immediately discoverable in VS Code, JetBrains, and any other tool that reads your SSH config.

Step 1: Open Twingate Client settings

  • Launch the Twingate Client on your development machine.
  • Click More (or the menu icon, depending on your platform).
  • Select Auto-sync SSH Server Configuration.

Step 2: Enable auto-sync

Toggle the setting to Enabled.

What this does

When enabled, the Twingate Client updates ~/.ssh/known_hosts with the public key of Twingate’s SSH CA. This allows your SSH client to automatically trust certificates issued by the Gateway. No TOFU (trust on first use) prompts, no manual ssh-keyscan, no fingerprint warnings.

The Client also writes entries to ~/.ssh/config for each SSH Resource you have access to. These entries include the hostname alias and connection details. IDEs that parse SSH config (VS Code Remote SSH, JetBrains Gateway) see these hosts immediately.

What gets synced

  • ~/.ssh/known_hosts: Updated with the SSH CA’s public key, prefixed with @cert-authority so the SSH client trusts all certificates signed by Twingate.
  • ~/.ssh/config: Populated with host entries for each SSH Resource. Hostnames match the Resource name configured in the Admin Console.

The configuration stays up to date as Resources are added, removed, or modified. You don’t need to manually refresh.

VS Code Remote SSH

VS Code Remote SSH lets you open a folder on a remote machine and work on it as if it were local. With Twingate, the remote host is a private SSH Resource — no public IP, no VPN, no key files.

Connect to a remote host

  • Open VS Code.
  • Install the Remote - SSH extension if you haven’t already (ms-vscode-remote.remote-ssh).
  • Open the Command Palette (Cmd+Shift+P on macOS, Ctrl+Shift+P on Windows/Linux).
  • Type Remote-SSH: Connect to Host and select it.
  • Choose a host from the list. Hosts from the Twingate-synced SSH config appear here automatically.
  • VS Code opens a new window connected to the remote host. The first connection may take a few seconds as VS Code installs its server component on the remote VM.

Open a project

Once connected:

  • Click Open Folder in the VS Code welcome screen.
  • Navigate to your project directory on the remote VM.
  • VS Code indexes the project and enables full IntelliSense, debugging, and terminal access.

File synchronization

VS Code transfers files automatically as you edit. For larger file operations (cloning a repository, downloading datasets), you can use the integrated terminal or transfer files manually via scp or rsync before connecting.

Transfer a local project to the remote VM before opening it in VS Code:

rsync -avz --progress ~/my-project/ my-dev-vm.int:/home/user/my-project/

The synced SSH config means you can reference my-dev-vm.int directly. No need for IP addresses or manual ProxyCommand configuration.

Troubleshooting

VS Code prompts for a fingerprint on first connection.

This means SSH config sync isn’t enabled or the SSH CA key hasn’t been synced yet. Enable Auto-sync SSH Server Configuration in the Twingate Client settings. The TOFU prompt will not appear on subsequent connections.

Host doesn’t appear in the host list.

Verify:

  • You have access to the SSH Resource in the Twingate Admin Console (check your group memberships).
  • Auto-sync is enabled in the Twingate Client.
  • The Twingate Client is running and connected.

Restart VS Code after enabling auto-sync to refresh the host list.

JetBrains Gateway

JetBrains Gateway provides remote development support for IntelliJ IDEA, PyCharm, GoLand, and other JetBrains IDEs. The IDE backend runs on the remote VM; the thin client runs on your laptop.

Connect via SSH

  • Open JetBrains Gateway.
  • Select SSH as the connection type.
  • Click New Connection.
  • In the connection configuration:
    • Host: Select a host from the auto-populated SSH config, or enter the hostname manually (e.g., my-dev-vm.int).
    • Username: Your SSH username on the remote VM.
    • Authentication: Choose OpenSSH config and authentication agent. Do not use key-based authentication. Twingate handles authentication via certificates.
  • Click Check Connection and Continue.
  • Gateway tests the connection and installs the IDE backend on the remote VM if it’s not already present.
  • Select your project directory on the remote VM.
  • Gateway launches the IDE. The editor UI runs locally; the backend (indexing, compilation, debugging) runs remotely.

SSH config integration

JetBrains Gateway reads the same ~/.ssh/config that Twingate populates. Hosts synced by the Twingate Client appear in Gateway’s host picker automatically. No manual configuration required.

Troubleshooting

Gateway shows “Connection refused” or “Host unreachable”.

Verify:

  • The Connector is running and is version 1.82.0 or later.
  • The Twingate Client is version 2025.310 or later.
  • You have access to the SSH Resource.

Check the Connector logs for connection errors. Ensure the SSH server on the target VM is running (sudo systemctl status sshd).

Gateway prompts for a password.

If password authentication is enabled on the SSH server, Gateway may prompt for a password even though Twingate uses certificate-based authentication. This is usually due to a misconfigured sshd_config. Verify that the TrustedUserCAKeys line is present and points to the correct CA public key file. Restart sshd after making changes.

Cursor and Claude Code on remote machines

Cursor is a fork of VS Code with integrated AI features. Claude Code is a CLI tool that can execute on remote machines over SSH. Both tools work transparently with Twingate SSH because they invoke the native ssh binary under the hood.

Cursor Remote SSH

Cursor supports VS Code’s Remote SSH extension. The setup is identical to VS Code:

  • Install the Remote - SSH extension in Cursor.
  • Open the Command Palette and select Remote-SSH: Connect to Host.
  • Choose a host from the auto-synced SSH config.
  • Cursor connects, installs its server component on the remote VM, and opens the remote workspace.

All AI features (code completion, chat, inline edits) work on the remote host. The language model context includes files on the remote VM, not your local machine.

Claude Code on a remote host

The Claude desktop app supports connecting to remote machines over SSH to run Claude Code directly on the remote host, closer to the codebase, build tools, and compute resources.

  • Ensure the Twingate Client is running and connected.
  • Enable Auto-sync SSH Server Configuration in the Twingate Client if you haven’t already. This makes the remote host immediately discoverable.
  • In Claude desktop, point it at the remote SSH host. Claude desktop invokes the native ssh binary under the hood, so the Twingate-synced SSH config is picked up automatically.

Claude Code runs on the remote machine with full access to the codebase, local APIs, and databases, while you interact with it from your laptop. Because Twingate issues certificates automatically, there are no key files to manage. The session is recorded like any other SSH session.

Why this works without modification

Tools like Cursor and Claude Code rely on the system ssh binary. Because Twingate operates at the SSH protocol level — not as a wrapper or proxy command — any tool that calls ssh works transparently. Some privileged access products require custom CLI wrappers that replace the native ssh binary, which breaks IDE integrations. Twingate uses the standard ssh command end-to-end.

File transfer: SCP, rsync, and SFTP

File transfer tools that use SSH as a transport work with Twingate without additional configuration.

SCP

Copy files to a remote host:

scp ./local-file.tar.gz my-dev-vm.int:/home/user/

Copy files from a remote host:

scp my-dev-vm.int:/home/user/remote-file.tar.gz ./

rsync

Synchronize directories with rsync:

rsync -avz --progress ~/my-project/ my-dev-vm.int:/home/user/my-project/

SFTP

Interactive SFTP sessions work:

sftp my-dev-vm.int

Automated SFTP (e.g., via scripting or CI/CD pipelines) also works. SFTP clients that read SSH config will pick up the Twingate-synced host entries automatically.

Large file transfers

File transfers of up to 100 MB work reliably. For larger files (multiple gigabytes), some Linux targets may experience timeouts or session interruptions depending on network conditions. If you encounter issues with very large transfers:

  • Use rsync with the --partial flag to resume interrupted transfers.
  • Compress files before transfer to reduce size.
  • Consider chunking large datasets into smaller archives.

Binary file transfer payloads are excluded from session recordings to keep log sizes manageable.

Port forwarding

Twingate SSH supports TCP/IP port forwarding (local and remote). This is useful for accessing services running on the remote host that aren’t exposed via a Resource.

Local port forwarding

Forward a local port to a service on the remote host:

ssh -L 8080:localhost:3000 my-dev-vm.int

This forwards port 8080 on your laptop to port 3000 on the remote VM. Useful for accessing a web server or database running on the remote host.

Remote port forwarding

Forward a port on the remote host to a service on your laptop:

ssh -R 9000:localhost:8000 my-dev-vm.int

This forwards port 9000 on the remote VM to port 8000 on your laptop. Useful for testing webhooks or callbacks from the remote environment to a local service.

Troubleshooting

TOFU prompts appearing on every connection

Symptom: Your SSH client shows “The authenticity of host ‘my-dev-vm.int’ can’t be established” and prompts you to accept the fingerprint every time you connect.

Cause: SSH config sync is disabled, or the SSH CA key hasn’t been added to ~/.ssh/known_hosts.

Solution:

  • Open the Twingate Client.
  • Enable Auto-sync SSH Server Configuration under More.
  • Verify the SSH CA key is present in ~/.ssh/known_hosts:
    grep "@cert-authority" ~/.ssh/known_hosts
    You should see an entry with @cert-authority followed by the CA’s public key.
  • Restart your IDE or SSH client and try again.

Host not appearing in IDE host picker

Symptom: VS Code, JetBrains Gateway, or another IDE doesn’t show your SSH Resource in the host list.

Cause: You don’t have access to the Resource, or auto-sync is disabled.

Solution:

  • Verify you have access to the SSH Resource in the Twingate Admin Console. Check your group memberships.
  • Enable Auto-sync SSH Server Configuration in the Twingate Client.
  • Restart the IDE to refresh its SSH config cache.
  • Check that the host entry exists in ~/.ssh/config:
    grep "Host my-dev-vm.int" ~/.ssh/config

Connection refused or timeout

Symptom: The IDE or SSH client shows “Connection refused” or times out when trying to connect.

Cause: The Connector or Client version is outdated, or the SSH server isn’t running on the target VM.

Solution:

  • Verify the Connector is version 1.82.0 or later. Check the Connector version in the Admin Console under Network > Connectors.
  • Verify the Twingate Client is version 2025.310 or later. Check the Client version in the Client settings.
  • Ensure the SSH server is running on the target VM:
    sudo systemctl status sshd
    If it’s not running, start it with:
    sudo systemctl start sshd
  • Check the Connector logs for errors. In Kubernetes deployments, check the Gateway pod logs:
    kubectl logs -n twingate deployment/twingate-gateway

File transfer fails or hangs

Symptom: SCP or rsync hangs during large file transfers, or the transfer completes but the file is corrupted.

Cause: Network interruptions, session timeouts, or issues with specific Linux kernel versions handling large payloads.

Solution:

  • Use rsync with the --partial and --progress flags to resume interrupted transfers:
    rsync -avz --partial --progress ./large-file.tar.gz my-dev-vm.int:/home/user/
  • Compress files before transferring to reduce size:
    tar -czf project.tar.gz ~/my-project/
    scp project.tar.gz my-dev-vm.int:/home/user/
  • For very large datasets (multi-GB), consider chunking into smaller archives or using a cloud storage intermediate (upload to S3, download from the remote VM).
  • If SFTP is required, verify the SFTP subsystem is enabled in the SSH server config:
    grep "Subsystem sftp" /etc/ssh/sshd_config

IDE prompts for a password

Symptom: The IDE prompts for a password even though Twingate uses certificate-based authentication.

Cause: The SSH server is configured to require password authentication, or the TrustedUserCAKeys setting isn’t configured correctly.

Solution:

  • Verify the SSH server trusts the Twingate SSH CA. Check sshd_config on the target VM:
    sudo grep "TrustedUserCAKeys" /etc/ssh/sshd_config
    It should point to the CA public key file:
    TrustedUserCAKeys /etc/ssh/twingate_ca.pub
  • Restart the SSH server after making changes:
    sudo systemctl restart sshd
  • Disable password authentication if it’s not required:
    PasswordAuthentication no

Session recording and audit trail

Every SSH session you open through an IDE or the command line is recorded. The Gateway captures a full terminal recording in asciicast v2 format, tied to your authenticated identity.

Recordings include:

  • All interactive shell commands
  • Output from executed commands
  • Timing information (when each command was run)

Recordings exclude:

  • Binary file transfer payloads (SCP content)
  • SFTP file data

Session recordings are exported to stdout on the Gateway and stay entirely on your infrastructure. Forward them to your SIEM (Splunk, Datadog, etc.), archive them in S3, or replay them in a browser using an asciicast player.

When you connect to a remote host via VS Code or JetBrains, your session is treated the same as any SSH session opened via the terminal. Every command the IDE runs remotely is logged. If you open a terminal in the IDE and run commands interactively, those commands are captured in the recording.

This gives you a complete audit trail of all remote development activity, required by compliance frameworks like SOC 2, ISO 27001, PCI-DSS, and HIPAA.

What works and what doesn’t

Supported

  • IDEs: VS Code Remote SSH, JetBrains Gateway (all IntelliJ-based IDEs), Cursor, any IDE that uses native SSH
  • File transfer: SCP, rsync, SFTP
  • Port forwarding: Local (-L) and remote (-R) TCP/IP port forwarding
  • Interactive shells: Full terminal access with command history
  • Remote commands: Non-interactive command execution (e.g., CI/CD SSH steps, Ansible, Terraform remote-exec)
  • Session recording: All sessions captured in asciicast format

Not supported

  • X11 forwarding: GUI applications over SSH are not supported. Use VNC or a remote desktop protocol instead.

Why this works better than alternatives

No custom CLI

Some privileged access products require you to use a custom CLI binary instead of ssh. These custom wrappers break IDE integrations because IDEs expect the standard ssh binary. With Twingate, you use the native ssh command end-to-end. VS Code, JetBrains, Cursor, and every other tool that shells out to ssh works without modification.

No agent on servers

Many PAM products require you to install agents on every SSH server. Twingate requires only a one-line configuration change in sshd_config to trust the SSH CA. This works on minimal Linux systems, embedded hardware, and environments where installing additional software isn’t permitted.

No VPN

Traditional VPNs require users to connect before SSHing. Twingate Client routes SSH traffic automatically. No separate VPN connection, no split tunneling configuration, no VPN status to monitor. The developer experience is identical to accessing a local VM.

No exposed ports

Bastion hosts expose a public SSH port. That port becomes a high-value attack target. With Twingate, the SSH server on your dev VM has no public IP. The Connector makes outbound-only connections. There’s no public endpoint to scan, no port to brute force, and no shared credential across teams.

Next steps

  • Configure session recording forwarding to send recordings to your SIEM or archive them in S3. See the SSH session recording guide.
  • Set up time-based access policies to grant contractors or vendors temporary access to specific development VMs. See the contractor and vendor access guide.
  • Integrate with CI/CD to use Twingate SSH in deployment pipelines without storing SSH keys as secrets.

Join us in the community subreddit to share your remote development setup and see what others are building.

Last updated 13 minutes ago