SSH (Secure Shell) is the standard protocol for secure remote server administration and file transfers on Debian systems, encrypting all data and credentials end-to-end so eavesdroppers cannot intercept login information or sensitive files. Unlike legacy protocols like Telnet and FTP, which transmit everything in plain text, SSH protects your remote access with industry-standard cryptography and multiple authentication methods (passwords, SSH keys, certificates). This guide covers installing and configuring SSH on Debian, hardening the OpenSSH server with firewall rules and security options, configuring key-based authentication, and deploying Fail2Ban to defend against brute force attacks.
You’ll learn how to verify SSH is running correctly, configure access restrictions, generate and deploy SSH keys for passwordless logins, and troubleshoot common connection issues. This is the complete workflow needed to safely expose SSH to the internet with multiple layers of protection.
These commands work across all currently supported Debian releases (13 Trixie, 12 Bookworm, and 11 Bullseye). The OpenSSH versions and configuration syntax are consistent, so you can use this guide regardless of which supported Debian version you’re running.
What is SSH and Why Use It?
SSH (Secure Shell) provides encrypted network communication between two systems, replacing insecure protocols like Telnet and rlogin that transmitted passwords and commands in plain text. When you connect to a Debian server over SSH, all data travels through an encrypted tunnel that prevents network eavesdropping, man-in-the-middle attacks, and credential theft. System administrators rely on SSH for secure remote server management, automated deployments, secure file transfers (via SCP and SFTP), and tunneling other protocols through encrypted connections.
OpenSSH is the most widely deployed SSH implementation, developed by the OpenBSD project and included in virtually every Linux distribution. Debian ships OpenSSH as the default SSH server and client, providing enterprise-grade security with minimal configuration. Once installed, SSH runs as a background service that listens for incoming connections on port 22, authenticating users through passwords, cryptographic keys, or certificates before granting shell access.
Update Debian Packages Before SSH Installation
Before installing the SSH server, update your Debian system to ensure all existing packages are current. This prevents potential conflicts and ensures you receive the latest security patches:
sudo apt update && sudo apt upgrade
This command runs two operations: apt update refreshes the list of available packages from Debian repositories (like checking for new mail), and apt upgrade installs newer versions of packages already on your system. The && operator ensures the second command only runs if the first succeeds. Expect to see output listing packages being upgraded; this may take 1-2 minutes on a fresh system.
Install SSH via APT Command
After updating your system, install the OpenSSH server package:
sudo apt install openssh-server
This command downloads and installs the SSH server software along with any required dependencies. You’ll see output showing package selection and download progress. When prompted “Do you want to continue?” press Y and Enter. The installation completes in seconds, and the SSH service starts automatically.
Confirm SSH Service is Running
Once the installation is complete, the SSH server will be enabled by default and will start automatically whenever you boot your system. You can check the status of the SSH server by executing the following command:
systemctl status ssh
The output confirms the SSH service is active and enabled:
● ssh.service - OpenBSD Secure Shell server
Loaded: loaded (/lib/systemd/system/ssh.service; enabled; preset: enabled)
Active: active (running) since Mon 2025-11-24 10:15:32 UTC; 2min ago
Main PID: 1234 (sshd)
Tasks: 1 (limit: 4915)
Memory: 2.1M
CPU: 45ms
CGroup: /system.slice/ssh.service
└─1234 "sshd: /usr/sbin/sshd -D [listener] 0 of 10-100 startups"
Verify SSH is Listening
Confirm SSH is listening on the correct port using the ss command (modern replacement for deprecated netstat):
sudo ss -tlnp | grep sshd
This command breaks down as: -t shows TCP connections, -l shows listening sockets (services waiting for connections), -n displays port numbers instead of service names, and -p shows which process owns the socket. The | grep sshd filters the output to show only SSH. If SSH is running correctly, you’ll see two lines (one for IPv4, one for IPv6):
LISTEN 0 128 0.0.0.0:22 0.0.0.0:* users:(("sshd",pid=1234,fd=3))
LISTEN 0 128 [::]:22 [::]:* users:(("sshd",pid=1234,fd=4))
The key indicator is LISTEN in the first column (this means SSH is actively accepting connections on port 22). If you changed the port earlier, you’ll see that custom port number instead of 22.
Debian uses the traditional
ssh.servicedaemon approach where SSH runs continuously once enabled. This differs from Ubuntu 24.04’s socket activation model but provides the same security and functionality for remote access.
With the SSH server installed and running, the next step is configuring security settings to protect against unauthorized access.
Harden SSH Server Security
The SSH configuration file is located at /etc/ssh/sshd_config. This file controls authentication methods, connection settings, and security policies for your SSH server.
Open SSHD Configuration File
To open the configuration file for editing, execute the following command in the terminal:
sudo nano /etc/ssh/sshd_config
This will open the configuration file in the nano editor, allowing you to make necessary changes.
The following security hardening options protect your SSH server from common attacks and unauthorized access attempts:
Configure UFW Firewall for SSH
Before modifying SSH configuration, secure the service through your firewall. Debian systems often use UFW (Uncomplicated Firewall) to manage network access. If UFW is not installed, install it first:
sudo apt install ufw
Allow SSH through the firewall on the default port 22:
sudo ufw allow 22/tcp
Enable UFW to activate the firewall rules:
sudo ufw enable
Verify the firewall status and confirm SSH access is allowed:
sudo ufw status
The output shows your active firewall rules:
Status: active To Action From -- ------ ---- 22/tcp ALLOW Anywhere 22/tcp (v6) ALLOW Anywhere (v6)
Look for the SSH rule showing ALLOW Anywhere (this confirms your firewall permits incoming SSH connections). If the status were REJECT or DENY, you would not be able to connect remotely. For detailed UFW configuration and management, see the UFW installation guide.
Change SSH Port (Optional)
SSH uses port 22 by default, which attackers frequently target in automated scans. Changing to a non-standard port reduces exposure to opportunistic attacks. To modify the port, locate this line in the configuration file:
#Port 22
Uncomment the line and replace 22 with your desired port number (e.g., 2222 or any unused port above 1024).
After changing the SSH port, you must update your firewall rules before restarting the SSH service. First, allow the new port through UFW (for example, sudo ufw allow 2222/tcp, replacing 2222 with your chosen port). Only then restart SSH with sudo systemctl restart ssh. Failing to update firewall rules first will lock you out of remote access.
Disable Root Login
Allowing direct root login creates a security risk since attackers know the username and only need to brute force the password. Disabling root login forces authentication through regular user accounts with sudo privileges. Locate this line in the configuration file:
#PermitRootLogin yes
Change “yes” to “no” to disable root login.
Allow or Deny Specific Users
Restrict SSH access to specific user accounts when multiple users exist on the system. This prevents unauthorized users from attempting SSH connections even if they have valid system accounts. Add these directives to the configuration file:
AllowUsers user1 user2
DenyUsers user3 user4
Replace “user1”, “user2”, “user3”, and “user4” with the actual usernames. After making changes to the configuration file, save and close it by pressing Ctrl+X, Y, and Enter.
Finally, to apply the changes, restart the SSH service using the following command:
sudo systemctl restart ssh
The SSH server applies the new security settings immediately and remains protected by your firewall rules.
Configure SSH Key Authentication
SSH key authentication provides stronger security than password-based logins. Keys use cryptographic pairs (public and private) to authenticate without transmitting passwords across the network. This section covers generating keys, copying them to your server, and testing key-based access.
Generate SSH Key Pair
First, generate a new SSH key pair on your local machine (the computer you’ll connect from):
ssh-keygen -t ed25519 -C "your_email@example.com"
This creates a cryptographic key pair using the Ed25519 algorithm. The -t ed25519 flag specifies Ed25519, which generates 256-bit keys that are faster to generate and verify than traditional 2048-bit or 4096-bit RSA keys while providing equivalent or better security. Ed25519 signatures are deterministic (no random number generation required), making them resistant to certain side-channel attacks that affect RSA. The -C flag adds a comment (your email helps identify which computer owns the key).
The command prompts you three times: first for the file location (press Enter to accept ~/.ssh/id_ed25519), then for a passphrase (optional but recommended; this password protects your private key if someone steals it). You’ll see output confirming the key files were created in your .ssh directory. While RSA keys remain widely supported, Ed25519 is the modern standard for new SSH key generation due to its performance and security advantages.
Copy Public Key to Debian Server
Transfer your public key to the Debian server using ssh-copy-id:
ssh-copy-id username@ip_address
Replace username with your Debian username and ip_address with your server’s IP. Enter your password when prompted. The command copies your public key to ~/.ssh/authorized_keys on the server and sets proper permissions automatically.
Test Key-Based Authentication
Connect to your server using the SSH key:
ssh username@ip_address
If configured correctly, SSH authenticates using your key instead of prompting for a password. If you set a passphrase on your key, you’ll need to enter it.
Disable Password Authentication (Optional)
After confirming key-based authentication works, disable password authentication entirely for maximum security. Edit the SSH configuration file:
sudo nano /etc/ssh/sshd_config
Find and modify these lines:
PasswordAuthentication no
PubkeyAuthentication yes
ChallengeResponseAuthentication no
Save the file and restart SSH:
sudo systemctl restart ssh
Before disabling password authentication, ensure you can successfully connect using SSH keys from all locations you need access. Keep an active SSH session open while testing to avoid locking yourself out. If you lose access to your SSH key, you will need physical or console access to restore password authentication.
SSH key authentication provides significantly stronger security than password-based authentication by eliminating brute-force attack vectors entirely. Production servers should disable password authentication completely once key-based access is confirmed working.
Protect SSH with Fail2Ban
Fail2Ban monitors SSH logs for repeated failed login attempts and automatically bans attacking IP addresses by updating firewall rules. This intrusion prevention tool significantly reduces brute force attacks against your SSH server. While changing ports and disabling root login help, Fail2Ban provides active defense against persistent attackers.
Install and configure Fail2Ban to protect your SSH service:
sudo apt install fail2ban
Fail2Ban activates automatically after installation and begins monitoring SSH by default. The service detects failed login attempts in /var/log/auth.log and temporarily bans IP addresses that exceed the configured threshold, typically five failures within ten minutes.
For detailed configuration including custom ban times, jail settings, and integration with UFW, see the Fail2Ban installation guide.
Connect to Remote Server via SSH
After installing and securing SSH, you can connect from any SSH client to remotely manage your Debian system.
Find Your Server IP Address
Determine your Debian server’s IP address using this command:
hostname -I
This displays your server’s IP addresses in a clean format. For example:
192.168.1.100 fd00::a1b2:c3d4:e5f6:7890
The first address (192.168.1.100 in this example) is typically your local network IPv4 address. Alternatively, if you need detailed network interface information, use ip addr show to identify specific interfaces and their configurations.
Connect from Remote Client
On the device you want to connect from, open the terminal. Type:
ssh username@ip_address
Replace “username” with your Debian system’s username and “ip_address” with the IP address you found earlier. For instance, if the username is “joshua” and the IP address is “192.168.1.100”, type:
ssh joshua@192.168.1.100
On your first connection to the server, SSH prompts you with a message like “The authenticity of host ‘192.168.1.100’ can’t be established. ED25519 key fingerprint is…” This is normal (SSH is asking you to verify the server’s identity to prevent man-in-the-middle attacks). Type “yes” and press Enter to accept and save the server’s key. Once accepted, SSH won’t ask again. Next, if using password authentication, enter your password when prompted. For key-based authentication, you’ll connect without a password (or enter your key passphrase if you set one during key generation).
Once connected, you have full command-line access to your Debian system. Common commands include ls to list files, cd to navigate directories, nano or vim to edit files, and sudo to run administrative tasks.
Debian 13 Release Notes and Compatibility
Debian 13 (Trixie) ships with OpenSSH 10.0p1, which introduces changes that affect existing SSH setups. If you’re upgrading from an older Debian release or managing servers with legacy SSH configurations, be aware of these breaking changes. See the Debian 13 release notes for complete details on all known issues and workarounds.
PAM Environment File No Longer Supported
OpenSSH in Debian 13 no longer reads the ~/.pam_environment file by default. This file was historically used to set environment variables for SSH sessions, but PAM deprecated this feature due to security concerns. If you relied on ~/.pam_environment to configure session variables, migrate them to your shell initialization files instead:
nano ~/.bashrc
Add your environment variables using the export command:
export MY_VAR="value"
export PATH=$PATH:/custom/bin
These settings will be active for all new SSH sessions. Existing connections won’t be affected, but after you upgrade or log in again, SSH will use the shell configuration instead.
DSA Keys No Longer Supported
OpenSSH 9.8p1 in Debian 13 has removed support for DSA (Digital Signature Algorithm) keys entirely. DSA keys are limited to 160-bit private keys and SHA-1 digests, making them cryptographically weak by modern standards. If you’re still using DSA keys to connect to servers, you must generate replacement Ed25519 keys before upgrading Debian or you’ll lose remote access.
Check if you’re using DSA keys by running:
ssh -v username@server 2>&1 | grep "Server accepts key"
If you see “ssh-dss” in the output, you’re using DSA. Generate a new Ed25519 key immediately:
ssh-keygen -t ed25519 -C "your_email@example.com"
ssh-copy-id -i ~/.ssh/id_ed25519.pub username@server
Test the new key works before removing the old DSA key from your system. If you have a legacy device that only supports DSA, the openssh-client-ssh1 package provides an older SSH implementation, but this is rarely needed in modern deployments.
Troubleshooting SSH Connection Issues
Connection Refused or Timed Out
If you receive “Connection refused” when attempting to connect, SSH is either not running or not listening on the expected port. Verify the service status on the server:
sudo systemctl status ssh
If the status shows inactive (dead), restart the service with sudo systemctl start ssh. If you changed the SSH port, verify you’re connecting to the correct port: ssh username@ip_address -p 2222 (replace 2222 with your custom port). “Connection timed out” usually indicates a firewall is blocking the connection (check that your UFW rules allow SSH and that external firewalls like ISP or cloud provider aren’t blocking the port).
Permission Denied During Key Authentication
This error means the server isn’t accepting your SSH key. Verify the key was copied correctly:
cat ~/.ssh/authorized_keys
You should see your public key starting with “ssh-ed25519” or “ssh-rsa”. If the file is empty or missing, copy your key again using ssh-copy-id username@ip_address. Also verify file permissions are correct on the server:
ls -ld ~/.ssh && ls -l ~/.ssh/authorized_keys
The .ssh directory should show permissions 700 and authorized_keys should show 600. If permissions are wrong, fix them: chmod 700 ~/.ssh && chmod 600 ~/.ssh/authorized_keys. Incorrect permissions are the most common cause of key authentication failures.
Locked Out After Disabling Password Authentication
If you disabled password authentication and lost your SSH key, you’ve locked yourself out remotely. You’ll need physical or console access to fix it. From the server console, edit the configuration file:
sudo nano /etc/ssh/sshd_config
Change PasswordAuthentication no back to PasswordAuthentication yes, save the file, and restart SSH with sudo systemctl restart ssh. You can now reconnect using your password and re-establish key-based access. Always keep at least one working authentication method accessible before disabling others.
SSH Session Closes Unexpectedly
SSH drops connections when configuration errors occur or the daemon crashes. Check the server’s SSH logs for detailed error messages:
sudo tail -20 /var/log/auth.log | grep sshd
Look for messages like “error: Could not load host key” or “fatal: Unmatched” which indicate configuration file syntax errors. Run a configuration syntax check:
sudo sshd -t
If you see errors, review your recent changes to /etc/ssh/sshd_config. Common mistakes include missing colons, incorrect option names, or improper quoting. Fix the error, verify syntax with sudo sshd -t again, and restart SSH.
Too Many Authentication Attempts or Banned by Fail2Ban
After multiple failed login attempts, SSH may reject new connections. If Fail2Ban is installed, it may have temporarily banned your IP address. Check the ban status:
sudo fail2ban-client status sshd
This shows banned IP addresses and when the ban expires (typically 10 minutes by default). To manually unban an IP, use:
sudo fail2ban-client set sshd unbanip 192.168.1.50
Replace 192.168.1.50 with the IP address to unban. Wait for the ban timer to expire naturally, or if you control the client machine, reconnect from a different network while the ban is active.
Bad Packet Length or Protocol Errors
This error typically occurs when non-SSH traffic is being sent to the SSH port, often because the port is forwarded to multiple services or a proxy is misconfigured. Verify SSH is the only service on that port:
sudo lsof -i :22
Only the SSH daemon (sshd) should appear in the output. If multiple processes are listed, disable or reconfigure the conflicting service. Also verify you’re not accidentally routing the SSH connection through a web proxy or HTTP tunnel, which would corrupt the SSH protocol.
Conclusion
Your Debian system now runs a hardened SSH server with firewall protection, key-based authentication, and automated intrusion prevention. You can manage the server remotely from anywhere with encrypted, authenticated connections while multiple security layers (UFW firewall rules, SSH key enforcement, port obfuscation, and Fail2Ban monitoring) defend against unauthorized access and brute force attacks.