What it is:
- Secure Shell — protocol for encrypted remote access to machines over an untrusted network
- Gives you a terminal session on a remote server, with all traffic encrypted end-to-end
- Uses the same asymmetric + symmetric encryption model as tls — asymmetric for authentication/key exchange, symmetric for bulk data
Problem it solves:
- Before SSH:
telnetandrshsent everything (including passwords) in plaintext - Need to administer servers, transfer files, and tunnel traffic without eavesdroppers seeing your commands or credentials
Authentication Methods
Password authentication
- Server prompts for password, you type it
- Simple but weaker — vulnerable to brute force, phishing
- Most production servers disable this in favor of key-based auth
Key-based authentication (preferred)
- Generate a key pair on your local machine:
ssh-keygen -t ed25519- Private key: stays on your machine, never shared (
~/.ssh/id_ed25519) - Public key: copied to the server (
~/.ssh/authorized_keys)
- Private key: stays on your machine, never shared (
- When you connect, the server sends a challenge
- Your client proves it holds the private key (without sending the key itself)
- Server checks against the public key on file — if it matches, you're in
Same concept as tls_certificates — the private key proves your identity without ever crossing the network.
SSH Agent
- Background process that holds your unlocked private keys in memory
- You unlock your key once (with passphrase), the agent handles subsequent authentications
ssh-addloads a key into the agent;ssh-add -llists loaded keys- Agent forwarding (
ssh -A): lets you authenticate from a remote server using keys on your local machine — the remote server never sees your private key
This is what docker_buildx uses with --ssh — forwards your agent into the build container so it can clone private repos without baking keys into image layers.
Common Use Cases
Remote login
ssh user@192.168.1.100 # password or key auth
ssh -i ~/.ssh/mykey user@host # specific private key
File transfer
scp file.txt user@host:/path/— simple copy over SSHsftp user@host— interactive file transfer sessionrsync -e ssh— efficient sync with delta transfer
Port forwarding (tunneling)
# Local forward: access remote service through local port
ssh -L 5432:localhost:5432 user@bastion
# Now localhost:5432 reaches the remote server's PostgreSQL
# Remote forward: expose local service to the remote side
ssh -R 8080:localhost:3000 user@server
Useful for reaching databases or internal services that are only accessible from the server.
Git authentication
git@github.com:user/repo.gituses SSH under the hood- GitHub/GitLab check your SSH public key to identify you — no password needed
SSH Config
~/.ssh/config lets you define shortcuts and per-host settings:
Host myserver
HostName 192.168.1.100
User deploy
IdentityFile ~/.ssh/deploy_key
Port 2222
Now ssh myserver expands to the full connection details.
Security Practices
- Use Ed25519 keys (modern, fast, short) — avoid RSA unless compatibility requires it
- Protect private keys with a passphrase + SSH agent
- Disable password authentication on servers (
PasswordAuthentication noinsshd_config) - Disable root login (
PermitRootLogin no) — use a regular user +sudo - Known hosts (
~/.ssh/known_hosts): SSH remembers each server's public key on first connect — warns you if it changes (possible MITM attack)
Agent forwarding to untrusted servers is risky: A compromised server with agent forwarding can use your loaded keys to authenticate as you to other servers. Only use -A with servers you trust, or prefer ProxyJump (ssh -J bastion target) which doesn't expose your agent.
First connection trust: When you SSH to a new server, you see "The authenticity of host can't be established... Are you sure you want to continue?" — this is SSH asking you to verify the server's public key fingerprint. Once accepted, it's saved in known_hosts and future connections are verified automatically.