Bash If Else Syntax With Examples

When working with Bash and shell scripting, you might need to use conditions in your script.

In programming, conditions are crucial : they are used to assert whether some conditions are true or not.

In this tutorial, we are going to focus on one of the conditional statement of the Bash language : the Bash if else statement.

We are going to see how you can use this statement to execute your scripts conditionally.

You will also learnt how you can use nested Bash if else statements to create more complex code.

Bash If Else Statement

In order to execute a Bash “if else” statement, you have to use four different keywords : if, then, else and fi :

  • if : represents the condition that you want to check;
  • then : if the previous condition is true, then execute a specific command;
  • else : if the previous condition is false, then execute another command;
  • fi : closes the “if, then, else” statement.

When using the “if else” statement, you will need to enclose conditions in single or double squared brackets.

if [[ condition ]]
then
  <execute command>
else
  <execute another command>
fi

Note that the “ELSE” statement is optional, if you omit it, nothing will be executed if the condition evaluates to false.

Note : you need to separate the condition from the squared brackets with a space, otherwise you might get a syntax error.

If Else Examples

Now that you know more about the Bash “if else” statement, let’s see how you can use it in real world examples.

In this section, we are going to build a script that prints a message if it is executed by the root user.

If the script is not executed by the root user, it is going to write another custom message.

In order to check whether the script is executed by root, we need to see if the UID of the caller is zero.

#!/bin/bash

# If the user is root, its UID is zero.

if [ $UID  -eq  0 ]
then
  echo "You are root!"
else
  echo "You are not root."
fi

If Else Examples bash-else-if

As stated earlier, the “else” statement is not mandatory.

If we omit in our script created earlier, we would still be able to execute the first “then” statement.

#!/bin/bash

# If the user is root, its UID is zero.

if [ $UID  -eq  0 ]
then
  echo "You are root!"
fi

If Else Examples bash-else-if-2

Now, what if you want to add additional “if” statements to your scripts?

Bash If Elif Statement

The “If Elif” statement is used in Bash in order to add an additional “if” statements to your scripts.

In order to execute a Bash “if elif” statement, you have to use five different keywords : if, then, elif, else and fi :

  • if : represents the condition that you want to check;
  • then : if the previous condition is true, then execute a specific command;
  • elif : used in order to add an additional condition to your statement;
  • else: if the previous conditions are false, execute another command;
  • fi : closes the “if, elif, then” statement.
if [[ condition ]]
then
  <execute command>
elif [[ condition ]]
then
  <execute another command>
else
  <execute default command>
fi

Again, the “ELSE” statement is optional, so you may want to omit it if you do not need a default statement.

if [[ condition ]]
then
  <execute command>
elif [[ condition ]]
then
  <execute another command>
fi

If Elif Examples

In our previous section, we used the “if else” statement to check whether a user is root or not.

In this section, we are going to check if the user is root or if the user has a UID of 1002.

If this is not the case, we are going to exit the script and return the prompt to the user.

if [[ $UID  -eq  0 ]]
then
  echo "You are root!"
elif [[ $UID  -eq 1002 ]]
then
  echo "You are user, welcome!"
else
  echo "You are not welcome here."
  exit 1;
fi

If Elif Examples elif

Congratulations, now you know how to use the “if elif” statement!

Now what if you want to have multiple conditions under the same “if” statement?

Multiple Conditions in If Else

In order to have multiple conditions written in the same “if else” statement, you need to separate your conditions with an “AND” operator or a “OR” operator.

# AND operator used in if else.

if [[ <condition_1> && <condition_2> ]];
then
   <execute command>
fi

# OR operator used in if else.
if [[ <condition_1> || <condition_2> ]];
then
   <execute_command>
else
   <execute_another_command>
fi

For example, if you want to write a script that checks that you are the root user and that you provided the correct parameter, you would write :

#!/bin/bash
 
# If the user is root and the first parameter provided is 0.
if [[ $UID -eq 0 && $1 -eq 0 ]];
then
    echo "You provided the correct parameters"
else
    echo "Wrong parameters, try again"
fi

Multiple Conditions in If Else and-operator-1

Nested If Else Statements

In some cases, you want to implement nested conditions in order to have conditions checked under preliminary conditions.

In order to have nested “if else” statements, you simply have to include the “if” statement in another “if” statement and close your nested statement before the enclosing one.

if [[ condition ]]
then  
  if [[ other condition ]]
  then
    <execute command>
  else
    <execute another command>
  fi
fi
Note : make sure to have a closing “fi” statement for every “if” statement that you open. One single “fi” is simply not enough for multiple “if” statements.

Nested Statements Examples

As an example, let’s say that you want to verify that the user is root before verifying that the first argument provided is zero.

To solve that, you would write a nested “if, then, else” statement in the following way :

#!/bin/bash

if [[ $UID -eq 0 ]]
then  
  if [[ $1 -eq 0 ]]
  then
    echo "You are allowed to execute this script."
  else
    echo "You should have provided 0 as the first argument."
  fi
fi

Nested Statements Examples nested-statements

Bash Tests

As you probably noticed, in the previous sections, we used the “-eq” operator in order to compare a variable value to a number.

We did a simple equality check, but what if you want to have an inequality check?

What if you wanted to check whether a value is greater than a given number for example?

In order to perform this, you will need Bash tests.

Bash tests are a set of operators that you can use in your conditional statements in order to compare values together.

Bash tests can be listed by running the “help test” command.

$ help test

Bash Tests help-test

When writing Bash tests, you essentially have three options :

  • Write conditions on file and directories : if they exist, if they are a character file, a device file and so on;
  • Write conditions on numbers : if they are equal to each other, if one is greater than the other;
  • Write conditions on strings : if a string variable is set or if two strings are equal to each other.

Bash File Conditions

Bash file conditions are used in order to check if a file exists or not, if it can be read, modified or executed.

Bash file tests are described in the table below :

Operator Description
-e Checks if the file exists or not
-d Checks if the file is a directory
-b Checks if the file is a block device
-c Checks if the file is a character device
f1 -nt f2 If file f1 is newer than file f2
f1 -ot f2 If file f1 is older than file f2
-r File can be read (read permission)
-w File can be modified (write permission)
-x File can be executed (execute permission)

For example, to check if a file is a directory, you would write the following script

#!/bin/bash

# Checking the first argument provided
if [[ -d $1 ]]
then  
  echo "This is a directory"
else
  echo "Not a directory"
fi

Bash File Conditions directory

Bash Number Conditions

Bash number conditions are used in order to compare two numbers : if they are equal, if one is greater than another or lower than another.

Here is a table of the most used Bash number conditions :

Operator Description
num1 -eq num2 Check if numbers are equal
num1 -ne num2 Check if numbers are not equal
num1 -lt num2 Checking if num1 is lower than num2
num1 -le num2 Lower or equal than num2
num1 -gt num2 Greater than num2
num1 -ge num2 Greater or equal than num2

For example, to check if a number is not equal to zero, you would write :

#!/bin/bash

# Checking the first argument provided
if [[ $1 -eq 0 ]]
then  
  echo "You provided zero as the first argument."
else
  echo "You should provide zero."
fi

Bash String Conditions

Bash string conditions are used to check if two strings are equal or if a string if empty.

Here is a table of the main Bash string conditions :

Operator Description
str1 = str2 Checks if strings are equal or not
str1 != str2 Checks if strings are different
-z str1 Checks if str1 is empty
-n str1 Checks if str1 is not empty

For example, to check if a user provided a value to your script, you would write :

#!/bin/bash

# Checking the first argument provided
if [[ -n $1 ]]
then  
  echo "You provided a value"
else
  echo "You should provide something"
fi

Conclusion

In today’s tutorial, you learnt about the Bash “If Else” statement.

You saw, with examples, that you can build more complex statements : using elif and nested statements.

Finally, you have discovered about Bash tests, what they are and how they are used in order to check conditions in scripts.

If you are interested in Linux System Administration, we have a complete section dedicated to it on the website, so make sure to check it out!

How To Count Files in Directory on Linux

As a system administrator, you are probably monitoring the disk space on your system all the time.

When browsing directories on your server, you might have come across directories with a lot of files in them.

Sometimes, you may want to know how many files are sitting in a given directory, or in many different directories.

In other words, you want to count the number of files that are stored in a directory on your system.

In this tutorial, we are going to see how you can easily count files in a directory on Linux.

Count Files using wc

The easiest way to count files in a directory on Linux is to use the “ls” command and pipe it with the “wc -l” command.

$ ls | wc -l

The “wc” command is used on Linux in order to print the bytes, characters or newlines count. However, in this case, we are using this command to count the number of files in a directory.

As an example, let’s say that you want to count the number of files present in the “/etc” directory.

In order to achieve that, you would run the “ls” command on the “/etc” directory and pipe it with the “wc” command.

$ ls /etc | wc -l

268

Count Files using wc-count

Congratulations, you successfully counted files in a directory on Linux!

Remark using wc command

An important command when using the “wc” command resides in the fact that it comes the number of newlines for a given command.

As a consequence, there is a big difference between those two commands

$ ls -l | wc -l

269

$ ls | wc -l

268

Even if we think that those two commands would give us the same output, it is not actually true.

When running “ls” with the “-l” option, you are also printing a line for the total disk allocation for all files in this directory.

Remark using wc command ls

As a consequence, you are counting a line that should not be counted, incrementing the final result by one.

count-files

Count Files Recursively using find

In order to count files recursively on Linux, you have to use the “find” command and pipe it with the “wc” command in order to count the number of files.

$ find <directory> -type f | wc -l

As a reminder, the “find” command is used in order to search for files on your system.

When used with the “-f” option, you are targeting ony files.

By default, the “find” command does not stop at the first depth of the directory : it will explore every single subdirectory, making the file searching recursive.

For example, if you want to recursively count files in the “/etc” directory, you would write the following query :

$ find /etc -type f | wc -l

2074

When recursively counting files in a directory, you might not be authorized to explore every single subentry, thus having permission denied errors in your console.

Count Files Recursively using find permission-denied

In order for the error messages to be redirected, you can use “output redirection” and have messages redirected to “/dev/null”.

