Skip to Content
DocsServerSSH Basics

SSH Basics

SSH (Secure Shell) is the most essential tool for managing Linux servers. This article covers OpenSSH installation and configuration, key management, and security best practices.

Installing OpenSSH

Installing the Server

# Install OpenSSH server sudo apt update sudo apt install openssh-server -y # Start and enable on boot sudo systemctl enable --now ssh # Check running status sudo systemctl status ssh # Check SSH listening port ss -tlnp | grep ssh

Installing the Client

# Ubuntu comes with the client pre-installed. If not: sudo apt install openssh-client -y

SSH Key Management

1Generate a key pair

ssh-keygen -t ed25519 -C "you@host" — keep the private key local, the public key is shareable.

2Push the public key

ssh-copy-id user@server appends the public key to the remote ~/.ssh/authorized_keys.

3Open a secure session

ssh user@server negotiates with your private key; the whole session is encrypted. Disable password login afterwards.

Key-based authentication is more secure and convenient than password authentication.

Generating a Key Pair

# Generate an Ed25519 key (recommended) ssh-keygen -t ed25519 -C "your_email@example.com" # Generate an RSA 4096-bit key (better compatibility) ssh-keygen -t rsa -b 4096 -C "your_email@example.com" # Specify a filename ssh-keygen -t ed25519 -f ~/.ssh/id_myserver -C "myserver key"

After key generation:

  • Private key: ~/.ssh/id_ed25519 (keep strictly secret)
  • Public key: ~/.ssh/id_ed25519.pub (can be distributed)

Copying the Public Key to the Server

# Method 1: Use ssh-copy-id (recommended) ssh-copy-id -i ~/.ssh/id_ed25519.pub user@server-ip # Method 2: Manual copy cat ~/.ssh/id_ed25519.pub | ssh user@server-ip "mkdir -p ~/.ssh && chmod 700 ~/.ssh && cat >> ~/.ssh/authorized_keys && chmod 600 ~/.ssh/authorized_keys" # Method 3: If you already have the public key content, add it directly on the server echo "ssh-ed25519 AAAA... your_email@example.com" >> ~/.ssh/authorized_keys

Managing the SSH Agent

# Start the SSH Agent eval "$(ssh-agent -s)" # Add a key to the Agent ssh-add ~/.ssh/id_ed25519 # List loaded keys ssh-add -l # Remove all loaded keys ssh-add -D

SSH Client Configuration

Edit ~/.ssh/config to simplify connections:

# ~/.ssh/config example Host myserver HostName 192.168.1.100 User ubuntu Port 22 IdentityFile ~/.ssh/id_myserver Host production HostName prod.example.com User deploy Port 2222 IdentityFile ~/.ssh/id_prod ForwardAgent yes Host jump HostName jump.example.com User admin # Connect to an internal server via a jump host Host internal HostName 10.0.0.50 User admin ProxyJump jump # Default settings for all hosts Host * ServerAliveInterval 60 ServerAliveCountMax 3 AddKeysToAgent yes Compression yes

Using the configured aliases:

# Connect directly using the alias ssh myserver # Equivalent to ssh -i ~/.ssh/id_myserver -p 22 ubuntu@192.168.1.100

SSH Server Configuration

The main configuration file is /etc/ssh/sshd_config.

Security Hardening Configuration

# Back up the original configuration sudo cp /etc/ssh/sshd_config /etc/ssh/sshd_config.bak # Edit the configuration sudo nano /etc/ssh/sshd_config

Recommended security settings:

# /etc/ssh/sshd_config # Change the default port (reduces scanning risk) Port 2222 # Listen only on a specific address ListenAddress 0.0.0.0 # Disable remote root login PermitRootLogin no # Disable password authentication (ensure key-based login is configured first) PasswordAuthentication no # Disable empty passwords PermitEmptyPasswords no # Enable public key authentication PubkeyAuthentication yes # Limit maximum authentication attempts MaxAuthTries 3 # Limit maximum concurrent unauthenticated connections MaxStartups 10:30:60 # Set login timeout LoginGraceTime 30 # Disable X11 forwarding (usually not needed on servers) X11Forwarding no # Disable insecure authentication methods KbdInteractiveAuthentication no # Display last login information PrintLastLog yes # Client keepalive detection ClientAliveInterval 300 ClientAliveCountMax 2 # Allow only specific users to log in AllowUsers ubuntu deploy # Or allow only specific groups # AllowGroups sshusers
# Check configuration syntax sudo sshd -t # Reload configuration (does not disconnect existing sessions) sudo systemctl reload ssh

