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)":
- Wrong permissions on
~/.ssh/orauthorized_keys - Public key not added to
~/.ssh/authorized_keys PasswordAuthentication noset but no key configured- SSH agent not running / key not loaded