Benjamin Sago / ogham / cairnrefinery / etc…

Technical notes Change the background colour in iTerm2 when accessing remote hosts

Something I find absolutely essential when dealing with remote servers is some way to automatically set the background colour of my terminal when SSHing. This lets me easily tell remote sessions apart from local ones, and stops me from accidentally running commands on the wrong machine. On the Internet, you’ll find no end of stories where machines or even entire websites were taken offline because of mistakes like this.

I have my own colour scheme, and I expect it to be very similar to others’:

Local terminals have a normal dark grey background.
Terminals running SSH into another remote server have their background tinted blue.
When I’m SSHing into a server handling live production traffic, the background is tinted red, reminding me to be very careful!

If you use a dedicated SSH program like PuTTY or SecureCRT, you can define SSH sessions that set the background colour and destination host for each machine you need to connect to. But if you just use the command-line ssh client running in a terminal, there needs to be a way to change the background colour after the terminal has already opened.

There are two parts necessary for this to work:

  1. The terminal needs to know which colours to use.
  2. The terminal needs to know when the processes it’s spawned have switched from running commands on the local machine, to running commands on a remote one, as well as when it’s switched back.

Because I’m fortunate enough to be in control of the servers I connect to, I use iTerm2’s Automatic Profile Switching feature for this, automatically switching to different profiles based on the hostname reported by my shell prompt.

If you can’t modify the servers themselves for whatever reason, check out the alternate approaches in this blog post.

Defining iTerm2 profiles

In iTerm2, a profile is a collection of settings that you can easily switch between. These settings include the background colour, foreground colours, and the font, as well as things like which bytes to send for keypresses and fine-grained settings for how the terminal behaves. Profiles can be edited by going to Preferences → Profiles.

In this case, we want to create one profile for each kind of remote server we want to change the background for. The original “Default” profile should be kept the same, so you can either create a new profile or duplicate an existing one.

There are two settings we need to change:

  1. The background colour, which can be set to whatever you want, in the Colors tab. You can also change other settings, such as the foreground colours, or the colour of the current row.
  2. In the Advanced tab, scroll down to Automatic Profile Switching, and add the hostname of every machine that should use this profile to the list.

iTerm2 Badges

Another thing I like to do set in my iTerm2 profiles is the Badge, which specifies the parameters of a big piece of text in the corner of the window:

Not only does this make it easier to see when I’m SSHed onto a remote machine instead of using my local one, it’s also easier to tell which machine I’m on, as it’s right there in big text.

Shell prompt hostname reporting

The second part of setting this up involves communicating to iTerm2 that the machine running commands in the terminal has changed.

This is done by sending a terminal escape code containing the hostname of the machine. iTerm2 has several proprietary escape codes, and one of them, RemoteHost, is what we need.

You can send this escape code at any time, as it’s just bytes. For example, you could use echo:

echo -e "\x1b]1337;RemoteHost=some-remote-server\x7"

Here, we send the code saying we are on a machine with the hostname some-remote-server. If you have a profile set up to respond to that hostname, iTerm2 should automatically switch to it once it receives this code. The -e flag is necessary for echo, so it handles the escaped characters in the string correctly.

For automatic switching, though, we need some way to automatically send this escape string. A good place to do this is to put it in the shell prompt, as this gets run on the remote machine after connecting via SSH and on the local machine after disconnecting, meaning iTerm2 gets notified as soon as the machine changes.

The simplest way to do this is to use iTerm2 shell integration. If you already have this set up, then your prompt should already contain the revelant escape code. If you don’t want to set up shell integration, just make sure that when your shell prints its prompt, the escape code containing the hostname is in there somewhere.

You will need to change the prompt on both your local and remote machines, so iTerm2 knows when you have stopped SSHing, and can change the profile back to the default one.