CYBERSECURITY | LINUX | UBUNTU | DEVSECOPS | SERVER
Security doesn't have to be complicated.
Most vulnerabilities happen because the fundamentals get overlooked. A secure Linux server starts with getting the basics right, and those basics will protect us from the vast majority of threats we'll actually face.
#1. Start With a Minimal Installation
Every package we don't install is a package that can't be exploited. Strip out anything we don't need, and install only what actually supports our workload.
This small decision at the very beginning pays off big later. A lean system is easier to patch, easier to monitor, and much harder to break into. By keeping our server simple, we're already doing one of the most effective security steps available. We can always add packages later when we actually need them.
Fewer packages = fewer vulnerabilities = smaller attack surface.
Check listening ports:
sudo ss -tulpnThis command lists all listening TCP and UDP ports on the system, along with the processes that own them. It is very useful for checking which services are running and which ports they are using.
Review the output carefully and verify that every listed service is expected. Disable or remove any service that is not required to reduce the attack surface of the system.
# Check enabled services:
systemctl list-unit-files --type=service | grep enabled
# Disable and stop service
sudo systemctl disable service_name
sudo systemctl stop service_name
# Remove unused packages
apt autoremove --purge#2. Lock Down SSH
SSH is the main way we access our servers, and that also makes it one of the first things attackers try to exploit. Securing SSH should always be a top priority.
Disable root login and password logins
Prevent direct root access over SSH. Always log in as a normal user and use sudo instead.
Edit SSH configuration file (/etc/ssh/sshd_config)
PermitRootLogin no
PasswordAuthentication noDisable root and password-based logins over SSH to reduce the risk of brute-force attacks.
New to SSH? Read my article here:
Change default SSH Port
The default SSH port is 22. Changing it to a non-standard port can reduce automated attacks.
Fail2ban
Consider installing fail2ban to automatically block IP addresses that show malicious behavior. It's a simple daemon that monitors logs and creates firewall rules to ban attackers after repeated failed login attempts.
#3. Enable a Firewall (Even in the Cloud)
A firewall controls which ports, protocols, and IP addresses are allowed to communicate with our server.
The basic principle is straightforward:
Block all incoming connections except the specific services we're running.
If we're hosting a web server, allow ports 80 and 443. For SSH, allow only our SSH port, and ideally restrict it to specific IP addresses if we have a static connection.
#4. Keep System Updated
When we don't install updates, attackers can easily take advantage of known problems in our software. Many attacks don't use new or advanced tricks, they use old bugs that already have fixes available.
Enable Automatic Security Updates
Automatic updates install important security fixes in the background, so we don't have to remember to do it ourself.
# On Ubuntu / Debian
sudo apt install unattended-upgrades
sudo dpkg-reconfigure unattended-upgrades
# On Rocky Linux / AlmaLinux / CentOS
sudo dnf install dnf-automatic
sudo systemctl enable --now dnf-automatic.timerImportant: Don't Forget Reboots! Some updates (like kernel fixes) only work after a reboot.
# Check if a reboot is needed
# Ubuntu
if [ -f /var/run/reboot-required ]; then echo "Reboot needed"; fi
# RHEL-based systems
sudo needs-restarting -r#5. Use Least Privilege for Users and Services
Running everything as root is dangerous. If something goes wrong, it goes very wrong. Services and users should only have the permissions they actually need, nothing more. This limits how much damage can happen if an account or service is compromised.
Don't Run Services as Root
Most modern services support running as their own user, for example:
nginxwww-datapostgresdocker
Always check service configs and make sure they run under a dedicated user account, not root. This way, if the service is exploited, the attacker doesn't automatically get full control of the system.
Use Sudo for Admin Tasks Only
Users should log in as normal users and only use sudo when needed.
- No direct root login
- Use
sudofor system changes - Keep admin access limited to trusted users
Give Only the Permissions That Are Needed
Not every user needs full sudo access. We can allow specific commands only.
sudo visudo
# deploy user can restart nginx, but can't run other admin commands.
deploy ALL=(ALL) NOPASSWD: /bin/systemctl restart nginx
#6. Monitor Logs
Logs tell us what's happening on our system. Monitoring logs helps us detect suspicious activity.
Get Daily Log Summaries
Install Logwatch or configure rsyslog to send daily summaries. We don't need to read every log line, but we should regularly scan the summaries for unusual patterns such as unexpected login attempts, service failures, or disk space issues.
Note: For more sophisticated monitoring, consider setting up centralized logging with tools like Elasticsearch and Kibana.
#7. Set Up Proper Backup and Recovery
No matter how secure our system is, failures still happen like hardware issues, accidental deletions, bad deployments, or security incidents. Backups are our last line of defense.
Automate Backups
Backups should run automatically and regularly. We can use rsync with cron, backup tools like BorgBackup or Restic, or cloud provider snapshots.
Follow the 3–2–1 Rule
A simple and effective strategy:
- 3 copies of our data
- 2 different storage types
- 1 off-site copy
This protects us from hardware failure, accidental deletion, and ransomware.
Back Up What Matters
Focus on data that cannot be easily recreated:
- Databases
- Application data
- User uploads
- Configuration files
- Secrets (securely stored)
Backing up the entire OS is usually less important than backing up critical data and configs.
# 8. File Integrity Monitoring
Security isn't just about blocking attacks, it's also about knowing when something suspicious is happening.
File Integrity Monitoring (FIM) is a security control that tracks and verifies changes to critical files, configurations, and system assets to ensure they remain authorized and unaltered.
Install and configure tools like AIDE (Advanced Intrusion Detection Environment) to monitor file integrity. These tools create a database of important system files and alert us when critical files change in unexpected ways.
#9. Harden Network Services
For any service we expose to the internet, spend time configuring it securely.
- Web servers should use
HTTPSwith modernTLSconfigurations. - Databases shouldn't listen on public interfaces unless absolutely necessary.
- Application frameworks should run with minimal privileges.
Read the security documentation for each service we deploy.
Final thoughts
Perfect security doesn't exist, but good security is achievable. Building a secure server isn't about implementing every possible security measure. It's about developing a security-conscious mindset.
Ask this questions:
Why does this service need to run? Who needs access to this resource? What happens if this component is compromised?
Don't stress about the advanced stuff yet. Get these basics in place first, and we'll already be ahead of the majority of servers on the internet.
Thanks for reading! Hope this article helps you build more secure and reliable servers. Learn, Share, Impact!