This is the first post of what I hope will be a series. In each post I will explain my configuration files in detail. Specifically, I will explain what were my goals when configuring that exact service, and why I set each configuration to its current value. These should not be considered as definite guides to these services, just real-world configuration examples and the reasoning behind them.

By writing these, I hope to provide useful real-world configuration examples that are easy to understand and thus easy to adjust, instead of the usual copy this configuration if you want to do X .

This post could either be read as a whole, or as a reference (click on a line to jump to its explanation).

What is this config for?

The goal of these configuration changes is to harden the security and ease the management of sshd . Another nice-to-have goal is to make the configuration generic enough so it could be reused among servers without sacrificing security or configurability.

The configuration below only includes values that I have changed, so default values are omitted.

The config file

Click on a line to jump to its explanation.

Reviewing the config

PermitRootLogin no

Disable root login. I don't allow directly logging in as the root user, only through sudo .

AuthorizedKeysFile /etc/ssh/authorized_keys/ %u

Usually, authorised keys are located in each user's home directory at: ~/.ssh/authorized_keys . This config changes it to be in a system directory. I also restrict the permissions of each file to be only writeable by root . This prevents an attacker compromising a user from adding his own pubkey to the list of authorised keys, and let me manage the users on the server in a centralised way. For example using a git repository that sends emails to all the admins.

PasswordAuthentication no PermitEmptyPasswords no ChallengeResponseAuthentication no AuthenticationMethods publickey

These directives control how one is allowed to authenticate to the server. I'm not interested in challenge-response, so that's off. I also don't trust users with setting secure passwords, so that's disabled. I also don't allow empty passwords, but since I don't allow passwords at all, this line is redundant. AuthenticationMethods controls which methods are allowed to be used to connect to the server. This makes sure we only allow public key authentication.

One added benefit to disabling password authentication is that bots don't try to bruteforce passwords on the server.

AllowGroups wheel ssh-user ssh-sftp-user

This line only allows users of the wheel (admins), ssh-user (any ssh user), and ssh-sftp-user (sftp only) groups to login. This makes administration easier and thus safer because it essentially makes ssh authentication into a normal UNIX group.

UsePAM yes

Enabling PAM does two major things. The first is handling authentication, though that is disabled because we explicitly disabled password and challenge-response above. The second is handling account checks (e.g. if the account allowed in PAM) and establishing the environment (e.g. print the MOTD), which is why this is turned on.

X11Forwarding yes

This allows running X applications on the server with the GUI forwarded to my laptop. I sometimes use this.

PrintMotd no

As the comment says, PAM already handles sessions and prints the Motd.

KexAlgorithms curve25519-sha256@libssh.org , ecdh-sha2-nistp521 , ecdh-sha2-nistp384 , ecdh-sha2-nistp256 , diffie-hellman-group-exchange-sha256 Ciphers chacha20-poly1305@openssh.com , aes256-gcm@openssh.com , aes128-gcm@openssh.com , aes256-ctr , aes192-ctr , aes128-ctr MACs hmac-sha2-512-etm@openssh.com , hmac-sha2-256-etm@openssh.com , umac-128-etm@openssh.com ,hmac-sha 2 - 512 ,hmac-sha 2 - 256 , umac-128@openssh.com

These directives restrict the key-exchange algorithm, ciphers and MACs sshd will be allowed to choose. This prevents outdated and insecure clients from connecting. While writing this post, I updated these to follow Mozilla guidelines, though I already had very similar lists before.

Note: I no longer ssh into my server from Android, but in the past I had issues because the client i was using didn't support recent enough Ciphers, so watch out with this one.

Subsystem sftp internal-sftp

This directive configures sshd to use the built-in sftp daemon. This is required for the ChrootDirectory configuration used below.

Match Group ssh-sftp-user

This directive means that the rest of the file (until the next Match directive) will only apply to users of the group ssh-sftp-user. I use it to better lock-down users that should only have sftp (file transfer) access.

Important: the Match directive takes effect until the end of the file, the next Match or the next Host . Do not get confused by the indentation, because it doesn't affect the scope!

X11Forwarding no AllowTcpForwarding no PermitTTY no

Disable X11 (discussed above) and TCP forwarding. TCP forwarding let users tunnel traffic through the server, for example using the -D , -L and -R flags to the ssh client.

ChrootDirectory %h

Lock these users to their home directories for extra safety. This requires the lock directory to be owned by root and not writable by anyone else. For example: drwxr-x--- 7 root backup 4096 Feb 9 11:49 backup

ForceCommand internal-sftp

Don't allow these users to run any commands other than the internal sftp implementation, again, to further restrict their access.

Please let me know if you spotted any mistakes or have any suggestions, and follow me on Twitter or RSS for updates.