How to Secure a Linux Server | Full Guide

Where necessary, you may need to have access to a VPS server so you can follow how to implement the steps in this article.  You can get a cheaper VPS Server from Contabo with 4vCPU cores, 8GM RAM, and 32TB Bandwidth for less than $5.50 per month. Get this deal here now

Table of Contents

Cloud VPS S

$5.50 Monthly
  • 4 vCPU Cores | 8GB RAM


$15.50 Monthly
  • 6 vCPU Cores | 16GB RAM


$17.50 Monthly
  • 8 vCPU Cores | 24GB RAM

Securing a Linux server is super important if you want to keep your system and data safe from any potential threats. Linux is known for being strong when it comes to security, but it’s still crucial to configure it properly and follow the best practices to create a secure environment.

In this guide, we’ll take you through all the steps you need to secure your Linux server, starting from the initial setup all the way to maintaining that high level of security.

Update and Patch Regularly

It’s crucial to keep your Linux system updated to protect it from security vulnerabilities. One way to do this is by using the package manager offered by your Linux distribution to regularly update all the installed packages.

Run the update command

In Linux, the update command is a crucial tool for managing software packages and keeping your system up-to-date. Here are the syntaxes for running the update command on the system;

sudo apt update

Alternatively, you can use the following syntax:

sudo apt-get update

Running the update command synchronizes your system’s local package database with the latest information from the configured software repositories. This database contains a list of available packages, their versions, dependencies, and other relevant details.

Run the upgrade command

Before you can upgrade existing packages or install new ones, you need to run update. This ensures your system has the most current information about available packages, allowing for accurate and successful operations.

Here is the syntax for using the upgrade command

sudo apt upgrade

It’s important to note that running the update command refreshes your software information like a library catalog, while the upgrade command downloads and installs the newest editions, giving you the latest versions of the tools and packages on your Linux system.

More than upgrading using the dist-upgrade command

The dist-upgrade command is used to perform comprehensive system upgrades. It goes beyond simply updating existing packages as the upgrade does, and also handles more complex situations involving:

  • Installing new dependencies: When updating a package, a new version may require additional packages to function properly. dist-upgrade automatically identifies and installs these dependencies.
  • Removing conflicting packages: Sometimes, upgrading a package might create conflicts with other installed software. dist-upgrade intelligently analyzes these conflicts and, if necessary, removes the conflicting package to ensure a smooth upgrade.
  • Upgrading to new distribution releases: In some cases, dist-upgrade can even be used to upgrade to a new version of your entire Linux distribution within the same software base (e.g., from Ubuntu 18.04 to 20.04). However, this requires special tools like do-release-upgrade and thorough preparation.

Limit the number of Users

Limiting user account access to your Linux system is important. This means that you need to understand the number of users you’ve given access to your system and remove some of them if necessary.

List and view all Users in Linux

Before you delete, you need to understand the type of users accessing registered on your server. This will allow you to understand who to remove. This is necessary especially if you have several users created on the Linux server.

There are several ways to list and display the registered users on Linux, but in this article, we will be using the following command:

cat /etc/passwd

Here’s an example of what the /etc/passwd file might look like, including entries for example users; root, ugacomp, admin, and support:

ugacomp:x:1001:1001:UgaComp User:/home/ugacomp:/bin/bash
support:x:1003:1003:Support User:/home/support:/bin/bash

In this example:

  • root is the superuser with UID 0.
  • ugacomp is a regular user with UID 1001.
  • admin is another user with UID 1002.
  • support is yet another user with UID 1003.

The fields are separated by colons, and each line represents a user’s information. The fields are, in order: username, password (or ‘x’ if the password is in /etc/shadow), UID, GID, user information, home directory, and login shell. The actual values may vary based on your system configuration.

Delete or remove unnecessary Users in Linux

After understanding the usernames assigned to users created on your Linux server, you can use the userdel command to remove who you don’t want to access the system. Here is the syntax to use;