$ find /etc -type f 2> /dev/null | wc -l

2074

Awesome, you recursively counted files in a directory on Linux!

Count Files using tree

An easy way of counting files and directories in a directory is to use the “tree” command and to specify the name of the directory to be inspected.

$ tree <directory>

3 directories, 3 files

Count Files using tree-command

As you can see, the number of files and directories is available at the bottom of the tree command.

The “tree” command is not installed on all hosts by default.

If you are having a “tree : command not found” or “tree : no such file or directory”, you will have to install it using sudo privileges on your system.

$ sudo apt-get install tree             (for Ubunbu/Debian hosts)

$ sudo yum install tree                 (for CentOS/RHEL hosts)

Counting hidden files with tree

In some cases, you may want to count hidden files on your system.

By default, whether you are using the “tree”, “find” or “ls” commands, hidden files won’t be printed in the terminal output.

In order to count hidden files using tree, you have to execute “tree” and append the “-a” option for “all”, followed by the directory to be analyzed.

$ tree -a <directory>

For example, if we count files and directories in your “/home” directory, you will be able to see that there is a difference because multiple hidden files are present.

$ tree /home/user

4321 directories, 27047 files

$ tree -a /home/user

9388 directories, 32633 files

Counting Files using Graphical User Interface

If you are using a Desktop interface like KDE or GNOME, you might have an easier time counting files in directories.

KDE Dolphin File Manager

A quick way of finding the number of files in a directory is to use the Dolphin File Manager.

Click on the bottom left corner of your user interface and click on the “Dolphin File Manager” entry.

KDE Dolphin File Manager dolphin-file-manager

When you are in the Dolphin File Manager, navigate to the folder that you want to explore.

Right-click on the folder and select the “Properties” option.

KDE Dolphin File Manager dolphin-2

The “Properties” window will open and you will be able to see the number of files and subdirectories located in the directory selected.

KDE Dolphin File Manager number-files-kde

Awesome, you counted the number of files in a directory on KDE!

GNOME Files Manager

If you are using GNOME as a Desktop environment, navigate to the “Activities” menu on the top-left corner of your Desktop, and search for “Files”.

GNOME Files Manager Files-GNOME

When in the “File Explorer”, select the folder to be inspected, right-click on it and select the “Properties” option.

GNOME Files Manager properties

When in the “Properties” window, you will be presented with the number of “items” available in the folder selected.

Unfortunately, you won’t be presented with the actual number of “files”, but rather the number of “items” which can be found to be quite imprecise.

GNOME Files Manager etc

Awesome, you found the number of items available in a directory on Linux!

Conclusion

In this tutorial, you learnt how you can easily count files in a directory on Linux.

You have seen that you can do it using native commands such as the “wc” and “find” commands, but you can also install utilities in order to do it quicker.

Finally, you have seen how you can do it using user interfaces such as GNOME or KDE.

If you are interested in Linux System Administration, we have a complete section dedicated to it on the website, so make sure to check it out!

How To Get Your IP Address on Linux

When working on Linux operating systems, knowing how to get your IP address is essential.

Getting your IP address is often the first step of most network troubleshooting processes.

If you are trying to reach a website but the website is no answering back, it might be because your network adapter is badly configured.

Similarly, you might want to reach internal addresses, but if your IP address is configured in the wrong subnet, you won’t be able to ping them.

In this tutorial, we are going to see how you can get your IP address on Linux easily.

We are also going to explain the difference between private IP addresses and public IP addresses.

Find your private IP on Linux

The easiest way to get your private IP address on Linux is to use the “ip” command with the “a” option for “address”.

$ ip a

$ ip address

When running the “ip” command, you will be presented with all the network interfaces available on your host.

In this case, the server has two network interfaces : the loopback address (or localhost) and the “enp0s3” interface.

For this network interface, you are presented with multiple information :

  • Network adapter general information : its state (up or down), its MTU as well as the qlen for the Etherner buffer queue;
  • Layer 2 information : in this case, you are running on the Ethernet protocol with a given MAC address and a broadcast address;
  • Layer 3 information : what you are probably interested in which is your IPv4 address in CIDR notation, the subnet broadcast address as well as the address lifetime (valid_lft and preferred_lft)
  • IPv6 addresses : this section might not appear in your network adapter configuration as not all interfaces are running IPv6 addresses. If this is the case, it will appear here.

Find IP Address using hostname

The “hostname” command is quite popular on Linux operating systems and it is used in order to get and set the hostname of a server.

In order to find your private IP address, use the “hostname” command with the “-I” option for IP address. Note that multiple IP addresses will be shown if you own IPv4 and IPv6 addresses on the same interface.

$ hostname -I

As you can see, in this case, my network adapter owns two different IP addresses :

  • 192.168.178.30 : which is a private IP address of the local subnet (192.168.178.0)

However, in this case, you are presented with the subnet mask which is not very handy if you are looking to allocate an IP to a new host on this subnet.

Find Subnet Mask using ifconfig

In order to use the ifconfig command, you need to have the “net-tools” package installed on your host.

In order to install the “net-tools”, simply run the “apt-get install” command with the “net-tools” package. You will need to have sudo rights to install packages on your system.

$ sudo apt-get install net-tools

In order to find the subnet mask for your host, use the “ifconfig” command with the interface name and pipe it with the “grep” command to isolate the “mask” string.

$ sudo ifconfig | grep -i mask

Find Subnet Mask using ifconfig mask

In this case, you are presented with subnet masks for every network interface (loopback interface included).

Note that you are also provided with the broadcast address if applicable.

Get your private IP address on Desktop

In some cases, you might find handy to find your private IP address by navigating the menus provided by your desktop environment.

  • To get your private IP address, open the “Settings” utility by browsing the “Activities” menu at the top left corner of your screen.

Get your private IP address on Desktop settings

  • Now that the “Settings” are open, find the “Network” section and click on the cog-wheel located at the right of your default network adapter.

Get your private IP address on Desktop network

  • In the settings of your default network adapter, you will be provided with your different IP addresses, as well as your hardware address (or MAC address) and your default DNS address.

Awesome, you have successfully found your private IP address using the desktop environment (in this case, GNOME)

Find Default Gateway IP Address

In some cases, you are not interested in your own IP address but in the IP address of the gateway.

In order to find the IP address of your default gateway, use the “ip” command with the “r” option for “route”. You can use the “grep” command in order to isolate the “default” string which is the default gateway.

$ ip r | grep default

$ ip route | grep default

Find Default Gateway IP Address ip-route

In this case, you are interested in the line with a “default” option which is the route taken for packets sent over the network by default.

Private and Public IP Addresses

In the previous sections, we have seen how you can easily have your IP address using several commands.

However, those commands were used to determine your private IP address, not your public one.

So what’s the difference between your private IP address and your public IP address?

In short, the private IP address is used on your specific private subnet, most of the time at home on a LAN network.

When you are trying to reach websites outside of your home network, you are using a public IP address that is assigned by your Internet Service Provider (or ISP).

As a consequence, you are not able to directly get your public IP address because it will be assigned to the network adapter of your default gateway (which is a router at home).

Private and Public IP Addresses schema

To get your public IP address, you will need to ask an external service unless you are able to connect to your router directly.

Find Public IP Address on Linux

The first method to find your public IP address on Linux is to use a external HTTP services.

Those HTTP services are programmed to send back the IP that made the request in the first place, which is your default public IP address.

In order to get your public IP address on Linux, use the “curl” command and add one of the following websites as a parameter :

  • ifconfig.io
  • ifconfig.co
$ curl http://ifconfig.io

222.265.124.60

Awesome, you have successfully identified your public IP address using a external third-party service.

Find Public IP Address using dig

The other way to get your public IP address on Linux is to use the “dig” utility.

The “dig” utility might not come directly with your distribution. If you do not own “dig”, you can install it by installing the “dnsutils” package on your machine.

$ sudo apt-get install dnsutils
Note : you need to have sudo privileges in order to install new packages on your machine.

Now that “dig” is correctly installed, you can perform a DNS query in order to get your public IP address.

To get your public IP address, use the “dig” command and specify specific DNS servers that are programmed in order to answer your own IP address back (in this case, Google DNS servers)

$ dig TXT +short o-o.myaddr.l.google.com @ns1.google.com

"222.265.124.60"

Great, you have successfully identified your public IP address on Linux!

Conclusion

In this article, you learnt how you can easily get your private IP address using command-line utilities already installed on your computer.

You have learnt about the difference between private IP addresses and public IP addresses and you have used external third-party utilities in order to identify your public IP address.

If you are interested in Linux System Administration, we have a complete section dedicated to this subject, so make sure to check it out!

How To Configure Linux as a Static Router

As a network administrator, you probably know how costly routers can be.

If you are configuring a complex network architecture, you might need Cisco or Netgear routers, as they embed advanced features for network management.

However, if you plan on creating a small network for your company, there might be a cheapier alternative.

What if you could configure a simple Linux server to act as a static router?

Using those features, you could have a Raspberry Pi on your site, that could handle the traffic over two or three different networks.

In this tutorial, we are going to see how you can configure a Linux host to act as a simple static router.

We are also going to review the basics of subnetting in order for you to understand the rules you put in place.

Prerequisites

In order to configure a Linux server as a static router, you need to have sudo privileges on your host.

In order to verify it, you can run the “sudo” command with the “-v” option.

$ sudo -v

If you don’t have sudo rights, you can have a look at our tutorials on becoming sudo on Debian or CentOS distributions.

Now that you have sudo privileges, there are essentially three steps in order to configure your static router :

  • You need to have a global view of your network architecture : what network IP addresses are and which networks will need to communicate with each other;
  • You need to configure the static routing table on your Linux router;
  • You need to enable IP forwarding for packets to flow down your router.

That’s quite a long program, so without further ado, let’s figure out the network architecture and what our network IP addresses are.

Understanding Network Architecture

For the sake of simplicity, we are going to configure a simple static router between two networks.

In order to determine the network IP addresses, let’s pick two hosts in each network : 192.168.200.2/24 and 192.168.190.2/24.

The two hosts don’t belong to the same subnet : as a consequence, they are not able to communicate directly.

