Exploring the Future of Internet Streaming Platforms

Internet streaming platforms are digital services that allow users to stream audio and video content from the internet. These services usually offer a wide range of content, from movies to television…

Smartphone

独家优惠奖金 100% 高达 1 BTC + 180 免费旋转




Managing multiple SSH environments

Daily, I end up having to SSH between VMs in the cloud, my desk workstation in the office, my home server, and things I cannot remember right now. Most of the time just doing a ssh user@<desired host>doesn't cut it. If it did, this blog would end right here.

To give some context, I work on a few different projects. A project may have some presence in the cloud and some presence in the data centers that the company operates. Most of these servers are running in-progress development environments with new features being tested out. And in the cloud, these environments might be spread across cloud-regions for various reasons.

Apart from my desk workstation and my home server, for security reasons, the hosts I need to connect to are walled off behind a bastion host(s), with generally a different set of bastions per environment and or project. Hence to actually connect to the hosts of interest through the bastion, I need to use a feature of SSH called ProxyCommandor more recently ProxyForwardwhich allows SSH to use the bastion as a proxy host and connect to the server of interest, while looking like a regular SSH connection to the user.

Lets start with an example with the following setting:

All this on the command line would look like

Now imagine you have to type that command in multiple times everyday….

SSH has a config file to deal with this situation. You can define all of the above in the config file and just use a short hand name and let SSH apply the configs from the file and get the same result.

The default location of your SSH config file is ~/.ssh/configand it probably won't exist if you have never used it. You can create one by running

And open it in your favorite editor.

The config file consists of a bunch of what is called a Hostsections which apply a bunch of options to a given set of hosts.
The format is roughly

While ~/.ssh/configis the default config file that ssh will load, you can specify an arbitrary config file using the -Foption to ssh:

With the default being equivalent to

And hence you can keep your config files anywhere you would like and use them using the above option and save you a bunch of time.

Here is an example of what can be in ~/.ssh/config:

Within a give ssh config file, multiple host patterns might match a given host, in such a case, ssh will make a union of all options with the firstof overlapping options taking affect. For example you could have the following in your config file:

When you now run ssh bastion.us-west-2.example.comboth Option1and Option2will be used. We will see how to use this feature to our advantage later in this blog.

Putting it all together for my nginx example above, we can have the following in ~/.ssh/config

And now all I need to type on my terminal is ssh nginx.us-west-2.example.comand I will be going through the bastion host.

As I alluded to earlier, the main point of this blog is easily managing different SSH configurations per environment and/or project you are working on. The config file I described above becomes an important piece of the solution, which might seem very obvious by now: a config file per environment.

Now you could very well put all your config files named by environment and/or project in a single directory and get away with it. However this can easily be hard to manage, a problem I personally encountered.

Here’s the structure I came up with. Let’s start by looking at the ~/.sshdirectory:

I just used ~/.sshas the directory of choice to use for managing the configurations since everything in there is related to SSH, however you could very well choose any other directory for this purpose.

Next we have one sub-folder per-project and a nested sub-folder per environment of that project. I have used the AWS regions us-east-1, us-west-1, and us-west-2as example environments above. Each of these folders contain a file called configthat contains all the SSH configuration needed for it, a private and public key file (this can be omitted if you have one public-private key across everywhere you need to access). The configwill be configured to use the correct private key file and will need an absolute path (you can still use ~) to it due to lack of features in the ssh config file.

All of this would work pretty nicely for anyone who don't need any fancy stuff like ProxyCommand.

But I do, and here's why it doesn't just work as expected.

Let's say the config file I had at the end of the last section is the one in ~/.ssh/project1/us-west-2/config. Here's what it looks like:

Now I should in theory be able to do the following:

And since I claimed it worked when the config file was in ~/.ssh/config, this should in the most logical case work.

But it doesn't, and here's the reason why. If you look at the ProxyCommandline, there is another ssh command being executed. So what is actually is happening is when I run ssh -F ~/.ssh/project1/us-west-2/config nginx.us-west-2.example.comis the following:

All of this looks good so far, but the devil is in the details. The child process created above executes blindly the command provided, which in this case is ssh user@bastion.us-west-2.example.com nc %h %p. This looks like a regular SSH command and does not contain the -F ~/.ssh/project1/us-west-2/configoption and hence will resort to using ~/.ssh/config,if one exists, to look for options to be applied for bastion.us-west-2.example.com. If you are lucky and something does match, the connection might go through, but I found out the hard way. It turns out that the -Foption is not passed in to any sub process that are spawned off as a result of the ProxyCommand, which from the SSH developers perspective is a reasonable assumption, but doesn't seem to be well documented, or I was just expecting too much!

So the easy fix is to update the config file to look as follows:

I personally feel typing ssh -F ~/.ssh/project1/us-west-2/config nginx.us-west-2.example.comis too much to type on the shell when I want to quickly get into the host, especially if there is an ongoing issue with it.

First, let's shorten the host part. Since SSH is doing a regex match on the Hostentries with what is provided on the command line, we can do the following:

Now the following would work just as before ssh -F ~/.ssh/project1/us-west-2/config nginx.

Now to get rid off the path to config file, I just used BASH aliases to fix it. For example, for the above you could have the following in your bash configuration.

And now you can sshp1uw2 nginxand get the same effect.

The alias idea can be applied to other SSH based commands such as scp.

I mentioned before that SSH will match all matching Host patterns for a given host in the config file. This allows us to use wildcards and move common configurations to one section.

Above you can see that some of the common configuration such as IdentityFileare defined in the single section Host *which matches all hosts. We then have a Matchsection which adds options when specific conditions are met. In my example I have added a condition to add the ProxyCommandconfiguration for all non-bastion hosts. Without the Matchsection, we would encounter an infinite loop trying to ssh into the bastion because you would spawn off a new ssh process as a result of the ProxyCommandthat loads the same file and applies the ProxyCommandagain and repeats infinitely.

So now, if you have your Bash alias and the above config, the following would work

Notice the following two options in the catch-all host section:

Everything you just read sounds, at a high level, very similar to the virtualenvin the Python world for example. Currently, I created all the directory hierarchies and the config files within them manually. But at some point this will definitely get out of hand and having something similar to virtualenvwhere I can activate and deactivate SSH environments would be really great.

I hope the blog helps you streamline your SSH configuration files and prevents a lot of typing on the shell when you are trying to SSH into different machines.

Add a comment

Related posts:

Token Model

Regardless of the growth of the SYC token, 48% of ICO revenue where be payed directly to the holder wallet in Ethereum. This means when you hold 1000 SYC Tokens in your wallet, you become 0.04 ETH…

The Four Suits

Tarot breathes language into our hopes, dreams, struggles, and fears that we keep under wraps consciously, or unconsciously. The biggest illusion seems to be that they don’t matter or exist if we…