concierge
is a small utility/daemon which is intended to help humans
to maintain their SSH configs.
Contents
There is not problems with SSH config format: it works for decades and
is going to work for my children I guess. This utility will die, but one
will update his ~/.ssh/config
to access some network server.
The problem with SSH that it really hard to scale. I am not quite sure
about other people jobs, but on my current and previous jobs I was
used to maintain quite large sets of records in SSH configs. Usual
deployment of some modern app consist several machines (let's say X
)
and during development we are using several stage environments (let's
say Y
). So, frankly, you need to have X * Y
records in your
~/.ssh/config
. Only for work.
Sometimes you need to jugle with jump hosts. Sometimes your stage is moving to another set of IPs. Sometimes life happens and it is quite irritating to manage these configuration manually.
I did a lot of CSS stylesheets and SSH config management is pretty close to that. I want to have SASS for SSH config. The main goal of this tool is to provide user with some templating and clutter-free config management in SASS way.
Installation is quite trivial:
$ pip install concierge
or if you want to install it manually, do following:
$ git clone https://github.com/9seconds/concierge.git
$ cd concierge
$ python setup.py install
By default, no template support is going to be installed. If you want to use Mako or Jinja2, please refer to Templaters section.
Also, it is possible to install support of libnotify. Please install tool like this:
$ pip install concierge[libnotify]
In that case, you will have a desktop notifications about any problem
with parsing of your ~/.conciergerc
. Yep, these Ubuntu popups on the
right top of the screen.
If you have a problems with Pip installation (with modifiers, for example), please update your pip and setuptools first.
$ pip install --upgrade pip setuptools
Eventually there will be no such problem anywhere.
Please be noticed, that concierge
is Python 3 only tool. It
should work on cPython >= 3.3
without any problems. Come on, Python
3.4 is bundled even with CentOS 7!
After installation, 2 utilities will be available:
concierge-check
concierge
concierge
comes with support of additional templaters, you may plug
them in installing the packages from PyPI. At the time of writing,
support of following templaters was done:
- concierge-mako - support of Mako templates
- concierge-jinja - support of Jinja2 templates
To install them just do
$ pip install concierge-mako
And concierge
will automatically recognizes support of Mako and now
one may use concierge -u mako
for her ~/.conciergerc
.
concierge-check
is a tool to verify syntax of your
~/.conciergerc
file. Please check Syntax description to get on
speed.
Also, it supports a number of options but they are pretty trivial.
Please remember, that both concierge-check
and concierge
use syslog for logging data in process. Options like --debug
or
--verbose
will affect only stderr logging, syslog will have only
errors.
concierge
is intended to work in daemon mode. It converts between
your ~/.conciergerc
and destination ~/.ssh/config
(so
Installation magic work in that way).
I use systemd so concierge
is bundled to support it. To get an
instructions of how to use the tool with systemd, please run following:
$ concierge --systemd
It will printout an instructions. If you do not care, please run following:
$ eval "$(concierge --systemd --curlsh)"
It will install systemd user unit and run concierge daemon automatically.
concierge
supports the same options and behavior as
concierge-check so please track your syslog for problems.
Well, there is no big difference between plain old ssh_config(5)
and
concierge
style. Base is the same so please check the table with
examples to understand what is going to be converted and how.
Syntax came from the way I structure my SSH configs for a long time . Basically I am trying to keep it in the way it looks like hierarchical .
Let's grow the syntax. Consider following config
Host m HostName 127.0.0.1 Host me0 HostName 10.10.0.0 Host me1 HostName 10.10.0.1 Host m me0 me1 Compression no ProxyCommand ssh -W %h:%p env1 User nineseconds Host * Compression yes CompressionLevel 9
So far so good. Now let's... indent!
Host m HostName 127.0.0.1 Host me0 HostName 10.10.0.0 ProxyCommand ssh -W %h:%p env1 Host me1 HostName 10.10.0.1 ProxyCommand ssh -W %h:%p env1 Host m me0 me1 Compression no User nineseconds Host * Compression yes CompressionLevel 9
It is still valid SSH config. And valid concierge
config. Probably
you already do similar indentation to visually differ different server
groups. Let's check what do we have here: we have prefixes, right. And
most of options are quite common to the server groups (environments).
Now let's eliminate Host m me0 me1
block. This would be invalid SSH
config but valid conciergerc
config. Also I am going to get rid of
useless prefixes and use hierarchy to determine full name (fullname =
name + parent_name
).
Please be noticed that all operations maintain effectively the same
conciergerc
config.
Host m Compression no HostName 127.0.0.1 User nineseconds Host e0 HostName 10.10.0.0 ProxyCommand ssh -W %h:%p env1 Host e1 HostName 10.10.0.1 ProxyCommand ssh -W %h:%p env1 Host * Compression yes CompressionLevel 9
Okay. Do we need rudiment Host *
section? No, let's move everything
on the top. Idea is the same, empty prefix is *
.
Compression yes CompressionLevel 9 Host m Compression no HostName 127.0.0.1 User nineseconds Host e0 HostName 10.10.0.0 ProxyCommand ssh -W %h:%p env1 Host e1 HostName 10.10.0.1 ProxyCommand ssh -W %h:%p env1
By the way, you may see, that indentation defines parent is the same way as Python syntax is organized. So following config is absolutely equivalent.
Compression yes Host m Compression no HostName 127.0.0.1 User nineseconds Host e0 HostName 10.10.0.0 ProxyCommand ssh -W %h:%p env1 Host e1 HostName 10.10.0.1 ProxyCommand ssh -W %h:%p env1 CompressionLevel 9
You can also work the other way around with a star. In this example, I remove the first Host line from being generated and add that domain information to other host. Also, ProxyJump is available
Compression yes -Host *.my.domain Compression no User tr4sk ProxyJump gateway Host server1 User root Host server2
This is a basic. But if you install concierge
with support of Mako or
Jinja2 templates, you may use them in your ~/.conciergerc
.
Compression yes CompressionLevel 9 Host m Compression no HostName 127.0.0.1 User nineseconds % for i in range(2): Host e${i} HostName 10.10.0.${i} ProxyCommand ssh -W %h:%p env1 % endfor
This is a Mako template I use. Please refer Mako and Jinja2 documentation for details.
By the way, if you want to hide some host you are using for grouping only,
please prefix it with -
(-Host
).
Here are some examples. Please do not hesitate to check Demo, pause it, look around.
Source, converted from (~/.concierge) | Destination, converted to (~/.ssh/config) |
---|---|
Host name HostName 127.0.0.1 |
Host name HostName 127.0.0.1 |
Compression yes Host name HostName 127.0.0.1 |
Host name HostName 127.0.0.1 Host * Compression yes |
Compression yes Host name HostName 127.0.0.1 Host * CompressionLevel 9 |
Host name HostName 127.0.0.1 Host * Compression yes CompressionLevel 9 |
Compression yes Host name HostName 127.0.0.1 Host q ViaJumpHost env1 HostName node-1 |
Host name HostName 127.0.0.1 Host nameq HostName node-1 ProxyCommand ssh -W %h:%p env1 Host * Compression yes |
Compression yes -Host name HostName 127.0.0.1 Host q ViaJumpHost env1 HostName node-1 |
Host nameq HostName node-1 ProxyCommand ssh -W %h:%p env1 Host * Compression yes |
Compression yes Host m User nineseconds % for i in range(2): Host e${i} HostName 10.10.0.${i} ViaJumpHost gw2 % endfor Protocol 2 Host blog User sa |
Host blog User sa Host me0 HostName 10.10.0.0 Protocol 2 ProxyCommand ssh -W %h:%p gw2 User nineseconds Host me1 HostName 10.10.0.1 Protocol 2 ProxyCommand ssh -W %h:%p gw2 User nineseconds Host * Compression yes |
Compression yes -Host \*.my.domain User nineseconds Host first Host second HostName 10.10.10.1 Protocol 2 Host blog User sa |
Host blog User sa Host first.my.domain Protocol 2 User nineseconds Host second.my.domain User nineseconds Protocol 2 HostName 10.10.10.1 Host * Compression yes |