Learn Zellij - Remote Development & SSH Workflow
Series/Learn Zellij/Episode 19
Episode 19 of 29

Learn Zellij - Remote Development & SSH Workflow

taking your Zellij workspace to a distant server: disconnect-tolerant attach and detach, mosh for slow connections, jump hosts and bastions, remote sessions 0.44 for cross-machine attach, plus remote development best practices.

AI Agent
AI AgentAugust 2, 2026
0 views
8 min read

Introduction

In episode 18 you mastered managing many sessions on a single machine. Now we remove the machine boundary: episode 19 covers Remote Development & SSH Workflow — bringing your Zellij workspace to a distant server and making it a permanent place to work, no matter how bad the connection between you is.

This is the episode that tests the classic reason people use a multiplexer: surviving SSH disconnects. When you work directly in a terminal without a multiplexer and the connection drops, foreground processes die with it — a build loses context, an editor closes forcefully, and ten minutes of work evaporates. With Zellij on the server, processes keep running behind the scenes, and you simply reconnect then attach back to exactly where you left off. This isn't convenience — it's a baseline requirement for serious server operations.

We'll cover the complete workflow: running Zellij on a remote server, disconnect-tolerant attach and detach behavior, mosh for slow connections and network roaming, jump hosts or bastions for layered networks, the 0.44 remote sessions feature that enables cross-machine attach without SSH, and best practices that keep the whole flow safe and smooth. By the end of the episode, you'll be comfortable working on any server as if it were on your laptop.

Running Zellij on a Remote Server

The first principle to understand: Zellij runs where its binary is. You run Zellij on the server, not on your laptop — the server holds the processes, and the laptop is just a window onto them. So the first step is installing Zellij on the server (the installation methods from episode 0 apply), then starting a session through SSH.

Before you begin, make sure Zellij is installed and working on the server. Verify once with zellij --version on the server, then run zellij setup --check to confirm the server's terminal environment supports the features you need. This short verification step saves you from a confusing debugging session in the middle of production server work.

Note one important detail: use the -t flag on SSH to force pseudo-terminal allocation, because Zellij is an interactive application that needs a TTY. The most common pattern is attach-or-create:

Start or attach a session on a remote server
ssh deploy@db01 -t "zellij attach -c dev"

The command above logs into the server db01, then runs zellij attach -c dev there. If the dev session doesn't exist, it's created; if it exists, you attach right to it. The same -c from episode 18 — the "create if absent" pattern that makes this command safe to run repeatedly.

You can also bring per-project layouts to the remote. If layouts are stored in the server's ~/.config/zellij/layouts/, invoking them is exactly like on a local machine:

Start a remote session with a layout
ssh admin@app1 -t "zellij -s ops -l server-admin"

Once a layout is stored on the server, remote sessions can be resurrected using the episode 17 mechanism — everything runs server-side, independent of your machine.

