A template for modern SSH Config
This was created with 3 use cases in mind:
- To help understand and initialize your
~/.ssh/config - To share config (NOT KEYS) among a few computers (e.g. office and laptop)
- To provide examples for common tasks (e.g. forwarding, proxying)
Here's what a properly configured ~/.ssh/ looks like:
.ssh/
├── authorized_keys
├── config
├── config.d/
│ └── example.sshconfig
├── ! id_ed25519
├── ! id_ed25519.pub
└── ! known_hosts
Notes:
- the
!prefix means DO NOT SHARE between machines - security:
id_*(keys) enable attackers to login as you, wherever you have access id_ed25519had already reached wide adoption by 2019 and is the preferred key type
(due to efficiency, convenience, and security)id_rsaandid_ecdsashould be replaced at your earliest convenience
(due to inefficiency, and potential future vulnerabilities)authorized_keysshows which keys allow login to the current user account- security:
configandconfig.d/*show which systems you access, and how - the
known_hostsfingerprint cache is updated each time you connect to a new host
If you use this template repo to get your SSH config started (and update with future example
- SET TO PRIVATE when creating from template

- CHANGE THE DEFAULT BRANCH after creating
(e.g. to 'private' or 'john' or 'macbook')
To update with new example configs:
git pull --rebase https://github.com/bnnanet/ssh-config-template.git public-
Create the directory structure
mkdir -p ~/.ssh/config.d/ chmod 0700 ~/.ssh/ chmod 0700 ~/.ssh/config.d/ touch ~/.ssh/authorized_keys chmod 0644 ~/.ssh/authorized_keys touch ~/.ssh/config touch ~/.ssh/config.d/example.sshconfig touch ~/.ssh/known_hosts chmod 0600 ~/.ssh/config chmod 0600 ~/.ssh/config.d/example.sshconfig chmod 0600 ~/.ssh/known_hosts
-
Create (but NOT overwrite) SSH Keys
if ! test -f ~/.ssh/id_ed25519; then # create key ssh-keygen -t ed25519 -f ~/.ssh/id_ed25519 -q -N "" # (re)set passphrase ssh-keygen -p -f ~/.ssh/id_ed25519 fi
-
Add an EXPLICIT .gitignore, if saving with git
(ignores EVERYTHING, then allows individually with!prefix)# ignore everything * # allow files that may reasonably be shared across machines # (NO KEYS!) !authorized_keys !config !config.d/ !config.d/**.sshconfig # allow git files !README.md !.gitignore !.gitkeep
~/.ssh/configis used for global config and fallbacks~/.ssh/config.d/<name>.sshconfigis used for groups or individual host config
Include ~/.ssh/config.d/*.sshconfig
## Global Defaults
Host *
User app
Port 22
StrictHostKeyChecking accept-new
ServerAliveInterval 3600
# Share sessions to the same host and keep them alive
ControlMaster auto
ControlPath ~/.ssh/%r@%h:%p
ControlPersist 15m
# Which keys to try, in order
IdentityFile ~/.ssh/id_ed25519
IdentityFile ~/.ssh/id_ecdsa
IdentityFile ~/.ssh/id_rsaHost example example.com example-XXXXXX.cloud.example.net
# Internal IP 10.0.0.101
Hostname example-1.ffffff.example.net
User app
Port 22~/.vimrc:
autocmd BufNewFile,BufRead *.ssh,*.sshconfig setfiletype sshconfigGitHub uses the ```ssh-config codeblock for sshconfig highlighting.
```ssh-config
# ssh example
Host example example.com example-XXXXXX.cloud.example.net
# Internal IP 10.0.0.101
Hostname example-1.ffffff.example.net
ProxyCommand sclient --alpn ssh %h
```# ssh example
Host example example.com example-XXXXXX.cloud.example.net
# Internal IP 10.0.0.101
Hostname example-1.ffffff.example.net
ProxyCommand sclient --alpn ssh %hFollow github-linguist/linguist#7041 for future updates.
This example forwards remote port 5432 on a postgres server to be able to listen on port 54321 locally.
Create a one-off local-forward connection like this:
ssh pg-XXXXXX.cloud.example.net -L 54321:127.0.0.1:5432 -fnNTOr create a reusable alias for ssh pg-forward using a config like this:
# ssh pg
Host pg-forward
Hostname pg-XXXXXX.cloud.example.net
# LocalForward <local-port> <remote-network-host>:<remote-port>
LocalForward 54321 127.0.0.1:5432
# -f Requests ssh to go to background just before command execution.
ForkAfterAuthentication yes
# -n Documented as implied by -f, but explicit is more reliable, at least on macOS
StdinNull yes
# -N Do not execute a remote command.
SessionType none
# -T Disable pseudo-tty allocation.
RequestTTY no
# Share the connection rather than erroring when run multiple times
ControlMaster auto
ControlPath ~/.ssh/%r@%h:%p
ControlPersist 15mThen each time the alias is used, the config will be applied automatically:
ssh pg-forwardNotes:
- instead of
127.0.0.1, you can choose another host that the ssh server has access to - such as forwarding web traffic from example.com:ssh webproxy-XXXXXX.cloud.example.net -L 3080:example.com:443 -fnNT
Using sclient:
(easy to remember)
# sclient
ProxyCommand sclient --alpn ssh %hUsing s_client:
(almost always already installed)
# openssl s_client
ProxyCommand openssl s_client -connect %h:443 -alpn ssh -quiet 2>/dev/nullFor how to multiplex SSH-over-TLS on the server, see mholt/caddy-l4#101.