_____ _ ___ _________ __ |_ _|__ _ __ _ __ ___ (_)_ __ __ _| \ \ / / ____\ \/ / | |/ _ \ '__| '_ ` _ \| | '_ \ / _` | |\ \ / /| _| \ / | | __/ | | | | | | | | | | | (_| | | \ V / | |___ / \ |_|\___|_| |_| |_| |_|_|_| |_|\__,_|_| \_/ |_____/_/\_\
SSH (Secure Shell) is a network protocol that creates a secure, encrypted communication channel between two computers. It was developed in 1995 by Finnish researcher Tatu Ylönen as an alternative to insecure Telnet and rlogin protocols. Today, SSH is the de facto standard method for connecting to remote servers, transferring files, and creating network tunnels.
The most basic use case for SSH is securely connecting to a remote server and executing commands. However, SSH's capabilities extend far beyond this: it offers many advanced features such as file transfer (SCP/SFTP), port forwarding, X11 forwarding (running graphical applications remotely), and creating VPN-like tunnels. From web developers managing servers to DevOps engineers automating processes, SSH is everywhere.
SSH is based on the client-server model. The following steps occur when establishing a connection:
# Basic connection (username@server address)
$ ssh user@server.example.com
# Connection with IP address
$ ssh root@192.168.1.100
# Connection on a different port (-p)
$ ssh -p 2222 user@server.example.com
# Verbose connection output (debugging)
$ ssh -v user@server.example.com
# Terminate the connection
$ exit
# or Ctrl+D
When you connect to a server for the first time, SSH shows the server's fingerprint and asks for confirmation. This is an important security step to verify the server's identity.
$ ssh user@new-server.com
The authenticity of host 'new-server.com (203.0.113.50)' can't be established.
ED25519 key fingerprint is SHA256:xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx.
Are you sure you want to continue connecting (yes/no/[fingerprint])? yes
Warning: Permanently added 'new-server.com' (ED25519) to the list of known hosts.
After confirmation, the server's key is saved in the ~/.ssh/known_hosts file. Subsequent connections perform this verification automatically.
Key-based authentication is much more secure and practical than using passwords. A key pair consists of two files: a private key and a public key that are mathematically related to each other.
# Generate an RSA key pair (4096 bits)
$ ssh-keygen -t rsa -b 4096 -C "email@example.com"
# Generate an Ed25519 key pair (recommended)
$ ssh-keygen -t ed25519 -C "email@example.com"
# Output:
# Generating public/private ed25519 key pair.
# Enter file in which to save the key (/home/user/.ssh/id_ed25519):
# Enter passphrase (empty for no passphrase):
# Enter same passphrase again:
# Your identification has been saved in /home/user/.ssh/id_ed25519
# Your public key has been saved in /home/user/.ssh/id_ed25519.pub
# Generate a key with a custom filename
$ ssh-keygen -t ed25519 -f ~/.ssh/project_key -C "project server"
Files created:
~/.ssh/id_ed25519 — Private key (NEVER share this with anyone!)~/.ssh/id_ed25519.pub — Public key (this is the file you copy to servers)After copying your public key to the remote server, you can connect without entering a password.
# Copy the public key to the server (easiest method)
$ ssh-copy-id user@server.example.com
# Manual copy (if ssh-copy-id is not available)
$ cat ~/.ssh/id_ed25519.pub | ssh user@server.example.com "mkdir -p ~/.ssh && chmod 700 ~/.ssh && cat >> ~/.ssh/authorized_keys && chmod 600 ~/.ssh/authorized_keys"
# Verify — you can now connect without a password
$ ssh user@server.example.com
SSH is very strict about key file permissions. Incorrect permissions will cause connection errors.
# Set correct permissions
$ chmod 700 ~/.ssh
$ chmod 600 ~/.ssh/id_ed25519
$ chmod 644 ~/.ssh/id_ed25519.pub
$ chmod 600 ~/.ssh/authorized_keys
$ chmod 644 ~/.ssh/known_hosts
The ~/.ssh/config file allows you to define shortcuts and custom settings for servers you frequently connect to. This way, you can use short aliases instead of typing long commands.
# ~/.ssh/config file example
# Global settings
Host *
ServerAliveInterval 60
ServerAliveCountMax 3
AddKeysToAgent yes
# Production server
Host production
HostName server.example.com
User deploy
Port 22
IdentityFile ~/.ssh/production_key
# Test server
Host test
HostName test.example.com
User developer
Port 2222
IdentityFile ~/.ssh/test_key
# GitHub
Host github.com
HostName github.com
User git
IdentityFile ~/.ssh/github_key
# Connection through bastion/jump host
Host internal-server
HostName 10.0.1.50
User admin
ProxyJump bastion.example.com
# You can now connect with short names
$ ssh production
# Equivalent: ssh -i ~/.ssh/production_key -p 22 deploy@server.example.com
$ ssh test
# Equivalent: ssh -i ~/.ssh/test_key -p 2222 developer@test.example.com
scp (Secure Copy Protocol) is used to copy files over SSH. Its syntax is similar to the cp command, but you can also send files to or download files from remote servers.
# Copy a local file to a remote server
$ scp file.txt user@server:/home/user/
# Copy from a remote server to the local machine
$ scp user@server:/var/log/app.log ./
# Copy a directory recursively (-r)
$ scp -r project/ user@server:/home/user/projects/
# Copy with a different port (-P uppercase!)
$ scp -P 2222 file.txt user@server:/tmp/
# Copy between two remote servers
$ scp user1@server1:/file.txt user2@server2:/destination/
# Copy with progress indicator
$ scp -v large-file.tar.gz user@server:/backup/
sftp (SSH File Transfer Protocol) provides an interactive file transfer session. It works with commands similar to FTP, but all communication is encrypted over SSH.
# Start an SFTP session
$ sftp user@server.example.com
# SFTP commands (within the session):
sftp> ls # List remote directory contents
sftp> lls # List local directory contents
sftp> cd /var/www # Change remote directory
sftp> lcd ~/Desktop # Change local directory
sftp> get file.txt # Download from remote
sftp> put local-file.txt # Upload to remote
sftp> mget *.log # Download multiple files
sftp> mput *.html # Upload multiple files
sftp> mkdir new-dir # Create remote directory
sftp> rm old-file.txt # Delete remote file
sftp> exit # Close session
SSH port forwarding allows you to create secure tunnels between local and remote ports. This feature is very useful for accessing services behind firewalls or encrypting traffic.
# Access remote MySQL through a local port
$ ssh -L 3307:localhost:3306 user@server.example.com
# You can now connect to remote MySQL via localhost:3307
# Access a web application on the remote network
$ ssh -L 8080:10.0.1.50:80 user@bastion.example.com
# localhost:8080 -> bastion -> 10.0.1.50:80
# Create a tunnel in the background (-f -N)
$ ssh -f -N -L 5432:localhost:5432 user@db-server.example.com
# Make local development server accessible remotely
$ ssh -R 8080:localhost:3000 user@server.example.com
# server:8080 -> local machine:3000
# Create a SOCKS proxy
$ ssh -D 1080 user@server.example.com
# Set browser proxy to SOCKS5: localhost:1080
PermitRootLogin no in the /etc/ssh/sshd_config file.# Recommended settings in /etc/ssh/sshd_config:
# Disable root login
PermitRootLogin no
# Disable password authentication
PasswordAuthentication no
# Do not allow empty passwords
PermitEmptyPasswords no
# Change the port
Port 2222
# Allow specific users
AllowUsers deploy developer
# Session timeout
ClientAliveInterval 300
ClientAliveCountMax 2
# Restart SSH service after changes
$ sudo systemctl restart sshd
# Start SSH agent
$ eval "$(ssh-agent -s)"
# Add key to agent
$ ssh-add ~/.ssh/id_ed25519
# List keys in agent
$ ssh-add -l
# Remove all keys from agent
$ ssh-add -D
SSH is the cornerstone of secure communication with remote systems. Establishing secure connections with the ssh command, generating key pairs with ssh-keygen, configuring key-based authentication with ssh-copy-id, managing connections with the SSH config file, secure file transfers with scp and sftp, and creating tunnels with port forwarding — all of these skills are essential in every system administrator's and developer's toolkit. Follow security best practices to keep your SSH infrastructure solid and boost your productivity.