In case it matters:
- OS: Ubuntu 10.04
- SSH: OpenSSH_5.3p1 Debian-3ubuntu5
I'd like one SSH config file to include another one. The use case would be to define whatever I want in my default .ssh/config file and then pre-pend a couple of extra things in a separate file (e.g. ~/.ssh/foo.config). I want the second file to incorporate the first one, though, so I don't have to duplicate everything in the first one. Is that doable? Thanks!
12 Answers
From 7.3p1 and up, there is the Include keyword,
which allows you to include configuration files.
IncludeInclude the specified configuration file(s). Multiple pathnames may be specified and each pathname may contain glob(3) wildcards and, for user configurations, shell-like “~” references to user home directories. Files without absolute paths are assumed to be in
Source: ssh_config(5).~/.sshif included in a user configuration file or/etc/sshif included from the system configuration file.Includedirective may appear inside aMatchorHostblock to perform conditional inclusion.
You should put the Include clause on top of the file.
For example you could have in ~/.ssh/config:
Include config.d/home
Host github.com HostName github.com User gitand in ~/.ssh/config.d/home:
Host laptop HostName laptop.lanFrom the comments, use the below to include all files in the config.d directory:
Include config.d/* 8 No, to my knowledge this is not possible.
Here are the links to corresponding open feature requests / bug tickets:
3If you want to start a ssh client, you could do this in bash:
#files are .ssh/config and ~/.ssh/foo.config
alias ssh='ssh -F <(cat .ssh/config ~/.ssh/foo.config)'then you use ssh normally and it will have both files read in that order.
For the server daemon sshd you could do the same, just use -f instead of -F and write this down where you start the daemon directly. you don't need an alias.
A second possibility according to the man page is to put the system wide configuration in /etc/ssh/ssh_config and the user one in ~/.ssh/config.
Update Apparently there is some problem with some bash versions and how the devices are created. (see )
This is a workaround (though in my opinion ugly):
mkfifo /tmp/ssh_fifo
cat ~/.ssh/config ~/.ssh/foo.config >/tmp/ssh_fifo &
ssh -F /tmp/ssh_fifo myserver
rm /tmp/ssh_fifoso if you want, you may create a function out of it (or a script):
ssh() { tmp_fifo=$(mktemp -u --suffix=_ssh_fifo) mkfifo "$tmp_fifo" cat ~/.ssh/config ~/.ssh/foo.config >"$tmp_fifo" 2>/dev/null & /usr/bin/ssh -F "$tmp_fifo" "$@" rm "$tmp_fifo"
} 8 Starting with ssh 7.3 (released on August 1st, 2016), an Include directive is available.
Include: Include the specified configuration file(s). Multiple path names may be specified and each pathname may contain glob wildcards and shell-like "~" references to user home directories. Files without absolute paths are assumed to be in
~/.ssh. AnIncludedirective may appear inside aMatchorHostblock to perform conditional inclusion.
(Here is the link to the resolved bug report, that also includes tha patch: )
Similarly to the other 'ugly' here's mine one-liner:
alias ssh="cat ~/.ssh/config.d/* > ~/.ssh/config; ssh" 4 Well, I kinda cheat to do this. In my bash .profile-ish files I have a block that replaces various pieces of my home directory on login, so I just generate a new one each time. Example:
rm ~/.ssh/config
cat ~/conf/myservers.sshconfig >> ~/.ssh/config
[ -f ~/conf/workservers.sshconfig ] && cat ~/conf/workservers.sshconfig >> ~/.ssh/config
(or something like this:)
for i in `ls ~/conf/sshconfigs` ; do cat $i >> ~/.ssh/config
done
chmod 600 ~/.ssh/configThis also lets me do things like add config blocks to the ssh config file only if i'm on host A or B, but not on my home systems.
Now I know, someone will gripe that if you log in a lot this could cause excessive slowdown, but in practice I've never actually noticed it. And I'm sure you could put this in a script and fire it via cron too.
I personally use those commands to compile the ssh config:
alias compile-ssh-config='echo -n > ~/.ssh/config && cat ~/.ssh/*.config > ~/.ssh/config'
alias ssh='compile-ssh-config && ssh'
# (This will get used by other programs depending on the ~/.ssh/config)
# (If you need you can run the compile-ssh-config command via cron etc.)or:
alias compile-ssh-config='echo -n > ~/.ssh/config-compilation && cat ~/.ssh/*.config > ~/.ssh/config-compilation'
alias ssh='compile-ssh-config && ssh -F ~/.ssh/config-compilation'
# (This is saver and won't over write an existing ~/.ssh/config file)because:
alias ssh='ssh -F <(cat .ssh/*.config)'does not work for me, returning:
ssh: Can't open user config file /dev/fd/63: Bad file descriptorHope this will be of any help.
1Another, FUSE-based solution (not tested myself):
"Rather than having to continue managing one big file, [...] instead build a config "file" dynamically from many smaller logical chunks."
I've also found an article doing this via FIFOs:
2None of these alias solutions work for git or other programs other than ssh.
I've slapped together a quick-and-dirty, but you might want to improve on it.
Add this to your ~/.bashrc
mkdir -p ~/.ssh/config.d/
[ -e ~/.ssh/config ] && mv ~/.ssh/config ~/.ssh/config.bak.$(date -Ins)
cat ~/.ssh/config.d/* > ~/.ssh/configEach time you start a session, it'll merge together all the files in ~/.ssh/config.d. (line 3)
The downside with this version is that if you change ~/.ssh/config next session you open your changes would be lost, so to prevent that I move the existing file to a .bak file. (line 2) The problem there is you're gonna have a whole lot of .bak files after a while.
You can easily upgrade SSH version on Ubuntu to v7.3 (tested on Ubuntu Xenial 16.04) by installing packages from Yakkety:
echo "deb yakkety main" > /etc/apt/sources.list.d/yakkety.list
apt-get update
apt-get install -y ssh
rm /etc/apt/sources.list.d/yakkety.list
apt-get updateCheck SSH version
ssh -V
OpenSSH_7.3p1 Ubuntu-1, OpenSSL 1.0.2g 1 Mar 2016Configure SSH to use includes from ~/.ssh/config.d directory
mkdir ~/.ssh/config.d
sed -i '1iInclude config.d/*' ~/.ssh/config My dumb answer :
- Tried to install OpenSSH > 7.3 on Xenial (16.04)
- Didn't like the mess it made
So I settled for this :
- Keep your separate OpenSSH config files in
~/.ssh/config.d/ - When you change one, do
cat ~/.ssh/config.d/* > ~/.ssh/config - On the glorious day you upgrade to a distro version that has OpenSSH 7.3p1 or newer, you can instead create a file that contains
Include config.d/*
I cannot upgrade SSH on my machine neither.
I used GNU make to generate the ssh config file only when needed:
# Concatenates all the .config files.
aInput = *.config
aOutput = ~/.ssh/config
aCurrentMakefile = $(lastword $(MAKEFILE_LIST))
$(aOutput): $(shell ls $(aInput)) $(aCurrentMakefile) @echo "Generating $(aOutput)" @echo "# File generated by $(aCurrentMakefile) on $(shell date +'%F %T.%6N')" > $(aOutput) @cat $(aInput) >> $(aOutput)Then ssh is aliased to
alias ssh='make -s -f ~/Tools/config.d/makefile -C ~/Tools/config.d && ssh'It works like a charm.