Skip to main content

CentOS

Maintaining CentOS filesystem

In this process, we will learn how to check the consistency and optionally repair CentOS 7 filesystems. Filesystem inconsistencies are rare events and filesystem checks normally are running automatically at boot time. But system administrators should also know how to run such tests manually if they believe there is a problem with the filesystem.

To Start With: What Do You Need?

To complete this process, you will require a working installation of the CentOS 7 operating system with root privileges. We will use virtual block devices instead of real disk devices because we cannot apply any file system check on a mounted disk. Therefore, you should have applied the Formatting and mounting a filesystem process and created a 1 gigabyte virtual block device with two partitions of half the total size: first, a partition with an XFS, and then another one with an ext4 filesystem. We will use the virtual block device named /dev/loop0 in this example.

As said before, these can be easily exchanged with real disk names.

The Process

  1. To begin with, log in as root and show information about the current block devices attached to the system:
    lsblk -io NAME,TYPE,SIZE,MOUNTPOINT,FSTYPE,MODEL
  2. Here, you should see two partitions on the loop0 device: /dev/loop0p1 and /dev/loop0p2. If you see that they are currently mounted to the system, unmount them now:
    umount /dev/loop0p1 umount /dev/loop0p2
  3. Now, let’s check the XFS filesystem which in our example is loop0p1 (change appropriately):
    xfs_repair -n /dev/loop0p1
  4. For the second partition on the disk that is ext4, we will use the following line
    fsck -f /dev/loop0p2

How Does It Work?

In this process, we have learned how easy it is to run a filesystem check on a XFS or ext4 filesystem. The most important lesson you should have learned here is that you always have to unmount your disk partitions before running any filesystem checks!

So, what did we learn from this experience?

Since we cannot run any filesystem checks on any mounted device, if you want to check your system’s disks and partitions, often you have to run such checks in the rescue mode where your filesystems are not mounted (for example, you cannot unmount the root partition to check because it’s needed by the system all the time, whereas, for a separate home partition, it would be possible).

For the XFS file system, we use the xfs_repair tool, and for all others we will use the fsck program with the -f parameter (force) to check our filesystem.

It is important to note that we always need to run fsck instead of the specific fsck. (such as fsck.ext4, fsck.btrfs), because it auto-detects the right tool for you. This is necessary because if you run the wrong specific fsck. tool on the wrong filesystem (let’s say running fsck.ext4 on a btrfs filesystem), it can completely destroy it!

There's more…

So far, we have only showed you how to check a filesystem using xfs_repair and fsck. If some errors occur during the “checking” run on an XFS filesystem, run xfs_repair without the -n option—for example, use xfs_repair /dev/loop0p1. On a non-XFS partition, such as ext4, you would run fsck with the -a option (a for auto repair)—for example, fsck -a /dev/loop0p2. For fsck, if you got a lot of errors, it’s best to use -y as well so that you do not have to confirm every error fix.

Now, let’s simulate what would happen if we got a corrupted XFS filesystem using our virtual block device (never do this on any real disk partition!):

  1. First, mount the /dev/loop0p1 partition to your root filesystem:
    mkdir /media/vbd-1 mount -t xfs /dev/loop0p1 /media/vbd-1
  2. Next, create a large number of files on this mounted filesystem—for example, 2000 files:
    for i in {1..2000}; do dd if=/dev/urandom bs=16 count=1 of=/media/vbd1/file$i; done
  3. Now, unmount the device and corrupt the filesystem using dd:
    umount /dev/loop0p1
    dd bs=512 count=10 seek=100 if=/dev/urandom of=/dev/loop0p1
  4. Now, run a filesystem check:
    xfs_repair -n /dev/loop0p1
  5. This will most likely show you a list of corrupted files; in order to fix it, use the following line:
    xfs_repair /dev/loop0p1

You can also simulate such a filesystem corruption on your ext4 virtual block device, and then repair it using fsck -ay /dev/loop0p2.

 

Scheduling tasks with cron in CentOS

In this process, we will investigate the role of server automation and the convenience of running specific tasks at predefined periods by introducing you to the time-based job scheduler known as cron. Cron allows for the automation of tasks by enabling the administrator to determine a predefined schedule based on any hour, any day, or any month. It is a standard component of the CentOS operating system, and it is the purpose of this process to introduce you to the concept of managing recurring tasks in order to take advantage of this invaluable tool and to make CentOS work for you.

To Start With: What Do You Need?

In a bid to complete this process, you will require a minimal installation of the CentOS 7 operating system with root privileges, and a console-based text editor of your choice. The crontab program uses Vim for file editing. If you do not know how to work with Vim, go through the tutorial shown in the article Introduction to Vim, Configuring the System

The Process

The purpose of this process is to create a script that will write the time and date with a few words of your choice to a text file every five minutes. This may seem to be a relatively simple exercise, but the intention is to show you that, from such simplicity, cron can be used to do so much more that will make working with CentOS an absolute pleasure.

  1. To begin this process, log in as root and create your first cron job by typing:
    crontab -e
  2. We will now create a simple cron job that will write the date and time with the words hello world to a file located at /root/cron-helloworld.txt every five minutes. To do this, add the following line:
    */5 * * * * echo `date` "Hello world" >>$HOME/cron-helloworld.txt
  3. When complete, simply save the file and exit the editor. The system will now respond with the following message:
    crontab: installing
    new crontab
  4. The preceding message informs you that the server is now creating the new cron job and will automatically activate it. You can view the output of the script by reviewing the file found at /root/cron-helloworld.txt (you have to wait 5 minutes), or by monitoring the logfile found at /var/log/cron (use tail -f /var/log/cron and Ctrl+C to exit).

How it works...

Cron is the name of a program that enables CentOS users to execute commands or scripts automatically at a specified time and date. Cron’s settings are kept in a user-specific file called crontab, and as we have seen in this process this file can be edited to create automated tasks as often as they are required.

So what did we learn from this experience?

The example used was very simple, but in many ways, this was the purpose of this process. Crontab uses a daemon, crond, which runs constantly in the background and checks once a minute to see if any of the scheduled jobs need to be executed. If a task is found, then cron will execute it. To edit an existing crontab file or to create a new crontab, we use the crontab -e command. To view a list of current cron jobs, you can type crontab -l. Alternatively, to view a list of the current jobs for another user, you can type crontab -u username -l. Tasks or jobs are generally referred to as cron jobs, and by avoiding complication in our first script, it was the intention to show you that the nature of command construction was very simple. The formation of a cron job looks like this:

