A less verbose and more legible way to manage .ssh/config
Go to file
2024-07-17 21:46:42 -06:00
src Parser: remove empty last line 2024-07-17 19:32:17 -06:00
systemd README: add systemd configs 2024-07-17 21:46:42 -06:00
tests Test: add integration tests 2024-07-17 20:59:12 -06:00
.gitignore Test: ignore .log files 2024-07-17 20:58:50 -06:00
LICENSE.md Init 2024-05-26 17:11:24 -06:00
README.md Readme: update for loop syntax 2024-07-17 19:23:47 -06:00

SSH Compose Pro

Streamline repetitive ssh config files with trait-style property inheritance!

ssh_config+ is meant for users with very large and repetitive ssh configs. This includes templating, an inheretence-style way of copying fields, and for loops to reduce repetitive lines.

See the example/ directory for an idea of capabilities, but here's a snippet:

__preamble:
  ssh_props:
    Port: 22
    IdentitiesOnly: yes
    ForwardX11: no

__uni_template:
  template: __preamble
  ssh_props:
    IdentityFile: ~/.ssh/computer_labs_key
    User: emiliko

undergrad:
  template: __uni_template
  ssh_props:
    Hostname: ug22.cs.ualberta.ca

ohaton:
  template: __uni_template
  ssh_props:
    Hostname: ohaton.cs.ualberta.ca

coronation:
  template: __uni_template
  ssh_props:
    Hostname: coronation.cs.ualberta.ca

Quick Start

mv ~/.ssh/config ~/.ssh/config_og
python3 src/ssh_config_to_yaml.py ~/.ssh/config_og --out ~/.ssh/config.yaml
# Do some edits on ~/.ssh/config.yaml. The migration script won't compress
# things with for-loops or templates. Then...
python3 ~/.ssh/config.yaml --out ~/.ssh/config

As a proof of concept, you can even chain the scripts! The order of hosts will change, but the config should function identically!

python3 src/main.py <(python3 src/ssh_config_to_yaml.py ~/.ssh/config)

Rules

The src/ssh_config_to_yaml.py script will assist in quickly migrating your existing config.

SSH Properties

Standard SSH config properties go under the ssh_props heading for every host. For example:

Host github.com
    Hostname github.com
    IdentityFile ~/.ssh/github_main
    LocalForward 3306 localhost:3306
    LocalForward 3302 localhost:3302
    LocalForward 3000 localhost:3000

Becomes:

github.com:
  ssh_props:
    Hostname: github.com
    IdentityFile: ~/.ssh/github_main
    LocalForward:
      - 3306 localhost:3306
      - 3302 localhost:3302
      - 3000 localhost:3000

Note that yaml does not support duplicate keys, so keys can take a list of properties instead to mimic repeated keys, as seen above.

Templates

Templates are "default" properties inherited from another host. Templates must be declared above the host that uses it. You can make a template-only host by declaring it with __ at the start of the name. You can also use another host as a template.

__preamble:
  ssh_props:
    Port: 22
    IdentitiesOnly: yes
    ForwardX11: no

#############################################################################
# Uni Computers
#############################################################################
__uni_template:
  template: __preamble
  ssh_props:
    IdentityFile: ~/.ssh/id_ed25519
    User: emiliko

ohaton:
  template: __uni_template
  ssh_props:
    Hostname: ohaton.cs.ualberta.ca

coronation:
  # Using __uni_template here would make more sense, but ohaton works too
  template: ohaton
  ssh_props:
    Hostname: coronation.cs.ualberta.ca

Will generate:

Host ohaton:
    ForwardX11 false
    Hostname ohaton.cs.ualberta.ca
    IdentitiesOnly true
    IdentityFile ~/.ssh/id_ed25519
    Port 22
    User emiliko

Host coronation:
    ForwardX11 false
    Hostname coronation.cs.ualberta.ca
    IdentitiesOnly true
    IdentityFile ~/.ssh/id_ed25519
    Port: 22
    User emiliko

As a note, properties inherited from templates will be overwritten entirely, even if they're multi-valued. For example:

__uni:
  ssh_props:
   LocalForward:
    - 3306 localhost:3306
    - 3302 localhost:3302
    - 3000 localhost:3000

ohaton:
  template: __uni
  ssh_props:
      LocalForward:
       - 9000 localhost:9000

Will overwrite all the LocalForward properties provided by the __uni template, generating:

Host ohaton
    LocalForward 9000 localhost:9000

For loops

For loops allow simple substitution of a single variable over a range or set of values. Ranges must be numerical, but sets can be any arbitrary string. Multiple different for loops can be declared under the for section.

orca:
  ssh_props:
    Hostname: 10.42.43.1
    User: emiliko
  for:
    - variable: port
      range: [9026, 9042, 1]
      property: LocalForward
      template: ${port} localhost:${port}
    - variable: env
      iter: ["FOO=bar", "BAR=foo"]
      property: SendEnv
      template: ${env}

Expands to:

Host orca
    Hostname 10.42.43.1
    LocalForward 9026 localhost:9026
    LocalForward 9027 localhost:9027
    LocalForward 9028 localhost:9028
    LocalForward 9029 localhost:9029
    LocalForward 9030 localhost:9030
    LocalForward 9031 localhost:9031
    LocalForward 9032 localhost:9032
    LocalForward 9033 localhost:9033
    LocalForward 9034 localhost:9034
    LocalForward 9035 localhost:9035
    LocalForward 9036 localhost:9036
    LocalForward 9037 localhost:9037
    LocalForward 9038 localhost:9038
    LocalForward 9039 localhost:9039
    LocalForward 9040 localhost:9040
    LocalForward 9041 localhost:9041
    SendEnv FOO=bar
    SendEnv BAR=foo
    User emiliko

For loops can be part of templates