This is the third post in a series where I read through man ssh_config and write about things I find interesting. Previous posts covered ObscureKeystrokeTiming and ChannelTimeout. Today, let's talk about Match version, a new directive that lets you conditionally apply configuration blocks based on the OpenSSH version. This is a game-changer for anyone who manages multiple machines with varying OpenSSH versions.
So, the idea is that if you keep a single ~/.ssh/config that you sync across multiple machines (through a dotfiles repo, or in my case, machines connected via Tailscale), you've probably run into this: you add a directive that's only supported in newer OpenSSH versions, and now your config is broken on every machine that hasn't been updated yet. You either maintain per-machine configs, comment things out when you switch contexts, or just avoid using new features until every machine catches up. None of these are great.
OpenSSH 10.0 (April 2025) introduced Match version in both ssh_config and sshd_config. It lets you conditionally apply configuration blocks based on the local OpenSSH version string.
From the sshd_config man page:
The Version keyword matches against the version string
of sshd(8), for example "OpenSSH_10.0".
On the client side, it works the same way. The version string is what ssh -V reports, like OpenSSH_10.2p1. You can match against it with wildcards. So if you want to use a feature that only exists in OpenSSH 10.x and later, you wrap it:
Match version "OpenSSH_10.*"
ChannelTimeout global=30m
Or if you want to set the new default post-quantum key exchange but only where it's available:
Match version "OpenSSH_10.*"
KexAlgorithms mlkem768x25519-sha256,curve25519-sha256
Machines running 9.x will silently skip the block. No errors, no broken configs.
This also works nicely with the version jump from 9.x to 10.0. OpenSSH 10.0 announces itself as SSH-2.0-OpenSSH_10.0, which broke some tools that matched version strings with patterns like OpenSSH_1*, expecting that the version would always start with a single digit. The Match version directive itself handles this gracefully since it uses standard wildcard matching, but it's a good reminder that version parsing in SSH is trickier than it looks now that we've crossed into double digits.
You can combine version matching with other Match predicates. For example, to apply settings only on newer versions connecting to a specific host:
Match version "OpenSSH_10.*" host "lxplus*.cern.ch"
ObscureKeystrokeTiming no
ChannelTimeout session=1h global=2h
One thing to be aware of: on older OpenSSH versions that don't understand Match version at all (anything before 10.0), the directive itself will cause a config parse error. So you can't use Match version to gate features for pre-10.0 machines, it only works for differentiating between 10.0 and later versions. For backward compatibility with genuinely old versions, you still need separate config files or a generation step.
For the sshd_config side, this is useful for fleet management. If you're rolling out OpenSSH updates incrementally across servers, you can ship one config that works everywhere:
Match version "OpenSSH_10.*"
ChannelTimeout session=30m global=1h
UnusedConnectionTimeout 5m
Servers still on 9.x will ignore the block (well, they'll error, so really you'd want all your servers on 10.x before using this in sshd_config). But once your fleet is on 10.0+, you can start using Match version to gate 10.1 or 10.2 features without worrying about breaking the 10.0 machines.
The practical upshot: if all your machines are on OpenSSH 10.0 or later, Match version makes a single portable ssh_config meaningfully more viable. It's one of those small features that doesn't sound exciting but removes a real friction point from day-to-day SSH config management.