Mathieu De Coster

Quality of Life with SSH

11 March 2025

As part of my day job, I've been working more than usually with SSH, working with remote connections to robots and creating SSH tunnels to handle (semi-)complex networking set-ups. I kept forgetting certain parts of my set-up every time I had to do this again, so I took some notes and decided to share them here.

This post contains information on:

The set-up

The robot set-up I most recently worked on has a router (we'll give it the hostname router) and a mini-PC connected to the router via ethernet (we'll give it the hostname brain, because it's where the robot application code is run.) We connect to router from our personal workstation over Wi-Fi. Let's assume everything is running Ubuntu 24.

diagram of setup

Let's say router is at the address 10.10.120.1 and brain at 10.10.42.57 (on router's network). We have an account user on both computers.

SSH configuration file

The first step is to set up an SSH configuration file, typically stored in ~/.ssh/config. Let's set it up so that we can simply use the command ssh router instead of ssh user@10.10.120.1.

$ cat ~/.ssh/config
Host router
	Hostname 10.10.120.1
	User user

Host brain
	Hostname 10.42.0.57
	User user
	ProxyJump router

Note that brain uses a ProxyJump via router, so that we can simply use ssh brain instead of having to go through the router manually.

Public-private key authentication

Right now, we always need to manually enter user's password (and twice if we SSH into brain). Let's use keys to authenticate instead. To generate a new key pair, we can use:

$ ssh-keygen -t ed25519

We don't want to store our private key in plain text, so enter a passphrase. We also don't want to have to enter this passphrase every time we use our key, so let's add it to the SSH agent:

$ ssh-add ~/.ssh/id_ed25519

The remote server must know about our public key. We shouldn't just copy it over there, but use these commands to do this securely:

$ ssh-copy-id user@router
$ ssh-copy-id user@brain

The keys will now be on the remote computers under ~/.ssh/authorized_keys.

Now we can enter ssh brain or ssh router and not have to enter any passphrases!

SSH tunneling

Let's say brain is running a service on some port, that we wish to connect to from our workstation directly. We can use an SSH tunnel for that. For example, we want to use ports 7000 and 7001 as if the service was running on our workstation.

$ ssh -N -L localhost:7000:brain:7000 -L localhost:7001:brain:7001 router

-N suppresses the output, and we add -L for every port. This command should "hang".

Now we can go to localhost:7000 (resp. localhost:7001) to access this service!

I recommend turning this into an alias, e.g.,

$ alias tun_brain="ssh -N -L localhost:7000:brain:7000 -L localhost:7001:brain:7001 router"

so we can just use

$ tun_brain

instead of remembering the tunnel command.

X forwarding

Let's say we want to run a graphical application on brain or router as if it were running on our own workstation. We can use X forwarding for that (assuming we're using X11 :).)

$ cat ~/.ssh/config
Host router
	Hostname 10.10.120.1
	User user
	ForwardX11 yes

Host brain
	Hostname 10.42.0.57
	User user
	ProxyJump router
	ForwardX11 yes

Now we can run, e.g., nautilus and get a graphical file browser on router or brain. Not the most useful application, but useful for other applications such as gnome-control-center to change settings.

Using git over SSH, over SSH

Finally, we want to be able to use git on the remote servers. But, remember how we shared an account with other people? We can use the SSH agent to securely transfer our keys on demand.

All we have to do is change our config again.

$ cat ~/.ssh/config
Host router
	Hostname 10.10.120.1
	User user
	ForwardX11 yes
	ForwardAgent yes

Host brain
	Hostname 10.42.0.57
	User user
	ProxyJump router
	ForwardAgent yes

Now we can use git on the remote computers without needing to store our private keys.