Using Drop-in Configuration

Ubuntu 26.04 supports adding standalone configuration files in /etc/ssh/sshd_config.d/:

# Create a custom configuration sudo tee /etc/ssh/sshd_config.d/hardening.conf << 'EOF' PermitRootLogin no PasswordAuthentication no MaxAuthTries 3 X11Forwarding no EOF sudo systemctl reload ssh

Common SSH Operations

Basic Connections

# Basic connection ssh user@server-ip # Specify a port ssh -p 2222 user@server-ip # Specify a key ssh -i ~/.ssh/id_myserver user@server-ip # Execute a remote command ssh user@server-ip "df -h && free -h" # Connect in verbose mode (for debugging) ssh -v user@server-ip ssh -vvv user@server-ip # Even more verbose

File Transfer

# SCP: Copy a file to remote scp localfile.txt user@server-ip:/remote/path/ # SCP: Copy a file from remote scp user@server-ip:/remote/file.txt ./local/ # SCP: Copy a directory scp -r ./local-dir user@server-ip:/remote/path/ # SFTP: Interactive file transfer sftp user@server-ip # rsync: Incremental sync (recommended for large numbers of files) rsync -avz --progress ./local-dir/ user@server-ip:/remote/dir/

SSH Port Forwarding

# Local port forwarding: Map a remote service to localhost # Access local port 8080 to reach remote MySQL ssh -L 8080:localhost:3306 user@server-ip # Remote port forwarding: Expose a local service to the remote machine # The remote machine's port 9090 will forward to local port 3000 ssh -R 9090:localhost:3000 user@server-ip # Dynamic port forwarding (SOCKS proxy) ssh -D 1080 user@server-ip # Run port forwarding in the background ssh -fNL 8080:localhost:3306 user@server-ip

SSH Jump Hosts

# Connect to a target server via a jump host ssh -J jump-user@jump-host target-user@target-host # Multi-hop jumping ssh -J user1@jump1,user2@jump2 user@target

Key File Permission Requirements

SSH has strict file permission requirements:

# Correct permission settings chmod 700 ~/.ssh chmod 600 ~/.ssh/id_ed25519 # Private key chmod 644 ~/.ssh/id_ed25519.pub # Public key chmod 600 ~/.ssh/authorized_keys # Authorized keys chmod 600 ~/.ssh/config # Client configuration

Brute-Force Protection

Using fail2ban

# Install fail2ban sudo apt install fail2ban -y # Create local configuration sudo tee /etc/fail2ban/jail.local << 'EOF' [sshd] enabled = true port = ssh filter = sshd logpath = /var/log/auth.log maxretry = 3 bantime = 3600 findtime = 600 EOF # Start the service sudo systemctl enable --now fail2ban # Check ban status sudo fail2ban-client status sshd # Manually unban an IP sudo fail2ban-client set sshd unbanip 1.2.3.4

Using UFW to Restrict SSH Access

# Allow SSH only from a specific subnet sudo ufw allow from 192.168.1.0/24 to any port 22 # Rate-limit connections (max 6 connections within 30 seconds) sudo ufw limit ssh

Troubleshooting

# View SSH service logs sudo journalctl -u ssh -f # View authentication logs sudo tail -f /var/log/auth.log # Test connection (verbose mode) ssh -vvv user@server-ip # Check server configuration syntax sudo sshd -t # Check the authorized_keys file cat ~/.ssh/authorized_keys # Check whether SELinux/AppArmor is blocking connections sudo aa-status

Common Issues

“Permission denied (publickey)”

# Check that the client key is correct ssh-add -l # Check authorized_keys permissions on the server ls -la ~/.ssh/ ls -la ~/.ssh/authorized_keys # Confirm public key authentication is enabled in sshd_config grep PubkeyAuthentication /etc/ssh/sshd_config

“Connection refused”

# Check whether the SSH service is running sudo systemctl status ssh # Check the port ss -tlnp | grep ssh # Check the firewall sudo ufw status

“Host key verification failed”

# Remove the old host key ssh-keygen -R server-ip # Or edit the known_hosts file to delete the corresponding line nano ~/.ssh/known_hosts
Last updated on