Conditional SSH configuration enables different security policies for specific users, groups, or network locations on the same server, while still using a single /etc/ssh/sshd_config file.
The Match keyword in OpenSSH switches the parser into a conditional context based on attributes such as User, Group, Address, LocalAddress, or Host, so directives inside the block override earlier global settings only for sessions that satisfy the conditions. Evaluation starts with global directives at the top of the file, then proceeds through each Match block in order, with later matches taking precedence over earlier ones when the same directive appears again.
Careful ordering and testing of Match blocks prevents accidental lockouts or overly permissive access, because a misplaced block can shadow later configuration or leave some connections without the intended restrictions. The examples below target a typical Linux server with systemd where the service name is ssh, although some distributions use sshd; root or sudo access on the server is required before altering the configuration.
$ whoami
user
$ sudo cp /etc/ssh/sshd_config /etc/ssh/sshd_config.bak.$(date +%F-%H%M)
A missing backup complicates recovery if a new Match block blocks remote logins or prevents sshd from starting.
$ sudo nano /etc/ssh/sshd_config
sudoedit or vim can replace nano based on local preference.
Match causes subsequent directives to be conditional until a new Match line, so any unconditional settings must appear before the first conditional block.
# Global authentication policy PasswordAuthentication no PubkeyAuthentication yes # Allow password auth from internal subnet only Match Address 192.0.2.0/24 PasswordAuthentication yes
The example assumes a baseline of PasswordAuthentication no earlier in the file so password logins stay disabled for all other sources.
# Restrict forwarding for deploy group and force internal SFTP Match Group deploy X11Forwarding no AllowTcpForwarding no PermitTTY no ForceCommand internal-sftp
Replace group name deploy with an existing system group that owns automation or SFTP-only accounts on the server.
$ sudo sshd -t
Silent output indicates a syntactically valid configuration; error messages reference the line that requires correction.
Related: How to test SSH server configuration
$ sudo sshd -T -C "user=deploy,addr=192.0.2.50,host=app.internal.example" | grep -E "passwordauthentication|pubkeyauthentication|allowtcpforwarding|x11forwarding|permittty|forcecommand" pubkeyauthentication yes passwordauthentication yes x11forwarding no permittty no allowtcpforwarding no forcecommand internal-sftp
sshd -T -C evaluates Match conditions without opening a network socket, which simplifies verification for different users and source addresses.
$ sudo systemctl restart ssh
An incorrect Match block can prevent new sessions from authenticating, so console or out-of-band access is important before restarting a heavily used server.
$ sudo systemctl status ssh ● ssh.service - OpenBSD Secure Shell server Loaded: loaded (/usr/lib/systemd/system/ssh.service; enabled; preset: enabled) Active: active (running) since Sun 2026-01-11 06:45:37 +08; 57s ago TriggeredBy: ● ssh.socket Docs: man:sshd(8) man:sshd_config(5) Process: 15478 ExecStartPre=/usr/sbin/sshd -t (code=exited, status=0/SUCCESS) Main PID: 15479 (sshd) Tasks: 1 (limit: 4546) Memory: 2.7M (peak: 5.3M) CPU: 359ms CGroup: /system.slice/ssh.service └─15479 "sshd: /usr/sbin/sshd -D [listener] 0 of 10-100 startups" ##### snipped #####
$ ssh -v deploy@host.example.net ##### snipped ##### debug1: Authentications that can continue: publickey,password Authenticated to host.example.net ([203.0.113.50]:22) using "publickey". debug1: channel 0: new session [client-session] ##### snipped #####
Combine verbose client logs with server-side journalctl -u ssh output to debug unexpected Match selections or overlapping conditions.