Welcome. You’ve seen ssh
in commands, heard it’s the key to managing servers, and know it’s a non-negotiable skill for developers and system administrators. Today, you will master it.
This post is a self-contained course. We will go from the absolute basics to securely managing cloud servers, automating workflows, and using developer tools like GitHub. This guide integrates best practices and professional workflows to ensure that by the end, you won’t just use SSH; you will understand it.
Let’s begin.
At its heart, SSH (Secure Shell) is a protocol for creating a secure, encrypted tunnel between a client (your computer) and a server (the remote machine you want to control). Everything that passes through this tunnel—your commands, the server’s responses, and any files you transfer—is protected from eavesdropping.
It replaced insecure tools like Telnet, which sent everything, including passwords, in plain text.
Your First Mission: Connect with a Password
When you first launch a new VPS or cloud server, the provider typically gives you three pieces of information:
123.45.67.89
)root
)Let’s make our first connection. Open a terminal on your computer (Terminal on macOS/Linux, PowerShell or WSL on Windows).
# The syntax is: ssh <username>@<ip_address>
ssh [email protected]
The very first time you connect, you will see a message about the host’s authenticity:
The authenticity of host '123.45.67.89 (123.45.67.89)' can't be established.
ED25519 key fingerprint is SHA256:AbCdEf...
Are you sure you want to continue connecting (yes/no/[fingerprint])?
This is an important security feature. SSH is showing you the server’s public “fingerprint” and asking you to verify it’s the correct machine. Type yes
and press Enter. The server’s identity is now stored in a file at ~/.ssh/known_hosts
on your computer, and you won’t be asked again unless the server’s key changes.
You’ll then be prompted for the password. Type it (you won’t see the characters) and press Enter.
Congratulations! Your command prompt has changed. You are now logged into the remote server. To end your session, simply type exit
.
While simple, password authentication is slow and vulnerable to automated brute-force attacks. It’s time to learn the professional standard.
SSH keys are the modern, secure way to authenticate. Instead of a password, you use a matched pair of cryptographic keys.
id_ed25519
): This is your secret. It lives on your client machine and should be protected as fiercely as any password. Never share it.id_ed25519.pub
): This is the lock. You can freely give this key to any server or service you want to access.The server uses the public key to issue a challenge that only the holder of the private key can solve, proving your identity without ever sending a secret over the network.
Let’s create a key pair using the secure and efficient ed25519
algorithm.
# The -C flag adds a comment, usually your email, for easy identification.
ssh-keygen -t ed25519 -C "[email protected]"
You’ll be asked a couple of questions:
Enter file in which to save the key...
: Press Enter to accept the default location (~/.ssh/id_ed25519
).Enter passphrase (empty for no passphrase):
: It is strongly recommended to set a passphrase. This encrypts your private key on your disk. Even if your laptop is stolen, attackers can’t use your key without the passphrase.To grant your key access, you must add its public content to the ~/.ssh/authorized_keys
file on the server.
Method A: The Easy Way (ssh-copy-id
)
This command is designed for exactly this purpose. It automatically logs in and appends your key correctly.
# Syntax: ssh-copy-id <username>@<ip_address>
ssh-copy-id [email protected]
It will ask for your password one last time.
Method B: The Manual Way
If your client doesn’t have ssh-copy-id
, you can do it manually. This command reads your public key file and pipes it into a remote command that appends it to the authorized_keys
file.
cat ~/.ssh/id_ed25519.pub | ssh [email protected] "mkdir -p ~/.ssh && chmod 700 ~/.ssh && cat >> ~/.ssh/authorized_keys && chmod 600 ~/.ssh/authorized_keys"
Now, try logging in: ssh [email protected]
. It should now ask for your key’s passphrase (if you set one) instead of the server password.
Typing your key’s passphrase for every single connection is annoying. The SSH Agent is a background program that securely stores your decrypted private key in memory, so you only have to enter your passphrase once per session.
Start the Agent: The agent usually starts automatically on modern systems. You can ensure it’s running with:
eval "$(ssh-agent -s)"
Add Your Key: Now, add your private key to the agent.
ssh-add ~/.ssh/id_ed25519
You will be prompted for your passphrase. Once entered, the agent holds the decrypted key, and you can ssh
into your server multiple times without being asked again. This is a massive workflow improvement.
This same key pair is your passport to services like GitHub, GitLab, and Bitbucket. Using it for git
operations is more secure and convenient than passwords.
Copy Your Public Key:
# On macOS, this command copies it directly to your clipboard
pbcopy < ~/.ssh/id_ed25519.pub
# On Linux, you might need xclip
# xclip -selection clipboard < ~/.ssh/id_ed25519.pub
# Or just display it to copy manually
# cat ~/.ssh/id_ed25519.pub
Add to GitHub: Go to Settings > SSH and GPG keys > New SSH key, paste your key, give it a title, and save.
Test the Connection:
ssh -T [email protected]
A successful message confirms you’re set up. Now, when you clone repos, use the SSH URL ([email protected]:...
) for password-free git push
and git pull
.
The client-side SSH config file (~/.ssh/config
) is a game-changer. It lets you create aliases for servers, so you don’t have to remember IP addresses, usernames, and custom ports.
Create or open the file ~/.ssh/config
on your local machine and add entries like this:
# Main production web server
Host webserver
HostName 123.45.67.89
User yourname
Port 2222 # Example of a custom port
# Dev database server
Host db-dev
HostName 198.51.100.50
User admin
# Use a different key for this host
IdentityFile ~/.ssh/work_key
# Prevent connection drops during long sessions
Host *
ServerAliveInterval 60
Now, connecting is as simple as:
ssh webserver
ssh db-dev
The ServerAliveInterval 60
in the Host *
block is a useful tip that applies to all connections. It sends a “keep-alive” packet every 60 seconds to prevent your connection from being dropped due to inactivity.
SSH is a full suite of tools. Let’s explore its other capabilities.
scp
and sftp
)scp
(Secure Copy): For quick, one-off file transfers.
scp /path/to/local/file.txt webserver:/remote/path/
scp webserver:/remote/path/file.txt /local/path/
sftp
(Secure File Transfer Protocol): For an interactive, FTP-like session.
sftp webserver
.get
, put
, ls
, and pwd
.This is an incredibly powerful security technique. Imagine a database on your server that’s only listening on localhost
for security. You can’t connect to it from the internet, but you can with an SSH tunnel.
Local Port Forwarding (-L
): Access a remote service locally.
# Syntax: ssh -L <local_port>:localhost:<remote_port> <ssh_alias>
ssh -L 8080:localhost:3306 webserver
Now, point your local database client to localhost:8080
, and the traffic will be securely tunneled to port 3306
on the webserver
.
You can execute a command on a server without opening a full interactive session. This is perfect for scripting.
# Check uptime on the server
ssh webserver "uptime"
# Gracefully reload Nginx without logging in
ssh webserver "sudo systemctl reload nginx"
Now that you’re using key-based authentication, you must harden your server by disabling weaker, legacy access methods. These changes are made in the server-side configuration file, /etc/ssh/sshd_config
.
Log in to your server: ssh webserver
Open the file with a text editor: sudo nano /etc/ssh/sshd_config
Find and change the following lines. Ensure you uncomment them by removing the leading #
.
Disable Password Authentication: This is the single most important security change you can make. It renders brute-force password attacks useless.
PasswordAuthentication no
Disable Root Login: You should always log in as a regular user and use sudo
. This provides better auditing and safety.
PermitRootLogin no
(Crucial: Before doing this, ensure you have created a non-root user and have successfully logged in as them with their SSH key!)
(Optional) Change the Port: Bots constantly scan the default port 22. Changing it (e.g., to Port 2222
) reduces log noise from automated attacks. Remember to update your ~/.ssh/config
if you do this.
Save the file (Ctrl+X
, Y
, Enter
in nano).
CRITICAL: Restart the SSH service to apply the changes.
sudo systemctl restart sshd
TEST: Do not close your current session. Open a new terminal and confirm you can still log in with your new settings. If you get locked out, you can still fix the config file from your original session. Once you’ve verified access, you can safely close all windows.
If you ever have trouble connecting, the -v
(verbose) flag is your best friend. It prints out detailed debugging information about the connection process, showing you exactly where it’s failing.
# Use up to three 'v's for more detail
ssh -vvv webserver
You’ve done it. You have progressed from a basic password login to a professional, secure, and efficient SSH workflow. You can generate and use keys, configure clients and servers, transfer files, forward ports, and harden your systems against common threats.
SSH is the bedrock of remote administration and modern development. You now have the keys to the kingdom. Use them with confidence.
Enjoyed the article? I write about 1-2 a month. Subscribe via email or RSS feed.