Neovim over ssh tunnel
Every now and then I find myself wanting to work with neovim remotely. Sure, I
can ssh
, and then start nvim
and have it work that way. But there is some
form of convenience of being able to just use the builtin server functionality.
On client
ssh -L localhost:4567:localhost:6666 server-addr \
"SOME_VAR=value nvim --headless --listen localhost:6666"
This will launch neovim on the server, and have it listen locally on port
6666
,
while ssh
opens port 4567
which will forward traffic to port 6666
on the
server (neovim that is).
On the client you can now do a remote connection to neovim using
nvim --remote-ui --server localhost:4567
It’s worth pointing out that you can have ssh simply just forwarding a port,
wihtout actually launching any program on the server. To do this, pass the
-N
flag (Do not open shell/execute remote command), and optionally
-f
(run in background and redirect output to /dev/null
).
ssh -fNL localhost:<local_port>:localhost:<server_port> <server-addr>
The downside to this is that you don’t know the process id of ssh
, so you can
have a hard time terminating it (need to use ps
or similar). Instead you can
set up control sockets
A more advanced setup using control sockets
To be able to control a connection that is running in the background you can
pass runtime flags to set things up, but this is pretty tedious. So to make this
a bit more convenient you can store a host specfic configuration for ssh
. To
do this create a directory for control paths, and a config file
mkdir -pm 700 ~/.ssh/controlmasters
Next, edit the file ~/.ssh/config
to contain the following
Host <nickname>
HostName <actual server address>
ControlPath ~/.ssh/controlmasters/%r@%h:%p
ControlMaster auto
ControlPersist 10m
If you created ~/.ssh/config
, make sure that you set the permissions to
0600
. ssh
is pretty picky about this.
Now you can re-establish the ssh tunnel using
ssh -fNL localhost:4567:localhost:6666 <nickname> \
"SOME_VAR=value nvim --headless --listen localhost:6666"
When you run the above command, you should get a file called
~/.ssh/controlmasters/<user>@<hostname>:<port>
This allows you to check status and terminate connections using commands like
ssh -O check <nickname>
ssh -O exit <nickname>
check
will provide you with process id and status, exit
will ask the control
master to terminate. You can read the documentation about how more
details.
This process set up here is called multiplexing, and it’s described better in the OpenSSH cookbook
Finally, it’s worth pointing out that this feature is only triggered if your using the configured nickname.
Another benefit of this configuration is that if you’re doing multiple connections to the same target, then the subsequent connections are much faster to set up, as you simply re-use the existing connection.