🌍 English · Leggi in italiano →

Ever had this happen? You kick off a backup, a long build, a half-terabyte rsync, or an agent chewing through tasks on your VPS. You close the laptop, go grab a coffee… and when you come back, the process is dead, killed along with your SSH session. Welcome to the wonderful world of SIGHUP.

Back in 2024, we published a cheatsheet dedicated to screen. But the way we work has changed since then: development harnesses, agents running for hours, remote VPS sessions that need to survive flaky connections (our own development stack works exactly like this). screen is still great, but it isn't the only tool in the box. So let's widen the scope: four tools, when to use them, and the commands you actually need.

The mental model: two families

Before getting into commands, the most useful thing is understanding that these tools solve the same problem in two very different ways:

  1. Detach a single process from the terminal so it can keep running on its own → nohup (and relatives such as disown and setsid). Fire and forget: launch it, walk away, check the output file later.
  2. Keep an entire interactive session alive, detach from it and reattach whenever you want, with multiple windows and panes → the multiplexers: screen, tmux, zellij. The session lives on the server; you just come and go.

Rule of thumb: if you only need to launch a long-running command and check its output later, nohup is enough. If you want to actually work inside a persistent session—open multiple shells, come back later, move between panes—you want a multiplexer.


nohup — fire and forget

What it is. A command that runs another command while ignoring SIGHUP, the signal the system may send when the terminal that launched a process disappears. It's part of GNU coreutils and is normally already available on Linux systems.

When to use it. One non-interactive background job where a log file is all you need: an overnight backup, a long compile, a migration script. No need to “get back inside” later.

The key thing about nohup is that you have to think about it beforehand: you decide from the start that the process needs to keep running after the SSH session is gone.

Essential commands.

# Run in the background and ignore SIGHUP.
# Without an explicit redirect, output normally goes to ./nohup.out
nohup ./backup.sh &

# Better: redirect stdout + stderr to your own log
nohup ./backup.sh > backup.log 2>&1 &

# Check that it's still running and follow the log
jobs -l
ps aux | grep backup.sh
tail -f backup.log

But what if you didn't think about it beforehand?

You started your command normally:

./long_task.sh

The process is running in the foreground and owns your terminal. Half an hour later, you suddenly remember you need to close the laptop, drop the SSH connection, or simply leave.

This is where disown gets genuinely useful.

First, temporarily suspend the process with:

Ctrl-Z

Bash gives you your prompt back. Now:

bg                # resume the process in the background
disown -h %1      # keep Bash from sending it SIGHUP

So the full rescue sequence is:

./long_task.sh

# ...oops, I need to close this SSH session...

# Ctrl-Z          → suspend the process
bg                # resume it in the background
disown -h %1      # protect it from the shell's SIGHUP

And that's the practical difference that really matters.

With:

./long_task.sh &
disown -h %1

you still need to know in advance that you want the process running in the background. At that point, you might as well start with nohup in the first place.

The real superpower of disown is that it's your Plan B: you've already started something in the foreground, it may have been running for ages, and only then do you realize you need to leave the SSH session.

Ctrl-Z → bg → disown, and the job can keep running.

Technical note: with -h, disown doesn't remove the job from Bash's job table; it marks it so Bash won't send it SIGHUP.

What about setsid? It starts the command in a new session, separating it even further from the terminal context:

setsid ./long_task.sh > out.log 2>&1

Again, though, this is a “think about it beforehand” solution.

Wait—what does > out.log 2>&1 actually mean?

> out.log sends (redirects) the command's normal output (stdout) to out.log. 2>&1 tells the shell to send errors (stderr) to the same place. In other words: everything the command would have printed to the terminal—including errors—ends up in out.log.

command > out.log 2>&1
#          ↑          ↑
#       output      errors
#       to file     to the same file

Gotcha. With nohup and disown, there is no reattach: the process keeps running, but you can't jump back into its session the way you can with screen, tmux, or zellij. That's why they're a good fit for non-interactive jobs with output redirected to a file.


