How to Exclude Users from `Match Group` in sshd

Deepak Prasad
Tested on RHEL 10.2 (Coughlan)
Package openssh-server 9.9p1-25.el10_2
Applies to Linux systems with OpenSSH (sshd)
Privilege root or sudo for sshd_config edits and service reload
Scope Match Group with User wildcards and negation; validation with sshd -t and sshd -T -C
Related guides OpenSSH authentication and sshd_config, SSH client config file, systemctl command, SSH command in Linux

OpenSSH lets you combine Group and User criteria on one Match line. To apply settings to a group while excluding one member, match all users with * and then add a negated username with !.

text
Match Group developers User *,!john
    AllowTcpForwarding no

A user must belong to developers, * provides the positive user match, and !john removes that one member from this block. Every criterion on the Match line must be satisfied before the indented options apply.


Quick Reference: Exclude Users from Match Group

Requirement Match syntax
Match one group Match Group developers
Group except one user Match Group developers User *,!john
Group except two users Match Group developers User *,!john,!alice
Match two groups Match Group developers,admins
Match group and one user Match Group developers User john
Validate syntax sudo sshd -t
Show effective configuration sudo sshd -T -C user=john,host=localhost,addr=127.0.0.1
WARNING
Do not use only User !john. A negated pattern excludes a match but does not create the positive match needed for the criterion itself.

1. How Match Group Works in OpenSSH

A Match block applies indented sshd_config options only when its criteria match. The block continues until another Match line or the end of the file.

text
Match Group developers
    AllowTcpForwarding no

Every member of developers gets AllowTcpForwarding no. Everyone else keeps the global default or another applicable Match block.

You can combine criteria on one line. Both must match:

text
Match Group developers User alice
    AllowTcpForwarding no

Here the logic is Group = developers and User = alice. Only alice receives the restriction, and only when she is in developers.


2. Exclude One User from a Match Group

This is the pattern most administrators need when one group member should skip a group-specific SSH setting.

text
Match Group admins User *,!foc
    Banner /etc/ssh/banner-admins.txt

The three parts work together:

  • Group admins — the user must belong to admins.
  • User * — provides a positive match for usernames.
  • !foc — removes foc from this block.

Effective logic:

text
member of admins
AND
any user
AND
not foc

So golinux matches when in admins, while foc does not—even if foc is also in admins.

An excluded user is not blocked from SSH. They simply do not receive the options inside this Match block. They keep global settings or another Match block that applies to them.


3. Exclude Multiple Users from a Group

List exclusions after the wildcard:

text
Match Group admins User *,!foc,!golinux
    Banner /etc/ssh/banner-admins.txt

* matches users positively. !foc and !golinux remove those accounts from this block.

Do not write:

text
Match Group admins User !foc,!golinux

A list with only negated patterns does not satisfy the User criterion. On OpenSSH 9.9, both foc and golinux then keep the default Banner instead of the group banner.

Another common case is SFTP-only members with exceptions:

text
Match Group sftpusers User *,!backup,!automation
    ForceCommand internal-sftp

backup and automation stay in sftpusers for filesystem or sudo policy, but this ForceCommand does not apply to them.


4. Exclude a User Without Removing Them from the Linux Group

Group membership for SSH Match rules comes from the system account, not from a separate group= parameter in sshd -T.

Confirm membership with id:

bash
id foc
output
uid=1011(foc) gid=1012(foc) groups=1012(foc),1011(admins)

foc is in admins, yet you can still exclude that account from a Match block without running:

bash
gpasswd -d foc admins

That matters when the user still needs the Linux group for filesystem permissions, sudo policy, or application access. Use:

text
Match Group admins User *,!foc

The exception exists only in OpenSSH configuration.


5. Validate sshd_config Before Reloading SSH

After editing /etc/ssh/sshd_config or a drop-in under /etc/ssh/sshd_config.d/, test syntax before reloading SSH:

bash
sudo sshd -t

A valid file produces no output and exits successfully:

Do not reload SSH until sshd -t passes. A syntax error looks like this:

bash
sudo sshd -t -f /tmp/bad-sshd-test.conf
output
/tmp/bad-sshd-test.conf: line 1: Bad configuration option: BadOption
/tmp/bad-sshd-test.conf: terminating, 1 bad configuration options

