ITcompressor IT — compressed and to the point
← Back to articles

SSH

SSH is an encrypted remote-access protocol: a shell on the server, file copying and traffic tunneling through a single port. The scenario of this article: the server web1.example.com, user admin.

Installing the server#

sudo apt update
sudo apt install openssh-server

The client (openssh-client) is already installed on Ubuntu; on machines without a server role — client only.

Server configuration#

The configuration lives in /etc/ssh/sshd_config. A basic safe set:

Port 22

# Root login over SSH is forbidden
PermitRootLogin no

# Key-based authentication
PubkeyAuthentication yes

# Keys live here
AuthorizedKeysFile .ssh/authorized_keys

# Password login — turn off once the keys are debugged
PasswordAuthentication no

# Verbose logging of connection attempts
LogLevel VERBOSE

Syntax check and restart:

sudo sshd -t
sudo systemctl restart ssh

sshd -t checks the config before the restart — that way you won't cut yourself off because of a typo. On Ubuntu/Debian the service is called ssh; in the RHEL family — sshd.

Enable PasswordAuthentication no only after the keys already work: otherwise you'll be locked out of server login (the last resort — the hoster's console/VNC).

Key generation#

The modern type — Ed25519 (short keys, fast verification):

ssh-keygen -t ed25519 -C "admin@laptop"

The keys appear in ~/.ssh/: the private id_ed25519 (never leaves the machine) and the public id_ed25519.pub (this is what you scatter over the servers).

RSA (ssh-keygen -t rsa -b 4096) — for very old servers where Ed25519 is not yet implemented.

ssh checks the permissions on ~/.ssh and the private key strictly:

chmod 700 ~/.ssh
chmod 600 ~/.ssh/id_ed25519

Copying the key to the server#

ssh-copy-id admin@web1.example.com

# A non-standard server port
ssh-copy-id -p 2222 admin@web1.example.com

The public key will be appended to the server's authorized_keys — password login will no longer be needed.

Connecting#

ssh admin@web1.example.com

# A non-standard port
ssh -p 2222 admin@web1.example.com

# A one-off command, without an interactive shell
ssh admin@web1.example.com "df -h /"

# Debugging connection problems (-vv — more verbose)
ssh -v admin@web1.example.com

The ~/.ssh/config file#

Host aliases: set it up once, then short ssh web1 calls without names/ports/keys:

# ~/.ssh/config
Host web1
    HostName web1.example.com
    User admin
    IdentityFile ~/.ssh/id_ed25519

Host db1
    HostName db1.example.com
    User admin
    Port 2222
    IdentityFile ~/.ssh/id_ed25519
ssh web1
scp backup.sh web1:/opt/

All options from config apply to scp and ssh-copy-id too — a host with an alias behaves like a regular name. The file must be readable only by you: chmod 600 ~/.ssh/config.

For logging in through an intermediate server (bastion) — the ProxyJump option: ssh -J bastion web1 or ProxyJump bastion in the Host web1 block.

Copying files: scp#

# A file to the server
scp deploy.sh admin@web1.example.com:/tmp/

# A file from the server to here
scp admin@web1.example.com:/var/log/app.log .

# A whole directory (recursively)
scp -r ./assets admin@web1.example.com:/var/www/

# The port uses a capital -P (in ssh it's a lowercase -p!)
scp -P 2222 file.txt admin@web1.example.com:~

# Preserve file times and permissions (-p)
scp -p admin@web1.example.com:/etc/nginx/nginx.conf .

Starting with OpenSSH 9.0 the default protocol is SFTP; for very old servers add -O (the old SCP protocol mode). For large directories and repeated syncs rsync -avz … is more convenient — it resumes and re-transfers only what changed.

The SSH agent#

The agent keeps decrypted keys in memory — the key passphrase is asked once per session:

eval $(ssh-agent)
ssh-add ~/.ssh/id_ed25519

On desktops (macOS, GNOME) the agent is usually already running — just ssh-add is enough. On macOS you can keep the key in the Keychain: ssh-add --apple-use-keychain.

Tunnels#

# Local forwarding: localhost:5432 → the DB on the server side
ssh -L 5432:localhost:5432 admin@db1.example.com

# Reverse: a server port leads to a service on your local machine
# (show a colleague your local development from the server)
ssh -R 8080:localhost:3000 admin@web1.example.com

# A SOCKS proxy on localhost:1080 — browser traffic through the server
ssh -D 1080 admin@web1.example.com

A tunnel lives as long as the ssh connection lives; run it with -N (no shell) and -T if you only need the tunnel: ssh -N -L 5432:localhost:5432 admin@db1.example.com.

← Back to articles