screen — the timeless classic

What it is. One of the classic terminal multiplexers. GNU Screen has been around since the 1980s and gives you persistent sessions you can detach from and reattach to. It's still very common, especially on older servers.

When to use it. You're connecting to a mixed bag of machines, maybe some old ones, where you don't want—or aren't allowed—to install anything else. Or you've been using Screen for twenty years and your fingers already know what to do.

Installation.

sudo apt install screen     # Debian/Ubuntu
sudo dnf install screen     # Fedora/RHEL

Essential commands. The command key—the prefix—is Ctrl-a.

screen -S work          # create a session named "work"

# ...inside the session...

# Ctrl-a d              → detach
#                         the session keeps running on the server

screen -ls              # list sessions
screen -r work          # reattach to the session
screen -x work          # shared attach

Inside the session:

  • Ctrl-a c → new window
  • Ctrl-a n / Ctrl-a p → next / previous window
  • Ctrl-a " → window list
  • Ctrl-a Esc → copy mode / scrollback
  • Ctrl-a d → detach

When Screen refuses to cooperate

This is where some of Screen's most useful commands come in.

SSH died, but the session still says Attached

Classic scenario: your SSH connection drops, you reconnect right away, and run:

screen -ls

and get something like:

12345.work    (Attached)

Screen still thinks the old connection is alive, so a normal:

screen -r work

may refuse to reattach the session.

Instead of waiting around, tell Screen:

screen -d -r work

The meaning is straightforward:

-d    detach from the old connection
-r    reattach here

Basically: detach it from wherever you think it's still connected, and give it to me here.

This is probably one of the most useful Screen commands to remember.

Detach a session from the outside

Sometimes you want to detach a session without—or without being able to—enter it first:

screen -S work -X detach

The session stays alive; it simply stops being attached to the previous terminal.

The session has completely lost its mind

Broken terminal, frozen program, input going nowhere—the session is beyond saving.

Sure, you could open another shell and run:

ps -ef

hunt down the right process and then use kill.

But when several similar processes are running, that isn't much fun—and killing the wrong one is surprisingly easy.

If you want to terminate the entire Screen session directly:

screen -S work -X quit

This terminates the Screen session from the outside.

This is the hammer: use it when you really want the Screen session gone. Programs still attached to its terminals will normally die with it; processes that have already detached or daemonized may keep running.

Before reaching for quit, if there's any chance the session is recoverable, try:

screen -S work -X detach
screen -d -r work

If it's still beyond saving:

screen -S work -X quit

Cleaning up dead sessions

After crashes, reboots, or ugly disconnects, screen -ls may show dead sessions or stale entries.

Clean them up with:

screen -wipe

It won't kill healthy sessions; it simply removes entries for sessions that no longer exist.

Screen emergency kit

# list sessions
screen -ls

# normal reattach
screen -r work

# session still says Attached:
# force detach + reattach
screen -d -r work

# detach it from the outside without terminating it
screen -S work -X detach

# unrecoverable session: terminate it
screen -S work -X quit

# clean up dead sessions
screen -wipe

If you use Screen regularly, these six commands are probably more useful than half of its available shortcuts.

Gotcha. The Ctrl-a prefix conflicts with Bash's “go to beginning of line” shortcut (use Ctrl-a a to pass it through). Mouse scrolling is awkward, and .screenrc is decidedly spartan compared with modern alternatives.

But Screen has one huge advantage: it's simple, robust, and when things go sideways, screen -d -r, -X quit, and -wipe will usually get you back in control without hunting down PIDs.


tmux — the modern de facto standard

What it is. One of the most common modern terminal multiplexers. It does everything Screen does, but adds much nicer window and pane management, excellent scripting, and—most importantly—a powerful configuration system through ~/.tmux.conf.

If you're going to learn one multiplexer, this is probably where I'd start.

Installation

On Debian/Ubuntu:

sudo apt update
sudo apt install tmux

On Fedora/RHEL:

sudo dnf install tmux

