SSH Configuration
It is recommended to utilize ssh-config to configure SSH.
This offers an easy and simple way to connect to servers via SSH without the need to write long SSH commands.
The configs can also be checked into a VCS and synchronized via a private git repo across multiple devices.
Furthermore, those configs are utilized by other applications such as scp
and rsync
.
Warning
Remember to never commit key material.
Put the path to the keys in a .gitignore
file.
Use other means to transfer the keys across multiple devices (i.e. by transferring them with scp
/rsync
, using a password manager capable of storing files securely, or using a physical storage device like a USB stick).
In order to start using it, one has to create a file called config
in ~/.ssh
.
It is sensible to cluster host definitions into their own sub config (i.e. in ~/.ssh/config.d/...
) and load those from within ~/.ssh/config
.
This allows to compartmentalize domain-specific configurations.
~/.ssh/config
:
# vi:syn=sshconfig
# Include all configs from sub dir
Include config.d/*.conf
# Suppress errors when connecting to a port on the local host
# Useful when one is forwarding to different machines from the same port
Match host localhost
StrictHostKeyChecking no
UserKnownHostsFile /dev/null
Documentation about the config format is available at ssh.com.
It is advisable to create domain-specific SSH key pairs and use those instead of password login, as this compartmentalizes the keys and don’t implicate unrelated domains in the case of a loss/compromise of the private key.
It also makes it easier to deprecate key pairs by simply deleting the private key.
The example configs assume the keys to be stored in ~/.ssh/keys
.
In order to create and distribute such key pairs, ssh.com provides a good guide.
In short, the procedure could look something like this (note that the variables enclosed in <>
will have to be changed):
# Make sure the directory already exists
[[ -d ~/.ssh/keys ]] || mkdir ~/.ssh/keys
# Create a key pair
# optionally set a password to encrypt the private key
ssh-keygen -f ~/.ssh/keys/<key_name> -t ed25519
# Copy the corresponding public key to the server's ~/.ssh/authorized_keys
ssh-copy-id -i ~/.ssh/keys/<key_name> <user>@<host>
# Test to verify
ssh -i ~/.ssh/keys/<key_name> <user>@<host>
Note
If the ssh-config already specifies the host (including the key pair), then the ssh-copy-id
command can be shortened to ssh-copy-id <host_abbr>
.
Tips
Maintain via Git
It can be very useful to maintain and share the configurations via Git.
For this, initialize the ~/.ssh
folder as a git repository, put the path to the keys (i.e. keys
) into a .gitignore
and add and commit it.
Then add the configurations as explained in this page (domain-specific configuration files etc.) and upload them to the remote (preferably in a private repository).
Once on a different machine, just clone the repository into ~/.ssh
.
Warning
Remember to never commit key material!
Put the path to the keys in a .gitignore
file.
Use other means to transfer the keys across multiple devices (i.e. by transferring them with scp
/rsync
or using a password manager capable of storing files securely).
If there are changes to the configurations in the future, just commit and push them, then pull to all additional affected client devices.
Make Use of Abbreviations
Using the Hostname
config, one can fix the actual hostname/IP behind a Host
directive for easy access: Instead of ssh dgx.cloudlab.zhaw.ch
, just use ssh dgx
instead.
Take advantage of SFTP/SSHFS
Certain file managers support adding network resources with a connection string.
For example, Nautilus (Linux, default file manager for the GNOME desktop and therefore available in all current Ubuntu desktop installations) allows SFTP shares to be accessed with a URI like: sftp://dgx
.
This makes browsing image data on remote file systems easier.
For Mac users, they have to install OSX Fuse and SSHFS in order to make use of this feature.
SOCKS5 Proxy
Using the DynamicForward
capability, one can create a SOCKS5 proxy to forward traffic to the remote and send off the packets from there.
This allows for connecting to the internet from the remote or access applications local to the remote only (i.e. a Jupyter-Lab or Label-Studio instance) without having to specify a local port forwarding every time.
To do this, it is recommended to specify the client side SOCKS5 proxy port on the commandline (using -D <port>
) instead of the ssh-config, to prevent port allocation problems when opening multiple SSH sessions at the same time.
Then the user’s browser can be configured to use the SOCKS5 proxy to connect to the internet.
It is recommended to use a selective proxy plugin for the browser (i.e. FoxyProxy) which can enable the proxy connection based on URL patterns, so only a select number of requests get channelled through the proxy.
Show Divergent Options in Config
To see how the configurations impact a specific host configuration, it is helpful to compare it to the defaults with diff
:
# Showing the configs for a specific host
diff -y --suppress-common-lines <(ssh -Go IdentityFile=~/.ssh/id_rsa none) <(ssh -G idgx)
# user embe | user re
# hostname dgx.cloudlab.zhaw.ch | hostname none
# identityfile ~/.ssh/keys/embe | identityfile ~/.ssh/id_rsa
# proxyjump apu <
# Comparing the configs of two hosts
diff -y --suppress-common-lines <(ssh -G dgx) <(ssh -G dgxa100)
# hostname dgx.cloudlab.zhaw.ch | hostname dgx-a100.cloudlab.zhaw.ch
# Set functions in the shell for easier usability
function sshconfig() {
first="$1"
second="$2"
arg=""
if [ $# -eq 1 ]; then
second="none"
arg="-o IdentityFile=~/.ssh/id_rsa"
fi
diff -y --suppress-common-lines <(ssh -G "$first") <(ssh -G $arg "$second")
}
# Can be used for one or two hosts:
sshconfig idgx
sshconfig dgx dgxa100
Example config
Variable parts enclosed in <>
Important
These configs assumes that the public key(s) have already been saved into the servers’ ~/.ssh/authorized_keys
, as explained here
# vi:syn=sshconfig
# All APU servers
# Accessible from the Internet
# Cannot be used as a jump proxy for intranet hosts anymore
Match host apu,apu2
User ubuntu
IdentityFile ~/.ssh/keys/<shortname>
Host apu
Hostname <ip>
Host apu2
Hostname <ip>
# i-prefix indicates proxy jump from internet for work from home access
Match host dublin,dgx,idgx,dgx1,idgx1,dgx2,idgx2,dgx3,idgx3,dgxa100,idgxa100
User <shortname>
IdentityFile ~/.ssh/keys/<shortname>
# Accessible only via intranet
Host dublin
Hostname dublin.zhaw.ch
# All DGX servers (accessible only via intranet)
Host dgx
Hostname dgx.cloudlab.zhaw.ch
Host dgx2
Hostname dgx2.cloudlab.zhaw.ch
Host dgx3
Hostname dgx3.cloudlab.zhaw.ch
Host dgxa100
Hostname dgx-a100.cloudlab.zhaw.ch
# vi:syn=sshconfig
Host github.com
User <username>
IdentityFile ~/.ssh/keys/github
# Github's servers don't all have the same host keys
StrictHostKeyChecking no
UserKnownHostsFile /dev/null
# For git remotes of the staff account
# When cloning repositories with the staff account, use this host name
Host <shortname>.github.zhaw.ch
Hostname github.zhaw.ch
User <shortname>
IdentityFile ~/.ssh/keys/<shortname>
# For git remotes of the student account
# When cloning repositories with the student account, use this host name
Host <stud_shortname>.github.zhaw.ch
Hostname github.zhaw.ch
User <stud_shortname>
IdentityFile ~/.ssh/keys/<stud_shortname>