Given the netmask of the first host, we are able to determine that the first network has an IP address of 192.168.200.0/24.

Similarly, the second network has an IP address of 192.168.190.0/24.

Using this information, we will be able to configure network interfaces on our Linux router.

Configuring Router Network Interfaces

In order to be able to route packets from one network to another, you need to have two network interfaces : one in the first network and another one in the second network.

In order to keep the tutorial simple, we are going to assume that both hosts are using the router as the default gateway for their respective networks.

This means that the first host is contacting the router on the 192.168.200.1/24 IP address and that second host is contacting the router on the 192.168.190.1/24 IP address.

First of all, you have to identify the network interfaces used for routing

$ ip link show

Private and Public IP Addresses schema

On this host, we have two network interfaces named “enp0s3” and “enp0s8”.

Note : You may have to write down those names as you will have to use them in the next section.

Now that you have your network interfaces names, you will configure your router with a static IP addresses.

Configuring Static IP Address on Debian

If you are running Debian or Ubuntu, head over to the /etc/network/interfaces file and add your two network interface information in it.

$ sudo nano /etc/network/interfaces

# Defining the first interface
auto <interface_name>
iface <interface_name> inet static
address 192.168.190.1
netmask 255.255.255.0

# Defining the second interface
auto <interface_name>
iface <interface_name> inet static
address 192.168.200.1
netmask 255.255.255.0
Note : do not forget to add the “auto” directive, otherwise your interfaces won’t be raised at boot time.

Save your file and restart your networking service in order for the changes to be applied.

$ sudo systemctl restart networking.service

$ sudo systemctl status networking.service

In this case, we are not using the NetworkManager : we are managing interfaces using the ifupdown utility (pretty much like in old distributions).

By now, your interfaces should be up and running, you can check them by running the “ip” command with the “a” option.

Îf your interfaces are not running, or marked as “DOWN”, you can bring them up by running the “ifup” command.

$ ifup <interface_name>

Configuring Static IP Address on CentOS

In order to configure your CentOS host with a static IP address, head over to the “/etc/sysconfig/network-scripts” directory and create two distinct files for your network interfaces.

$ touch ifcfg-enp0s3 && touch ifcfg-enp0s8

To configure a static IP address, you can add the following information in your file.

# Content of enp0s3

BOOTPROTO="static"
IPADDR=192.168.200.1
NETMASK=255.255.255.0
NAME="enp0s3"
ONBOOT="yes"

# Content of enp0s8
BOOTPROTO="static"
IPADDR=192.168.190.1
NETMASK=255.255.255.0
NAME="enp0s8"
ONBOOT="yes"
Note : do not forget to add the “ONBOOT” directives in order for your interfaces to be raised at boot time.

Now that you have your router connected to both networks, you will need to add a static route between your two networks in order for them to communicate.

Creating Static Routes using ip

Having two network interfaces does not mean that your kernel will naturally route packets from one interface to another.

First of all, make sure to list the existing routes that may exist on your server by running the “ip route” command.

$ ip route

Creating Static Routes using ip-route

Deleting existing static routes

If static routers are already defined for your network interfaces, you will need to delete them : otherwise, you won’t be able to add new ones.

To delete a route, use the “ip route” command with the “delete” option and specify the route to be deleted.

$ ip route delete <route>

In our case, we want to delete routes that are pointing to the 192.168.190.0/24 and 192.168.200.0/24 networks.

$ ip route delete 192.168.190.0/24

$ ip route delete 192.168.200.0/24

$ ip route

Deleting existing static routes ip-route-2

Now that routes are deleted, you can add the ones you are interested in.

Creating new static routes

In order for the packets to flow from the first network to the second, your first network card need to point to the second one and vice-versa.

First, you can create a route from the first network adapter IP address to the second network IP address.

$ ip route add 192.168.200.0/24 via 192.168.190.1

Using this rule, all packets coming using the 192.168.190.1 interface as their gateway can be redirected to the 192.168.200.0 network.

Similarly, you can add another route in the opposite direction in order for your packets to be able to flow back.

$ ip route add 192.168.190.0/24 via 192.168.200.1

Now that your routes are added, you can verify that they are up and active by running the “ip route” command again.

$ ip route

Creating new static routes ip-route-3

Now that your routes are added, there is one last step that you need to configure in order for your hosts to be able to ping each other.

Enabling IP forwarding on Linux

Even if routes exist, the Kernel will not naturally forward packets to corresponding network interfaces without configuration.

In order to enable IP forwarding, head over to the /etc/sysctl.conf file and look for the “net.ipv4.ip_forward” parameter.

$ vi /etc/sysctl.conf

By default, this parameter is set to “0”, but you want to set it to “1” in order to enable IP forwarding.

Enabling IP forwarding on Linux ip-forwarding
Save your file and refresh the system configuration by running the “sysctl” command.

$ sysctl -p /etc/sysctl.conf

Enabling IP forwarding on Linux sysctl

Testing network connectivity

Now that IP forwarding is enabled, you should be able to ping from a host on the first network to a host on the second network.

In order to check it, connect to a host on the first network and run a “ping” command on a host located on the second network.

$ ping <host_second_network>

In our case, we would want to ping the “192.168.190.2/24” host from the “192.168.200.2/24” one.

Testing network connectivity ping-network

Awesome! Your first host is able to ping the second one.

As an additional check, you could make sure that your second host is able to ping the first one.

Great!

Now that your setup is ready, you should be able to add new hosts to both networks and start communicating between the two networks.

Conclusion

In this tutorial, you learnt how you can easily configure a Linux system as a static router.

This setup can be quite useful if you plan on building a small network infrastructure for your company.

Instead of buying and having to configure a Cisco router, you can simply use a Raspberry Pi as a static router.

If your company grows and you plan on having a bigger network infrastructure, then you can check managed routers as they will probably offer more flexibility to your needs.

If you are interested in Linux System Administration, we have a complete section dedicated to it on the website, so make sure to check it out!

Single User Mode Secure Boot on Ubuntu & Debian

On Ubuntu and Debian hosts, the single user mode, also referred as the rescue mode, is used to perform critical operations.

The single-user mode can be used to reset the root password or to perform file systems checks and repairs if your system is unable to mount them.

In this tutorial, we are going to see how you can boot on single user mode on Debian and Ubuntu hosts and how to reset the root password.

We are also configure our target units (rescue and emergency) to prompt for a password on single-user mode boot.

Note: in order to boot into rescue or emergency targets, you are need physical access to the machine to interrupt the default GRUB boot process.

Rescue & Emergency Targets on Debian

On recent Debian distributions, systemd is responsible for booting your Linux host using a default target.

If you want to check the default target run by systemd, you can run the following command

$ systemctl get-default

Rescue & Emergency Targets on Debian get-default

As you can see, my system is set to boot on graphical target by default.

As I don’t own any desktop environment like GNOME or KDE, it is going to boot in a simple shell.

However, the graphical target is not the only target available on Linux, you can boot in the following modes:

  • poweroff : used to shutdown your host and power off the system;
  • rescue : a mode used to boot your system with a rescue shell;
  • emergency : similar to the rescue mode except that no services are launched and no filesystems are mounted;
  • multi-user : the default mode on Linux systemd systems, used to boot your host in a non-graphical system (without a desktop environment);
  • graphical : includes the multi-user target and a graphical environment such a KDE or GNOME for example;
  • reboot : shutdowns the system and reboot it immediately

As their names reflect it, those modes are used in order to perform maintenance operations on a Linux system, but they need to be done securely to avoid any security leaks.

In this article, we are going to focus on the rescue and emergency modes and see how we can securely on them.

We are also going to see how booting in single user mode can be used to change the root password or to perform simple filesystems checks.

Configuring the Root Account on Debian

By default, when entering single user mode, you are going to be given a root prompt with complete privileges.

As a consequence, in order to boot in single-user mode (or rescue mode), your root account needs to be unlocked and it needs to have a password.

Checking Root Account Lock Status

On Ubuntu, root accounts are disabled by default as a security measure, and you can choose to have it disabled on Debian 10 also (if you don’t specify a root password when installing Debian)

In order to check if your root account is locked, run the following command

$ sudo -s
$ cat /etc/shadow | grep root

Checking Root Account Lock Status locked-account

As you can see, there is an exclamation mark on the space reserved for the password : it means that the root is locked.

Setting a Root Account Password

In order to set a password for the root account, run the following command

$ sudo passwd

Setting a Root Account Password passwd-root

If you go back to check the content of your shadow file, you should now see that the content has been modified and that no exclamation mark are presented.

Awesome, now we can start booting into single user mode from the GRUB bootloader screen.

Booting in Rescue Mode from GRUB

In order to boot into single user mode, or rescue mode, you are going to interrupt the default boot process when starting your machine.

Reset your machine and interrupt the boot process by pressing a key arrow in the GNU GRUB menu.

If you are running a Debian based distribution, this is what you should see on your screen

Booting in Rescue Mode from GRUB-menu

As described in the bottom description panel, press ‘e’ in order to edit the boot commands

You should now see the following window on your screen

Booting in Rescue Mode from GRUB-2

Using the directional arrows, navigate to the Linux kernel booting line and put the following string at the end of the line.

systemd.unit=rescue.target

You can also simply type “1”, it is equivalent to booting in single user mode on Debian.

Booting in Rescue Mode from GRUB boot-rescue

As described below the boot script, press F10 to boot into rescue target.

Your Linux Kernel will be loaded and your initial virtual filesystem will be loaded.

Before having the access, you will be prompt with the root password that you just changed before.

Booting in Rescue Mode from GRUB rescue-mode

Type the password you defined before, and you should now have a root shell directly into your host.

root-rescue

Awesome! Now that you have a root shell into the host, you can start by changing the root password or by checking your filesystems.

Security Recommendations for Single User Mode

When it comes to the single user mode, or the rescue target, it is important that this mode is password-protected on your system.

As you can see, it is the case by default on Debian 10, but you have to make sure on other distributions that it is the case.

If any intruder has physical access to your machine, in a data-center for example, it could be as easy as rebooting the machine, interrupting the boot process and launching a non-protected single user mode.

From there, every file can be deleted, copied or transferred to a non secure server.

