How to Configure SSH Key-Based Authentication Only on macOS (Disabling Password Logins)


31 views

When exposing your Mac's SSH service to the internet, password authentication becomes a significant vulnerability. Brute force attacks targeting weak passwords are extremely common. Key-based authentication provides cryptographic security that's orders of magnitude stronger.

On macOS, the SSH daemon configuration file is located at /etc/sshd_config. You'll need sudo privileges to edit it:

sudo nano /etc/sshd_config

Find and modify these crucial directives:

PasswordAuthentication no
ChallengeResponseAuthentication no
UsePAM no
PubkeyAuthentication yes

For each user who needs access, create the ~/.ssh/authorized_keys file:

mkdir -p ~/.ssh
touch ~/.ssh/authorized_keys
chmod 700 ~/.ssh
chmod 600 ~/.ssh/authorized_keys

Add public keys to this file, one per line. For example:

ssh-rsa AAAAB3NzaC1yc2EAAA... user@client-machine

On client machines, generate keys with:

ssh-keygen -t ed25519 -f ~/.ssh/macmini_access

This creates two files:

  • macmini_access (private key - keep secure)
  • macmini_access.pub (public key - add to authorized_keys)

After configuration changes:

sudo launchctl stop com.openssh.sshd
sudo launchctl start com.openssh.sshd

Verify password login is disabled:

ssh -o PreferredAuthentications=password user@yourmac

This should fail with "Permission denied (publickey)".

Test key authentication:

ssh -i ~/.ssh/macmini_access user@yourmac

Consider these extra security measures:

# Change default port
Port 2222

# Limit user access
AllowUsers adminuser deployuser

# Enable fail2ban
brew install fail2ban

If connections fail:

  • Verify file permissions (700 for .ssh, 600 for authorized_keys)
  • Check system logs: sudo tail -f /var/log/system.log
  • Test with verbose output: ssh -vvv user@host

MacOS comes with OpenSSH server pre-installed, which uses the same configuration files as Linux systems. The main configuration file is located at /etc/sshd_config. Before making changes, it's crucial to back up the original file:

sudo cp /etc/sshd_config /etc/sshd_config.bak

Edit the SSH daemon configuration file with your preferred text editor (using nano here as example):

sudo nano /etc/sshd_config

Find and modify (or add if they don't exist) these directives:

PasswordAuthentication no
ChallengeResponseAuthentication no
UsePAM no
AuthenticationMethods publickey
PubkeyAuthentication yes

Before disabling password authentication, ensure you have working SSH keys set up. On your client machine, generate a new key pair:

ssh-keygen -t ed25519 -f ~/.ssh/macmini_access

Copy the public key to your Mac mini:

ssh-copy-id -i ~/.ssh/macmini_access.pub username@macmini.local

Or manually append the public key to ~/.ssh/authorized_keys on the server.

Before restarting the SSH service, test your configuration:

sudo sshd -t

If no errors are reported, restart the SSH service:

sudo launchctl stop com.openssh.sshd
sudo launchctl start com.openssh.sshd

On macOS, enable the firewall and configure it to allow incoming SSH connections:

sudo /usr/libexec/ApplicationFirewall/socketfilterfw --add /usr/sbin/sshd
sudo /usr/libexec/ApplicationFirewall/socketfilterfw --unblockapp /usr/sbin/sshd

For additional security, consider implementing these measures:

# Change default SSH port
Port 2222

# Limit authentication attempts
MaxAuthTries 3

# Restrict users who can SSH in
AllowUsers yourusername

# Enable logging
LogLevel VERBOSE

If you get locked out, you'll need physical access to the machine to revert changes. Keep a backup session open until you confirm key-based authentication works.

Check logs for authentication issues:

tail -f /var/log/system.log | grep sshd

For multiple macOS machines, consider using a configuration management tool like Ansible:

- name: Configure SSH Key Authentication Only
  hosts: mac_minis
  become: yes
  tasks:
    - name: Backup sshd_config
      copy:
        src: /etc/sshd_config
        dest: /etc/sshd_config.bak
        remote_src: yes
    - name: Configure SSH
      lineinfile:
        path: /etc/sshd_config
        regexp: "^{{ item.regexp }}$"
        line: "{{ item.line }}"
        state: present
      with_items:
        - { regexp: '^#?PasswordAuthentication', line: 'PasswordAuthentication no' }
        - { regexp: '^#?ChallengeResponseAuthentication', line: 'ChallengeResponseAuthentication no' }
        - { regexp: '^#?UsePAM', line: 'UsePAM no' }
    - name: Restart SSH
      service:
        name: sshd
        state: restarted