SSH Basics

beginner ssh remote-access security keys

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_keys on the server
  • File permissions are wrong (SSH refuses keys with loose permissions)
  • We’re using the wrong key (check IdentityFile in 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.