Malicious programs can also be installed to track the host activity and to steal personal information.

Sulogin login shell

Luckily for you, standard Debian distributions are configured to ask for the root password when booting in single user mode.

It can be seen by inspecting the rescue and emergency services on your host (located at /usr/lib/systemd/system)

$ cat /usr/lib/systemd/system/rescue.service

Sulogin login shell rescue-service

By default, when starting, your system is going to launch the systemd-sulogin-shell in rescue mode, which is safe from unauthorized access.

However, you have to make sure that this file was not altered and that the system is not instructed to launch a simple shell (like /bin/sh for example).

This would result in having an unsafe single user mode, essentially having a major security breach if anyone has physical access to the machine.

Conclusion

In this tutorial, you learnt about the single user mode on Debian-based distributions and how it is related to the rescue and emergency targets on Linux.

You learnt that this mode needs to be password protected as it offers a root shell for users who were to log into it.

You also had a look at how you can instruct the GRUB to boot into this mode, and how it can be used to perform maintenance operations on your system.

If you are curious about Linux system administration, we have a complete section dedicated to it on the website.

How To Change IP Address on Linux

As a network administrator, you are probably managing various Linux machines over different subnets of your company infrastructure.

As network topology changes, you may need to change the IP address already implemented on some machines.

Also, if you switched from DHCP to static IP addressing, you will also need to change the IP address on some of your computers.

Luckily for you, Linux has multiple ways of changing your IP address, whether you want it to be dynamic or static.

You will see how it is possible to have multiple IP addresses for a single machine and how you can assign IP addresses to virtual network adapters.

Prerequisites

Before changing your IP address, make sure to have a look at your current IP address.

To find your current IP address, you can use the “ip” command with the “a” option for address.

$ ip a

As you can see from the screenshot, my host is equipped with two network adapters :

  • the loopback address (or localhost) which is used to test the network connectivity of your own computer;
  • the “enp0s3” interface : acting as a main network adapter, the network card has multiple IP addresses associated with it (IPv4 and IPv6) followed by the IP address assigned to them.

In the present situation, my computer can be reached on “192.168.178.31/24” via the “192.168.178.1/24” gateway.

Change IP Address using ifconfig

On modern distributions, the “ifconfig” command has been completely deprecated and it is now advised to use the “ip” command.

However, you should still be able to use the “ifconfig” to change your IP address.

$ which ifconfig

/usr/sbin/ifconfig

To change your IP address on Linux, use the “ifconfig” command followed by the name of your network interface and the new IP address to be changed on your computer.

To assign the subnet mask, you can either add a “netmask” clause followed by the subnet mask or use the CIDR notation directly.

$ ifconfig <interface_name> <ip_address> netmask <netmask_address>
Note : in order to change your IP address, you will need to be an administrator on your computer (part of the sudo group on Debian/Ubuntu or wheel on CentOS/RedHat)

For example, given the IP addresses used in the previous sections, if we want to change our IP address (to 192.168.178.32/24), we would run the following command

$ ifconfig enp0s3 192.168.178.32/24

$ ifconfig enp0s3 192.168.178.32 netmask 255.255.255.0

In order to verify that your IP address was correctly changed, you can run the “ifconfig” command followed by the name of your network adapter.

$ ifconfig <interface_name>

From DHCP to Static

When manually changing your IP address, Linux automatically understands that you want to change from using a DHCP server to static IP addressing.

This information is materialized in the “ifconfig” command : in the first screenshot, you can see that my IP address was assigned with a “dynamic” parameter also called DHCP.

This is not the case anymore after assigning the IP address manually.

Note that your changes are not made permanent by modifying your IP settings with the “ifconfig” : they are only modified for the current session.

Change IP Address Permanently using ifupdown

On Linux, changing your IP address using network utilities does not mean that your IP configuration will be saved on reboots.

Network Files on Debian & Ubuntu

In order to change your IP address on Linux, you will have to add your network configuration in the “/etc/network/interfaces” or create this file if it does not exist already.

# Content of /etc/network/interfaces

iface eth0 inet static
address <ip_address>
netmask <network_mask>
gateway <gateway_ip>

For example, let’s say that you want to change your IP to be “192.168.178.32” with a subnet mask of “255.255.255.0” and a default gateway of “192.168.178.1”.

To change your IP address to reflect those changes, you would edit the content of your interfaces file and add the following content

$ vim /etc/network/interfaces

# Content of /etc/network/interfaces

iface eth0 inet static
address 192.168.178.32
netmask 255.255.255.0
gateway 192.168.178.1

In order for the changes to be applied, you will need to restart your networking service (managed by ifupdown)

# For systemd hosts

$ sudo systemctl restart networking.service

# For pre-systemd hosts

sudo /etc/init.d/networking restart

After restarting your networking service, you should be able to see your new IP by running the “ifconfig” or the “ip” command.

$ ifconfig

$ ip address

Network Files on CentOS & Red Hat

In order to change your IP address on Linux, you will have to add your network configuration in the “/etc/sysconfig/network-scripts” directory.

In the “/etc/sysconfig/network-scripts”, identify the network interface to be modified and start editing it.

$ ls -l /etc/sysconfig/network-scripts

$ nano <file>

Network Files on CentOS & Red Hat network-centos

In order to set an IP to be static on CentOS or RHEL, you want to modify the “BOOTPROTO” parameter from “dhcp” to “static” and add your network information such as the netmask or the default gateway.

On recent distributions such as CentOS 8 or RHEL 8, you have to use the nmcli utility in order for the changes to be effective.

However, if you are still using the network service (for distributions such as CentOS 7 or RHEL 7), you can restart the network service for the changes to be applied.

$ nmcli device reapply <interface_name> (on CentOS 8)

$ systemctl restart network.service (on CentOS 7/RHEL 7)

Awesome!

You successfully changed your IP address on Linux.

Make sure to execute the “ip” command again to verify that your changes were applied.

$ ip a

$ ifconfig

Change IP Address using Network Manager

On modern distributions, equipped with systemd, you may have come across the Network Manager many times.

The Network Manager is an all-in-one tool that exposes multiple utility tools in order to change connections, devices or connectivity settings (even wireless) on your host.

One of those utilities is called “nmcli” and this is what we are going to use in order to change our IP address.

To change your IP address, use “nmcli” on the “device” section and specify that you want to “modify” the “ipv4.address” of your network card.

$ nmcli device modify <interface_name> ipv4.address <ip_address>

Change IP Address using Network Manager nmcli

When using the “nmcli device modify” command, your Network Manager will automatically create a new connection file in the /etc/NetworkManager/system-connections folder.

Change IP Address using Network Manager system-connections

In order for the changes to be effective, you will need to “reapply” parameters to your current connection settings.

$ nmcli device reapply <interface_name>

Congratulations, you successfully changed your IP using the Network Manager!

However, changing settings using the nmcli tool won’t make your changes persistent over multiple reboots.

Change IP Address Permanently using Network Manager

In order for changes to be persistent, you need to edit the connection files located at /etc/NetworkManager/system-connections.

In order to change your IP address, edit the Network Manager configuration file, identify the line to be modified and set the IP address accordingly.

Change IP Address Permanently using Network Manager

Save the file and make sure to reapply the device configuration by using the “nmcli” command with the “device reapply” options.

$ nmcli device reapply

Now that your changes are effective, you can check your IP address by running the “ifconfig” or “ip” commands.

Modify IP Address using Graphical Interface

In some cases, you may want to modify your IPv4 address by navigating through graphical windows.

On modern distributions, the network parameters can be managed by the “network” icon (which is called nm-applet) located at the top right corner of your screen.

Modify IP Address using Graphical Interface nm-applet

In your network settings, click on the “gear wheel” next to the connection to be modified.

Modify IP Address using Graphical Interface nm-applet-2

Next, in the IPv4 section of your connection settings, you can set your IP method to manual and attribute your static IP address.

Modify IP Address using Graphical Interface nm-applet-3

To change your IP address, simply click on “Apply” and restart the networking services by using nmcli.

$ nmcli networking off

$ nmcli networking on

That’s it! You just changed your IP address on Linux.

How networking is managed on Linux

As of January 2020, on recent distributions, you may deal with several tools that are used by your distribution to configure networking.

Most of the time, the Network Manager and ifupdown are managing networking.

$ sudo systemctl status NetworkManager

$ sudo systemctl status networking

In some distributions, “ifupdown” might not be installed at all and interfaces are only managed by the NetworkManager.

However, if the two services exist on your computer, you will be able to declare interfaces in the /etc/network/interfaces file without the NetworkManager interfering with those settings.

How networking is managed on Linux networking

If you want the Network Manager to manage interfaces declared in the interfaces file, you will have to modify the “managed” parameter to true in the NetworkManager.conf configuration file.

How networking is managed on Linux managed

Conclusion

In this tutorial, you learnt how you can successfully change your IP address on Linux : either using the Network Manager or the ifupdown utility.

You also learnt how networking is managed and architectured on Linux and how you should configure it to avoid IP address conflicts.

If you are interested in Linux system administration, we have a complete section dedicated to it on the website, so make sure to check it out!

How To List Services on Linux

As a system administrator, you are probably dealing with a lot of services every day.

On Linux, services are used for many different purposes.

They may be used in order to start a SSH server on your machine or they can perform some operations on a specific hour or day.

Whether you are using a Debian based distribution or a RedHat one, querying services is very similar.

However, given the distribution you are using, and more specifically the initialization system (init or systemd), you may have to use different commands.

In this tutorial, you will learn how you can, given your system manager, list all services on your Linux machine.

Determine the system manager used

As you probably know, recent distributions use the Systemd system manager.

However, it has not always been the case : in the past, most distributions used the SysVinit system manager.

As a consequence, there are really two ways of managing your services on a Linux system.

Before learning the commands to list services, you have to know the system manager that you are currently using.

To determine your current system manager, the easiest way is to use the “pstree” command and to check the first process ever run on your system.

$ pstree | head -n 5

Determine the system manager used pstree

If you see “systemd“, it obviously means that you are currently using systemd. However, if you see “init“, it means that you are using SysVinit.

On Ubuntu 14.04, that is still using the old init system, your “pstree” may look like this.

