10 things you must do to secure your linux server
Securing your Ubuntu server is essential to protect against unauthorized access, breaches, and downtime. This guide walks you through practical steps—covering updates, SSH hardening, firewalls, intrusion detection, and backups—to keep your system safe and resilient.
Update & Upgrade Regularly
One of the most fundamental steps to securing your Ubuntu server is keeping it up to date. Software vulnerabilities are the primary targets for attackers, and running outdated packages can leave your server exposed to known exploits. By regularly updating and upgrading your system, you ensure that security patches, bug fixes, and performance improvements are applied promptly, reducing the risk of compromise.
Start by refreshing your package lists and upgrading installed packages with the following
Commands:
sudo apt update && sudo apt upgrade -y
sudo apt install unattended-upgrades
sudo dpkg-reconfigure unattended-upgrades
During configuration, ensure that automatic security updates are enabled. This allows critical updates to be applied without your intervention, keeping your system secure even when you’re busy with other tasks.
For more granular control, you can manually configure which updates are automatically installed. Open the configuration file:
sudo nano /etc/apt/apt.conf.d/50unattended-upgrades
Add or verify the following lines to ensure only stable security updates are applied automatically:
Unattended-Upgrade::Allowed-Origins {
"Ubuntu stable";
"Ubuntu ${distro_codename}-security";
};
After making these changes, restart the unattended-upgrades service to apply the configuration:
sudo systemctl restart unattended-upgrades
By combining regular manual updates with unattended upgrades, you create a robust foundation for server security. Keeping your Ubuntu system updated not only protects against vulnerabilities but also ensures system stability, compatibility, and optimal performance.
Create a Non-Root User
Running commands as the root user on your Ubuntu server is risky. A single typo or malicious script executed as root can compromise your entire system. To reduce this risk, it’s highly recommended to create a non-root user with administrative privileges. This approach ensures that day-to-day operations are performed safely, and critical system changes are still controlled via sudo
when necessary.
Step 1: Create a New User
Start by creating a new user account. Replace username
with your preferred username.
sudo adduser username
You’ll be prompted to enter a password and optional user details such as full name, room number, or contact information. While these details are optional, setting a strong password is essential for security. Make sure it’s unique and not easily guessable
Step 2: Grant Administrative Privileges
To allow this user to perform administrative tasks, add them to the sudo
group:
sudo usermod -aG sudo username
This ensures that the new user can execute commands with elevated privileges using sudo
. For example, instead of logging in as root, the user can run:
sudo sudo apt update
sudo apt upgrade
Step 3: Disable Direct Root Login
For added security, prevent anyone from logging in as root via SSH. Open the SSH configuration file:
sudo nano /etc/ssh/sshd_config
Locate the line:
#PermitRootLogin prohibit-password
And change it to:
PermitRootLogin no
Save the file and restart the SSH service to apply changes:
sudo systemctl restart ssh
This ensures that all remote administrative actions must go through your non-root user, reducing the risk of unauthorized root-level access.
Step 4: Test the New User
Before closing your current session, test logging in as the new user:
ssh username@server-ip
Verify that you can execute commands with sudo
and that root login is no longer possible via SSH.
By creating a non-root user and disabling direct root login, you establish a safer baseline for server management. It’s a simple but highly effective step to protect your Ubuntu server from accidental or malicious system changes.
Secure SSH Access
SSH (Secure Shell) is the primary method to remotely access and manage your Ubuntu server. While convenient, it can also be a major attack vector if left unsecured. Securing SSH helps protect your server from brute-force attacks, unauthorized access, and potential compromise.
Step 1: Change the Default SSH Port
By default, SSH runs on port 22, which attackers frequently target. Changing the default port adds an extra layer of security.
Open the SSH configuration file:
sudo nano /etc/ssh/sshd_config
Find the line specifying the port (or add it if missing):
Port 2222
You can choose any unused port above 1024. Save the changes and restart SSH:
sudo systemctl restart ssh
Update your firewall to allow the new port and remove access to the default port:
sudo ufw allow 2222/tcp
sudo ufw delete allow 22/tcp
Step 2: Enable SSH Key Authentication
Password-based logins are vulnerable to brute-force attacks. SSH key authentication is far more secure. Generate a key pair on your local machine:
This creates a public and private key. Copy the public key to the server:
ssh-keygen -t rsa -b 4096
This creates a public and private key. Copy the public key to the server:
ssh-copy-id -i ~/.ssh/id_rsa.pub username@server-ip
Alternatively, you can manually add the key:
cat ~/.ssh/id_rsa.pub | ssh username@server-ip "mkdir -p ~/.ssh && cat >> ~/.ssh/authorized_keys"
Test the login:
ssh -p 2222 username@server-ip
If successful, you can proceed to disable password authentication.
Step 3: Disable Password Authentication
Disabling password login ensures only users with the correct SSH key can access your server. Edit the SSH configuration file:
sudo nano /etc/ssh/sshd_config
Set the following line:
PasswordAuthentication no
Restart SSH to apply the change:
sudo systemctl restart ssh
Step 4: Additional SSH Hardening Tips
- Limit SSH access by IP: Only allow trusted IP addresses to connect via SSH in your firewall rules.
- Use
AllowUsers
orAllowGroups
: Restrict login to specific users or groups by addingAllowUsers username
in/etc/ssh/sshd_config
. - Enable two-factor authentication (2FA): Add another layer of protection with tools like Google Authenticator or Duo Security.
By changing the default port, enforcing key-based authentication, and disabling passwords, you significantly reduce the risk of unauthorized access. SSH hardening is one of the most effective steps to protect your Ubuntu server from cyberattacks.
Configure a Firewall (UFW)
A firewall is a critical security layer that protects your Ubuntu server by controlling incoming and outgoing network traffic. Using UFW (Uncomplicated Firewall), you can easily manage firewall rules and prevent unauthorized access while allowing legitimate traffic.
Step 1: Install and Enable UFW
UFW comes pre-installed on most Ubuntu systems. You can check if it’s installed and install it if necessary:
sudo apt update
sudo apt install ufw -y
Enable UFW to start protecting your server:
sudo ufw enable
Check the firewall status:
sudo ufw status verbose
Step 2: Allow Only Necessary Ports
Only open ports required by your server’s services to minimize the attack surface. Common examples include:
SSH (custom port if changed):
sudo ufw allow 2222/tcp
HTTP (web traffic):
sudo ufw allow 80/tcp
HTTPS (secure web traffic):
sudo ufw allow 443/tcp
Database services (if needed):
sudo ufw allow 3306/tcp # MySQL
sudo ufw allow 5432/tcp # PostgreSQL
FTP or other services:
sudo ufw allow 21/tcp # FTP
Step 3: Set Default Policies
To strengthen security, define default rules before enabling UFW:
sudo ufw default deny incoming
sudo ufw default allow outgoing
This ensures all incoming traffic is blocked by default except the ports you explicitly allow, while outgoing connections remain unrestricted.
Step 4: Reload and Verify UFW
After adding your rules, reload UFW to apply the changes:
sudo ufw reload
Check the status to ensure rules are active:
sudo ufw status verbose
You should see a list of allowed ports and default policies clearly defined.
Install Fail2Ban
Even with a firewall in place, your Ubuntu server can still be vulnerable to brute-force attacks, where attackers repeatedly try to guess your passwords. Fail2Ban is a powerful tool that monitors log files and automatically blocks IP addresses that exhibit suspicious behavior. Installing and configuring Fail2Ban significantly reduces the risk of unauthorized access.
Step 1: Install Fail2Ban
First, update your package list and install Fail2Ban:
sudo apt update
sudo apt install fail2ban -y
Once installed, enable and start the service so it runs automatically on boot:
sudo systemctl enable fail2ban --now
Verify that Fail2Ban is running:
sudo systemctl status fail2ban
You should see the service active and running.
Step 2: Configure Fail2Ban for SSH
Fail2Ban uses “jails” to define rules for specific services, such as SSH. To create or modify a local jail configuration, edit /etc/fail2ban/jail.local
:
sudo nano /etc/fail2ban/jail.local
Add or update the following SSH rules:
[sshd]
enabled = true
port = 2222 # Replace with your custom SSH port
filter = sshd
maxretry = 3 # Number of failed attempts before banning
bantime = 3600 # Ban duration in seconds (1 hour)
findtime = 600 # Time window to count failed attempts (10 minutes)
Step 3: Restart Fail2Ban
After saving the configuration, restart the service to apply changes:
sudo systemctl restart fail2ban
Step 4: Verify Fail2Ban is Working
Check the status of the SSH jail:
sudo fail2ban-client status sshd
This command shows active bans and currently banned IP addresses.
sudo fail2ban-client status
sudo fail2ban-client status
Why Fail2Ban Matters
Fail2Ban provides automated protection against repeated login attempts, which are common in brute-force attacks. When combined with a firewall, SSH key authentication, and strong passwords, Fail2Ban helps create a layered security approach, making it much harder for attackers to compromise your Ubuntu server.
Disable Unused Services & Ports
Minimizing your server’s attack surface is a crucial step in hardening your Ubuntu server. Every open port and active service is a potential entry point for attackers. By disabling services you don’t need and closing unnecessary ports, you reduce the risk of exploitation and improve overall server security
Step 1: Identify Active Services and Open Ports
Start by checking which services are running and which ports are open:
sudo netstat -tulnp
If netstat
is not installed, use:
sudo ss -tulnp
These commands list all active TCP and UDP ports along with the processes using them. Look for services that you don’t need for your server’s operation. Common unnecessary services might include apache2
, mysql
, postgresql
, ftp
, or cups
if your server doesn’t require them.
Step 2: Stop and Disable Unneeded Services
Once you identify unnecessary services, stop them immediately to prevent them from running:
sudo systemctl stop service-name
For example, if Apache is running but not needed:
sudo systemctl stop apache2
Next, disable the service so it doesn’t start automatically on boot:
sudo systemctl disable service-name
Continuing the Apache example:
sudo systemctl disable apache2
Step 3: Remove Unnecessary Packages
For services you won’t use at all, removing the package entirely reduces potential vulnerabilities:
sudo apt remove --purge package-name -y
For example, to remove PostgreSQL if it’s not needed:
sudo apt remove --purge postgresql -y
After removal, your server is cleaner and uses fewer resources, improving performance and security.
Step 4: Verify Changes
After stopping, disabling, or removing services, recheck open ports:
sudo netstat -tulnp
Ensure only the necessary services are listening. You should see your essential services like SSH (custom port), HTTP, HTTPS, or any database services you intentionally left active.
Step 5: Regular Maintenance
Disabling unused services is not a one-time task. As you install new software or deploy applications, periodically audit your server to ensure no unnecessary services or ports are left open. Tools like lsof -i
and ufw status
can help you monitor network activity and keep your server secure.
Why This Matters
Every active service and open port is a potential security risk. By disabling or removing unnecessary components, you significantly reduce the server’s exposure to attacks. This proactive approach complements firewalls, Fail2Ban, and SSH hardening to create a robust, layered defense strategy.
Enable AppArmor or SELinux
Strengthening your Ubuntu server’s security goes beyond firewalls and SSH hardening. Mandatory Access Control (MAC) frameworks like AppArmor and SELinux provide an additional layer of defense by restricting what applications can do, even if they’re compromised. This prevents attackers from exploiting a single service to gain broader access to your system.
Step 1: Check AppArmor Status
Ubuntu comes with AppArmor enabled by default. To verify its status, run:
sudo aa-status
This command lists all loaded profiles and shows whether they’re in enforce mode (actively restricting apps) or complain mode (logging policy violations without enforcement).
Step 2: Enforce Profiles
To strengthen security, ensure critical applications like Nginx, MySQL, or Postfix are in enforce mode. For example, to enforce the Nginx profile:
sudo aa-enforce /etc/apparmor.d/usr.sbin.nginx
You can view all available profiles with:
ls /etc/apparmor.d/
If needed, load custom profiles using:
sudo apparmor_parser -r /etc/apparmor.d/custom-profile
Step 3: Consider SELinux for Advanced Control
While AppArmor is easier to manage, SELinux offers fine-grained security policies. It’s not enabled by default on Ubuntu, but you can install and activate it.
Install SELinux:
sudo apt install selinux-basics selinux-policy-default auditd -y
Activate SELinux in permissive mode (logs violations but doesn’t enforce):
sudo selinux-activate
sudo reboot
Once the server reboots, switch to enforcing mode:
sudo setenforce 1
To make enforcing mode permanent, edit the SELinux configuration file:
sudo nano /etc/selinux/config
Set:
SELINUX=enforcing
Verify SELinux status:
sestatus
Step 4: Fine-Tune Policies
Both AppArmor and SELinux allow you to create custom policies for specific applications. This is useful for applications that require special permissions, while still keeping strict controls in place for the rest of the system.
Why This Matters
Even if an attacker compromises an application, MAC frameworks limit their ability to escalate privileges or access sensitive files. By using AppArmor or SELinux, you create a layered security model that strengthens your server against sophisticated attacks.
Install & Configure a Host Intrusion Detection System (HIDS)
While firewalls and access controls protect your Ubuntu server from external threats, monitoring internal system changes is equally important. A Host Intrusion Detection System (HIDS) helps detect unauthorized modifications, suspicious activities, and potential intrusions by continuously monitoring system files and configurations. One of the most popular HIDS tools is Tripwire.
Step 1: Install Tripwire
Start by installing Tripwire:
sudo apt install tripwire -y
During the installation, you will be prompted to create a site key and a local key, which are used to sign Tripwire policies and reports. Keep these keys secure, as they are critical for the integrity of your HIDS setup.
Step 2: Initialize Tripwire Database
After installation, initialize the Tripwire database to create a baseline snapshot of your current system:
sudo tripwire --init
This baseline records the state of your system files, directories, and permissions, allowing Tripwire to detect any unauthorized changes later.
Step 3: Perform Integrity Checks
You can check the integrity of your system at any time:
sudo tripwire --check
Tripwire will generate a report highlighting any modifications, additions, or deletions compared to the baseline.
- Legitimate changes, such as package updates, should be incorporated into the baseline.
- Suspicious or unexpected changes should be investigated immediately.
Step 4: Update the Baseline Database
If changes are valid and intentional, update the Tripwire database to reflect the new state:
sudo tripwire --update -r /var/lib/tripwire/report/your-hostname-yyyyMMdd-HHmmss.twr
This ensures that future integrity checks only flag unauthorized or unexpected modifications.
Step 5: Automate Regular Checks
To maintain continuous protection, schedule automatic daily checks using cron:
sudo crontab -e
Add a line like:
0 2 * * * /usr/sbin/tripwire --check | mail -s "Tripwire Daily Report" admin@example.com
This runs Tripwire at 2 AM daily and emails the report to the system administrator.
Step 6: Analyze Reports
Tripwire reports can show:
- Changes in system binaries
- Unauthorized file modifications
- Permission changes
- Newly created or removed files
Careful monitoring of these reports allows you to detect intrusion attempts early and take corrective action before damage occurs.
Why HIDS is Critical
Even a well-secured server can be compromised if attackers gain access through zero-day exploits or misconfigurations. HIDS acts as an early warning system, helping you detect intrusions and maintain the integrity of your Ubuntu server over time. By combining Tripwire with other security measures like firewalls, SSH hardening, and AppArmor/SELinux, you create a multi-layered security strategy that significantly reduces risk.
Enable Log Monitoring
Monitoring your Ubuntu server logs is a crucial step in maintaining security and system health. Logs provide insight into what’s happening on your server, helping you detect suspicious activity, troubleshoot issues, and prevent potential attacks before they escalate. By proactively monitoring logs, you gain visibility into failed login attempts, system errors, and unusual behavior.
Step 1: Check Authentication Logs
Start by monitoring authentication attempts to identify potential unauthorized access:
sudo cat /var/log/auth.log | grep "Failed password"
This command filters your authentication log for failed login attempts. Frequent failures from the same IP address can indicate a brute-force attack, allowing you to take action quickly.
You can also check for successful logins:
sudo cat /var/log/auth.log | grep "Accepted password"
Tracking both failed and successful login attempts helps you spot suspicious activity patterns.
Step 2: Monitor System Logs in Real-Time
To keep an eye on system activities and events as they happen, use:
sudo tail -f /var/log/syslog
This streams log entries in real time, letting you see system operations, warnings, errors, or unexpected behavior as they occur. You can stop the stream anytime by pressing Ctrl + C
.
Step 3: Monitor Specific Service Logs
Depending on your server’s role, monitor logs for critical services such as:
- Web server (Nginx/Apache):
sudo tail -f /var/log/nginx/access.log sudo tail -f /var/log/nginx/error.log
- Database (MySQL/PostgreSQL):
sudo tail -f /var/log/mysql/error.log
- SSH:
Already covered under authentication logs, but monitoring/var/log/auth.log
in real-time is helpful.
Step 4: Automate Log Alerts
For ongoing monitoring, set up automated alerts. One simple way is to use logwatch
:
sudo apt install logwatch -y
Configure it to send daily summaries of important events to your email:
sudo nano /etc/logwatch/conf/logwatch.conf
Set the following options:
MailTo = your-email@example.com Detail = High Range = yesterday
This ensures you receive daily updates highlighting suspicious activity, errors, and system changes.
Step 5: Combine with Fail2Ban
Log monitoring works best when combined with tools like Fail2Ban, which automatically reacts to suspicious activity. While Fail2Ban scans logs for repeated failed login attempts, your manual log checks can catch anomalies not covered by automation.
Step 6: Best Practices for Log Management
- Rotate logs regularly to prevent disk space issues:
sudo logrotate /etc/logrotate.conf
- Store critical logs off-server or on a secure backup to ensure historical data is preserved.
- Review logs at least daily, or more frequently for high-traffic servers.
- Use centralized logging tools like Graylog, ELK Stack, or Splunk for enterprise environments.
Why Log Monitoring Matters
Log monitoring is your early-warning system. It allows you to detect attacks, misconfigurations, or performance issues before they escalate. By maintaining vigilance over authentication attempts, system events, and service activity, you strengthen your Ubuntu server’s overall security posture and reduce downtime caused by unnoticed problems.
Regular Backups & Disaster Recovery
Backing up your Ubuntu server regularly is essential for protecting your data and ensuring business continuity. Even with the best security measures in place, hardware failures, accidental deletions, ransomware, or other disasters can result in data loss. A solid backup strategy combined with a disaster recovery plan ensures you can restore your server quickly and minimize downtime.
Step 1: Identify What to Back Up
Before implementing a backup strategy, decide which data and configurations are critical. Typically, this includes:
- Application files and configurations (
/var/www
,/etc
,/opt
) - Databases (MySQL, PostgreSQL, MongoDB)
- User data (
/home/username
) - System configurations for services and firewalls
Prioritizing important files helps optimize storage and ensures essential data is never missed.
Step 2: Choose a Backup Method
Several methods exist for backing up your server:
a) Using rsync
for File Backups
rsync
is a fast and flexible tool for copying files locally or to a remote server. Example:
rsync -avz /important/files/ /backup/location/
This copies files and preserves permissions, timestamps, and symbolic links. Use the -z
option to compress data during transfer.
b) Database Backups
For MySQL or MariaDB:
mysqldump -u root -p database_name > /backup/location/database_name.sql
For PostgreSQL:
pg_dump -U postgres database_name > /backup/location/database_name.sql
Automate database backups with cron jobs to ensure they happen consistently.
c) Full Server Snapshots
If your server is virtualized (like on AWS, DigitalOcean, or VMware), consider creating full snapshots periodically. This allows you to restore the entire system to a previous state in case of critical failures.
Step 3: Automate Backups
Automation ensures backups happen regularly without manual intervention. Use cron to schedule tasks:
sudo crontab -e
Example: Daily file backup at 2 AM:
0 2 * * * rsync -avz /important/files/ /backup/location/
Example: Weekly database backup every Sunday at 3 AM:
0 3 * * 0 mysqldump -u root -pYourPassword database_name > /backup/location/database_name_$(date +\%F).sql
Step 4: Off-Site and Cloud Storage
Storing backups on the same server is risky. Always maintain off-site backups:
- Remote server via SSH:
rsync -avz /backup/location/ user@remote-server:/backup/
- Cloud storage services: AWS S3, Google Drive, Backblaze B2
- External drives: For physical redundancy
Redundant storage ensures data remains safe even if the server itself is compromised.
Step 5: Test Your Backups
A backup is only useful if it works. Regularly test restoration procedures:
rsync -avz /backup/location/ /restore/location/
For databases, import the backup into a test database:
mysql -u root -p test_database < /backup/location/database_name.sql
Testing helps identify corrupt or incomplete backups before a disaster occurs.
Step 6: Disaster Recovery Plan
A disaster recovery (DR) plan defines steps to restore operations after a failure:
- Identify critical systems and their recovery priorities.
- Maintain a list of all backup locations and credentials.
- Document restoration steps for files, databases, and configurations.
- Regularly update the plan and test it to ensure it works under real conditions.
Having a DR plan ensures that, in case of ransomware attacks, hardware failure, or accidental deletion, you can quickly recover and minimize downtime.
Why Regular Backups Matter
Regular backups combined with a tested disaster recovery plan are the safety net for your Ubuntu server. They protect against data loss, reduce recovery time, and provide peace of mind knowing your critical data is secure and recoverable. No matter how well-secured your server is, data can still be lost—backups are your last line of defense.
Conclusion
Securing your Ubuntu server is not a one-time task—it’s an ongoing process that requires vigilance, planning, and regular maintenance. By following best practices like keeping your system updated, creating non-root users, hardening SSH, configuring firewalls, installing Fail2Ban, disabling unnecessary services, implementing AppArmor or SELinux, setting up intrusion detection, monitoring logs, and maintaining regular backups with a disaster recovery plan, you significantly reduce the risk of unauthorized access, data breaches, and system compromise.
Remember, security is layered: no single measure is enough on its own. Consistently applying these strategies will help you create a robust, resilient server environment. Protecting your server means protecting your data, your applications, and ultimately, the trust of your users or clients. Start implementing these steps today and make security an integral part of your Ubuntu server management routine.