Forwarding Discord's RPC socket over SSH

Cascavel -

I’m doing 99% of my coding in a “big” machine instead of my laptop. I do that by SSH’ing into it, hopefully into a tmux session, and coding on Neovim.

Neovim has a neat plugin that shows what’re doing as a Discord Rich Presence thing… but, Discord is running on my laptop, so… how can I make this work?

Investigating

After digging some source and testing a little, I found out that Discord’s bind itself to a socket in one of the following places:

  • /var/run/discord-ipc-0 on iOS;
  • $TMPDIR/discord-ipc-0 on macOS;
  • [[\\.\pipe\]]discord-ipc-0 on Windows, whatever the hell that means;
  • $XDG_RUNTIME_DIR/discord-ipc-0 on Linux.

So, my idea was: what if I do a remote port forwarding of that socket?

I tested it with:

ssh -v -R /var/run/discord-ipc-0:$TMPDIR/discord-ipc-0 myhost

And it worked!

But I don’t want to type all that every time… so… let’s make it better!

Client config

First, we need to add some settings to our ~/.ssh/config file: mainly, RemoteForward and a Match host instruction.

Here’s the relevant parts from mine:

Match host myhost exec "ln -sf $TMPDIR/discord-ipc-0 /tmp/discord-ipc-0"

Host myhost
  RemoteForward /run/user/1000/discord-ipc-0 /tmp/discord-ipc-0

Explanation

We need the Match host with the exec linking the file because, as it seems, we can’t use environment variables in the RemoteForward step.

Then, we need the RemoteForward, target being the server’s $XDG_RUNTIME_DIR/discord-ipc-0 file and source being our linked /tmp/discord-ipc-0.

And that’s pretty much it here.

Server config

On our server, we need to enable StreamLocalBindUnlink, otherwise, the first time you SSH into it it’ll work, but the next times it won’t, as the socket would be dangling from the previous one.

StreamLocalBindUnlink tells SSH to remove the socket if the exists, before trying to bind it again.

You can enable it with something like:

echo "StreamLocalBindUnlink yes" | sudo tee -a /etc/ssh/sshd_config.d/discord.conf
sudo service sshd restart

And that’s it!

Results

You should now be able to SSH into your host and test the connection with socat:

ssh -v myhost
socat -u OPEN:/dev/null UNIX-CONNECT:/run/user/1000/discord-ipc-0

You shouldn’t get any errors, and SSH will print out some logs as we’re connecting with -v (verbose - not required from now on).

Then, running:

nvim presence-over-ssh

With the presence plugin install should set your rich presence status to “Playing a game: Neovim”:

Example Rich Presence Status coming from neovim over SSH.

Example Rich Presence Status coming from neovim over SSH.

And that’s pretty much it!

You should be able to disconnect/reconnect and always get a valid socket, so it should “just work”.

neovim discord ssh
Avatar photo Carlos is a Site Reliability Engineer who enjoys working on OpenSource. Twitter Tweet