userdel username

Replace username with the actual username you want to delete.

To also delete the user’s home directory and its contents, add the -r flag:

userdel -r username

You can again use the cat /etc/passwd command to check if the user has been removed from the user list.

cat /etc/passwd

Downgrade user permissions

If you don’t want to permanently remove users from your system, you can simply downgrade their permissions.

List the sudo users from the sudoers file

The sudoers group in Linux isn’t actually a group in the traditional sense. It’s a special designation for users who are allowed to run commands with root privileges using the sudo command.

Assuming the following Linux users have various permissions:


If you want to filter out only sudo users in the above table, you can simply run the following command on your terminal;

sudo cat /etc/sudoers | awk '/User_Alias.*ADMINS/{flag=1; next} /[^[:space:]]/{flag=0} flag'

If you use the above command, it will output the lines containing the sudo users within the “ADMINS” alias, belonging to the sudoers group;


In this example:

  • ugacomp is a sudo user.
  • jane is also a sudo user.
  • Jessy is a sudo user as well.

Alternatively, if you can’t use the above command, you can simply use the sudoers files and view who the sudo users are. Run the following command to view the sudoers file in Ubuntu Linux;

sudo visudo

Here is the sample output of the sudoers file containing various users like ugcomp, jane, Jessy, root, john and mary

# Sample sudoers file with dummy users and permissions

# User alias
User_Alias ADMINS = ugacomp, jane, Jessy

# Define sudo privileges
root   ALL=(ALL:ALL) ALL

# Dummy user with limited permissions
john ALL=(root) /bin/ls

# Dummy user with permission to restart Apache
mary ALL=(ALL) /etc/init.d/apache2 restart

In the above file, the sudo users are defined by these lines below;

User_Alias ADMINS = ugacomp, jane, Jessy

# Define sudo privileges
root   ALL=(ALL:ALL) ALL

Removing a single sudo user

Removing a user from the sudoers group, means that they will not have privileged access to the server. Here is the syntax;

sudo gpasswd -d username sudo

You will need to replace username it with the actual username of the user you want to downgrade their permission.

Removing multiple sudo users

To remove multiple sudo users in Ubuntu using the terminal, you need to edit the sudoers file. You can use the visudo command, which provides a safe way to edit the sudoers file with syntax checking.

Run the following command on your terminal:

sudo visudo

Navigate to the section where the sudo privileges are defined. This is typically under the User_Alias or individual user lines. Remove the lines corresponding to the users you want to remove. For example, if you want to remove users “john” and “mary,” you might see lines like:

User_Alias ADMINS = alice, bob, john, mary

# Or individual user lines:
mary ALL=(ALL) /etc/init.d/apache2 restart

Now, you can remove users from the sudo group and assign them as regular users; See the configuration below:

# Comment out or remove the lines related to sudo access for the specified users
# User_Alias ADMINS = alice, bob, john, mary
# john ALL=(ALL:ALL) ALL
# mary ALL=(ALL) /etc/init.d/apache2 restart

# Add new lines to remove sudo privileges for the specified users
alice ALL=(ALL) /usr/sbin/nologin
bob ALL=(ALL) /usr/sbin/nologin
john ALL=(ALL) /usr/sbin/nologin
mary ALL=(ALL) /usr/sbin/nologin

Replace /usr/sbin/nologin with the path to the shell you want to use for these users. Using /usr/sbin/nologin ensures that the users cannot log in interactively.

Save the changes and exit the editor. In visudo, you can usually save by typing :wq and pressing Enter.

Secure SSH Access

SSH (Secure Shell) is a common method for remote server access. To enhance security, we need to configure some settings associated with SSH access to the server;

Change the default SSH port

Attackers often use automated scripts to scan for open ports, targeting commonly used defaults like port 22 for SSH. Changing the default SSH port makes it less likely for your server to be discovered in these initial scans, reducing the overall number of attacks.