Make sure it's there:

tmux -V

Now create your first session:

tmux new -s dev

You're inside tmux.

The command key, known as the prefix, defaults to:

Ctrl-b

That means almost every tmux command starts by pressing Ctrl-b, releasing it, and then pressing the second key. For example, Ctrl-b d detaches from the session.

tmux ls
tmux attach -t dev

And we're already at the behavior we came here for: you can close SSH, come back later, and reattach to the exact same session.

Before learning shortcuts, let's make tmux nicer

tmux works perfectly well out of the box, but a few small tweaks make it much nicer to live in.

Your user configuration file is:

~/.tmux.conf

If it doesn't exist:

nano ~/.tmux.conf

Here's a good starter config:

# -----------------------------
# Mojalab starter .tmux.conf
# -----------------------------

# Use Ctrl-a as the prefix instead of Ctrl-b
set -g prefix C-a
unbind C-b
bind C-a send-prefix

# Mouse: select panes, resize, scroll
set -g mouse on

# Start window numbering at 1 instead of 0
set -g base-index 1

# Start pane numbering at 1 too
setw -g pane-base-index 1

# More scrollback
set -g history-limit 50000

# Open new windows in the current directory
bind c new-window -c "#{pane_current_path}"

# Split while keeping the current directory
bind '"' split-window -v -c "#{pane_current_path}"
bind % split-window -h -c "#{pane_current_path}"

# Reload the config without leaving tmux
bind r source-file ~/.tmux.conf \; display-message "tmux.conf reloaded"

Reload it:

tmux source-file ~/.tmux.conf

Or, once you're inside tmux, from now on you can simply use:

Ctrl-a r

What did we just change?

1. Ctrl-a instead of Ctrl-b

tmux uses Ctrl-b by default, but the prefix can be changed directly in the config.

We use:

set -g prefix C-a
unbind C-b
bind C-a send-prefix

So anyone coming from Screen immediately feels at home:

Ctrl-a d

detaches.

One thing to keep in mind: Ctrl-a is also Bash's shortcut for moving to the beginning of the line. If you need to send a real Ctrl-a to the program running inside tmux, press:

Ctrl-a Ctrl-a

2. Turn on the mouse

set -g mouse on

Sounds trivial, but it changes the experience quite a bit.

You can use the mouse to:

  • select a pane;
  • resize panes;
  • switch windows from the status bar;
  • use the scroll wheel for scrollback.

tmux supports all of this natively when the mouse option is enabled.

3. Start numbering at 1

By default, tmux starts with window 0.

We use:

set -g base-index 1
setw -g pane-base-index 1

Now windows and panes start at 1, which I personally find more natural.

4. Give ourselves more scrollback

set -g history-limit 50000

tmux keeps a history of the output in each pane. Raising the limit is handy when you're running builds, logs, or agents that produce a lot of output.

5. Keep new windows and splits in the current directory

This is one of those changes you notice immediately.

Without configuration, when you open a new window or pane, you may not land in the directory you were working in.

We use:

bind c new-window -c "#{pane_current_path}"
bind '"' split-window -v -c "#{pane_current_path}"
bind % split-window -h -c "#{pane_current_path}"

So if you're in:

/var/www/myproject

and open a new window or split, the new terminal starts there too. This pattern also appears in the official tmux recipes.

The shortcuts you actually need

With our config, the prefix is Ctrl-a.

Ctrl-a d        detach

Ctrl-a c        new window
Ctrl-a n        next window
Ctrl-a p        previous window

Ctrl-a %        side-by-side split
Ctrl-a "        top/bottom split

Ctrl-a arrows   move between panes

