
Secure Shell (SSH) lets sysadmins securely manage remote systems. It’s powerful, complicated, and confusing. Lose the confusion. SSH Mastery: OpenSSH, PuTTY, Tunnels and Keys rescues you from sifting through decades of obsolete online tutorials and quickly makes you an SSH journeyman. You’ll learn to: • eliminate passwords • manage access by users, groups, addresses, and more • securely move files around your network • forward graphic displays • proxy TCP connections • build SOCKS proxies • centrally manage and distribute keys and configurations • use SSH as secure transport for other applications • build virtual private networks • create Certificate Authorities for truly large scale deployment Master Secure Shell with SSH Mastery!
He also wrote Absolute FreeBSD and PGP & GPG: Email for the Practical Paranoid, among many others.
One of the newest tricks I haven't written down just yet is tunnelling a TCP port of a different machine than what you connect to over SSH. This is good for connecting to that Windows XP machine you have no control over (since it probably controls some industrial machine) but that you have to provide access to to certain people e.g. for maintenance of the industrial machine. This works reliably for e.g. tunnelling VNC, RDP and even Samba/CIFS for the occasional file transfer (e.g. a new executable file of some industrial control software). If you have no means to do a proper VPN, SSH is installed pretty much everywhere on current OSes (even current Windows 10 ships with an SSH client).
http://www.amazon.com/SSH-Mastery-OpenSSH-PuTTY-Tunnels/dp/1...
http://www.amazon.com/SSH-Mastery-OpenSSH-PuTTY-Tunnels-eboo...
This isn't true. TOML allows table names with periods and asterisks. It also supports top-level keys. This is what the TOML may look like for your SSH config:
include = "~/.ssh/my-org/*"
# We write `"*.co.uk"` rather than `host."*.co.uk"`.
# `Host` in ssh_config(5) introduces sections,
# and TOML has table headers for sections.
# A more complete design would have something for `Match`.
["*.co.uk"]
proxy-command = "ssh bastion@my-uk-server.co.uk nc %h %p 2> /dev/null"
[newServer]
hostname = "newServer.url"
user = "adminuser"
port = 2222
identity-file = "~/.ssh/id_rsa.key"
["anotherServer.tld"]
hostname = "anotherServer.url"
user = "mary"
port = 2222
(Personally, I am not a fan of indenting TOML.)> And you can't change how or when includes are loaded or what they overload without adding some kind of "priority" key-value, and then having to read each entry, do some math, change all the values to load different things at different places. (and looking back, I actually screwed up the TOML config, because it was so confusing!)
Right, your TOML is invalid. TOML requires you to quote strings. You might have it mixed up with another INI-derived format.
It could be because TOML is inherently more confusing than ssh_config(5), but I doubt it is actually more confusing to a newcomer. For example, a newcomer might think that indentation in SSH config is semantic when it isn't. I know because I once made this mistake. A newcomer must also remember that `Host` and `Match` are special and introduce new sections despite looking like other declarations. What is more likely is that you learned SSH config by studying the man page or reading a book like SSH Mastery and forgot the effort it took, and now you have "the curse of knowledge" about it (https://en.wikipedia.org/wiki/Curse_of_knowledge), but you haven't studied the TOML spec the same way.
A numeric "priority" key would indeed make for a pretty miserable user experience. Don't implement one if you can help it. There are different, better ways to express how an include should only affect certain keys.
The way I would do it in a TOML-based SSH config file is probably with dotted keys for tables. (I wouldn't necessarily choose TOML for this task, but TOML is your example.) For instance:
[my-org]
include = "~/.ssh/my-org/*"
[my-org."*.example.com"]
# Host inherits from `my-org`.
["*.example.net"]
# Host doesn't inherit from `my-org`.
> Don't choose a generic solution if it's going to give the user a pain in the ass.I agree, with a caveat. The caveat is that you probably overestimate how unique your configuration needs are and underestimate the value of picking something standard. Using a standard format means you tap into its network effects. The user gets "free" syntax highlighting and completion in their editor, automatic formatting, and tools like https://github.com/kislyuk/yq to query and modify config files. This is also an important part of user experience. If the format is custom, you will have to implement syntax highlighting for Vim, Emacs, VS Code, etc., and the user will have to install it.
I think the right approach is to sort your concerns into the essential and the inessential, then choose a format based on the essential concerns. (Do you need includes to only apply to subsequent lines, or could you apply them by name or by nesting?) When you choose, prioritize standard formats. And if your needs are complex enough, consider embedding an interpreter like Lua or Starlark for configuration, or have the user write code in non-embedded Python or another language to generate JSON config that your software reads.