To change the default SSH port on a Linux server, we need to edit the SSH configuration file located in the following path;

sudo nano /etc/ssh/sshd_config 

In this article, we’re using the nano editor and the sshd_config file will look as follows:

#   $OpenBSD: sshd_config,v 1.101 2017/03/14 07:19:07 djm Exp $

# This is the sshd server system-wide configuration file.  See
# sshd_config(5) for more information.

# This sshd was compiled with PATH=/usr/local/bin:/bin:/usr/bin

# The strategy used for options in the default sshd_config shipped with
# OpenSSH is to specify options with their default value where
# possible, but leave them commented.  Uncommented options override the
# default value.

Port 22
#AddressFamily any
#ListenAddress ::

# The default requires explicit activation of protocol 1
#Protocol 2

# HostKey for protocol version 1
#HostKey /etc/ssh/ssh_host_key
# HostKeys for protocol version 2
#HostKey /etc/ssh/ssh_host_rsa_key
#HostKey /etc/ssh/ssh_host_dsa_key
#HostKey /etc/ssh/ssh_host_ecdsa_key
#HostKey /etc/ssh/ssh_host_ed25519_key

# Lifetime and size of ephemeral version 1 server key
#KeyRegenerationInterval 1h
#ServerKeyBits 1024

# Ciphers and keying
#RekeyLimit default none

# Logging
#SyslogFacility AUTH
#LogLevel INFO

# Authentication:

#LoginGraceTime 2m
#PermitRootLogin prohibit-password
#StrictModes yes
#MaxAuthTries 6
#MaxSessions 10

#RSAAuthentication yes
#PubkeyAuthentication yes

# The default is to check both .ssh/authorized_keys and .ssh/authorized_keys2
# but this is overridden so installations will only check .ssh/authorized_keys
#AuthorizedKeysFile      .ssh/authorized_keys

#AuthorizedPrincipalsFile none

#AuthorizedKeysCommand none
#AuthorizedKeysCommandUser nobody

# For this to work you will also need host keys in /etc/ssh/ssh_known_hosts
#RhostsRSAAuthentication no
# similar for protocol version 2
#HostbasedAuthentication no
# Change to yes if you don't trust ~/.ssh/known_hosts for
# RhostsRSAAuthentication and HostbasedAuthentication
#IgnoreUserKnownHosts no
# Don't read the user's ~/.rhosts and ~/.shosts files
#IgnoreRhosts yes

# To disable tunneled clear text passwords, change to no here!
#PasswordAuthentication yes
#PermitEmptyPasswords no

# Change to yes to enable challenge-response passwords (beware issues with
# some PAM modules and threads)
#ChallengeResponseAuthentication no

# Kerberos options
#KerberosAuthentication no
#KerberosOrLocalPasswd yes
#KerberosTicketCleanup yes
#KerberosGetAFSToken no

# GSSAPI options
#GSSAPIAuthentication no
#GSSAPICleanupCredentials yes

# Set this to 'yes' to enable PAM authentication, account processing,
# and session processing. If this is enabled, PAM authentication will
# be allowed through the ChallengeResponseAuthentication and
# PasswordAuthentication.  Depending on your PAM configuration,
# PAM authentication via ChallengeResponseAuthentication may bypass
# the setting of "PermitRootLogin without-password".
# If you just want the PAM account and session checks to run without
# PAM authentication, then enable this but set PasswordAuthentication
# and ChallengeResponseAuthentication to 'no'.
#UsePAM yes

#AllowAgentForwarding yes
#AllowTcpForwarding yes
#GatewayPorts no
#X11Forwarding no
#X11DisplayOffset 10
#X11UseLocalhost yes
#PermitTTY yes
#PrintMotd yes
#PrintLastLog yes
#TCPKeepAlive yes
#UseLogin no
#PermitUserEnvironment no
#Compression delayed
#ClientAliveInterval 0
#ClientAliveCountMax 3
#UseDNS no
#PidFile /var/run/
#MaxStartups 10:30:100
#PermitTunnel no
#ChrootDirectory none
#VersionAddendum none