Ctrl-a z        zoom current pane
Ctrl-a [        copy mode / scrollback

Ctrl-a ?        show all key bindings

Ctrl-a r        reload ~/.tmux.conf

The % and " splits and ? help are standard tmux bindings.

Sessions: create, enter, leave, destroy

# new session
tmux new -s dev

# list sessions
tmux ls

# reattach
tmux attach -t dev

# shorter equivalent
tmux a -t dev

To detach from inside tmux:

Ctrl-a d

If a session is completely disposable:

tmux kill-session -t dev

Or, if you want to stop all of tmux, including every session:

tmux kill-server

That one is definitely the big red button.

What if the session is already attached?

tmux is a little friendlier than Screen here.

You can attach while simultaneously disconnecting the other clients from that session:

tmux attach -d -t dev

In other words:

-d    disconnect other clients
-t    select the session

It's the conceptual equivalent of:

screen -d -r work

The good stuff: panes

This is where tmux starts to feel very different from the classic Screen workflow.

You can have something like this inside a single window:

+----------------------+-------------------+
|                      |                   |
|   editor / agent     |     tail log      |
|                      |                   |
|                      +-------------------+
|                      |                   |
|                      |       shell       |
+----------------------+-------------------+

For example:

Ctrl-a %

splits the window vertically, giving you two side-by-side panes.

Then:

Ctrl-a "

splits the current pane horizontally.

And:

Ctrl-a arrows

moves you between panes.

Want to temporarily make one pane full-screen?

Ctrl-a z

Press it again to return to the previous layout.

A small .tmux.conf, not a religion

Online you'll find .tmux.conf files hundreds of lines long, plugin managers, themes, status bars showing CPU, RAM, Git, weather, and probably the phases of the moon.

You don't need to start there.

Our starter config does just a handful of useful things:

Ctrl-a
mouse
numbering from 1
more scrollback
keep the current directory
quick config reload

That's already enough to turn tmux from “Screen with different keys” into something much nicer to use every day.

Later, if you actually need it, you can go further: plugins, session persistence, automatic layouts, editor integrations, and much more.

But first, learn to be comfortable inside a tmux session.

Bonus: tmux-resurrect — what about a reboot?

We've seen that a tmux session happily survives a dropped SSH connection.

But what if the server goes down?

Normally, the answer is simple: goodbye session. A reboot terminates tmux and, of course, every process that was running inside it.

This is where tmux-resurrect, one of the most interesting plugins in the tmux ecosystem, comes in.

The idea is simple: Resurrect saves the structure of your tmux environment and lets you rebuild it later.

Among other things, it can remember:

  • sessions;
  • windows;
  • panes;
  • layouts;
  • working directories;
  • some running programs.

But here's the important part: it does not freeze processes in RAM and magically keep them alive through a reboot.

It saves enough information to rebuild the workspace and, for some supported programs, restart what was running.

Install it with TPM

The easiest way to manage tmux plugins is TPM — Tmux Plugin Manager.

First, clone it:

git clone https://github.com/tmux-plugins/tpm ~/.tmux/plugins/tpm

Then open:

nano ~/.tmux.conf

and add this at the bottom of the file:

# -----------------------------
# Plugins
# -----------------------------

# tmux-resurrect
set -g @plugin 'tmux-plugins/tpm'
set -g @plugin 'tmux-plugins/tmux-resurrect'

# Start TPM
run '~/.tmux/plugins/tpm/tpm'

Keep:

run '~/.tmux/plugins/tpm/tpm'

at the bottom of the plugin section.

Now reload the configuration:

tmux source-file ~/.tmux.conf

Then, from inside tmux, press:

Ctrl-a I

That's an uppercase I: TPM will install the plugins declared in .tmux.conf.

Remember, Ctrl-a is our custom prefix. With stock tmux it would be Ctrl-b.

Save the workspace

Let's say your dev session has three panes:

+----------------------+-------------------+
|                      |                   |
|   project            |    tail log       |
|                      |                   |
|                      +-------------------+
|                      |                   |
|                      |      shell        |
+----------------------+-------------------+

Save its state with:

Ctrl-a Ctrl-s

Resurrect saves the current state.

Keep working as usual.

Restore it

After a reboot, start tmux again:

tmux

and press:

Ctrl-a Ctrl-r

Resurrect will try to rebuild the saved workspace: sessions, windows, panes, layouts, and directories.

So the two commands worth remembering are:

Ctrl-a Ctrl-s    → SAVE

Ctrl-a Ctrl-r    → RESTORE

We can go one step further

Resurrect expects you to save the state yourself.

Another plugin from the same family, tmux-continuum, can save state automatically at regular intervals and make session restoration even smoother.

Add this to .tmux.conf:

set -g @plugin 'tmux-plugins/tmux-continuum'

Your plugin section now becomes:

# -----------------------------
# Plugins
# -----------------------------

set -g @plugin 'tmux-plugins/tpm'
set -g @plugin 'tmux-plugins/tmux-resurrect'
set -g @plugin 'tmux-plugins/tmux-continuum'

run '~/.tmux/plugins/tpm/tpm'

Reload:

tmux source-file ~/.tmux.conf

and install the new plugin:

Ctrl-a I

Continuum can save tmux state periodically, so you don't have to remember Ctrl-a Ctrl-s every time.

But don't confuse this with systemd

This is the important part.

tmux-resurrect and tmux-continuum are fantastic for rebuilding a workspace.

They are not a replacement for systemd.

If after a reboot we want to get back to:

dev session
├── editor
├── shell in /var/www/myproject
└── log window

Resurrect is exactly the right tool.

But if we have:

python worker.py

and that worker must always be running, must start automatically at boot, and must restart if it crashes, we shouldn't be relying on tmux.

That's a service.

And that's where we want something like:

systemd
supervisor
Docker restart policy

The difference is subtle but fundamental:

tmux-resurrect
      ↓
rebuilds our workspace

systemd / supervisor / Docker
      ↓
manages the service lifecycle

Resurrect is for us coming back to work.

A service manager is for the process that needs to keep working without us.


zellij — the newcomer that actually helps you out

What it is. Zellij is a modern terminal multiplexer written in Rust, but its philosophy is quite different from tmux.

With tmux, you install an incredibly powerful tool and then gradually build your environment around it: .tmux.conf, shortcuts, plugins, TPM, Resurrect...

Zellij takes a different approach: it tries to be pleasant to use thirty seconds after installation.

You jump in and immediately get panes, tabs, session management, layouts, floating panes, and—most importantly—a bar at the bottom of the screen that keeps reminding you which keys do what.

In other words, instead of expecting you to learn the multiplexer first, Zellij tries to teach you while you use it.

Installation

Zellij probably won't already be sitting on your server, so you'll most likely need to install it.

If you have Rust and Cargo:

cargo install --locked zellij

Check it:

zellij --version

Then just start it:

zellij

Or, better yet, give the session a name right away:

zellij -s dev

And you're in.

You notice the difference immediately

The interesting bit is what you see at the bottom of the screen.

Zellij works through different modes and shows the available shortcuts right in the interface.

Conceptually, something like:

+----------------------------------------------------+
|                                                    |
|                     shell                          |
|                                                    |
|                                                    |
+----------------------------------------------------+
| Ctrl-p PANE | Ctrl-t TAB | Ctrl-o SESSION | ...   |
+----------------------------------------------------+

So you don't need to memorize twenty key combinations before doing anything useful.

Want to work with panes?

Ctrl-p

That puts you in Pane mode, and Zellij shows you what you can do next.

You can create a pane, move between panes, resize them, or close them.

For tabs:

Ctrl-t

For session operations:

Ctrl-o

This is probably the most obvious difference from Screen and tmux: Zellij works hard to be discoverable.

Let's build a real workspace

Say we're working on a project and want:

  • our editor or agent on the left;
  • logs at the top right;
  • a shell at the bottom right.

Something like:

+----------------------------------------------------+
| TAB: dev                                           |
+-------------------------------+--------------------+
|                               |                    |
|                               |  tail -f app.log   |
|       editor / agent          |                    |
|                               +--------------------+
|                               |                    |
|                               |      shell         |
+-------------------------------+--------------------+
| Ctrl-p PANE | Ctrl-t TAB | Ctrl-o SESSION | ...   |
+----------------------------------------------------+

This is exactly the kind of setup where a multiplexer starts making a lot more sense than a merely persistent shell.

Floating panes

Then Zellij pulls out one of its nicest tricks: floating panes.

Instead of carving up the layout yet again, you can open a temporary terminal on top of what you're doing.

Conceptually:

+----------------------------------------------------+
|                                                    |
|          editor / agent          log               |
|                                                    |
|        +------------------------------+            |
|        |                              |            |
|        |       floating shell         |            |
|        |                              |            |
|        +------------------------------+            |
|                                                    |
+----------------------------------------------------+

They're perfect for thirty-second jobs where you don't want to wreck your layout: check a process, run git status, fire off a command, or quickly inspect something.

And it's a good example of Zellij's philosophy: a lot of conveniences that need configuration elsewhere are simply part of the normal experience here.

Sessions: detach and come back

Of course, we can do the thing that brought us here in the first place: leave a session alive when we disconnect from SSH.

List available sessions with:

zellij list-sessions

and get back into ours with:

zellij attach dev

From inside Zellij, enter Session mode with:

Ctrl-o

and detach.

Keep the distinction clear:

detach → you leave, but the session stays alive.

quit → you terminate Zellij and therefore the session.

If something inside is still chewing through work and you want to find it there later, you want detach, not quit.

The Session Manager

Zellij also comes with a built-in session manager.

With the default keybindings, open it with:

Ctrl-o w

From there you can view and switch sessions, create a new one, rename one, disconnect other clients, and generally manage sessions without having to remember names and shell commands.

And there's another neat surprise: modern Zellij versions can retain metadata for exited sessions and resurrect their context, rebuilding layouts, tabs, panes, and the commands associated with them.

That does not mean the old processes somehow survived a reboot. Just like tmux-resurrect, the workspace is reconstructed and commands may be relaunched. The old process and its runtime memory are gone.

It's another small clue to Zellij's philosophy: it doesn't want to be just an invisible process you control through shell commands; it wants to be an actual interactive workspace.

What if we build the workspace in advance?

This is where we get to one of Zellij's most interesting features: layouts.

We can describe how our environment should look and ask Zellij to build it for us.

Let's create a layout for our project:

mkdir -p ~/.config/zellij/layouts
nano ~/.config/zellij/layouts/mojalab-dev.kdl

A first layout could look like this:

layout {
    tab name="dev" {
        pane split_direction="vertical" {
            pane size="65%"
            pane {
                pane command="tail" {
                    args "-f" "app.log"
                }
                pane
            }
        }
    }
}

The idea is simple:

TAB dev
│
├── 65% → main pane
│
└── 35%
    ├── tail -f app.log
    └── shell

Now we can start directly with:

zellij --layout mojalab-dev

and Zellij sets up the workbench for us.

That's an interesting step beyond simply “reopening three terminals”: we're describing our workspace as configuration.

We can keep different layouts:

mojalab-dev.kdl
backend.kdl
monitoring.kdl
production-debug.kdl

and launch whichever environment we need.

Zellij has a config file too

Of course we can customize it.

The main file is:

~/.config/zellij/config.kdl

But here's an important difference from what we just did with tmux:

we don't need to start by editing it.

We can happily use Zellij with its defaults, learn how it thinks, and only then change the things that actually bother us.

We can also generate a starter configuration:

mkdir -p ~/.config/zellij
zellij setup --dump-config > ~/.config/zellij/config.kdl

Now all the available options are in front of us and we can tweak them at our leisure.

It's almost the opposite of our .tmux.conf approach: instead of immediately building our ideal tmux, with Zellij we can start from the defaults and only remove or change what we don't like.

So is Zellij better than tmux?

No.

And that's probably the wrong question.

tmux has years of maturity behind it, a huge ecosystem, nearly limitless configuration, excellent scripting, and an enormous amount of documentation.

You can turn it into exactly the tool you want.

Zellij starts from a different idea: maybe you shouldn't have to transform the tool before it's comfortable to use.

If you know tmux by heart and have spent years perfecting your .tmux.conf, switching may make absolutely no sense.

But if you're installing a terminal multiplexer for the first time today, Zellij is genuinely interesting because panes, tabs, sessions, and layouts start making sense within minutes.


At a glance

Tool What persists Interactive reattach Windows / panes Learning curve Usually preinstalled Best for
nohup Single process No No Very low Yes One long-running, fire-and-forget command
screen Session Yes Yes (basic) Medium Often Older servers, “it's already there”
tmux Session Yes Yes (excellent) Medium Sometimes Daily work, scripting, the modern standard
zellij Session Yes Yes (modern) Low No Get productive quickly, minimal config

So which one should I use?

  • I just need to launch a process and check its output later → nohup, with output redirected to a file. Simple and normally already available.
  • I want a persistent remote workspace and only want to learn one tool → tmux. It's everywhere in documentation, dotfiles, and sysadmin workflows.
  • I'm on an old machine and don't want to install anything → screen, if it's already there.
  • I'm starting from scratch and want to be productive immediately without tinkering first → zellij.

In our case—a VPS hosting development harnesses and processes that need to survive hours of work and unstable connections—the winning combination is tmux for working sessions (detach, close the laptop, come back, everything is still there) plus nohup for fire-and-forget batch jobs that don't need interaction.

Two tools, two different jobs, zero processes murdered by a dropped connection.

🔗 Related: that €5 VPS—and how I watch my coding agents run on it straight from a browser—has a story of its own: My coding-agent buddies live on a €5 VPS.

Four tools, four personalities

At this point we can summarize the entire article in a much less scientific—but perhaps more useful—way:

Screen is the good old reliable Swiss Army knife you find in the drawer.

tmux is the workshop you can equip exactly the way you want.

Zellij is the modern workshop where the tools are already hanging in the right places when you walk in.

And nohup is the guy we toss the hammer to on our way out: “Keep going, I'm outta here.” 😂

Oddly enough, that's also a pretty decent way to decide which one to use.

What if it needs to survive a reboot too?

We've already touched on this in the tmux section, but it's worth making the distinction crystal clear.

nohup, screen, tmux, and zellij protect our work from the end of an SSH connection, but a server reboot is a different story: when the machine shuts down, the running processes are terminated.

tmux-resurrect and Zellij's session resurrection can rebuild a workspace; they do not magically make processes survive a reboot.

If you had a shell open in /var/www/myproject, they can recreate that context. If a particular command was running, in some cases it can be launched again. But the old process—with its memory and runtime state—is gone.

Think of it as three different levels:

SSH connection drops
    ↓
nohup / screen / tmux / zellij
    ↓
the work keeps running

Server reboots
    ↓
tmux + tmux-resurrect / Zellij session resurrection
    ↓
I can rebuild my workspace

The process MUST always be available
and restart automatically if it dies
    ↓
systemd / supervisor / container restart policy

That last boundary is the important one.

If we're doing development and simply want our workspace back quickly after a reboot, tmux-resurrect or Zellij's built-in session resurrection are exactly the kind of convenience we want.

But if the process is an application, worker, daemon, or anything else that must start at boot and restart automatically after a crash, we should not rely on a terminal multiplexer.

That's systemd, a process supervisor, or—if we're working with containers—a Docker restart policy territory.

In short:

SSH session dies → keep the process or terminal alive

server restarts → rebuild the workspace

service must always be there → use a real service manager

They look like similar problems, but they're three different requirements.

Conclusion

SIGHUP doesn't have to be scary anymore. Whether you choose the minimalism of nohup, the ubiquity of screen, the power of tmux, or the modern approach of zellij, the principle is the same: your work lives on the server, not in the fragile SSH session sitting on top of it.

Pick the tool for the job, not because it's fashionable—and the next time you close the laptop, your backup (or your agent) will keep working as if nothing happened.