Keep your current administrator SSH session open while testing. Open a second terminal for reload and login checks so a bad change cannot lock you out.


6. Verify Which Match Rules Apply to a User

Repeated SSH logins are slow for troubleshooting. OpenSSH extended test mode shows the effective configuration for a connection context.

On the lab host, the drop-in sets a default banner and a group banner for admins except foc:

text
Banner /etc/ssh/banner-default.txt

Match Group admins User *,!foc
    Banner /etc/ssh/banner-admins.txt

Check which banner applies to golinux:

bash
sudo sshd -T -C user=golinux,host=localhost,addr=127.0.0.1 | grep -i '^banner '
output
banner /etc/ssh/banner-admins.txt

golinux is in admins and is not excluded, so the group banner applies.

Check the excluded user:

bash
sudo sshd -T -C user=foc,host=localhost,addr=127.0.0.1 | grep -i '^banner '
output
banner /etc/ssh/banner-default.txt

foc keeps the global banner because the Match block does not apply.

The -C connection specification accepts values such as user, host, addr, laddr, lport, and rdomain. Group membership is derived from the supplied user account. There is no group=admins parameter.

Filter for any option you set inside the block, not only Banner:

bash
sudo sshd -T -C user=golinux,host=localhost,addr=127.0.0.1 | grep -i allowtcpforwarding

7. Reload SSH Safely

After sshd -t succeeds, reload the daemon instead of restarting it. A reload applies the new configuration to new connections without dropping existing sessions.

On RHEL, Rocky Linux, AlmaLinux, and Fedora:

bash
sudo systemctl reload sshd

On Ubuntu and Debian the service name is usually ssh:

bash
sudo systemctl reload ssh

Keep your current session open, then test a new login from another terminal:

Test the excluded user first:

bash
ssh foc@localhost

Then confirm a non-excluded group member:

bash
ssh golinux@localhost

Use these logins to confirm behavior you already predicted with sshd -T. Prefer reload over restart when a reload is enough.


8. Match Group Exclusion vs AllowUsers, AllowGroups and DenyUsers

Searchers asking how to exclude an SSH user often mean one of two different problems.

Match Group ... User *,!john — John can still log in, but a particular group-specific SSH setting does not apply to him:

text
Match Group sftpusers User *,!john
    ForceCommand internal-sftp

DenyUsers john — John cannot log in through SSH at all.

AllowGroups sshusers — Only members of listed groups may use SSH.

DenyGroups contractors — Members of the group are denied SSH access.

Match exclusions shape which options apply. AllowUsers, DenyUsers, AllowGroups, and DenyGroups control whether login is permitted.


9. Common Match Mistakes

Problem Cause / fix
User !john does not behave as expected Add a positive wildcard: User *,!john
Multiple exclusions fail Use User *,!john,!alice
Exception user cannot SSH at all Check AllowUsers, AllowGroups, DenyUsers, and DenyGroups separately
Settings after Match affect unexpected users A Match block continues until another Match or end of file
Configuration reload fails Run sshd -t and correct syntax first
Two Match blocks set the same option OpenSSH uses the first obtained applicable value
Works on one distro but reload command fails RHEL uses sshd; Debian and Ubuntu commonly use ssh
Group rule does not apply Verify membership with id USER

Only a subset of sshd_config directives is allowed inside a Match block. Check the Match section of the manual for your installed OpenSSH version:

bash
man sshd_config

Search inside the manual for the Match section, or press / and type Match.


Summary

Exclude one user from a group Match block:

text
Match Group GROUP User *,!USER

Exclude several users:

text
Match Group GROUP User *,!USER1,!USER2

Always validate before reload:

bash
sudo sshd -t

Inspect effective settings:

bash
sudo sshd -T -C user=USER,host=localhost,addr=127.0.0.1

Reload SSH, keep your current session open, and confirm with a new login.


References

Omer Cakmak

Linux Administrator

Highly skilled at managing Debian, Ubuntu, CentOS, Oracle Linux, and Red Hat servers. Proficient in bash scripting, Ansible, and AWX central server management, he handles server operations on OpenStack, KVM, Proxmox, and VMware.

  • Debian
  • Ubuntu
  • Linux
  • Red Hat Enterprise Linux
  • Shell Script
  • System Administration