Determine the system manager used pstree-init

List Services using systemctl

The easiest way to list services on Linux, when you are on a systemd system, is to use the “systemctl” command followed by “list-units”. You can specify the “–type=service” option in order to restrict the results to services only.

$ systemctl list-units --type=service

List Services using systemctl list-services-linux-systemd

By default, this command will show you only the services that are active or the services that have failed on your system. In the screenshot above, most of the services are active but the logrotate one (highlighted in red) is marked as failed.

Awesome, you learnt how you can easily list your services on a Linux server.

However, as you may have noticed, you did not have access to all services : what about inactive services? What about services that were not loaded by systemd on boot?

List All Services on Linux using list-units

In order to list all services, meaning active and inactive, you have to use the “systemctl list-units” command followed by the “–all” option.

Similarly, you can limit the results to services only by using the type filter.

$ systemctl list-units --type=service --all

List All Services on Linux using list-units list-inactive-services

As you can see, inactives services also listed which might be convenient if you just wrote your service and looking after it in the list.

In this case, only loaded services are listed. On boot, systemd loads unit files and it may choose not to load a specific service if it finds that it won’t be used by the system.

As a consequence, there is a real difference between “loaded” and “installed” services. “Installed” services mean that unit files can be found in the corresponding paths.

Disabling Root Login over SSH ssh-root-login

List Services By State

In some cases, you may only be interested in services that have failed. For that, you can specify the state that you are looking for as an option of the systemctl command.

$ systemctl list-units --state=<state>

$ systemctl list-units --state=<state1>,<state2>

Where “state” can be one of the following values : active, inactive, activating, deactivating, failed, not-found or dead.

For example, if we are only interested in “failed” services, we are going to run the following command

$ systemctl list-units --state=failed

List Services By State failed-service

List All Service Files using list-unit-files

Finally, if you are interested in “loaded“, “installed“, “disabled” as well as “enabled” service files, there is a another command that might be pretty handy.

In order to list all service files available, you have to use the “systemctl” command followed by “list-unit-files”. Optionally, you can specify the type by using the “–type=service” option.

$ systemctl list-unit-files --type=service

List All Service Files using list-unit-files list-installed-services

Alternatively, you can use the “grep” command in order to search for specific paths on your system that may contain service files.

$ ls -l /etc/systemd/system /usr/lib/systemd/service | egrep .service$

List All Service Files using list-unit-files list-files-using-grep

Congratulations, you learnt how you can list services if your system is using systemd!

List Services using service

The easiest way to list services on Linux, when you are on a SystemV init system, is to use the “service” command followed by “–status-all” option. This way, you will be presented with a complete list of services on your system.

$ service --status-all

List Services using service list-services-init-system

As you can see, each service is listed preceded by symbols under brackets. Those symbols mean :

  • + : means that the service is running;
  •  : means that the service is not running at all;
  • ? : means that Ubuntu was not able to tell if the service is running or not.

So why are some services to tell if they are running or not, and some are not able to?

It all comes down to the implementation of the init script. In some scripts, such as the udev script for example, you are able to see that the “status” command is implemented.

udev-status

This is not the case for the “dns-clean” script for example which is the reason why you have a question mark when you query this service.

List SysVinit Services in Folders

Another way of listing the current list of services is to use the “ls” command on the folders containing all scripts on a Linux system, namely “/etc/init.d”.

