SSH (Secure Shell) is how we remotely access servers. Instead of physically sitting at a machine, we open a terminal, type ssh user@server, and we’re in. The entire session is encrypted — unlike the old days of Telnet where everything went over the wire in plain text.
Every backend developer, DevOps engineer, and anyone who deploys code to a server uses SSH daily. It’s one of those tools we absolutely need to know.
Password vs Key-Based Auth
When we SSH into a server, we need to prove who we are. There are two ways:
Password authentication — The server asks for a password, we type it in. Simple, but not great:
- Passwords can be brute-forced
- We have to type them every time
- If we manage 10 servers, that’s 10 passwords to remember
Key-based authentication — We generate a key pair (private + public). We put the public key on the server. When we connect, SSH uses math to verify we have the matching private key — without ever sending the key over the network. This is better because:
- No password to brute-force
- No password to type (or remember)
- The private key never leaves our machine
Generating SSH Keys
The modern standard is Ed25519 — it’s fast, secure, and produces short keys.
# Generate a new SSH key pair
ssh-keygen -t ed25519 -C "manish@pman47.cc"
# It will ask:
# - Where to save (default: ~/.ssh/id_ed25519) — just hit Enter
# - Passphrase — optional but recommended (encrypts the key on disk)
# This creates two files:
# ~/.ssh/id_ed25519 ← PRIVATE key (never share this)
# ~/.ssh/id_ed25519.pub ← PUBLIC key (put this on servers)
The private key is like our house key — we never give it to anyone. The public key is like the lock — we install it on every server we want to access.
# Copy the public key to a server
ssh-copy-id user@server-ip
# This adds our public key to ~/.ssh/authorized_keys on the server
# Or manually copy it
cat ~/.ssh/id_ed25519.pub
# Copy the output and paste it into ~/.ssh/authorized_keys on the server
After this, we can SSH in without a password:
ssh user@server-ip
# No password prompt — key auth just works
The SSH Config File
Typing ssh ubuntu@144.24.126.230 -i ~/.ssh/oracle_key -p 2222 every time is painful. The SSH config file at ~/.ssh/config lets us create shortcuts.
# ~/.ssh/config
# Oracle Cloud VPS
Host oracle
HostName 144.24.126.230
User ubuntu
IdentityFile ~/.ssh/oracle_ed25519
Port 22
# GitHub
Host github.com
HostName github.com
User git
IdentityFile ~/.ssh/github_ed25519
# Work server with jump host
Host work-prod
HostName 10.0.1.50
User deploy
IdentityFile ~/.ssh/work_key
ProxyJump bastion.work.com
Now instead of that long command, we just type:
ssh oracle # connects to the VPS
ssh work-prod # connects through the jump host automatically
git clone git@github.com:pman47/gyaan.git # uses the right key
SSH Keys for Git
GitHub and GitLab support SSH key authentication for pushing and pulling repos. Once we add our public key to our GitHub account, we never need to type passwords for Git operations.
# Add SSH key to the ssh-agent (so we don't type the passphrase every time)
eval "$(ssh-agent -s)"
ssh-add ~/.ssh/github_ed25519
# Test the connection
ssh -T git@github.com
# Hi pman47! You've successfully authenticated, but GitHub
# does not provide shell access.
# Clone using SSH (not HTTPS)
git clone git@github.com:pman47/gyaan.git
The SSH URL format is git@github.com:user/repo.git. If we’re still using HTTPS URLs (https://github.com/...), we can switch:
# Switch a repo from HTTPS to SSH
git remote set-url origin git@github.com:pman47/gyaan.git
Port Forwarding / Tunneling
SSH isn’t just for remote terminals. We can also use it to create encrypted tunnels — forwarding a port on our local machine to a port on a remote machine (or vice versa).
Local port forwarding — Access a remote service as if it were local:
# Forward local port 5432 to the remote server's PostgreSQL
ssh -L 5432:localhost:5432 ubuntu@oracle
# Now we can connect to the remote Postgres from our local machine:
# psql -h localhost -p 5432 -U postgres
This is incredibly useful when a database or service is behind a firewall and only accessible from the server. We create an SSH tunnel and access it through localhost.
The -N flag runs SSH without opening a shell — useful when we only need the tunnel:
# Just create the tunnel, no interactive shell
ssh -L 5432:localhost:5432 -N ubuntu@oracle
Common SSH Troubleshooting
When SSH doesn’t work, here are the usual suspects:
# Permission issues — SSH is strict about file permissions
chmod 700 ~/.ssh # directory must be 700
chmod 600 ~/.ssh/id_ed25519 # private key must be 600
chmod 644 ~/.ssh/id_ed25519.pub # public key can be 644
chmod 600 ~/.ssh/config # config file must be 600
# Debug connection issues with verbose mode
ssh -v user@server # shows what's happening step by step
ssh -vvv user@server # maximum verbosity for stubborn issues
If we see “Permission denied (publickey)”, it usually means:
- The public key isn’t in
~/.ssh/authorized_keyson the server - File permissions are wrong (SSH refuses keys with loose permissions)
- We’re using the wrong key (check
IdentityFilein config)
In simple language, SSH gives us encrypted remote access to servers, and key-based auth with a config file makes connecting to multiple servers effortless and secure.