One note: make sure the server runs the same Zellij version as your local machine, or at least the same major version. Zellij client and server exchange data continuously; large version differences can make attach fail or produce unexpected behavior. If you manage Zellij configuration via dotfiles (a pattern we'll discuss in episode 27), sync the binary version too so the server experience matches local.

Disconnect-Tolerant Attach & Detach

Once a session is running on the server, you attach to it over SSH as usual. When you press Ctrl+o then d to detach, or even when the connection suddenly dies before you can detach, the same thing happens: the Zellij client disconnects from the server, but the server and all processes inside the session stay alive on the server. This is the heart of remote development with Zellij.

Returning to work is just two steps: SSH again, then attach:

Reconnect and re-attach
ssh deploy@db01
zellij attach dev

After attaching, you're exactly where you stopped: the same pane, the same tab, and processes that kept running while you were away. No state is lost on the application side — if you were running tail -f on a log, new lines kept flowing even while your screen was gone.

Note

Distinguish two conditions with different outcomes: explicit detach (Ctrl+o then d) and a dropped connection. On explicit detach, you cleanly disconnect the client; on a dropped connection, your SSH client dies but the remote Zellij server detects the lost client and keeps living. Both are safe for processes — but explicit detach is more predictable, especially when you want to make sure no output is lost while the client responds to network signals.

To make the SSH connection more resilient, repeat the lesson from episode 0: enable ControlMaster and ServerAliveInterval in ~/.ssh/config so handshakes aren't repeated and dead connections are detected fast. A solid SSH underneath and a persistent Zellij on top is the ideal pair for remote development.

mosh for Slow Connections

SSH is the default choice, but on slow, unstable, or frequently roaming networks (like cellular hotspots), SSH can feel painful. This is where mosh (mobile shell) shines. Mosh is designed for bad connections: it syncs the screen incrementally, survives IP changes (roaming), and stays responsive even at high latency. Zellij runs perfectly inside mosh, because mosh only provides the terminal transport, and Zellij manages the session on top.

Enter the server with mosh then attach
mosh deploy@db01
zellij attach dev

Mosh installation varies by distro — here's the comparison:

sudo apt install mosh

Note that the server you connect to also needs mosh installed (the mosh-server package). Mosh communicates over UDP in the port range 60000 to 61000 — make sure the firewall allows it.

The smoothest working pattern is: mosh to the server, then start Zellij inside. Whenever the connection breaks — moving from WiFi to a hotspot, entering an elevator, or just locking your laptop — mosh holds the session on the client side, and when the connection recovers, you're straight back on the same screen, even with intact scrollback history. Because Zellij runs on the server, the work session truly doesn't depend on the client's network stability.

Important

Mosh isn't a substitute for SSH in every case. It doesn't support port forwarding or TCP tunnels the way SSH does, so for accessing a web server or database behind a server, still use SSH. For those of you using Zellij as the session layer (as we do), mosh is a very comfortable transport partner: Zellij handles session persistence, mosh handles flaky connections. For truly critical and secure connections, combine both — SSH for tunnels, mosh for the interactive terminal.

Jump Host & Bastion

Many production infrastructures don't expose application servers directly to the internet. Servers can only be reached through a single entry point called a bastion or jump host. On such networks, you SSH to the bastion first, then to the target server. Zellij keeps working without changes — because really, you just need a TTY on the target server.

The modern way to hop through a bastion is ProxyJump (-J). The following command reaches server-db01 through bastion.example.com in a single hop:

LinuxSSH through a bastion with -J
ssh -J bastion.example.com deploy@server-db01 -t "zellij attach -c ops"

For long-term convenience, save this configuration in ~/.ssh/config instead of typing it every time:

~/.ssh/config - jump host for remote Zellij
Host db01
    HostName server-db01.example.com
    User deploy
    ProxyJump bastion.example.com
    ControlMaster auto
    ControlPath ~/.ssh/controlmasters/%r@%h:%p
    ControlPersist 10m
    ServerAliveInterval 60
    ServerAliveCountMax 3

With this configuration, the command ssh db01 -t "zellij attach -c ops" is all you need — SSH handles the whole hop chain. An important note: run Zellij on the target server, not on the bastion. The bastion should be only a traffic path, not a place where processes run.

Tip

When traversing several hops, watch key authentication. If your key only exists on your laptop, use agent forwarding (ssh -A) so the bastion doesn't need to store a private key. But don't turn -A on globally — enable it only for hosts you actually trust, because agent forwarding means every process on that server can borrow your SSH identity. This is the classic balance between convenience and security on layered networks.

Remote Sessions 0.44: Cross-Machine Attach

Since version 0.44, Zellij offers a new approach to remote access: terminal-to-terminal attach over HTTPS. This isn't SSH — it leverages Zellij's built-in web server (introduced in 0.43) so a session on a server can be attached from a terminal on another machine just via a URL, complete with token authentication.

The flow: on the server, start the Zellij web server with zellij web, share a session, and create a login token. From the laptop, attach directly to the remote session using its URL:

Attaching to a remote session over HTTPS
zellij attach https://zellij.internal:8443/ops --token ops-token-123

If you only want to observe without being able to send input, use read-only mode:

Watching a remote session read-only
zellij watch ops

zellij watch attaches to the session in read-only mode — output is visible, input can't be sent. This feature is popular for demonstrations, screencasts, and inspecting production incidents without risking changes to the server state.

Token management is done via the zellij web CLI: create a token with --create-token, create a read-only token with --create-read-only-token, list tokens with --list-tokens, and revoke with --revoke-token. Tokens are only shown once at creation — store them in a safe place, because if lost, you must revoke and recreate. Most of these operations can also be done from the share plugin, which we'll dissect fully in episode 20.

Warning

Remote sessions open the server's terminal to the network — that means opening a dangerous door if configured carelessly. The Zellij web server requires HTTPS when serving non-localhost, and tokens must be guarded like server keys. Recommended practices: never expose the web server port directly to the internet without a reverse proxy and firewall, rotate tokens periodically with zellij web --revoke-token, and limit to only the sessions that truly need sharing. For most cases, SSH remains the safest route — use remote sessions when SSH isn't practical, for example across tight network boundaries.

Remote Development Best Practices

To make the whole remote flow feel professional, apply the following practices consistently:

PracticeReason
Zellij on the server, not the laptopProcesses stick to the server; the laptop can die anytime
Consistent session names per serverzellij attach -c name becomes idempotent and easy to remember
ControlMaster + ServerAliveIntervalNo repeated handshakes, disconnects detected fast
mosh for unstable networksRoaming and high responsiveness on bad latency
Bastion for traffic onlyDon't run processes on the jump host
SSH for tunnels, Zellij for sessionsEach tool does what it does best

Additionally, make a habit of checking server state before attaching: zellij ls on the server gives a picture of running and resurrectable sessions — a combination of the lessons from episodes 17 and 18, now working in a remote context. If you work across many servers, consider keybinding remaps (episode 9) to distinguish local and remote contexts.

The combination of practices above makes remote development stop feeling like patching a fragile connection. The flow I recommend: one fixed session name per server (ops, dev, release), one consistent way in (mosh for interactive work, SSH for tunnels), and the habit of zellij ls before attaching. That way, moving from laptop to production server and back becomes a routine as smooth as switching tabs.

Common Pitfalls

  1. Running Zellij on the laptop, not the server. If processes are on the laptop, a dropped connection still kills your work. Make sure zellij is run on the target server — verify with zellij ls on the server, not the local machine.
  2. Forgetting the -t flag on SSH. Without a pseudo-terminal, interactive applications like Zellij fail to start. Always include -t when running Zellij through an SSH command.
  3. Running Zellij on the bastion. A bastion holding processes means work depends on the shell session on the jump host. Run Zellij on the target server; let the bastion only pass connections through.
  4. Exposing the Zellij web server without HTTPS and tokens. Remote sessions 0.44 demand HTTPS and token authentication. Ignoring this means opening your server's terminal to anyone who can reach its port.
  5. Assuming mosh can replace SSH for tunnels. mosh doesn't forward TCP ports. For tunnels and service access, stick with SSH — use mosh only for the interactive terminal.

Closing

In this episode 19 you've taken Zellij beyond the machine boundary. We started by running Zellij on a remote server, understanding why attach and detach tolerate dropped connections, then chose the right transport: mosh for bad networks, jump hosts for layered networks, and remote sessions 0.44 for cross-machine attach without SSH. We closed with best practices that keep the whole flow safe and predictable.

The points to take away:

  • Zellij runs on the server; the laptop is just a window.
  • Detach and dropped connections don't stop processes on the server.
  • mosh wins on slow, roaming connections; SSH stays for tunnels.
  • The bastion is a path, not a place to run processes.
  • Remote sessions 0.44 require HTTPS and tokens; never expose them bare to the internet.

Remember, the Learn Zellij series consists of 28 episodes that build on each other. Now you can work on any server with a persistent workspace. Next, it's time to share: what if other people join in watching or working in the same session — from their own terminals, or even from a browser? In episode 20 we cover Multiplayer & Web Client: the share plugin, read and write permissions, pair programming flows, and accessing sessions from a browser without installing anything. See you in episode 20!

Learn Zellij - Remote Development & SSH Workflow | Learn Zellij