$ ls -l /etc/init.d/*

List SysVinit Services in Folders initd-folder

Conclusion

In this tutorial, you learnt how you can easily list services on a Linux system whether you are using systemd or SysVinit ones.

If you are interested in creating your own services, we recommend that you have a look at the following resources. They might be really useful in order to correctly achieve that.

  • Writing a startup script for init systems;
  • Starting services at boot using systemd;

If you are interested in Linux System Administration, we have a complete section on this subject on the website, so make sure to check it out.

How To Encrypt Partition on Linux

In one of our previous articles, we learnt how you can encrypt your entire root filesystem on Linux easily.

However, in some cases, you may want to encrypt one simple partition that may store some of your important files.

As you already know, encrypting your disks is crucial. If your laptop were to be stolen, you would probably lose all your personal information.

However, there are some ways for you to cope with this problem : by encrypting your disk partitions.

In this tutorial, you will learn about all the steps necessary to encrypt an entire disk partition, secure it with a passphrase or with a keyfile.

For the example, the article will be illustrated on a RHEL 8 operating system, but there should not be any differences if you use another one.

Prerequisites

In order to execute most of the commands provided in this article, you need to have administrator rights.

To check whether this is the case or not, you can execute the “groups” command and verify that you belong to the “sudo” group for Debian-based distributions or “wheel” for RedHat based ones.

$ groups

How To Encrypt Partition on Linux groups

If you don’t have such rights, you can read one of our articles on the subject about getting sudo rights for Ubuntu or CentOS distributions.

Encrypt Partition using cryptsetup

As specified in the previous articles, encrypting a partition involves formatting the entire disk.

As a consequence, if you plan on encrypting a disk with existing data, you should now that your data will be erased in the process. To avoid losing anything, you should make a backup of your data on an external disk or in an online cloud.

Create New Partition on disk

In order to encrypt a partition, we are going first to create a new one using the “fdisk” utility. For the example, we are going to create a new partition named “sdb1” on the “sdb” disk.

$ sudo fdisk /dev/sdb

Create New Partition on disk fdisk-utility

In the fdisk utility, you can create a new partition using the “n” keyword and specify that you want a partition with a size of 5 GBs for example.

Create New Partition on disk create-partition-fdisk

If you are not sure about how to use “fdisk” or how to create partitions, we have a dedicated article about this subject.

At the end of the process, you need to use the “w” keyword in order to write the changes to the disk.

Create New Partition on disk write-changes-disk

Awesome, now that your partition is created, we are going to format it as a LUKS partition.

Format Disk Partition as LUKS

To encrypt the partition, we are going to use a command related to the LUKS project.

The LUKS project, short for Linux Unified Key System, is a specification used in order to encrypt all storage devices using special cryptographic protocols. As described, LUKS is only a specification, you will need a program that implements it.

In this case, we are going to use the “cryptsetup” utility. As explained in the manual section, cryptsetup aims at creating encrypted spaces for dm-crypt.

First of all, make sure that you have the “cryptsetup” command using the “which” command.

$ which cryptsetup

Format Disk Partition as LUKS which-cryptsetup

If the cryptsetup cannot be found on your server, make sure to install it using one of the following commands

$ sudo apt-get install cryptsetup                     (for Debian distributions)

$ sudo yum install cryptsetup                         (for RHEL/CentOS distributions)

To create your LUKS partition, you need to execute the “cryptsetup” followed by “luksFormat” and the name of the partition to be formatted.

$ sudo cryptsetup luksFormat /dev/sdb1

Format Disk Partition as LUKS cryptsetup-luksformat

First of all, you are reminded that encrypting your disk will actually format it in the process.

After typing “YES” in capital letters, you will have to choose a passphrase in order to secure your device.

LUKS supports two ways of protecting your media : using a passphrase (the one that we currently use) and using keys. For now, you can choose a safe password and your partition should be formatted automatically.

Now that your partition is created, you can inspect it using the “lsblk” command : the partition should be marked as “crypto_luks“.

$ lsblk -f

lsblk-command

Awesome! Now that the volume is formatted, we can open it and create a simple ext4 filesystem on it.

Create ext4 Filesystem on Partition

By default, your encrypted volume is closed meaning that you cannot access data that is available on it.

In order to “open”, meaning “unlocking” your volume, you have to use the “cryptsetup” command again followed by “luksOpen” and the name of the volume.

At the end of the command, provide a name for your open volume, in this case we are going to choose “cryptpart“.

$ sudo cryptsetup luksOpen /dev/sdb1 cryptpart

Create ext4 Filesystem on Partition cryptsetup-luksopen

As you can guess, you are asked to provide the passphrase that you chose in the previous section.

Running the “lsblk” command again, you probably noticed that one volume was created under the “sdb1” encrypted volume named “cryptpart“. The “device mapper”, which is one of the frameworks of the Linux Kernel, did that for you.

Now that your volume is unlocked, it is time for you to create a new ext4 filesystem on it.

To create a new filesystem on your partition, use the “mkfs” command followed by the filesystem format, in this case “ext4”.

$ sudo mkfs.ext4 /dev/mapper/cryptpart

mkfs-command

Awesome, the filesystem was created.

You can now mount it and add new files to it. Files created on this volume will automatically be encrypted.

$ mkdir -p /home/devconnected/files 

$ sudo mount /dev/mapper/cryptpart /home/devconnected/files

$ sudo chown devconnected:devconnected /home/devconnected/files

mount-encrypted-partition

Awesome, now that your data is safe on an encrypted partition, let’s see how you can mount the encryption partition on boot.

Modify crypttab and fstab files

Many system administrators know the existence of the fstab file that is used by your init process to mount drives.

However, when dealing with encrypted partitions, there is another file that comes into play : /etc/crypttab.

Similarly to the fstab file, crypttab is read by your init process when booting. Given the information provided in it, it will ask you to unlock the partition or it will read a key file in order to do it automatically.

Note : the /etc/crypttab may not exist on your system. If it is not the case, you may have to create it.

crypttab-columns

The columns of the crypttab are described above :

  • Device name : you can give your decrypted device any name that you want. Furthermore, it will be automatically created by the device mapper under the “/dev/mapper” path. In the previous section, we chose “cryptpart” for this column;
  • Encrypted device UUID : in order to find which partition contains the encrypted data, your system needs to have its UUID meaning its unique identifier;
  • Method of authentication : as explained, you can choose “none” for the passphrase or you can specify a path to the key. The key method will be explained in the last chapter of this article;
  • Mount options : using this column, you can specify the number of tries for a passphrase, the cipher, the encryption method and many other parameters. The complete list of options is available in the “crypttab” manual page.
$ sudo nano /etc/crypttab

# Content of the crypttab file
cryptpart    UUID=<partition_uuid>    none    luks

crypttab-file-2

If you have doubts about the UUID of your encrypted partition, you can use the “blkid” command with a simple “grep” pipe.

$ sudo blkid | grep -i luks

blkid-command

Now that the “/etc/crypttab” file is modified, you will have to modify the “fstab” file to specify the mountpoint.

$ sudo blkid | grep -i ext4

$ sudo nano /etc/fstab

fstab-file

In the fstab columns, you have to specify :

  • The decrypted device UUID : in order to find it, you can use the “blkid” command but make sure that you opened the device before proceeding. If the device is closed, you won’t be able to find your UUID;
  • The mount point : where the decrypted device is going to be mounted. If the path does not exist, it is going to be created automatically;
  • The filesystem type : in this case, we chose to use “ext4” but it may be different on your system;
  • Dump and pass options : we don’t want the filesystem to be checked on boot-time, so we can keep it to the default values.

When you are done, save your file and you should be good to go.

Given the steps you just performed, your device is ready and it should automatically be mounted on boot.

Verify encrypted device mounting on boot

In order to verify that the device is correctly mounted, we can restart our server and wait for the initramfs module to open the encrypted device.

$ sudo reboot

Verify encrypted device mounting on boot encryption-boot

This is the screen that you should see, at least on RHEL8, when starting your server. If you provide the passphrase, your machine should be able to unlock it and mount it for you.

Once you are logged in your server, you can check that the encrypted partition was correctly mounted using the “lsblk” once again.

$ lsblk -f | grep sdb1 -A 2

lsblk-mounted

Congratulations, you successfully encrypted a partition on Linux using LUKS!

Create Keys For Encrypted Partition

As explained before, LUKS handles two authentication methods, namely passphrases and key files.

In the previous section, we used passphrases but it can be quite handy for you to also have a authentication key.

First of all, create a key file and store it somewhere safe (in directories that regular users cannot navigate to, like “/boot” or “/root“).

$ echo "supersecretpass" > volume-key

$ sudo mv volume-key /boot/

create-volume-key

As you can see, by default, the file was created using the user credentials and it has too many permissions.

Using the “chown” and “chmod” commands, we can set “root” as the owner of the file and change its permissions to read-only.

$ sudo chown root:root /boot/volume-key

$ sudo chmod 0400 /boot/volume-key

read-only-file

Now that the file is set to read-only, we can add it as a key in one of the slots of our LUKS volume.

Add Key to LUKS Volume

In order to add a key to your LUKS volume, you need to execute the “cryptsetup” command followed by the “luksAddKey”, the name of the encrypted volume and the path to the key.

$ sudo cryptsetup luksAddKey <encrypted_device> <path_to_key>

$ sudo cryptsetup luksAddKey /dev/sdb1 /boot/volume-key

Add Key to LUKS Volume luks-add-key

In order to perform this operation, you will be prompted for your passphrase. When provided, the key will be automatically added to your keyslots.

To verify that the key was correctly added, you can inspect your keyslots using the “luksDump” command.

$ sudo cryptsetup luksDump /dev/sdb1

Add Key to LUKS Volume luks-dump-command

Now that the key is added, you only need to modify the “/etc/crypttab” in order for your system to find it on boot.

$ sudo nano /etc/crypttab

# Content of the crypttab file
cryptpart    UUID=<partition_uuid>    /boot/volume-key    luks

When rebooting, your encrypted partition will be mounted automatically!

auto-mount-linux

Conclusion

In this article, you learnt how you can easily encrypt your partition on Linux using the LUKS project and its implementation named cryptsetup.

You can saw that you can use a “key file” in order for your partition to be unlocked automatically.

If you are interested in a full system encryption, we recently wrote an article on the subject.

Also, if you want to read more about Linux System Administration, make sure to have a look at our dedicated section on the website.

How To Find Last Login on Linux

If you are working in a medium to big-sized company, it is quite likely that you are working with many other system administrators.

As you are performing your sysadmin tasks, some users may try to connect to your server in order to perform their daily tasks.

However, in some cases, you may find that something has changed on your server. As a consequence, you are wondering who performed the change.

Luckily for you, there are many ways to find who last logged in on your server.

In this tutorial, you will learn about the different useful commands that you can use in order to check the last logins on your computer.

Find Last Login using last

The easiest way to find the last login on your Linux computer is to execute the “last” command with no options. Using this command, you will be presented with all the last logins performed on the computer.

$ last

# To check the last ten login attempts, you can pipe it with "head"

$ last | head -n 10

Find Last Login using last-command

As you can see, by default, the output is truncated : the “devconnected” user is only displayed as “devconne” with simply using the last command.

If you find last logins using complete usernames and hostnames, you have to append the “-w” option or “–fullnames“.

$ last -w

$ last --fullnames

Find Last Login using last-complete-output

Last Command Columns

When taking a look at the last command, the output can be a bit confusing. There are many columns but we don’t exactly know what they stand for.

First of all, there is a difference between user login and reboots.

As you can see, user logins start with the name of the user that connected to the computer. On the other hand, “reboot” logs obviously start with the “reboot” keyword.

User Log In Columns

For user logs, the meaning of the different columns is the following :

  • Username : the username who connected to the computer;
  • TTY : the index of the TTY used by the user in order to connect to the computer. “:0” denotes that the connection is local and you may use the “tty” command in order to find the device used by the user;
$ tty

Last Command Columnstty-command
The user is using /dev/pts/0 to interact with the system

  • The name of the display : as X is used as the display server on every machine, it may use a local display (:0, :1 and so on) or a remote display. If you are interested in running graphical applications remotely, you may read our guide about the X protocol;
  • Hour of the login : starting the server is quite different from logging into it. This hour represents the time where the password was actually provided in the interface;
  • Login status : either you are “still logged in” or “down” with the duration of the session.

Last Command Columns last-session-duration

For example, in the following example, the session duration was twelve minutes.

Pseudo reboot columns

On every reboot, your system adds a new line to the current list of reboots performed on your computer.

Those special lines, starting with “reboot“, have the following columns :

  • Reboot : specifying that this is not a log in but rather a system reboot;
  • Details about the reboot : in this case it was actually a “system boot” meaning that the system just started;
  • Kernel version : the kernel version loaded when booting up the system. It might be different if you host different version of the kernel on your boot partition.
  • Hour of the boot : the hour represents the time of the system boot. It is either followed by a “still running” indication or the end hour followed by the session duration in paranthesis.

Now that you have seen how you can list all last logins on your server, let’s see if you are interested in bad login attempts.

Find Last Login By Date

In some cases, you may be interested in login that were made since or until a specific date in the past, or in the last five minutes.

To find the last login by date, execute the “last” command with the “–since” command and specify the date to find the last logins for.

Similarly, you can use the “–until” command in order to find login attempts made until a given date in the past.

$ last --since <date>

$ last --until <date>

So what are the dates that you can use in order to search?

Date formats are specified in the last documentation page.

Find Last Login By Date last-date-formats

As an example, let’s say that you want to find all login attempts were in the past two days, you would execute the following command

$ last --since -2days

Find Last Login By Date last-since-two-days

Similarly, if you want to find all login attempts made five days in the past, you would run the following command

$ last --until -5days

As a diagram often helps more than words, here is a way to understand the “–since” and “–until” options.

Find Last Login By Date linux-last-login-command

Find Last Bad Login Attempts using lastb

In order to find the last bad login attempts on your Linux server, you have to use the “lastb” with administrator rights.

$ sudo lastb

If you are not sure about how to check such rights, make sure to read our dedicated guides.

Find Last Bad Login Attempts using lastb-command-linux

As you can see, the output is quite similar to the one from the “last” command : the username attempted, the device used as well as the time of the attempt.

In this case, the duration “(00:00)” will be fixed as a connection attempt has no duration at all.

Note that the device line can display “ssh:notty” in case that the log in attempt was made from a SSH terminal.

Inspecting the auth.log file

Alternatively, you can inspect the content of the “/var/log/auth.log” file in order to see all failed attempts on your server.

$ tail -f -n 100 /var/log/auth.log | grep -i failed

Inspecting the auth.log file auth-log-failed-attempts

Find Last SSH Logins on Linux

In order to find the last SSH logins performed on your Linux machine, you can simply inspect the content of the “/var/log/auth.log” and pipe it with “grep” to find SSH logs.

$ tail -f -n 100 /var/log/auth.log | grep -i sshd

Find Last SSH Logins on Linux sshd-logs-last

Alternatively, you can inspect the logs of the SSH service by running the “journalctl” command followed by the “-u” option for “unit” and the name of the service.

$ sudo journalctl -r -u ssh | grep -i failed

Find Last SSH Logins on Linux journactl-command

Note : interested in listing services and their statuses on your server? Here is a guide about listing your services on Linux.

If you don’t see any logs related to the SSH service, it might be related to your SSH configuration file, namely to the “PrintLastLog” option.

$ cat /etc/ssh/sshd_config | grep PrintLastLog

Find Last SSH Logins on Linux print-last-log-ssh

If this option is set to “No” on your server and you wish to print last logs, make sure to uncomment the line with the “yes” value. Do not forget to restart your SSH server after that.

$ sudo nano /etc/ssh/sshd_config

PrintLastLog yes

$ sudo systemctl restart ssh

$ sudo systemctl status ssh

Great! You learnt how you can find the last SSH logs on your computer.

List User Last Login on Linux

In order to find last login times for all users on your Linux machine, you can use the “lastlog” command with no options. By default, you will be presented with the list of all users with their last login attempts.

Alternatively, you can use the “-u” option for “user” and specify the user you are looking for.

$ lastlog

$ lastlog -u <user>

List User Last Login on Linux lastlog-command

As you can see, with no options, the command will return the list of all accounts on your machine, even the root one and system ones.

Conclusion

In this tutorial, you learnt how you can easily find the last login attempts made on a Linux computer.

Whether those attempts were made through a login shell or a SSH session, you now know which files to inspect and which tools to use in order to retrieve them.

Remember that you can inspect those files but you can also plot them on a dashboarding solution such as Kibana, here’s a guide on how to achieve that.

If you are interested in Linux System Administration, we have a complete section dedicated to it on the website, so make sure to have a look!

How To Encrypt Root Filesystem on Linux

As a system administrator, you probably already know how important it is to encrypt your disks.

If your laptop were to be stolen, even a novice hacker would be able to extract the information contained on the disks.

All it takes is a simple USB stick with a LiveCD on it and everything would be stolen.

Luckily for you, there are ways for you to prevent this from happening : by encrypting data stored on your disks.

In this tutorial, we are going to see the steps needed in order to perform a full system encryption. You may find other tutorials online focused on encrypting just a file or home partitions for example.

In this case, we are encrypting the entire system meaning the entire root partition and the boot folder. We are going to encrypt a part of the bootloader.

Ready?

Prerequisites

In order to perform all the operations detailed in this guide, you obviously need to have system administrator rights.

In order to check that this is the case, make sure that you belong to the “sudo“ group (for Debian based distributions) or “wheel“ (on RedHat based ones).
How To Encrypt Root Filesystem on Linux checking-sudo

If you see the following output, you should be good to go.

Before continuing, it is important for you to know that encrypting disks doesn’t come without any risks.

The process involves formatting your entire disk meaning that you will lose data if you don’t back it up. As a consequence, it might be a good idea for you to backup your files, whether you choose to do it on an external drive or in an online cloud.

If you are not sure about the steps needed to backup your entire system, I recommend that you read the following tutorial that explains it in clear terms.

Now that everything is set, we can begin encrypting our entire system.

Identify your current situation

This tutorial is divided into three parts : one for each scenario that you may be facing.

After identifying your current situation, you can directly navigate to the chapter that you are interested about.

If you want to encrypt a system that already contains unencrypted data, you have two choices :

  • You can add an additional disk to your computer or server and configure it to become the bootable disk : you can go to the part one.
  • You cannot add an additional disk to your computer (a laptop under warranty for example) : you will find the information needed on part two.

If you are installing a brand new system, meaning that you install the distribution from scratch, you may encrypt your entire disk directly from the graphical installer. As a consequence, you can go to part three.

Design Hard Disk Layout

Whenever you are creating new partitions, encrypted or not, it is quite important to choose the hard disk design ahead of time.

In this case, we are going to design our disk using a MBR layout : the first 512 bytes of the bootable disk will be reserved for the first stage of the GRUB (as well as metadata for our partitions).

The first partition will be an empty partition reserved for systems using EFI (or UEFI) as the booting firmware. If you choose to install Windows 10 in the future, you will have a partition already available for that.

The second partition of our disk will be formatted as a LUKS-LVM partition containing one physical volume (the disk partition itself) as well as one volume group containing two logical volumes : one for the root filesystem and another one for a small swap partition.

As you can see, the second stage of the GRUB will be encrypted too : this is because we chose to have the boot folder stored on the same partition.

Design Hard Disk Layout mbr-disk-design

Of course, you are not limited to the design provided here, you can add additional logical volumes for your logs for example.

This design will be our roadmap for this tutorial : we are going to start from a brand new disk and implement all the parts together.

Data-at-rest encryption

This tutorial focuses on data-at-rest encryption. As its name states, data-at-rest encryption means that your system is encrypted, i.e nobody can read from it, when it is resting or powered off.

Data-at-rest encryption data-at-rest-encryption

This encryption is quite useful if your computer were to be stolen, hackers would not be able to read data on the disk unless they know about the passphrase that you are going to choose in the next sections.

However, there would still be a risk that your data is erased forever : having no read access to a disk does not mean that they cannot simply remove partitions on it.

As a consequence, make sure that you keep a backup of your important files somewhere safe.

Encrypting Root Filesystem on New Disk

As detailed during the introduction, we are going to encrypt the root filesystem from a new disk that does not contain any data at all. This is quite important because the encrypted disk will be formatted in the process.

Head over to the system that you want to encrypt and plug the new disk. First of all, identify your current disk, which is probably named “/dev/sda” and the disk that you just plugged in (probably named “/dev/sdb”).

If you have any doubts about the correspondence between names and disk serials, you can append vendors and serials with the “-o” option of lsblk.

$ lsblk -do +VENDOR,SERIAL

Encrypting Root Filesystem on New Disk listing-drives-linux

In this case, the disk with data is named “/dev/sda” and the new one is named “/dev/sdb”.

First of all, we need to create the layout we specified in the introduction, meaning one partition that is going to be a EFI one and one LUKS-LVM partition.

Creating Basic Disk Layout

The first step on our journey towards full disk encryption starts with two simple partitions : one EFI (even if we use MBR, in case you want to change in the future) and one for our LVM.

To create new partitions on your disk, use the “fdisk” command and specify the disk to be formatted.

$ sudo fdisk /dev/sdb

As explained in the introduction, the first partition will be a 512 Mb one and the other one will take the remaining space on the disk.

Creating Basic Disk Layout create-w95-partition

In the “fdisk” utility, you can create a new partition with the “n” option and specify a size of 512 megabytes with “+512M“.

Make sure to change the partition type to W95 FAT32 using the “t” option and specifying “b” as the type.

Awesome, now that you have your first partition, we are going to create the one we are interested in.

Creating Basic Disk Layout create-second-partition

Creating the second partition is even simpler.

In the fdisk utility, use “n” in order to create a new partition and stick with the defaults, meaning that you can press “Enter” on every steps.

When you are done, you can simply press “w” in order to write the changes to disk.

Now, executing the “fdisk” command again will give you a good idea of the changes that you performed on the disk.

$ sudo fdisk -l /dev/sdb

Creating Basic Disk Layout fdisk-command-disk

Great!

Your second partition is ready to be formatted so let’s head to it.

Creating LUKS & LVM partitions on disk

In order to encrypt disks, we are going to use LUKS, short for the Linux Unified Key Setup project.

LUKS is a specification for several backends implemented in some versions of the Linux kernel.

In this case, we are going to use the “dm-crypt” submodule of the Linux storage stack.

As its names states, “dm-crypt” is part of the device mapper module that aims at creating a layer of abstraction between your physical disks and the way you choose to design your storage stack.

Creating LUKS & LVM partitions on disk dm-crypt

This information is quite important because it means that you can encrypt pretty much every device using the “dm-crypt” backend.

In this case, we are going to encrypt a disk, containing a set of LVM partitions, but you may choose to encrypt a USB memory stick or a floppy disk.

In order to interact with the “dm-crypt” module, we are going to use the “cryptsetup” command.

Obviously, you may need to install it on your server if you don’t have it already.

$ sudo apt-get instal cryptsetup

$ which cryptsetup

Creating LUKS & LVM partitions on disk which-cryptsetup

Now that the cryptsetup is available on your computer, you will create your first LUKS-formatted partition.

To create a LUKS partition, you are going to use the “cryptsetup” command followed by the “luksFormat” command that formats the specified partition (or disk).

 $ sudo cryptsetup luksFormat --type luks1 /dev/sdb2
Note : so why are we specifying the LUKS1 formatting type? As of January 2021, GRUB (our bootloader) does not support LUKS2 encryption. Make sure to leave a comment if you notice that LUKS2 is now released for the GRUB bootlader.

Creating LUKS & LVM partitions on disk cryptsetup-luksformat

As you can see, you are notified that this operation will erase all data stored on the disk. Check the disk that you are formatting one last time, and type “YES” when you are ready.

Right after, you are prompted with a passphrase. LUKS uses two authentication methods : a passphrase based one which is essentially a password that you enter on decryption.

LUKS can also use keys. Using keys, you can for example store it on a part of your disk and your system will be able to look after it automatically.

Choose a strong passphrase, enter it again and wait to the disk encryption to complete.

Creating LUKS & LVM partitions on disk cryptsetup-luksformat-2

When you are done, you can check with the “lsblk” command that your partition is now encrypted as a LUKS one.

Awesome! You now have an encrypted partition.

$ lsblk -f

list-encrypted-drives

To check that your partition is correctly formatted, you can use the “cryptsetup” command followed by the “luksDump” option and specify the name of the encrypted device.

$ sudo cryptsetup luksDump /dev/sdb2

cryptsetup-luksdump

Your version should be set to “1” for the “LUKS1” format and you should see below the encrypted passphrase in one of the keyslots.

Creating Encrypted LVM on disk

Now that your LUKS encrypted partition is ready, you can “open” it. “Opening” an encrypted partition simply means that you are going to access data on the disk.

To open your encrypted device, use the “cryptsetup” command followed by “luksOpen”, the name of the encrypted device and a name.

$ sudo cryptsetup luksOpen <encrypted_device> <name>

cryptsetup-luksOpen

In this case, we chose to name the device “cryptlvm“.

As a consequence, using the “lsblk” command again, you can see that a new device was added to the existing device list. The second partition now contains a device named “cryptlvm” which is your decrypted partition.

Now that everything is ready, we can start creating our two LVM : one for our root partition and one for swap.

First of all, we are going to create a physical volume for our new disk using the “pvcreate” command.

# Optional, if you don't have LVM commands : sudo apt-get install lvm2

$ sudo pvcreate /dev/mapper/cryptlvm

create-physical-volume

Now that your physical volume is ready, you can use it to create a volume group named “cryptvg“.

$ sudo vgcreate cryptvg /dev/mapper/cryptlvm

vgcreate-command

Now that your volume group is ready, you can create your two logical volumes.

In this case, the first partition is a 13Gb one and the swap partition will take the remaining space. Make sure to modify those numbers for your specific case.

In order to host our root filesystem, we are going to create an EXT4 filesystem on the logical volume.

$ sudo lvcreate -n lvroot -L 13G cryptvg

$ sudo mkfs.ext4 /dev/mapper/cryptvg-lvroot

create-root-logical-volume

Creating the swap partition can be achieved using the same steps, using the “lvcreate” and the “mkswap” one.

$ sudo lvcreate -n lvswap -l 100%FREE cryptvg

$ sudo mkswap /dev/mapper/cryptvg-lvswap

create-swap-logical-volume

Awesome! Now that your partitions are created, it is time for you to transfer your existing rootfilesystem on the newly created one.

Transfer Entire Filesystem to Encrypted Disk

Before transferring your entire filesystem, it might be a good idea to check that you have enough space on the destination drive.

$ df -h

In order to transfer your entire filesystem to your newly created partition, you are going to use the “rsync” command.

Mount your newly created logical volume and start copying your files and folders recursively to the destination drive.

$ sudo mount /dev/mapper/cryptvg-lvroot /mnt

$ sudo rsync -aAXv / --exclude="mnt" /mnt --progress

This process can take quite some time depending on the amount of data that you have to transfer.

After a while, your entire filesystem should be copied to your encrypted drive. Now that the “/boot” is encrypted, you will need to re-install the stage 1 of the GRUB accordingly.

Install and Configure GRUB Bootloader

So, why would you need to re-install and re-configure your GRUB accordingly?

To answer this question, you need to have a basic idea of the way your system boots up when using a BIOS/MBR conventional booting process.

Install and Configure GRUB Bootloader linux-bios-boot-process

As explained in the introduction, GRUB is split into two (sometimes three) parts : GRUB stage 1 and GRUB stage 2. The stage 1 will only look for the location of the stage 2, often located in the “/boot” folder of your filesystem.

The stage 2 is responsible for many tasks : loading the necessary modules, loading the kernel into memory and starting the the initramfs process.

As you understood, the stage 2 is encrypted here, so we need to tell the stage 1 (located in the first 512 bytes of your disk) that it needs to be decrypted first.

Re-install GRUB Stage 1 & 2

In order to reinstall the first stage of the GRUB, you first need to enable the “cryptomount” that enables access to encrypted devices in the GRUB environment.

To achieve that, you need to edit the “/etc/default/grub” file and add the “GRUB_ENABLE_CRYPTODISK=y” option.

However, you are currently sitting on the system that you are trying to encrypt. As a consequence, you will need to chroot into your new drive in order to execute the commands properly.

Chroot in Encrypted Drive

To chroot into your encrypted drive, you will have to execute the following commands.

$ sudo mount --bind /dev /mnt/dev
$ sudo mount --bind /run /mnt/run

$ sudo chroot /mnt/

$ sudo mount --types=proc proc /proc
$ sudo mount --types=sysfs sys /sys

Chroot in Encrypted Drive lsblk-chroot

Now that you executed those commands, you should now be in the context of your encrypted drive.

$ vi /etc/default/grub

grub-enable-cryptodisk-1

GRUB_ENABLE_CRYPTODISK=y

As stated in the GRUB documentation, this option will configure the GRUB to look for encrypted devices and add additional commands in order to decrypt them.

Now that the stage 1 is configured, you can install it on your MBR using the grub-install command.

$ grub-install --boot-directory=/boot /dev/sdb
Note : be careful, you need to specify “/dev/sdb” and not “/dev/sdb1”.

grub-install-stage-1

As you probably noticed, when providing no options for the GRUB installation, you have by default an “i386-pc” installation (which is designed for a BIOS-based firmware).

Re-install GRUB Stage 2

Using the steps detailed above, the stage 1 has been updated but we also need to tell the stage 2 that it is dealing with an encrypted disk.

To achieve that, head over to the “/etc/default/grub” and add another line for your GRUB stage 2.

GRUB_CMDLINE_LINUX="cryptdevice=UUID=<encrypted_device_uuid> root=UUID=<root_fs_uuid>"

This is an important line because it tells the second stage of the GRUB where the encrypted drive is and where the root partition is located.

To identify the UUIDs needed, you can use the “lsblk” command with the “-f” option.

$ lsblk -f

lsblk-uuids

Using those UUIDs, we would add the following line to the GRUB configuration file.

GRUB_CMDLINE_LINUX="cryptdevice=UUID=1b9a0045-93d5-4560-a6f7-78c07e1e15c4 root=UUID=dd2bfc7f-3da2-4dc8-b4f0-405a758f548e"

To update your current GRUB installation, you can use the “update-grub2” command in your chrooted environment.

$ sudo update-grub2

update-grub2-command

Now that you updated your GRUB installation, your GRUB menu (i.e the stage 2) should be modified and you should see the following content when inspecting the “/boot/grub/grub.cfg” file.

grub-configuration-file

As you can see, the GRUB configuration file was modified and your system is now using “cryptomount” in order to locate the encrypted drive.

For your system to boot properly, you need to check that :

  • You are loading the correct modules such as cryptodisk, luks, lvm and others;
  • The “cryptomount” instruction is correctly set;
  • The kernel is loaded using the “cryptdevice” instruction we just set in the previous section.
  • The UUID specified are correct : the “cryptdevice” one is pointing to the LUKS2 encrypted partition and the “root” one to the ext4 root filesystem.

Modify crypttab and fstab files

One of the first steps of initramfs will be to mount your volumes using the “/etc/crypttab” and “/etc/fstab” files on the filesystem.

As a consequence, and because you creating new volumes, you may have to modify those files in order to put the correct UUID in them.

First of all, head over to the “/etc/crypttab” file (you can create it if it does not exist already) and add the following content

$ nano /etc/crypttab

# <target name>   <source device>        <key file> <options>
  cryptlvm        UUID=<luks_uuid>       none       luks

Modify crypttab and fstab files crypttab-file

If you are not sure about the UUID of your encrypted device, you can use the “blkid” to get the information.

$ blkid | grep -i LUKS

Now that the crypttab file is modified, you only need to modify the fstab accordingly.

$ nano /etc/fstab

# <file system>       <mount point>   <type>  <options>             <dump>    <pass>
UUID=<ext4 uuid>      /               ext4    errors=remount-ro     0         1

Again, if you are not sure about the UUID of your ext4 filesystem, you can use the “blkid” command again.

$ blkid | grep -i ext4

Almost done!

Now that your GRUB and configuration files are correctly configured, we only need to configure the initramfs image.

Re-configure initramfs image

Among all the boot scripts, initramfs will look for the root filesystem you specified in the previous chapter.

However, in order to decrypt the root filesystem, it will need to invoke the correct initramfs modules, namely the “cryptsetup-initramfs” one. In your chrooted environment, you can execute the following command :

$ apt-get install cryptsetup-initramfs

In order to include the cryptsetup modules in your initramfs image, make sure to execute the “update-initramfs” command.

$ update-initramfs -u -k all

That’s it!

You have successfully assembled all the needed pieces in order to create a fully encrypted disk on your system. You can now reboot your computer and have a look at your new boot process.

Boot on Encrypted Device

When booting, the first screen that you will see is the first stage of the GRUB trying to decrypt the second stage of the GRUB.

Boot on Encrypted Device grub-stage-1-encrypted

If you see this password prompt, it means that you don’t have any errors in your stage 1 configuration.

Note : be aware that this screen may not follow your usual keyboard layout. As a consequence, if you have an incorrect password prompt, you should try pretending that you have a US keyboard or an AZERTY one for example.

When providing the correct password, you will be presented with the GRUB menu.

grub-stage-2

If you see this screen, it means that your stage 1 was able to open the stage 2. You can select the “Ubuntu” option and boot on your system.

boot-lock-screen

On the next screen, you are asked to provide the passphrase again.

This is quite normal because your boot partition is encrypted. As a consequence, you need one passphrase in order to unlock the stage 2 and one to unlock the entire root filesystem.

Luckily, there is a way to avoid that : by having a key file embedded in the initramfs image. For that, ArchLinux contributors wrote an excellent tutorial on the subject.

In this case, we are just going to provide the passphrase and press Enter.

After a while, when the init process is done, you should be presented with the lock screen of your user interface!

Congratulations, you successfully encrypted an entire system on Linux!

lock-screen

Encrypting Root Filesystem on Existing Disk

In some cases, you may have to encrypt an existing disk without the capability of removing one of the disks on your computer. This case may happen if you have a disk under warranty for example.

In this case, the process is quite simple :

  • Make a bootable USB (or removable device) containing an ISO of the distribution of your choice;
  • Use the device in order to boot and log into a LiveCD of your distribution;
  • From the LiveCD, identify the hard disk containing your root distribution and make a backup of it;
  • Mount the primary partition on the folder of your choice and follow the instructions of the previous chapter;

So why do you need to use a LiveCD if you want to encrypt a non-removable disk?

If you were to encrypt your main primary disk, you would have to unmount it. However, as it is the root partition of your system, you would not be able to unmount it, as a consequence you have to use a LiveCD.

Encrypting Root Filesystem From Installation Wizard

In some cases, some distributors embed the encryption process right into the installation wizard.

If you are not looking to transfer an existing filesystem from one system to another, you might be tempted to use this option.

Taking Ubuntu 20.04 as an example, the installation process suggests disk encryption in the disk configuration wizard.

Encrypting Root Filesystem From Installation Wizard
If you select this option, you will have a similar setup to the one done in the previous sections. However, most distributions choose not to encrypt the “/boot” folder.

encrypted-system-from-wizard

If you want to encrypt the “/boot” folder, we recommend that you read the first section of this tutorial.

Troubleshooting

As open-source changes constantly, there is a chance that you are not able to boot your system, even if you followed the steps of this tutorial carefully.

However, as error sources are probably infinite and specific to every user, there would be no point enumerating every single issue that you can encouter.

However, most of the time, it is quite important to know on which step of the boot process you are failing.

If you see a screen with a “grub rescue” prompt, it probably means that you are stuck on the stage 1, thus that the bootloader was not able to locate the disk containing the second stage.

If you are in an initramfs prompt, it probably means that something wrong happened during the init process :

  • Are you sure that you specified the filesystems to mount in the crypttab and fstab files?
  • Are you sure that all modules were currently loaded in your initramfs image? Aren’t you missing the cryptsetup or lvm modules for example?

initramfs-screen

Below are some resources that we found interesting during the writing of this tutorial, they may have some answers to your problems :

  • Encrypting an entire system : a similar tutorial for ArchLinux;
  • Manual System Encryption on Ubuntu : steps used in order to chroot in a root filesystem.

Conclusion

In this tutorial, you learnt how you can encrypt an entire root filesystem, with the “/boot” folder, using the LUKS specification.

You also learnt about the Linux boot process and the different steps that your system goes through in order to launch your operating system.

Achieving a full-system encryption is quite lengthy but it is very interesting for users that are willing to dig deeper into the Linux and open source world.

If you are interested in Linux System Administration, make sure to read our other tutorials and to navigate to our dedicated section.