# no default banner path
#Banner none

# override default of no subsystems
#Subsystem   sftp    /usr/libexec/sftp-server

# Example of overriding settings on a per-user basis
#Match User anoncvs
#   X11Forwarding no
#   AllowTcpForwarding no
#   PermitTTY no
#   ForceCommand cvs server

From your sshd_config file, locate the line that says Port 22 as shown below;

Port 22

Now, you need to change the port number to your desired value, preferably a high port number above 1024 that’s not commonly used by other services. In this article, we’re using port port 2250 as a substitute for the default SSH port 22. See below;

Port 2250

Make sure to choose a unique port that’s not used by any other service. You can learn more about ports in this guide.

RECOMMENDED READING: A Beginner’s guide to understanding Ports in Linux Systems

Make sure to save the changes after you’ve made the appropriate edits to your sshd_config file. Also, you will need to restart SSH server by running the following command;

sudo systemctl restart sshd

When you change the SSH port, you will also need to open it to the firewall. In this example, we’re using ufw firewall to open the example port 2250 as seen below;

sudo ufw allow 2250/tcp

To ensure the changes take effect, you can reload the UFW rules:

sudo ufw reload

Disable root login via SSH

Disabling root login in SSH is a good security practice as it adds an extra layer of protection to your system.

To disable root access to the server, you need to log in as a user with sudo privileges. Then we need to use a text editor to open the sshd_configuration file, which is usually located on this path;

sudo nano /etc/ssh/sshd_config

Please replace nano with your preferred text editor, such as vim or gedit.

Once the sshd_config file is opened, you need to find the following line:

PermitRootLogin no

All you have to do is to change to yes and the root login capability will be disabled. See the command below;

PermitRootLogin yes

After making the necessary edits, save the changes and then restart your SSH server using the following command;

sudo systemctl restart ssh

Limit the number of SSH login attempts

Limiting the number of SSH login attempts helps to prevent brute force attacks, and this can be done by locating the following lines in the SSH configuration file, or adding them if they don’t exist:

MaxAuthTries 3

This line sets the maximum number of authentication attempts before the connection is closed. You can also set the time in seconds during which the user must complete authentication using the following line below. Adjust the value as needed.

LoginGraceTime 30

Use Key-based authentication

Key-based SSH authentication is a more secure and convenient way to log into a remote server than using password authentication.

Here’s a step-by-step guide on how to set up and use key-based SSH authentication:

  • Generate SSH Key Pair

Open a terminal on your local machine and run the following command:

ssh-keygen -t rsa -b 2048

You can also specify a different algorithm (e.g., -t ed25519) and key size if you prefer. Follow the prompts to specify the file location and set a passphrase.

  • Copy the Public Key to the Remote Server

On the local machine, use the following command to copy the public key to the remote server. Replace username and remote-server with your actual username and server address:

ssh-copy-id username@remote-server

If ssh-copy-id is not available on your system, you can manually copy the contents of the local ~/.ssh/ (or the specified file) and append it to the ~/.ssh/authorized_keys file on the remote server:

cat ~/.ssh/ | ssh username@remote-server 'cat >> ~/.ssh/authorized_keys'
  • Turn off password authentication

If you’ve successfully set up the key-based authentication, you can turn off password authentication to further strengthen the security of your server.

This can be done by editing the sshd_config file and locating the following line;

PasswordAuthentication no

You need to change the value of the directive to yes to turn off password authentication as seen below;

PasswordAuthentication yes

Save the changes and restart the SSH server always

Close unnecessary Firewall Ports

It’s recommended not to unnecessarily have various ports open on the server. So, you can check the status of your firewall ports by running the following command;

sudo ufw status

