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-upgradesDuring 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-upgradesAdd 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-upgradesBy 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 usernameYou’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 usernameThis 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 upgradeStep 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_configLocate the line:
#PermitRootLogin prohibit-passwordAnd change it to:
PermitRootLogin noSave the file and restart the SSH service to apply changes:
sudo systemctl restart sshThis 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-ipVerify 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_configFind the line specifying the port (or add it if missing):
Port 2222You can choose any unused port above 1024. Save the changes and restart SSH:
sudo systemctl restart sshUpdate your firewall to allow the new port and remove access to the default port:
sudo ufw allow 2222/tcp
sudo ufw delete allow 22/tcpStep 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 4096This creates a public and private key. Copy the public key to the server:
ssh-copy-id -i ~/.ssh/id_rsa.pub username@server-ipAlternatively, 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-ipIf 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_configSet the following line:
PasswordAuthentication noRestart SSH to apply the change:
sudo systemctl restart sshStep 4: Additional SSH Hardening Tips
- Limit SSH access by IP: Only allow trusted IP addresses to connect via SSH in your firewall rules.
- Use
AllowUsersorAllowGroups: Restrict login to specific users or groups by addingAllowUsers usernamein/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 enableCheck the firewall status:
sudo ufw status verboseStep 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/tcpHTTP (web traffic):
sudo ufw allow 80/tcpHTTPS (secure web traffic):
sudo ufw allow 443/tcpDatabase services (if needed):
sudo ufw allow 3306/tcp # MySQL
sudo ufw allow 5432/tcp # PostgreSQLFTP or other services:
sudo ufw allow 21/tcp # FTPStep 3: Set Default Policies
To strengthen security, define default rules before enabling UFW:
sudo ufw default deny incoming
sudo ufw default allow outgoingThis 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 reloadCheck the status to ensure rules are active:
sudo ufw status verboseYou 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 -yOnce installed, enable and start the service so it runs automatically on boot:
sudo systemctl enable fail2ban --nowVerify that Fail2Ban is running:
sudo systemctl status fail2banYou 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.localAdd 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 fail2banStep 4: Verify Fail2Ban is Working
Check the status of the SSH jail:
sudo fail2ban-client status sshdThis command shows active bans and currently banned IP addresses.
sudo fail2ban-client status
sudo fail2ban-client statusWhy 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 -tulnpIf netstat is not installed, use:
sudo ss -tulnpThese 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-nameFor example, if Apache is running but not needed:
sudo systemctl stop apache2Next, disable the service so it doesn’t start automatically on boot:
sudo systemctl disable service-nameContinuing the Apache example:
sudo systemctl disable apache2Step 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 -yFor example, to remove PostgreSQL if it’s not needed:
sudo apt remove --purge postgresql -yAfter 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 -tulnpEnsure 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-statusThis 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.nginxYou can view all available profiles with:
ls /etc/apparmor.d/If needed, load custom profiles using:
sudo apparmor_parser -r /etc/apparmor.d/custom-profileStep 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 rebootOnce the server reboots, switch to enforcing mode:
sudo setenforce 1To make enforcing mode permanent, edit the SELinux configuration file:
sudo nano /etc/selinux/configSet:
SELINUX=enforcingVerify SELinux status:
sestatusStep 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 -yDuring 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 --initThis 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 --checkTripwire 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.twrThis 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 -eAdd a line like:
0 2 * * * /usr/sbin/tripwire --check | mail -s "Tripwire Daily Report" admin@example.comThis 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/syslogThis 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.login 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 -yConfigure it to send daily summaries of important events to your email:
sudo nano /etc/logwatch/conf/logwatch.confSet the following options:
MailTo = your-email@example.com Detail = High Range = yesterdayThis 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.sqlFor PostgreSQL:
pg_dump -U postgres database_name > /backup/location/database_name.sqlAutomate 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 -eExample: 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).sqlStep 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.sqlTesting 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.