Entries are separated by a single or tabbed space, and the allowed values are primarily numeric (that is, 0-59 for a minute, 0-23 for an hour, 1-31 for a day of the month, 1-12 for the month of the year, and 0-7 for day of the week). However, in saying this, it is also true to say that there are more specific operators ( / , -) and cron-specific shortcuts (that is, @yearly, @daily, @hourly, and @weekly) that do allow for additional controls. For example, where the / operator is used to step through specified units, it can be read as every, so in our process, the use of */5 will run the task every five minutes while the use of */1 runs the task every minute. As an addition to this, you should be aware that the use of this syntax will align all commands on the hour. So, with this in mind, the most suitable template or starting point for anyone wanting to write their first cron job is to start with a series of five asterisks followed by the command, like this:

* * * * * /absolute/path/to/script.sh

Then, proceed to configure the minute, hour, day, month, and day-of-the-week values as desired. For example, if you want a particular PHP script to run at 8 P.M. (20:00 hrs) on every weekday (Monday-Friday), it may look like this:
0 20 * * 1-5 /full/path/to/your/php/script.php

So, with this in mind, and by completing this process, you can see how cron can be used to manage a database backup, run a scheduled system backup, provide support to websites by activating scripts at predefined intervals or run various bash scripts and a whole lot more.

There's more…