This command will display the current status of the UFW, including information about which rules are active, whether the firewall is enabled, and the default policies for incoming and outgoing traffic.

Remove unnecessary port rules

If there is a port number that is open through the firewall, and you don’t want it to run, delete it using the following syntax;

sudo ufw delete allow <port_number>

For example, if you want to remove the RTMP port 1935, you can use the following command;

sudo ufw delete allow 1935

Block Port scanning in Ubuntu

Port knocking is a security technique used to protect a system from port scanning attacks by requiring a series of connection attempts to specific ports in a particular order before allowing access to a service.

Here’s how you can implement port knocking on Ubuntu using the knockd daemon:

Install Knockd

First, you need to install the knockd package. Open a terminal and run:

sudo apt-get update
sudo apt-get install knockd

Configure Knockd

Open the knockd configuration file in a text editor. You can use any text editor of your choice, such as nano or vim. For example:

sudo nano /etc/knockd.conf

Add the following configuration to the file:

     logfile = /var/log/knockd.log

     sequence    = 7000,8000,9000
     seq_timeout = 15
     tcpflags    = syn
     start_command     = /sbin/iptables -A INPUT -s %IP% -p tcp --dport 22 -j ACCEPT
     cmd_timeout       = 10
     stop_command      = /sbin/iptables -D INPUT -s %IP% -p tcp --dport 22 -j ACCEPT

This example assumes that you want to open SSH access on port 22. Adjust the sequence and start_command accordingly, if you want to open different ports or services.

After saving the configuration, restart the knockd service:

sudo service knockd restart

Implement File System Security

Defining the file permissions and ownerships on your Linux system is very important in strengthing security. This can be achieved by using the following methods;

Using the chmod utility

In Ubuntu and other Linux-based systems, file permissions are managed using the chmod command. You can use chmod to change the permissions of a file or directory. The basic syntax is as follows:

chmod options permissions file

Let’s say you want to give read, write, and execute permissions to the owner of a file called example.txt, read and execute permissions to the group, and read-only permissions to others. The permission settings for this would be rwxr-xr--. You can achieve this with the following command:

chmod 754 example.txt
  • 7 corresponds to rwx (read, write, and execute) for the owner.
  • 5 corresponds to r-x (read and execute) for the group.
  • 4 corresponds to r-- (read only) for others.

You can also use symbolic notation to modify permissions. Here’s an example:

chmod u=rwx,g=rx,o=r example.txt
  • u=rwx sets read, write, and execute for the owner.
  • g=rx sets read and execute for the group.
  • o=r sets read-only for others.

Here’s a table that represents various permissions using the numeric notation and symbolic notation in the chmod command:

Here’s a table that represents various permissions using the numeric notation and symbolic notation in the chmod command:

Numeric NotationSymbolic NotationPermission
0No permission
3-wxWrite, execute
5r-xRead, execute
6rw-Read, write
7rwxRead, write, execute

In the numeric notation, each digit represents a different user category:

  • First digit: Owner
  • Second digit: Group
  • Third digit: Others

Using the chown utility

In Linux, ownership of files and directories is managed using the chown command. The chown command allows you to change the owner and/or group of a file or directory. Here’s the basic syntax:

sudo chown [options] owner:group file_or_directory

The above command is broken down as below;

  • owner: The user to whom you want to assign ownership.
  • group: The group to which you want to assign ownership. This is optional. If you don’t specify a group, the file or directory will be assigned to the user’s default group.
  • file_or_directory: The file or directory for which you want to change ownership.

For example, you can change the owner of a file as seen below;

sudo chown username:groupname filename

If you want to change the owner of a directory, here is the command you can use;

sudo chown -R username:groupname directoryname

The -R option is used for recursive ownership changes, applying changes to all files and subdirectories within the specified directory.

Remember to replace username, groupname, filename, and directoryname with the actual user, group, file, and directory names.

Regular Backups

