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