📋 Overview
This comprehensive guide covers essential server hardening techniques for Ubuntu Server, focusing on security measures that should be implemented as a non-root user. Server hardening is the process of securing a server by reducing its attack surface and implementing security best practices to protect against potential threats and unauthorized access.
- Understanding and using sudo for administrative tasks
- Implementing SSH key authentication
- Configuring SSH for secure remote access
- Keeping your server updated
- Implementing firewall policies
- Using Fail2Ban for intrusion prevention
🛡️ Understanding Sudo: The Superuser Command
What is Sudo?
Sudo (Superuser Do) is a powerful command that allows permitted users to execute commands with elevated privileges without switching to the root user account. This approach provides an additional layer of security and accountability by making administrators more conscious of their actions and creating an audit trail of privileged operations.
How Sudo Works
Common Sudo Usage Examples
Example 1: Rebooting the Server
Call to reboot failed: Interactive authentication required.
$ sudo reboot
[sudo] password for andrew:
Connection closed by remote host.
Example 2: Editing Configuration Files
[ Error writing /etc/ssh/sshd_config: Permission denied ]
$ sudo nano /etc/ssh/sshd_config
[sudo] password for andrew:
[ File opens successfully for editing ]
Example 3: Clearing Cached Password
[ Clears the cached sudo password ]
When to Use Sudo
| Task Type | Requires Sudo? | Example |
|---|---|---|
| Installing packages | ✓ Yes | sudo apt install nginx |
| Updating packages | ✓ Yes | sudo apt update |
| Restarting services | ✓ Yes | sudo systemctl restart ssh |
| Editing system config files | ✓ Yes | sudo nano /etc/ssh/sshd_config |
| Viewing directories | ✗ No | ls -la |
| Changing your own files | ✗ No | nano myfile.txt |
🔑 SSH Key Authentication: Passwordless Security
Understanding SSH Key Authentication
SSH key authentication is a more secure alternative to password-based authentication. It uses a public-private key pair where the private key remains on your local machine (encrypted with a passphrase) and the public key is stored on the server. This method is significantly more secure because it eliminates the risk of password brute-force attacks and provides stronger cryptographic security.
🔐 Private Key (Encrypted)
Never leaves your machine
🔓 Public Key
Stored in ~/.ssh/authorized_keys
How SSH Key Authentication Works
Step-by-Step Implementation Guide
-
Verify You're on Your Local Machine
Before proceeding, ensure you're working on your local machine, not logged into the server. Check your terminal prompt.
$ hostname
HP ← Local machine
If you see your server hostname (e.g., "2404"), you're logged into the server. Type 'exit' to log out. -
Generate the SSH Key Pair
Create a 4096-bit RSA key pair on your local machine. This command works identically on Linux, Mac, and Windows (Git Bash).
$ ssh-keygen -t rsa -b 4096
Generating public/private rsa key pair.
Enter file in which to save the key (/home/andrew/.ssh/id_rsa):
my_2404_server_keys ← Use underscores, no spaces
Enter passphrase (empty for no passphrase):
******** ← Strong passphrase (NOT your server password)
Enter same passphrase again:
********
Your identification has been saved in /home/andrew/.ssh/my_2404_server_keys
Your public key has been saved in /home/andrew/.ssh/my_2404_server_keys.pubUnderstanding the Passphrase: The passphrase encrypts your private key on your local machine. It is NOT the password you use to log into your server. You'll need this passphrase each time you use the private key to connect to your server. -
Verify Key Generation
Check that both keys were created with correct permissions.
$ ls -l ~/.ssh/
-rw------- 1 andrew andrew 3389 Nov 05 10:30 my_2404_server_keys ← Private key (600)
-rw-r--r-- 1 andrew andrew 742 Nov 05 10:30 my_2404_server_keys.pub ← Public key (644) -
Copy Public Key to Server
Use ssh-copy-id to securely transfer and configure your public key on the server.
$ ssh-copy-id -i ~/.ssh/my_2404_server_keys.pub [email protected]
/usr/bin/ssh-copy-id: INFO: attempting to log in with the new key(s)
[email protected]'s password: ← Enter your server password (one last time)
Number of key(s) added: 1
Now try logging into the machine with:
ssh '[email protected]'
and check to make sure that only the key(s) you wanted were added.What Just Happened: The ssh-copy-id command connected to your server using SSH, created the necessary directories and files, added your public key to ~/.ssh/authorized_keys, and set the correct permissions automatically. -
Test SSH Key Authentication
Verify that you can log in using your private key instead of a password.
$ ssh -i ~/.ssh/my_2404_server_keys [email protected]
Enter passphrase for key '/home/andrew/.ssh/my_2404_server_keys':
******** ← Enter your passphrase to unlock the private key
Welcome to Ubuntu 24.04 LTS
andrew@2404:~$ ← Successfully logged in! -
Disable Password Authentication
Now that SSH key authentication works, disable password-based login for enhanced security.
$ cd /etc/ssh/sshd_config.d/
$ sudo nano 50-cloud-init.conf
[sudo] password for andrew:
# Find and modify the following line:
PasswordAuthentication yes
PasswordAuthentication no ← Change to 'no'
# Save and exit: Ctrl+X, then Y, then Enter -
Restart SSH Service
Apply the configuration changes by restarting the SSH service.
$ sudo systemctl restart ssh
[ SSH service restarted successfully ] -
Verify Password Authentication is Disabled
Log out and test that password authentication no longer works.
$ exit
logout
Connection to 192.168.1.100 closed.
$ ssh -i ~/.ssh/my_2404_server_keys [email protected]
Enter passphrase for key '/home/andrew/.ssh/my_2404_server_keys':
********
andrew@2404:~$ ← Only key authentication works now!
- DO NOT lose the private key file on your PC/Mac
- Create a backup copy on a USB stick and store it securely
- If you lose your private key and password authentication is disabled, you will be locked out of your server
- Keep your passphrase in a secure password manager
⚡ Server Updates: Keeping Your System Secure
Regular system updates are crucial for maintaining server security. Updates include security patches, bug fixes, and performance improvements that protect your server from known vulnerabilities and exploits.
Understanding System Update Messages
System restart required
Pending kernel upgrade
Running kernel version: 5.15.0-87-generic
Expected kernel version: 5.15.0-91-generic
When Server Restart is Required
After creating a new server instance, many hosting providers (like Vultr, DigitalOcean, AWS) automatically run package updates. If kernel updates are applied, you'll see a "System restart required" message. Here's how to handle it:
[sudo] password for andrew:
Connection to 192.168.1.100 closed by remote host.
# Wait a minute or two for the server to reboot
$ ssh -i ~/.ssh/my_2404_server_keys [email protected]
ssh: connect to host 192.168.1.100 port 22: Connection refused
# Server still rebooting, wait a bit longer...
$ ssh -i ~/.ssh/my_2404_server_keys [email protected]
Enter passphrase for key:
Welcome to Ubuntu 24.04 LTS
andrew@2404:~$ ← Restart complete, messages cleared
Regular Update Commands
| Command | Purpose | When to Use |
|---|---|---|
sudo apt update |
Updates package lists from repositories | Before installing or upgrading packages |
sudo apt upgrade |
Upgrades installed packages to newer versions | Weekly or when security updates available |
sudo apt dist-upgrade |
Upgrades packages and handles dependencies | For major system upgrades |
sudo apt autoremove |
Removes unnecessary packages | After upgrades to clean up |
$ sudo apt upgrade -y
$ sudo apt autoremove -y
$ sudo reboot ← Only if kernel was updated
🔥 Firewall Configuration: Closing Unused Ports
Implementing a firewall policy is one of the most crucial steps in server hardening. A properly configured firewall acts as a barrier between your server and potential threats, allowing only necessary traffic while blocking everything else.
Common Ports and Services
| Port | Service | Protocol | Should Allow? |
|---|---|---|---|
| 22 | SSH | TCP | ✓ Yes (for remote access) |
| 80 | HTTP | TCP | ✓ If running web server |
| 443 | HTTPS | TCP | ✓ If running web server |
| 3306 | MySQL | TCP | ✗ Block (internal only) |
| 5432 | PostgreSQL | TCP | ✗ Block (internal only) |
🛡️ Fail2Ban: Intrusion Prevention
Fail2Ban is an intrusion prevention framework that protects your server from brute-force attacks by monitoring log files and automatically blocking IP addresses that show malicious behavior, such as too many failed login attempts.
How Fail2Ban Works
- Automatically blocks brute-force SSH login attempts
- Protects web applications from DDoS and authentication attacks
- Reduces server load from malicious traffic
- Creates detailed logs of attack attempts
- Configurable rules for different services
📝 Summary and Best Practices
Security Checklist
| Security Measure | Status | Priority |
|---|---|---|
| Created non-root user with sudo privileges | ✓ Complete | Critical |
| Implemented SSH key authentication | ✓ Complete | Critical |
| Disabled password authentication | ✓ Complete | Critical |
| Applied system updates | ✓ Complete | High |
| Configure firewall (UFW) | Pending | Critical |
| Install and configure Fail2Ban | Pending | High |
Key Takeaways
- Always use sudo for administrative tasks to maintain security and accountability
- SSH key authentication is mandatory - never rely solely on passwords
- Generate keys locally on your PC/Mac, never on the server
- Backup your private key securely - losing it means losing access
- Keep systems updated regularly to patch security vulnerabilities
- Implement firewall rules to minimize attack surface
- Use Fail2Ban to protect against brute-force attacks
- Never lose your SSH private key - store it securely with backups
- Keep your passphrase in a password manager
- Always verify you're on your local machine before generating keys
- Test SSH key authentication before disabling password login
- Document your security configurations for disaster recovery
Quick Reference Commands
ssh-keygen -t rsa -b 4096
# Copy public key to server (LOCAL machine)
ssh-copy-id -i ~/.ssh/keyfile.pub user@server
# Login with SSH key (LOCAL machine)
ssh -i ~/.ssh/keyfile user@server
# Update system (ON server)
sudo apt update && sudo apt upgrade -y
# Restart SSH service (ON server)
sudo systemctl restart ssh
# Clear cached sudo password (ON server)
sudo -k
🎯 Next Steps
With SSH key authentication successfully implemented and password authentication disabled, your server is significantly more secure. The next phase of hardening will focus on configuring the firewall and implementing Fail2Ban. These steps will be completed in subsequent sections to create a comprehensive security posture for your Ubuntu server.
Remember: Security is not a one-time setup but an ongoing process. Regularly review logs, update systems, and stay informed about security best practices and emerging threats.