To delete or disable a cron job, it is simply a matter of either removing the instruction from an individual user’s cron file or by placing a hash (#) at the beginning of the line. Individual cron files can be found at /var/spool/cron/, and the use of the hash will either disable the cron job or allow you to write comments. To completely remove a crontab file, you can also use crontab -r. For example, if you want to remove the cron job created in the main process, you can log in as root and begin by typing the command, crontab -e. At this point, you may either remove the entire line or comment it out, as shown here:
# */15 * * * * echo `date` "Hello world" >>$HOME/cron-helloworld.txt

Next, save the file. There are also some special cron directories in the filesystem for system-wide cron jobs that will if you drop a script file in it, run it automatically at a certain time point. The folders are called cron.daily, cron.hourly, cron.weekly, and cron.monthly in the /etc directory and their names refer to the time point that they are run. Just remove the script from the folder if you don’t want to execute it any more. Take a look at the Monitoring important server infrastructure process for an example.

 

CentOS troubleshooting in rescue mode

We all make mistakes and this is especially true for novice Linux system administrators. Linux can have a steep learning curve and sooner or later there will be a point in your career where your CentOS installation does not start up due to a broad number of reasons, including hardware problems or human mistakes such as configuration errors. If this has happened to you then you can use the CentOS rescue mode in order to boot an otherwise unbootable system and try to undo your mistakes or find out the root of the problems. In this process, we will show you three common use cases when to use this option:

  • Accessing the filesystem for recovering important data or undoing changes to configuration files if CentOS is not booting up
  • Changing the root password if you forgot it
  • Re-installing the boot loader which can be damaged when installing another operating system on the same hard disk where CentOS is installed

To Start With: What Do You Need?

In order to complete this process, you will require a standard installation media (CD/DVD or USB device) of the CentOS 7 operating system. For recovering the data from the system, you will need to connect some sort of external storage device to the system, such as an external hard disk or a working network connection to another computer to copy all your precious data to a different location.

The Process:

To begin this process, you should boot your server from the CentOS installation CD/DVD or the USB device and wait until the first welcome splash screen appears with the cursor waiting at the Test this media & install CentOS 7 menu option.

Reaching rescue mode

  1. From the main menu, use the down arrow key to select Troubleshooting and then press the Return key to proceed.
  2. On the troubleshooting screen, use the down arrow key to highlight Rescue a CentOS system. When you are ready, press the Return key to proceed.
  3. After some loading time, we enter the rescue screen, which includes various confirmation sub-screens. To begin this section, use the left and right arrow keys to choose Continue and press the Return key to proceed.
  4. On the first sub-screen, choose OK and press the Return key to proceed.
  5. Again, in the following sub-screen, choose OK and press the Return key to proceed.
  6. On the next screen, choose the Start shell and by using the Tab key, highlight OK and press the Return key to proceed.
  7. By completing the preceding steps, you will launch a shell session. You will notice this at the bottom of your display. The current status of the shell session will read as follows:
    bash-4.2#_
  8. At the prompt, type the following instruction to change the root filesystem, before pressing the Return key to complete your request:
    chroot /mnt/sysimage
  9. Congratulations! You just reached the rescue mode. To exit it at any time, simply type the following command and then press the Return key to complete your request (don’t do this right now as this will restart the system):
    reboot
  10. After the basic rescue mode is reached, we have the following options, depending on the type of problem.

Accessing the filesystem

If you are now in the rescue mode and need to back up important files from the filesystem, you need a destination location for the data transfer. For transferring the data we want to recover from the server to another computer please physically connect an external USB device to it. You can also use network storages for the recovery. For example, you could import an NFS server share and copy data to it. 

  1. On the rescue mode command line, type in the following command, which will show you all the current partitions connected to the system, and then press the Return key to complete your request:
    fdisk -l
  2. You now need to find out the right device name with the partition number of your connected device; comparing the total size or the filesystem output of the various devices with the specifications from your stick can help you in this process. You can also try the following trick: run the fdisk -l command twice, first with the plugged-in USB device and then again with the USB device unplugged, and compare the output of both the commands. It should be different from one device name which you are searching for!
  3. If you have found the right device name in the list, create a directory to mount the stick to the filesystem:
    mkdir /mnt/hdd-recover
  4. Next, mount the disk partition to this folder. Here we assume that the USB device of interest has the device name sdd1 (please change if different on your system):
    mount /dev/sdd1 /mnt/hdd-recovery
  5. The original system’s hard disk’s root partition has been mounted under a specific folder by the rescue system automatically (under /mnt/sys image), if you need to access it for example to change configuration files which caused startup problems or make a full or partial backup. For example, if you need to back up your Apache web server configuration files, use:
    cp -r /mnt/sysimage/etc/http /mnt/hdd-recovery
  6. If you need to access the data that lives on partitions other than the currently mounted root partition, use fdisk -l to identify the partition of interest. Then create a directory and mount the partition to it and change to that directory to access your data similar you did when mounting the USB device.
  7. To finish backing up the files, type:
    reboot

Accessing the filesystem

  1. If you are in the rescue mode for changing the root password, just use the following command and provide a new password:
    passwd
  2. To complete changing the password, type:
    reboot

Re-install the CentOS boot loader

  1. We will now use the fdisk command to find the name of all the current partitions. To do this, type the following instruction and then press the Return key to complete your request:
     fdisk –l
  2. Now run the following command:
    dmesg | grep -Fq "EFI v"
  3. If the preceding command does not produce any output look for the * symbol in the fdisk listing in the boot column to find the correct start partition, and assuming that your boot disk is on /dev/sda1 (change this as required), type the following:
    grub2-install /dev/sda
  4. Otherwise, if there is an output, run instead:
    yum reinstall grub2-efi shim
  5. If no error is reported, the console should respond as follows:
    # this device map was generated by anaconda
    (hd0) /dev/sda
  6. The console output from the last step has confirmed that GRUB has now been successfully restored.
  7. To reboot the computer, type:
    reboot

How Does It Work?

There are a broad variety of problems which can be resolved by the tools provided through the rescue mode environment. Often these problems refer to booting problems but can also be from different types, such as forgetting the root password. Rescue mode can be a lifesaver and an understanding of it is a very important skill to learn. 

Tip

Remember to always be careful when working with bootloader commands as improper use can make your operating system unbootable.

 

Troubleshooting SELinux

In this process, you will learn how to troubleshoot SELinux policies, which is most often needed when access to some SELinux objects has been denied and you need to find out the reasons for it. In this process, we will show you how to work with the sealert tool, which will create human-readable and understandable error messages to work with.

To Start With: What Do You Need?

To complete this process, you will require a working installation of the CentOS 7 operating system with root privileges. It is assumed that you are working through serially process by process, so by now you should have installed the SELinux tools and applied the Working with policies process, as we will produce some SELinux denial events in order to show you how to use the log file tools.

The Proces

  1. To begin, login as root and provoke a SELinux denial event:
    touch /var/www/html/test2.html
    semanage fcontext -a -t user_tmp_t /var/www/html/test2.html
    restorecon -v /var/www/html/test2.html
    curl http://localhost/test2.html
  2. Now, let’s generate an up-to-date human readable log file:
    sealert -a /var/log/audit/audit.log
  3. In the program’s output, you will get a detailed description of any SELinux problem and, at the end of each so called alert, you will even find a suggested solution to fix the problem; in our example, the alert of interest should read (the output is truncated) as shown next:
    SELinux is preventing /usr/sbin/httpd from open access on the file
    /var/www/html/test2.html.
    /var/www/html/test2.html default label should be httpd_sys_content_t

How Does It Work?

Here in this process, we showed you how easily one can troubleshoot SELinux problems using the sealert program. We started by provoking a SELinux deny access problem by creating a new file in the web root directory and assigning it a wrong context type of value user_tmp_t, which has no access rule defined in the httpd policy. Then, we used the curl command to try and fetch the website and actually produce the Access Vector Cache (AVC) denial message in the SELinux logs. Denial messages are logged when SELinux denies access. The primary source where all SELinux logging information is stored in the audit log file, which can be found at /var/log/audit/audit.log, and easier-to-read denial messages will also be written to /var/log/messages. Here, instead of manually grepping for error messages and combining both log files, we use the sealert tool, which is a convenience program that will parse the audit and messages log file and present valuable AVC content in a human-readable format. At the end of each alert message, you will also find a suggested solution to the problem. Please note that those are auto-generated messages and should always be questioned before applying.

 

Delivering the mail with Dovecot in CentOS

In a previous process, you were shown how to configure Postfix as a domain-wide mail transport agent. As we have learned in the first process of Postfix that it only understands the SMTP protocol and does a remarkable job to transport messages from another MTA or mail user client to other remote mail servers or storing mails which are destinated to itself into its local mailboxes. After storing or relaying mails, Postfix jobs end. Postfix can only understand and speak the SMTP protocol and is not capable of sending messages to anything other than MTAs. Any possible recipient user for a mail message who wants to read his mails would now need to log in to the server running the Postfix service using ssh and look into his local mailbox directory, or alternatively use mailx locally to view his messages on a regular basis to see if there are any new mails. This is highly inconvenient and nobody would use such a system. Instead, the users choose to access and read their mail from their own workstations other than where our Postfix server is located. Therefore, another group of MTAs has been developed, sometimes are called access agents and which have the main functionality to synchronize or transfer those local mailbox messages from the server running the Postfix daemon over to external mailing programs where users can read them. These MTA systems use different protocols than SMTP, namely POP3 or IMAP. One such MTA program is Dovecot. Most professional server administrators would agree that Postfix and Dovecot are perfect partners and it is the purpose of this process to learn how to configure Postfix to work with Dovecot in order to provide a basic POP3/IMAP and a POP3/IMAP over SSL (POP3S/IMAPS) service for our mailboxes to provide an industry standard e-mail service for your users across the local network.

To Start With: What Do You Need?

To complete this process, you will require a working installation of the CentOS 7 operating system with root privileges, a console-based text editor of your choice, and a connection to the Internet in order to download additional packages. It is also assumed that you are working through this chapter division process by the process in the order that they appear and for this reason, it is expected that Postfix has been configured as a domain-wide MTA.

Note
This process serves as a guide to setting up a basic POP3S/IMAPS service for trusted users on a local network. It is not suitable for general Internet use without applying additional security measures.

The Process

Dovecot is not installed by default, and for this reason we must begin by installing the necessary packages by following the given steps:

  1. To start, log in as root and type in the following command:
    yum install dovecot
  2. Once installed, enable the Dovecot service at boot by typing:
    systemctl enable dovecot
  3. Now open the main Dovecot configuration file in your favorite text editor, after creating a backup copy, by typing:
    cp /etc/dovecot/dovecot.conf /etc/dovecot/dovecot.conf.BAK
    vi /etc/dovecot/dovecot.conf
  4. Begin by confirming the protocols we want to use by activating (removing the # sign at the beginning of the line) and modifying the following line, so it reads:
    protocols = pop3 imap imaps pop3s
  5. Next, enable Dovecot to listen to all network interfaces instead of only the loopback address. Search for the line #listen = *, ::, then modify it so it reads:
    listen = *
  6. Now save and close the file in the usual way before making a backup of the 10mail.conf file and afterwards opening it in your favorite text editor:
    cp /etc/dovecot/conf.d/10-mail.conf /etc/dovecot/conf.d/10
    mail.conf.BAK
    vi /etc/dovecot/conf.d/10-mail.conf
  7. Scroll down and uncomment (remove # character) the following line, so it reads:
    mail_location = maildir:~/Maildir
  8. Again, save and close the file in the usual way before creating a backup copy and then opening the following file in your favorite text editor:
    cp /etc/dovecot/conf.d/20-pop3.conf /etc/dovecot/conf.d/20
    pop3.conf.BAK
    vi /etc/dovecot/conf.d/20-pop3.conf
  9. Start by uncommenting the following line:
    pop3_uidl_format = %08Xu%08Xv
  10. Now scroll down and amend the following line:
    pop3_client_workarounds = outlook-no-nuls oe-ns-eoh
  11. Save and close the file in the usual way. Now we will allow plain text logins. To do this, make a backup before opening the following file:
    cp /etc/dovecot/conf.d/10-auth.conf /etc/dovecot/conf.d/10
    auth.conf.BAK
    vi /etc/dovecot/conf.d/10-auth.conf
  12. Change the line #disable_plaintext_auth = yes to state:
    disable_plaintext_auth = no
  13. Save and close the file. In our final configuration setting, we will tell Dovecot to use our self-signed server certificate. Just use your Postfix certificate from another process in this segment or create a new one (otherwise skip this step):
    cd /etc/pki/tls/certs; make postfix-server.pem
  14. Open Dovecot’s standard SSL config file after making a backup of the file:
    cp /etc/dovecot/conf.d/10-ssl.conf /etc/dovecot/conf.d/10-ssl.conf.BAK
    vi /etc/dovecot/conf.d/10-ssl.conf
  15. Now change the following line (ssl = required) to read:
    ssl = yes
  16. Now change the following two lines to point to your server’s own certificate path:
    ssl_cert = /etc/pki/tls/certs/postfix-server.pem
    ssl_key =
  17. Save and close this file. Next, enable IMAP, IMAPS, POP3, and POP3S ports in our firewall to allow incoming connections on the corresponding ports. For POP3 and IMAP, we need to specify our own firewalld service files, since they are not available in CentOS 7 by default:
    sed 's/995/110/g' /usr/lib/firewalld/services/pop3s.xml | sed 's/ over
    SSL//g' > /etc/firewalld/services/pop3.xml
    sed 's/993/143/g' /usr/lib/firewalld/services/imaps.xml | sed 's/ over
    SSL//g' > /etc/firewalld/services/imap.xml
    firewall-cmd --reload
    for s in pop3 imap pop3s imaps; do firewall-cmd --permanent --add
    service=$s; done;firewall-cmd --reload
  18. Now save and close the file before starting the Dovecot service:
    systemctl start dovecot
  19. Finally, to test our new POP3/SMTP network service, just login on another computer in the same network and run the following commands to use mailx to access the local mailboxes on the remote Postfix server, which is provided by Dovecot with the different access agent protocols. In our example, we want to access the local mailbox of the system user john on our Postfix server with the IP 192.168.1.100 (to login to john’s account, you need his Linux user password) remotely:
    mailx -f pop3://john@192.168.1.100
    mailx -f imap://john@192.168.1.100
  20. Next, to test the secure connections, use the following commands and type yes to confirm that the certificate is self-signed and not trusted:
    mailx -v -S nss-config-dir=/etc/pki/nssdb -f pop3s://john@192.168.1.100
    mailx -v -S nss-config-dir=/etc/pki/nssdb -f imaps://john@192.168.1.100
  21. For all four commands, you should see the normal mailx inbox view of your mailbox with all your mail messages of user john as you would run the mailx command locally on the Postfix server to read local mails.

How Does It Work?

Having successfully completed this process, you have just created a basic POP3/SMTP service, (with or without SSL encryption) for all the valid server users in your network, which will deliver local mails from the Postfix server to the client’s e-mail program. Every local system user can directly authenticate and connect to the mail server and fetch their mail remotely. Of course, there is still much more that can be done to enhance the service, but you can now enable all local system account holders to configure their favorite e-mail desktop software to send and receive e-mail messages using your server.

Note
POP3 downloads the mails from the server on a local machine and deletes them afterwards, whereas IMAP synchronizes your mails with your mail server without deleting them.

So what did we learn from this experience?

We started the process by installing Dovecot. Having done this, we then enabled Dovecot to run at boot before proceeding to make a few brief changes to a series of configuration files. Starting with the need to determine which protocol will be used in the Dovecot configuration file at /etc/dovecot/dovecot.cf here we will use: IMAP, POP3, IMAPS, and POP3S. As with most other essential networking services, after installation they only listen on the loopback device, so we enabled Dovecot to listen to all network interfaces installed in the server. In the 10-mail.conf file we then confirmed the mailbox directory location for Dovecot (with the mail_location directive) as the location Postfix will put them into on receiving mails so Dovecot can find them here and pick them up. Following this, we then opened the POP3 protocol in 20-pop3.conf by adding a fix relating to various e-mail clients (for example, for the Outlook client) using the pop3_uidl_format and pop3_client_workarounds directives. Finally, we enabled plain text authorization by making several changes to /etc/dovecot/conf.d/10-auth.conf. Remember that using plain text authorization with POP3 or IMAP without SSL encryption is considered insecure but because we were concentrating on a local area network (for a group of trusted server users) we should not necessarily see this as a risk. Afterwards, we enabled POP3 and IMAP over SSL (POP3S and IMAPS) by pointing the ssl directives in the 10ssl.conf file to some existing self-signed server certificates. Here we changed ssl = required to ssl=yes to not force the client connecting to the Dovecot service to use SSL encryption, as we do want to give the user the choice to enable encrypted authentication if he likes to but not make it mandatory for older clients. Afterwards, to make our Dovecot service available from the other computers in our network, we had to enable the four ports to allow POP3, IMAP, POP3S, and IMAPS, 993, 995, 110, 143, by using the predefined firewalld service files and creating the missing ones for IMAP and POP3 ourselves. Later, we started the Dovecot service and tested our new POP3/IMAP server using the mailx command remotely. By supplying an -f file parameter, we were able to specify our protocol and location. For using SSL connections, we needed to supply an additional nssconfig-dir option pointing to our local Network Security Services database where certificates are stored in CentOS 7.

Remember, if you happen to encounter any errors, you should always refer to the log file located at /var/log/maillog. Using plain text authorization should not be used in a real corporate environment and POP3/IMAP over SSL should be preferred.

There's more…

In the main process, you were shown how to install Dovecot in order to enable trusted local system users with system accounts to send and receive e-mails. These users will be able to use their existing username as the basis of their e-mail address, but by making a few enhancements you can quickly enable aliases, which is a way to define alternative e-mail addresses for existing users.

To start building a list of user aliases, you should begin by opening the following file in your favorite text editor:
vi /etc/aliases

Now add your new identities to the end of the file, where will be the name of the actual system account:
#users aliases for mail
newusernamea:
newusernameb:

For example, if you have a user called john who currently (only) accepts e-mails at john@centos7.home, but you want to create a new alias for john called johnwayne@ centos7.home, you will write:
johnwayne: john

Repeat this action for all the aliases, but when you have finished remember to save and close the file in the usual way before running the following command: newaliases.

Setting up e-mail software in CentOS

There are a vast number of e-mail clients on the market and by now you will want to start setting up your local users to be able to send and receive e-mails. This isn’t complicated by any means, but in order to have a good starting point you will want to consider the following principles. The format of the e-mail address will be system_username@domainname.home.

The incoming POP3 settings will be similar to the following:
mailserver.centos7.home, Port 110
Username: system_username
Connection Security: None
Authentication: Password/None

For POP3S, just change the port to 995 and use Connection Security: SSL/TLS. For IMAP, just change the port to 143, and for IMAPS use port 993 and Connection Security: SSL/TLS.

The outgoing SMTP settings will be similar to the following:
mailserver.centos7.home, Port 25
Username: system_username
Connection Security: None
Authentication: None

 

 

Working with CentOS virtual FTP users

In this process, you will learn how to implement virtual users in order to break away from the restriction of using local system user accounts. During the lifetime of your server, there may be occasions when you wish to enable FTP authentication for a user that does not have a local system account. You may also want to consider implementing a solution that allows a particular individual to maintain more than one account in order to allow access to different locations on your server. This type of configuration implies a certain degree of flexibility afforded by the use of virtual users. Since you are not using a local system account, it can be argued that this approach gives improved security.

To Start With: What Do You Need?

To complete this process, you will require a working installation of the CentOS 7 operating system with root privileges and a console-based text editor of your choice. It is expected that your server will be using a static IP address and that vsftpd is already installed with a chroot jail and is currently running. This process needs the policycoreutils-python package installed.

The Process

  1. The first step is to login as root on our vsftpd server and create a plain text file called virtual-users.txt that maintains a list of usernames and passwords of the virtual users. To do this, type the following command:
    vi /tmp/virtual-users.txt
  2. Now add your usernames and corresponding passwords in the following way:
    virtual-username1
    password1
    virtual-username2
    password2
    virtual-username3
    password3

    Note
    Repeat this process as required for every user you need but, for obvious reasons, maintain a good password policy and do not use the same virtual-username more than once.

  3. When you have finished, simply save and close the file in the usual way. Then, proceed to build the database file by typing the following command:
    db_load -T -t hash -f /tmp/virtual-users.txt /etc/vsftpd/virtualusers.db
  4. Having done this, we will now create the PAM file that will use this database to validate the virtual users. To do this, type the following command:
    vi /etc/pam.d/vsftpd-virtual
  5. Now add the following lines:
    auth required pam_userdb.so db=/etc/vsftpd/virtual-users
    account required pam_userdb.so db=/etc/vsftpd/virtual-users
  6. When you have finished, save and close the file in the usual way. Open the main vsftpd configuration file in your favorite text editor as follows:
    vi /etc/vsftpd/vsftpd.conf
  7. Now, in the opened file, search for the line pam_service_name=vsftpd and disable it by adding a # sign at the beginning of the line so that it reads as follows:
    #pam_service_name=vsftpd
  8. Scroll down to the bottom of the file and add the following lines by customizing the value for local_root to suit your own specific needs—this will be the base directory in which all your virtual users will live in (for example, we will use /srv/virtualusers/$USER as shown here):
    virtual_use_local_privs=YES
    guest_enable=YES
    pam_service_name=vsftpd-virtual
    user_sub_token=$USER
    local_root=/srv/virtualusers/$USER
    hide_ids=YES
  9. Now create a subfolder for each virtual user you defined in a previous step in your /tmp/virtual-users.txt file within the directory that you stated with the local_root directive. Remember to delegate the ownership of this folder to the FTP user. To keep up with our /srv/virtualusers example, we will use the following commands to do this in an automatic way (again, customize the /srv/virtualusers directory if needed):
    for u in `sed -n 1~2p /tmp/virtual-users.txt`;
    do
    mkdir -p /srv/virtualusers/$u
    chown ftp: /srv/virtualusers/$u
    done
  10. Now we need to inform SELinux to allow read/write access to our custom local_root directory outside of the typical /home directory:
    setsebool -P allow_ftpd_full_access on
    semanage fcontext -a -t public_content_rw_t "/srv/virtualusers(/.*)?"
    restorecon -R -v /srv/virtualusers
  11. Next, restart the FTP service as follows:
    systemctl restart vsftpd
  12. For security reasons, remove the plain text file now and protect the generated database file with this:
    rm /tmp/virtual-users.txt chmod 600 /etc/vsftpd/virtual-users.db

How Does It Work?

Having followed the previous process, you will be now able to invite an unlimited number of virtual users to access your FTP service. The configuration of this feature was very simple; your overall security has been improved and all access is restricted to a defined local_root directory of your choice. Please note that this usage of virtual users will disable your system users’ login to the FTP server from the first process.

So what did we learn from this experience?

We began this process by creating a new temporary text file that will contain all our usernames with the corresponding passwords in plain text. We then added all the required usernames and passwords one after another sequentially separated by newlines. Having done this for each of our virtual users, we then saved and closed the file before proceeding to run the db_load command that is installed on CentOS 7 by default. This can be used to generate a BerkeleyDB database out of our text file, which will be used for the FTP user authentication later in this process. Having completed this step, our next task was to create a Pluggable Authentication Modules (PAM) file at /etc/pam.d/vsftpd-virtual. This reads the previous database file to provide authentication from it for our vsftpd service using a typical PAM configuration file syntax (for more, see man pam.d). Then, we opened, modified, and added new configuration directives to the main vsftpd configuration file at /etc/vsftpd/vsftpd.conf in order to make vsftpd aware of our virtual users’ authentication via PAM.

The most important setting was the local_root directive that defines the base location where all your user directories will be placed for your virtual users. Don’t forget to put the $USER string at the end of your path. You were then prompted to create the relevant virtual hosting folder for every virtual user you have defined in the text file before.

Since virtual users are not real system users, we had to assign the FTP system user to take full ownership of the files for our new FTP users. We used bash for loop to automate the process for all our users defined in the temporary /tmp/virtual-users.txt file. Next, we set the proper SELinux boolean to allow virtual users access to the system and also the right context on our /srv/virtualusers directory. Applying all these changes was simply a matter of restarting the vsftpd service using the systemctl command.

Afterwards, we removed the temporary user text file because it contains our passwords in plain text. We protected the access to the BerkleyDB database file by removing all access other than root. If you update, add, or remove FTP users on a regular basis, it’s better to not delete this temporary plain text /tmp/virtual-users.txt file but rather put it in a safe place such as the /root directory. Then, you should also protect this using chmod 600. Then, you can rerun the db_load command whenever you make a change to this file to keep your users up-to-date. If you need to add new users at a later point, you have to create new virtual user folders for them as well (Please rerun the commands from step 9). Run the restorecon -R -v /srv/virtualusers command afterwards.

You can now test your new virtual user accounts by logging in to the FTP server using your newly created accounts from this process.

 

Using CentOS disk quotas

When administering a Linux multiuser system with many system users, it is wise to set some kind of restrictions or limits to the resources shared by the system. On a filesystem level, you can either restrict the available hard disk space or the total file number to a fixed size at a user, group, or directory level. The introduction of such rules can prevent people from “spamming” the system, filling up its free space, and generally,  users will get more aware of the differentiation between important and unimportant data and will be more likely to keep their home directories tidy and clean. Here in this process, we will show you how to set up a disk quota limiting system for XFS filesystems, which puts restrictions on the amount of data your system’s user accounts are allowed to store.

To Start With: What Do You Need?

To complete this process you will require of the CentOS 7 operating system with root access and a console-based text editor of your choice. For this process to work, and in order to set quotas, you will need at least one system user account next to your root account; if you don’t have one yet, please refer to the process Managing users and their groups, Managing the System to learn how to create one. Also, in the main process, it is expected that your CentOS 7 uses the XFS filesystem, which is standard on installation. Finally, your CentOS 7 installation needs to have been installed on a disk with at least 64 GB space, otherwise, the installer will not create a separate logical /home volume, which is required in this process to make quotas work.

The Process:

Here, we will learn how to set up a quota system for the XFS filesystem in two different ways: first, setting limits on the user and groups, and then on the directory (project) level. Disk quota systems have to be set on filesystem mount.

Enabling user and group quotas

  1. To begin, log in as root and open the fstab file, which contains static mount information:
    vi /etc/fstab
  2. Now, navigate the cursor to the line containing /home (with the up and down arrow keys) and move it to the word defaults, and then add the following text after defaults, separated by commas:
    uquota,gquota
  3. The complete line will look like the following (your device name will be different, depending on your individual LVM name; here, it is myserver):
    /dev/mapper/myserver-home /home XFS defaults,uquota,gquota 0 0
  4. Save and close the file, then remount the /home partition to activate the quota directive:
    umount /home;mount -a
  5. Next, create a user quota on the total file size for a specific user named john (change appropriately to match a user available on your system):
    xfs_quota -x -c 'limit bsoft=768m bhard=1g john' /home/
  6. Next, create a user quota for the total amount of files another user, joe, can have:
    xfs_quota -x -c 'limit isoft=1000 ihard=5000 joe' /home/
  7. Let’s create a file amount and size limit for everyone in the user group devgrp (the filesystem group devgrp must exist):
    xfs_quota -x -c 'limit -g bsoft=5g bhard=6g isoft=10000 ihard=50000 devgrp' /home
  8. Finally, show the whole quota report for the home volume:
    xfs_quota -x -c 'report -bi -h' /home

Enabling project (directory) quotas

In order to enable disk quotas for a single directory instead of user or group quotas, we have to add the project quota directive called pquota to the volume containing the directory. As we will use a directory called /srv/data for our project quota, we need to take the full underlying / root partition under quota control. For the root partition, we have to set quota flags as kernel boot options:

  1. To begin with, open the following file as root after first making a backup of it:
    cp /etc/default/grub /etc/default/grub.BAK
    vi /etc/default/grub
  2. Add the rootflags=pquota directive to the end of the line (add one whitespace character before it) starting with GRUB_CMDLINE_LINUX= before the closing double quote as shown here:
    GRUB_CMDLINE_LINUX="rd.lvm.lv=centos/root rd.lvm.lv=centos/swap
    crashkernel=auto rhgb quiet rootflags=pquota"
  3. Save and close the file, and then rebuild the grub configuration with our new boot option:
    grub2-mkconfig -o /boot/grub2/grub.cfg
  4. Now, add the pquota flag to your root volume in /etc/fstab as well:
    vi /etc/fstab
  5. Navigate the cursor to the line containing the root mount point / and move it to the word defaults, and then add the following text, separated by a comma:
    ,prjquota
  6. The complete line will look similar to the following:
    /dev/mapper/myserver-root / XFS defaults,prjquota 0 0
  7.  Next, reboot your computer to apply your changes to the root volume:
    reboot
  8. After rebooting, make sure that the root volume has project quota enabled, which is defined as the prjquota flag in the volume’s options (otherwise, if it is wrong and doesn’t work, it will show as noquota):
    cat /etc/mtab | grep root
  9. Next, let’s create our target folder that we want to set quotas for:
    mkdir /srv/data
  10. We need to add a project name and an associated new, unique ID:
    echo "myProject:1400" >> /etc/projid
  11. Now, define that /srv/data will use quota rules from our project ID:
    echo "1400:/srv/data" >> /etc/projects
  12. Next, initialize the project quota for the root volume:
    xfs_quota -xc 'project -s myProject' /
  13. Finally, apply the following rule to create specific directory limits:
    xfs_quota -x -c 'limit -p bsoft=1000m bhard=1200m myProject' /
  14. Print out our quota rules for this device:
    xfs_quota -x -c 'report -bi -h' /

How Does It Work?

In this process, you will learn how easy it is to set up a quota system on a user, group, or directory (project) level seject) level. Also, you have learned that there are two basic ways of defining quotas: either put a restriction on the total file size (called blocks), or a limit on the number of files (called inodes).

So, what have we learned from this experience?

We began this process setting user and group quotas. As you have seen, a quota system can easily be enabled by adding associated directives to the partition of choice in the /etc/fstab file. Therefore, we began this process by opening this file and adding the special quota keywords for the XFS user, and group quotas to our /home partition. In order to apply these changes, we had to remount the filesystem using the mount command. As the quota system had been successfully started, we used the xfs_quota -x -c command line to set some quota limits on our enabled filesystem /home. -x enables expert mode while -c lets us run commands as arguments on the command line. When running xfs_quota without the -c option, you will get to an interactive prompt instead. First, we set some user limits for the users, john and joe. We did this by defining the following parameters with numbers: bsoft, bhard, isoft, ihard. As you can see, there are both soft and hard limits for file size (blocks) and file amount (inodes). Block quotas can be given in the typical metrics such as kilobyte (k), megabyte (m), and gigabyte (g), whereas an inode is a number. A soft limit is a threshold that, when crossed, prints out a warning message to the command line, whereas a hard limit will stop the user from adding any more data or files to the filesystem under quota protection. Afterwards, we set a group-based quota. If you use the -g flag, the limit will be defined for a group instead of the user. Using group rules can be very helpful to separate your users into different groups depending on the amount of files or total file size they should be allowed to have. Finally, we generated a report for all our current quota limits. The command we used there was 'report -bi -h', which generates reports for used filespace (-b for blocks) and the total amount of files (-i for inodes). -h specified that we want the output to be human-readable in megabytes or gigabytes.

To test that quotas work, let’s create the following block and inode quotas for the user jack:
xfs_quota -x -c 'limit bhard=20m jack' /home/
xfs_quota -x -c 'limit ihard=1000 jack' /home/

Log in as the user jack (su -jack) and run the following command:
dd if=/dev/urandom of=~/test.dd bs=1M count=21

With this command, the user john will try to create a 21 megabyte size file, but when starting to write the twentieth megabyte, the following error message will appear:
dd: error writing '/home/jack/test.dd': Disk quota exceeded

Now, delete the ~/test.dd file so that we can start another test. The same happens if you exceed your file amount limit. Test the following quota limit by trying to create 2,000 multiple files while the quota is limited to 1,000; do this by adding a lot of new files: for i in {1..2000}; do touch ~/test$i.txt; done. This results in the following error message:
touch: cannot touch '/home/jack/test1001.txt': Disk quota exceeded

To temporarily turn off user and group quota checking for a specific filesystem, you can run xfs_quota -x -c 'off -u -g' /home/ (-u for user, -g for group) as root user. This is only temporary; to re-enable it, you need to remount the filesystem of interest, which is umount /home;mount -a. To remove a specific quota rule, just set its limit to zero, for example:
xfs_quota -x -c 'limit bhard=0 john' /home

Next, we set up quota on a directory, instead of the user/group level. This is a feature only XFS file systems are capable of; all other filesystems can only set quotas on a disk or partition level. Being able to control the disk usage of a directory hierarchy is useful if you do not otherwise want to set quota limits for a privileged user or groups. To activate directory quota, we first had to enable this as a kernel boot option because, by default, the root volume is flagged as noquota. Also, we added the prjquota directive in /etc/fstab to the root partition to make it work. If you want to learn more about kernel boot options, read the boot loader process. To set file system flags for the root partition, we needed to reboot the system. After doing this, we made sure that the boot option has been set successfully by looking into the mtab file, which is a file that lists all currently mounted filesystems. Next, we set up a project name with an associated unique project ID (we randomly choose 1400) in the /etc/projid file. In the next step, we applied this new project ID (1400) to a directory in the /etc/projects file called /srv/data. This system allows the application of specific project quota rules to many different directories. Afterwards, we initialized project quota for the root partition using the project option with the xfs_quota command, and then created a limit quota rule for this project name. All directories that are defined in the /etc/projects file under the corresponding project id are affected by this rule. This type of system can be used for fine-grain multiple folder quota rules. For every directory, you can set up a new project name or reuse a specific one, making this system very flexible.

In this process, we have created a block size hard limit of 1,200 megabytes for our project name, which is myProject. To test this quota, type the following:
dd if=/dev/zero of=/srv/data/dd.img bs=1M count=1201

This should stop dd, exactly after writing 1200 megabytes, with the following command line error message:
dd: error writing '/srv/data/dd.img': No space left on device

There's more…

As the name implies, the xfs_quota program shown in this process only works for XFS filesystems. If you want to use disk quotas on a user or group level for other file systems such as ext4 or btrfs, you have to install the quota package (yum install quota). Setting quotas work in a similar way to the steps shown in this process; please read the manual man quota to get you started.

 

Managing CentOS users and their groups

In this process, we will learn how to manage your system’s users and groups on CentOS 7. Essential user and group managing skills are one of the most important CentOS system administrator fundamentals.

To Start With: What Do You Need?

To complete this process, you will need a working installation of the CentOS 7 operating system with root privileges and a console-based text editor of your choice.

The Process

This process shows you how to manage users and groups by learning how to add, delete, and modify them:

  1. To begin this process, we log in as root and type the following command to get a list of all the users known to the system: cat /etc/passwd.
  2. Now, show the root user ID (UID) and group ID (GID):
    id root
  3. Next, we will run the following command to add a new user to the system (exchange your_new_username with a username of your choice):
    useradd your_new_username
  4. However, in order to complete this process, you will be expected to provide a suitable password. To do this, type the following command (change your_new_username with a username of choice) than enter a secure password when prompted:
    passwd your_new_username

    Note
    Passwords should not be less than six characters, but should not be longer than sixteen characters. They should consist of alphanumeric values, and for obvious reasons, you must avoid the use of whitespaces. Do not use a dictionary-based word and refrain from using a known or obvious phrase.

  5. Next, create a new group and give it a special name:
    groupadd your_new_group
  6. Then, we add our new user to this new group:
    usermod -G your_new_group your_new_username
  7. Finally, let’s print the user ID and group IDs of our new user to see what has changed:
    id your_new_username 

How it works…

The purpose of this process was to create a new user and group and show how to connect them together.

So, what did we learn from this experience?

First, we printed out the content of file /etc/passwd to show all the current users in the system. This list not only contains normal user-accounts that belong to real persons but also accounts that are used to control and own a specific application or service. Then, we used the id command to display the unique user UID and GID for our existing user root. In Linux, every user can be identified by their UID and GID, and every file in the filesystem has specific permission settings that manage its access for the file owner, group owner and the rest of the users. For each of those three groups, you can enable or disable read, write, and execute permissions using the command, chmod (use man chmod to learn more, and also check out man chown). The owner and group permissions correspond to a UID and GID that we can display for every file using ls -l.

Next, we issued the useradd command that required us to supply a suitable name for the new user, which in turn will enable the server to establish the new identity with a default set of values and criteria that includes a user ID, home directory, primary group (GID), and also set the default shell to bash. Completing this process is simply a matter of confirming a suitable password. To remove a user, there is the opposite command, userdel, which works similarly but can be given the option -f to remove the home directory instead of leaving it on the system. Next, we used the groupadd command, which, as the name implies, will create a new group and associate a new unique GID to it. Afterward, we made our user in question a member of the new group that we created before using the usermod -G command. As said before, each user has exactly one unique UID and GID. The first group is the primary group and is mandatory; however, a user can belong to a number of different groups, which are then called secondary groups. The primary group is needed when creating a new file because it will set the GID and UID of the user creating it. To delete a group, we can use the groupdel command. Finally, we used the id command again on our new user to show its UID, primary GID, and the new secondary GID groups we added to it.

You are now able to fully control your user and groups with just a few commands: useradd, usermod, userdel, groupadd, groupmod, and groupdel.

 

CentOS boot loader customization

When you turn on your computer, the boot loader is the first program that starts up and is responsible for loading and transferring control to an underlying operating system. Nowadays, almost any modern Linux distribution uses the GRand Unified Bootloader version 2 (GRUB2) for starting the system. It has a lot of flexibility in configuration and supports a lot of different operating systems. In this process, we will show how to customize the GRUB2 boot loader by disabling the waiting time of the menu display and therefore improving the time it takes for booting the system.

To Start With: What Do You Need?

In order to implement this process, you will require access to an already installed CentOS 7 operating system (minimal or any other CentOS 7 installation type will work) with root privileges. Also, you need to have some basic experiences with a text-based editor, such as nano, for changing the configuration files.

The Process: 

We initiate this process by opening the main GRUB2 configuration file with our text editor of choice and modifying it.

  1.  First, log in as root into your system and create a copy of the GRUB2 configuration file for backup and rollback, if needed. Press the Return key to finish:
    cp /etc/default/grub /etc/default/grub.BAK
  2. Open the main GRUB2 configuration file that we want to edit with the following command and press the Return key (here we will use the editor nano, if you have not installed it yet type yum install nano):
    nano /etc/default/grub
  3. Press the Return key in the first line where the cursor is at to insert a new line at the top, and then insert the following line:
    GRUB_HIDDEN_TIMEOUT=0
  4. Adda # sign to the beginning of the following line, as shown:
    GRUB_TIMEOUT=0
  5. Now save the file in the nano using Ctrl+o (and Return to confirm the filename to save). Use Ctrl+x to exit the editor and then run the following command:
    dmesg | grep -Fq "EFI v"
  6. If the preceding command does not produce any output, run the following command:
    grub2-mkconfig -o /boot/grub2/grub.cfg
  7. Otherwise, if there is an output, run:
    grub2-mkconfig -o /boot/efi/EFI/centos/grub.cfg
  8. If grub2-mkconfig is successful, it will print Done. Now reboot your system using the following command:
    reboot
  9. During the rebooting process, you will notice that the GRUB2 boot menu will not appear anymore and the system will boot up faster.

How does it work?

Having completion of this process, we now know how to customize the GRUB2 boot loader. In this easy process, we only showed you very basic modifications to the boot loader but it can do much more! It supports a broad variety of filesystems and can boot almost any compatible operating system. This is also particularly useful if you plan to run multiple operating systems on the same machine. 

 

Working with policies

At the core of every SELinux system are the policies. These are the exact rules that define the access rights and relationships between all our objects. As we have learned earlier, all our system’s objects have labels, and one of them is a type identifier that can then be used to enforce rules laid down by policies. In every SELinux enabled the system, by default, all access to any object is prohibited unless a policy rule has been defined otherwise. Here, in this process, we will show you how we can query and customize SELinux policies. As you may notice, some of the commands have already been applied in other processes, such as for the httpd or ftpd daemons. Here, you will find out how policies work.

To Start With: What Do You Need?

To complete this process, you will require a working installation of the CentOS 7 operating system with root privileges. It is assumed that you are working through this segment process by process, so by now you should have installed the SELinux tools from the previous process and generated all SELinux man pages for the policies. For our tests here, we will use the Apache web server, so please make sure it is installed and running on your system (Refer to the process Installing Apache and serving web pages in, Providing Web Services).

The Process

  1. To begin, log in as root and type the following command to show all SELinux Boolean policy settings, filtered by the httpd daemon only:
    semanage boolean -l | grep httpd
  2. To get more information about a specific policy and its contained Booleans, read the corresponding man page; for example, for httpd type the following:
    man httpd_selinux
  3. Here, within the manual pages for the httpd policy, we will, among others, find detailed information about every httpd policy Boolean available. For example, there is a section about httpd_use_nfso. To toggle single policy features, use the setsebool command together with the policy Boolean name with the on or off parameter, as shown here:
    setsebool httpd_use_nfs on setsebool httpd_use_nfs off

How Does It Work?

Here in this process, we have shown you how to work with SELinux Booleans. Remember that SELinux follows the model of least privilege, which means that SELinux policies enable only the least amount of features to any object; like a system service, they need to perform their task and nothing more. These features of a policy can be controlled (activated or deactivated) using corresponding SELinux Booleans at runtime without the need to understand the inner workings of policy writing. It is a concept to make policies customizable and extremely flexible. In other processes, we have already worked with enabling SELinux Booleans to add special policy features, such as enabling Apache or FTP home directories, which are all disabled by default.

What did we learn from this experience?

SELinux Booleans are like switches to enable or disable certain functionalities in your SELinux policy. We started this process using the semanage command to show all Booleans available on the system, and we filtered by http to get only those related to this service. As you can see, there are a huge number of Booleans available in your system, and most of them are disabled or off (the model of least privilege); to get more information about a specific policy and its Boolean values, use the SELinux man pages that we installed in a previous process. Sometimes, it can be difficult to find a specific man page of interest. Use the following command to search for man page names that are available: man -k _selinux | grep http. In our example, httpd_selinux is the correct man page to get detailed information about the httpd policy. Finally, if we decide to switch a specific SELinux Boolean feature, we will use the setsebool command. You should remember that setting Booleans in this way only works until reboot. To make those settings permanent, use the -p flag, for example, setsebool -P httpd_use_nfs on.

There's more…

With all our knowledge from the previous processes so far, we are now able to show an example where we put everything together. Here, we will see SELinux security contexts and policies in action for the httpd service. If the Apache web server is running, we can get the SELinux domain name of the httpd process using the following line:
ps auxZ | grep httpd

This will show us that the httpd domain (type) is called httpd_t. To get the SELinux label of our web root directory, type in the following command:
ls -alZ /var/www/html

This will tell us that the security context type of our Apache web server’s web root directory is called httpd_sys_content_t. Now, with this information, we can get the exact rules for the Apache domain from our policy:
sesearch --allow | grep httpd_t

This will print out every httpd policy rule available. If we filter the output for the httpd_sys_content_t context type, the following line comes up for files again:
allow httpd_t httpd_sys_content_t : file { ioctl read getattr lock open }

This shows us which source target context is allowed to access, which destination target context, and with which access rights. In our example for the Apache web server, this specifies that the httpd process that runs as domain httpd_t can access, open, and modify all the files on the filesystem that match the httpd_sys_content_t context type (all files in the /var/www/html directory match this criterion). Now, to validate this rule, create a temporary file and move it to the Apache web root directory: echo "CentOS7 Cookbook" > /tmp/test.txt;mv /tmp/test.txt /var/www/html. Any file inherits the security context of the directory in which it is created. If we had created the file directly in the web root directory, or had copied the file instead of moving it (copying means creating a copy), it would automatically be in the correct httpd_sys_content_t context and fully accessible by Apache. But, as we moved the file from the /tmp directory, it will stay as the user_tmp_t type in the web root directory. If you now try to fetch the URL, for example,, curl http://localhost/test.txt, you should get a 403 forbidden message. This is because the user_tmp_t type is not part of the httpd_t policy rule for file objects, because, as said before, everything that is not defined in a policy rule will be blocked by default. To make the file accessible, we will now change its security context label to the correct type:
semanage fcontext -a -t httpd_sys_content_t /var/www/html/test.txt restorecon -v /var/www/html/test.txt

Now, again fetch curl http://localhost/test.txt, which should be accessible, and print out the correct text: CentOS7 cookbook.

Remember that, if you copy a file, the security context type is inherited from the targeted parent directory. If you want to preserve the original context when copying, use cp

preserve=context instead.