On CentOS servers configured for SSH key authentication (PasswordAuthentication no), we often need to maintain strict security for shell access while allowing password-based authentication for specific services like SFTP. This is particularly common when integrating with applications like Drupal that may require password authentication for file transfers.
The OpenSSH server provides granular control through its configuration file (/etc/ssh/sshd_config). Here's how to implement selective authentication:
# Global setting remains key-only
PasswordAuthentication no
# Match block for SFTP users
Match Group sftpusers
PasswordAuthentication yes
ForceCommand internal-sftp
ChrootDirectory /var/sftp/%u
PermitTunnel no
AllowAgentForwarding no
AllowTcpForwarding no
X11Forwarding no
Here's the complete procedure with concrete examples:
- Create an SFTP user group:
groupadd sftpusers - Add your Drupal service user:
useradd -G sftpusers drupal_user passwd drupal_user - Set up chroot environment:
mkdir -p /var/sftp/drupal_user/upload chown root:root /var/sftp/drupal_user chmod 755 /var/sftp/drupal_user chown drupal_user:sftpusers /var/sftp/drupal_user/upload
After restarting sshd (systemctl restart sshd), verify the setup:
# Test regular SSH (should fail with password)
ssh drupal_user@yourserver.com
# Test SFTP (should succeed with password)
sftp drupal_user@yourserver.com
When implementing this setup:
- Use strong passwords for SFTP accounts
- Regularly audit SFTP user activity
- Consider implementing fail2ban for SFTP attempts
- Set appropriate umask values in the SFTP chroot
For more granular control, you can match specific users instead of groups:
Match User drupal_user,backup_user
PasswordAuthentication yes
ForceCommand internal-sftp
Many server administrators face this dilemma: needing password-based SFTP access for specific applications while enforcing key-only authentication for SSH shell access. This is particularly common with CMS platforms like Drupal that rely on SFTP for file operations but where shell access should remain secured by SSH keys.
The solution lies in properly configuring Match blocks in /etc/ssh/sshd_config. Here's a working example:
# Global settings (applies to all connections)
PasswordAuthentication no
PubkeyAuthentication yes
# Special rules for SFTP subsystem
Match Group sftpusers
ForceCommand internal-sftp
PasswordAuthentication yes
PubkeyAuthentication no
ChrootDirectory /var/sftp
PermitTunnel no
AllowAgentForwarding no
AllowTcpForwarding no
X11Forwarding no
1. Create a dedicated group for SFTP users:
sudo groupadd sftpusers
2. Create a chroot directory with proper permissions:
sudo mkdir -p /var/sftp/uploads sudo chown root:root /var/sftp sudo chmod 755 /var/sftp sudo chown sftpuser:sftpusers /var/sftp/uploads
3. Add your Drupal service user to the group:
sudo usermod -a -G sftpusers drupal_user
4. Configure the Drupal settings.php to use SFTP:
$settings['file_chmod_directory'] = 0775; $settings['file_private_path'] = '/var/sftp/uploads/private'; $config['system.file']['path']['temporary'] = '/var/sftp/uploads/tmp';
When implementing this setup:
- Use strong passwords for SFTP accounts
- Regularly rotate passwords
- Monitor SFTP login attempts
- Consider implementing fail2ban for SFTP connections
- Set appropriate umask values (022 recommended)
If connections fail, check:
sudo tail -f /var/log/secure # Common errors include: # - Incorrect directory permissions # - SELinux context issues (run: restorecon -Rv /var/sftp) # - Missing ForceCommand directive