All articles
3 min read

Comprehensive SSH Guide

A practical SSH reference covering connections, key-based auth, SCP file transfer, SSH config file, agent forwarding, security hardening, and GitHub integration.

SSH (Secure Shell) is the standard way to connect to remote Linux servers and transfer files securely. This guide covers everything from basic connections to key management and server hardening.

Connecting to a Server

# Connect with a username
ssh username@192.168.1.100

# Connect on a non-default port
ssh -p 2222 username@192.168.1.100

# Connect with a specific identity file
ssh -i ~/.ssh/my_key username@192.168.1.100

Generating SSH Keys

# Ed25519 (recommended — modern, fast, secure)
ssh-keygen -t ed25519 -C "your@email.com"

# RSA 4096-bit (for compatibility with older systems)
ssh-keygen -t rsa -b 4096 -C "your@email.com"

Keys are saved to ~/.ssh/id_ed25519 (private) and ~/.ssh/id_ed25519.pub (public). Never share the private key.

Copying Your Key to a Server

# Recommended: uses ssh-copy-id
ssh-copy-id username@server-ip

# Manual alternative
cat ~/.ssh/id_ed25519.pub | ssh username@server-ip \
  "mkdir -p ~/.ssh && chmod 700 ~/.ssh && cat >> ~/.ssh/authorized_keys && chmod 600 ~/.ssh/authorized_keys"

SSH Config File (~/.ssh/config)

Instead of typing long connection strings, define hosts in ~/.ssh/config:

Host myserver
    HostName 192.168.1.100
    User alice
    Port 22
    IdentityFile ~/.ssh/id_ed25519

Host prod
    HostName prod.example.com
    User deploy
    IdentityFile ~/.ssh/deploy_key
    ForwardAgent yes

Then connect with just:

ssh myserver

SSH Agent

The SSH agent holds your decrypted keys in memory so you don't need to enter the passphrase repeatedly:

# Start the agent
eval "$(ssh-agent -s)"

# Add a key
ssh-add ~/.ssh/id_ed25519

# List loaded keys
ssh-add -l

# Remove all keys
ssh-add -D

Agent forwarding lets you use your local keys when SSH-ing from one server to another:

ssh -A username@jump-server
# Now you can SSH from jump-server to other hosts using your local key

File Transfer with SCP

# Copy local file to remote
scp ~/file.txt username@server-ip:~/destination/

# Copy remote file to local
scp username@server-ip:~/remote-file.txt ./local-dir/

# Copy a directory recursively
scp -r ~/mydir username@server-ip:~/

# Using a non-default port
scp -P 2222 file.txt username@server-ip:~/

File Transfer with SFTP

sftp username@server-ip

# Inside the sftp prompt:
put localfile.txt          # upload
get remotefile.txt         # download
ls                         # list remote files
lls                        # list local files
cd /path/on/server         # change remote directory
lcd /local/path            # change local directory
mkdir newdir               # create remote directory
exit

Running Remote Commands

# Run a single command and exit
ssh username@server-ip "sudo systemctl restart nginx"

# Run a multi-line command
ssh username@server-ip << 'EOF'
  cd /var/www
  git pull
  sudo systemctl reload nginx
EOF

GitHub SSH Setup

Set up SSH keys for GitHub to avoid entering your password on every push:

# Generate a GitHub-specific key
ssh-keygen -t ed25519 -C "github@youremail.com" -f ~/.ssh/id_ed25519_github

# Add to ssh-agent
ssh-add ~/.ssh/id_ed25519_github

# Add to ~/.ssh/config
echo "
Host github.com
    HostName github.com
    User git
    IdentityFile ~/.ssh/id_ed25519_github" >> ~/.ssh/config

# Test the connection
ssh -T git@github.com

Then add the public key (~/.ssh/id_ed25519_github.pub) to GitHub under Settings → SSH and GPG keys.

Server Security Hardening

Edit /etc/ssh/sshd_config on the server:

# Disable root login
PermitRootLogin no

# Require key-based auth (disable passwords)
PasswordAuthentication no

# Limit login attempts
MaxAuthTries 3

# Disable empty passwords
PermitEmptyPasswords no

# Restrict to specific users (optional)
AllowUsers alice bob

# Change default port (optional — reduces automated scanning)
Port 2222

Reload SSH after changes:

sudo systemctl reload sshd

Always verify you can still connect in a second session before closing your current one — a mistake in sshd_config can lock you out.

Troubleshooting

# Verbose output to diagnose connection issues
ssh -vvv username@server-ip

# Check sshd is running on the server
sudo systemctl status sshd

# Verify authorized_keys permissions (must be 600)
chmod 600 ~/.ssh/authorized_keys
chmod 700 ~/.ssh

Common causes of "Permission denied (publickey)":

  1. Wrong permissions on ~/.ssh/ or authorized_keys
  2. Public key not added to ~/.ssh/authorized_keys
  3. PasswordAuthentication no set but no key configured
  4. SSH agent not running / key not loaded