Editing remote files over SSH by pretending to use rmate

Today, many developers edit files on a remote computer by using VSCode's remote editing functionality, or by opening an in-terminal editor like Nano or Vim. However, these are not your only options. There's another elegant and easy-to-use alternative, which was invented by TextMate over 10 years ago.

Easy Usage

I have my remote VPS configured such that I can edit files on it simply by SSHing to it and issuing sl <filepath>. This command returns instantly, placing me back at the shell, but not before opening the specified file in Sublime Text on my local computer. I can edit the file in Sublime, and when I press Save, the file changes are magically written back to the file on my server.

If the file requires root access to edit, I can still do something similar. I can run sudoedit <filepath>, which will again open and edit the file in Sublime on my computer, but it will wait for me to close the file locally before the command exits and results are written to the remote server.

These options are super easy to use for editing files if I'm already at a console on the remote machine. I can initiate the editing session on the remote computer, but then I can do my editing on my computer. This means that I have the editing experience that I'm used to, with zero latency and my Sublime configuration.

How

This is made possible because of a tool developed for TextMate called rmate. This was a companion to the mate command, which was the CLI tool for opening files in TextMate (on the same computer). You could instead run rmate on a remote computer and it would work as described above, opening the file in your local instance of TextMate for local editing.

https://macromates.com/blog/2011/mate-and-rmate/ mate and rmate, from the TextMate blog

Today, I don't use rmate on the server and I don't use TextMate on my laptop, but I can still take advantage of this workflow.

Note on terminology:
I'm going to use "server" and "server-side" to refer to my VPS, the machine I'm connecting to over SSH. This is technically the "rmate client," since it initiates the rmate connection. But I'll avoid this confusing terminology.

On the server, I use Harald Lapp's re-implementation of the rmate script in pure bash. (The original version was written in Ruby, which I don't have globally installed on my VPS.) This project's README is also an excellent reference—it has links and instructions which I drew from when writing this post.

https://github.com/aurora/rmate

On my computer, I use the Sublime Text plugin RemoteSubl, which implements the local side of the rmate connection. If you don't use Sublime Text, there are plugins for other editors like VSCode and Pulsar (the editor formerly known as Atom).

https://github.com/randy3k/RemoteSubl

I find it amusing that I’m not using the original rmate technology on the client or the server; yet, both of them think that the other one is. In this way, even though TextMate is not as relevant as it once was, its name and innovations live on.

Configuration

If you're a CLI pro, this configuration will be trivial. However, if you're a CLI pro, you probably have a method for editing remote files that you're happy with. So I'm going to walk through this slowly so that you can follow along, provided you're already familiar with SSH.

This configuration is in-depth so that, at the end of it, you'll have the best remote editing experience possible. There are simpler instructions in the repositories for the tools linked above, but I've found a little bit more configuration is required to remove the pain points and make it so that you don't have to fall back to vi.

Remote configuration

The first step is installing the rmate bash script on your remote server. Since this is a simple script, we just need to download it, mark it as executable, and make sure it is on the path. I personally place it in ~/bin and then add that directory to my path, to avoid globally installing with sudo.

mkdir -p ~/bin
curl -Lo ~/bin/rmate https://raw.githubusercontent.com/aurora/rmate/master/rmate
chmod +x ~/bin/rmate

Then we need a few simple changes to the remote .bashrc (or equivalent if you're using a different shell):

# Set PATH to include ~/bin
export PATH="$HOME/bin:$PATH"

# Set $EDITOR so other tools know what editor to use
# This should be an absolute path, not `rmate` or `~/bin/rmate`
export EDITOR="$HOME/bin/rmate -w"

# Create an alias for our use
alias sl="rmate"

The first change adds ~/bin to the PATH, as we discussed.

The second change sets $EDITOR. This is used by tools like git commit and sudoedit. sudoedit in particular is tricky to configure since it looks up the editor without your modified PATH or aliases, so it should be an absolute path to the editor executable. The -w at the end of the EDITOR tells rmate to wait until the file has been closed on your remote computer—this is the behavior that most tools expect from $EDITOR.

sudoedit is a helper provided by sudo  for editing files which require root access, without running your editor as the root user.

The third change is a simple alias so that you don't have to type rmate if you don't want to. I use sl since that's the alias I have on my local computer to open Sublime Text, and it makes for seamless transitions between the local and remote CLI.

Local Configuration

There are also a couple of things to set up locally in order for this to work.

First, you need an editor plugin, as discussed above. Check the settings for your plugin, you may need to turn it on or make sure that it's using the default rmate port (52698). However, subsequent times that you open your editor, it will start automatically and will not require further action, which is very convenient.

Second, you need to configure SSH to forward the rmate port when you connect to the remote computer. This can be done by passing an option at the command line, but this is cumbersome if you, like me, are using this as your default strategy for editing remote files.

Instead, I highly recommend creating a rule in your SSH config. On Mac, my SSH config lives in ~/.ssh/config, and the rule that I've added looks like:

# rmate forwarding
RemoteForward 52698 localhost:52698

This means that when you open an ssh connection to a remote computer, it automatically creates a connection between port 52698 on the remote and local machines which rmate can use for communication.

It's overkill to explain in this post, but you can of course configure this forwarding rule on a per-host basis, which is what I do in practice.

Conclusion

There are a couple of drawbacks to this.

However, these are all very minor and understandable issues.

In my experience, this workflow is much more convenient than opening the file in Vim or Nano on the remote machine, and it's a lot simpler than mounting the remote filesystem or installing VSCode remote editing tools to edit a config file. Not to mention that these solutions rarely play well with sudo.rmate is a really impressive piece of engineering from the TextMate team, and I hope that I can continue using it for a long time.

Background from Hero Patterns; CC BY 4.0