Implement a robust backup strategy to protect your data in case of a security breach or hardware failure. Use tools like rsync or tar to create backups and store them in a secure, remote location.

# Example: Backup using rsync

rsync -avz /path/to/source/ user@remote:/path/to/backup/

Monitoring and Logging

Fail2Ban is a security tool that helps protect Linux servers from malicious activities by monitoring log files for suspicious behavior and blocking IP addresses that exhibit such behavior. Here’s a step-by-step guide on how to set up Fail2Ban on Ubuntu:

Update Package List

First, update the package list before installing FailzBan

sudo apt update

Install Fail2Ban

After running an update, you can now install Fail2Ban

sudo apt install fail2ban

Configure Fail2Ban

The main configuration file for Fail2Ban is located at /etc/fail2ban/jail.conf. It’s recommended to create a local configuration file to avoid modifying the default one directly:

sudo cp /etc/fail2ban/jail.conf /etc/fail2ban/jail.local

Now, edit the local configuration file:

sudo nano /etc/fail2ban/jail.local

Adjust the settings as needed. Here are some common configurations:

  • Find the [DEFAULT] section and set ignoreip to specify trusted IP addresses.
  ignoreip = your_trusted_ip
  • Adjust the bantime, findtime, and maxretry parameters to define how long an IP will be banned, the time window for counting retries, and the maximum number of retries allowed.
  • Customize the [sshd] section to secure the SSH daemon.
  enabled = true
  port = ssh
  logpath = %(sshd_log)s

After making the necessary edits, you can restart fail2ban using this command;

sudo service fail2ban restart

Check if fail2ban is running using this command;

sudo fail2ban-client status

This should display information about the jails and their status.

To test if Fail2Ban is working, try to log in multiple times with incorrect credentials or perform other actions that might trigger the configured rules. After reaching the maximum allowed retries, the offending IP should be banned.

Monitor Fail2Ban Logs

You can monitor Fail2Ban logs to see its activity:

sudo tail -f /var/log/fail2ban.log

Adjust paths and settings according to your specific use case and services.

Keep Services to a Minimum

Disable unnecessary services to minimize the attack surface. Identify and stop services that are not essential for your server’s functionality.

List all running Services

You can start by listing all running services using this command.

sudo service --status-all

The sample output after running the above command would be as follows;

$ sudo service --status-all

 [ + ]  apache2
 [ + ]  vsftpd
 [ + ]  ssh
 [ ? ]  rdp

In this example:

  • “[ + ]” indicates that the service is running.
  • “[ ? ]” indicates that the service status is unknown.

Stop a Service

If you want to stop unwanted service, you can run the following command

sudo service servicename stop

For example, if you want to stop the apache service, here is the command you can use

sudo service apache2 stop


Securing a Linux server is an ongoing process that requires vigilance and regular updates. By following these steps and staying informed about the latest security practices, you can significantly reduce the risk of security breaches and ensure the integrity of your Linux server.

It’s important to note that the key to a secure server is a combination of strong configuration, regular maintenance, and a proactive approach to security.

Hire us to handle what you want

Hire us through our Fiverr Profile and leave all the complicated & technical stuff to us. Here are some of the things we can do for you:

  • Website migration, troubleshooting, and maintenance.
  • Server & application deployment, scaling, troubleshooting, and maintenance
  • Deployment of Kubernetes, Docker, Cloudron, Ant Media, Apache, Nginx,  OpenVPN, cPanel, WHMCS, WordPress, and more
  • Everything you need on AWS, IBM Cloud, GCP, Azure, Oracle Cloud, Alibaba Cloud, Linode, Contabo, DigitalOcean, Ionos, Vultr, GoDaddy, HostGator, Namecheap, DreamHost, and more.

We will design, configure, deploy, or troubleshoot anything you want. Starting from $10, we will get your job done in the shortest time possible. Your payment is safe with Fiverr as we will only be paid once your project is completed.