Skip to main content

CentOS

Working with Postfix in CentOS

In a previous process, we learned how to install and configure Postfix as our domain-wide e-mail server. When it comes to working with e-mails, there are lots of different tools and programs available for Linux and we already showed you how to send e-mails through the sendmail program as well as the swaks utility. Here in this process, we will show you how to work with one of the most commonly used mail utilities in Unix and Linux, called mailx, which has some useful features missing in the sendmail package for sending mails or reading your mailbox.

The Process

We will begin this process by installing the mailx package on our server running our domain-wide Postfix service, as it is not available on CentOS 7 by default.

  1. Begin by logging in as root and typing the following command:
    yum install mailx
  2. The easiest way is to use mailx with its standard input mode, as follows:
    echo "this is the mail body." | mail -s "subject" john@centos7.home
  3.  You can also send mails from a text file. This is useful when calling the mailx command from a shell script, using multiple recipients, or attaching some files to the e-mail:
    cat ~/.bashrc | mail -s "Content of roots bashrc file" john
    echo "another mail body" | mail -s "body" john,paul@example.com,chris
    echo "this is the email body" | mailx -s "another testmail but with
    attachment" -a "/path/to/file1" -a "/path/to/another/file"
    john@gmail.com

Connecting mailx to a remote MTA

One big advantage over the sendmail program is that we can use mailx to directly connect to and communicate with remote MTA mail servers. In order to test this feature, log in to another Linux-based computer, which should be in the same network as our Postfix server, install the mailx package, and send a mail through our Postfix server’s IP address 192.168.1.100 (we have already opened the incoming SMTP firewall port in a previous process). In our example, we will send a local mail to the user john:
echo "This is the body" | mail -S smtp=192.168.1.100 -s "This is a remote test" -v john@centos7.home

Reading your local mails from the mailbox

Not only can the mail x program send e-mail messages to any SMTP server, it also provides a convenient mail reader interface for your local mailbox when started locally on the Postfix server. If you run the mail program with -f specifying a user mailbox, the program will start by showing you all the inbox e-mails. But remember that mailx can only read local mailboxes when the program is started on the same server your mailboxes are located at (if you want to use it to access your mailbox remotely you need to install an MTA access agent such as Dovecot—see later—with POP3 or IMAP). For example, login as Linux system user john on the Postfix server, and then, to open the mail reader with your user’s local mailbox, type: mailx -f ~/Maildir.

You will now be presented with a list of all the mail messages in your current inbox. If you want to read a specific mail, you need to type in its number and press the Return key. After reading it, you can type d followed by Return to delete it or r followed by Return to reply to it. To go back to your current mail message overview screen, type z followed by Return. If you have more than one screen of mail messages, type z-(z minus) followed by Return to go back one page. Type x followed by Return to exit the program. To learn more, refer to the mailx manual (man mailx).

How Does It Work?

In this process, we showed you how to install and use mailx, a program to send and read your Internet mail. It is based on an old Unix mail program called Berkely mail and provides the functionality of the POSIX mailx command. It should be installed on every serious CentOS 7 server because it has some advantages over the sendmail program and understands the protocols IMAP, POP3, and SMTP (If you need an even more user-friendly mail reader and sender, you can check out mutt. Type yum install mutt to install it. Then type man mutt to read its manual).

So what did we learn from this experience?

We started this process by installing the mailx package using the YUM package manager on our Postfix server. It includes the mailx command line program which can be run either with the command mail or mailx. Afterwards, we ran the program with the -s parameter, which specifies an e-mail subject and; also you need a recipient e-mail address as argument, either an external address or a local Linux system user name or mail. Without anything else, mailx suspects it’s running on the same server as the mail server is on, so it implicitly sends the mail to the localhost MTA, which is Postfix in our example. Also, in its most simple form, mailx starts in interactive mode, which lets you type in the message body fields manually at the command line. This is good for quickly writing a mail for testing, but in most cases you will use mailx by piping in content from another source. Here we showed you how to do this by using the echo command to write a string to the Standard Input (STDIN) of mailx, but you can also cat a file content into it.

One often used example is to send some kind of file output or a log file content of a failing command to an administrator user or system reports at a certain scheduled time point using cron. Afterwards, we saw that we could also send mails to multiple recipients by comma-separating their e-mail addresses, and showed you how to send attachments along with your mail messages by using the -a option. In the next section, we then showed you how to send mails to a remote SMTP mail server using the -S option to set internal options (variable=value). This is a very useful feature if you haven’t specified your standard mail server on your DNS server or for testing a remote mail server. Finally, in the last section we showed you how you could read your local mailbox on your Postfix server using mailx. It has a convenient browsing functionality to read, delete, and reply, and do advanced e-mail management for your local mailbox. You do this by typing in commands into the mailx interactive sessions followed by pressing the Return key. Remember, if you don’t like this way of browsing your mails, you can also always read or filter your mails in your user’s ~/Maildir directory using command-line tools, such as grep, less, and so on. For example, to search all new mails for the case-intensive keyword PackPub.com, type grep -i packtpub ~/Maildir/new.

 

Installing and configuring the FTP service on CentOS

While there are several modern and very secure network file sharing technologies, the good old File Transfer Protocol (FTP) remains one of the most widely used and popular protocols to share and transfer files between computers. There are a number of different FTP servers available in the Linux world. In this process, you will learn how to install and configure very secure FTP daemon (vsftpd), which is a well-known FTP server solution that supports a wide range of features and enables you to upload and distribute large files across a local network and the Internet. Here, we will show how to install the vsftpd daemon and provide some basic settings with the main goal being to increase the security of the daemon.

Note

After working on this process, you are advised to use SSL/TLS encryption to further strengthen your FTP server. 

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 facilitate the downloading of additional packages. It is expected that your server will be using a static IP address and that it maintains one or more system user accounts.

The Process

vsftpd is not installed by default. For this reason, we must begin this process by installing the relevant packages and associated dependencies:

  1. To do this, log in as root and type the following command:
    yum install vsftpd
  2. After we have created a backup copy of it, open the main configuration file in your favorite text editor as follows:
    cp /etc/vsftpd/vsftpd.conf /etc/vsftpd/vsftpd.conf.BAK vi /etc/vsftpd/vsftpd.conf
  3. To disable anonymous users, scroll down and find the following line: anonymous_enable=YES, and then change this as follows:
    anonymous_enable=NO
  4. Uncomment (remove # at beginning of the line) the following lines to enable the chroot environment for more security:
    chroot_local_user=YES
    chroot_list_enable=YES
  5. Next, scroll down to the bottom of the file and add the following line:
    use_localtime=YES
  6. Finally, add the following line to enable local users to write to their home directories:
    allow_writeable_chroot=YES
  7. Save and close the file. Then create the following empty file:
    touch /etc/vsftpd/chroot_list
  8. Next, configure the firewall to allow incoming FTP connections to the server on port 21:
    firewall-cmd --permanent --add-service=ftp
    firewall-cmd --reload
  9. Now, we allow SELinux to use the FTP home directory feature:
    setsebool -P ftp_home_dir on
  10. Enable vsftpd at boot:
    systemctl enable vsftpd
  11. To complete this process, type the following command to start the FTP service:
    systemctl start vsftpd
  12. Now, we can test the connection from any client computer in the same network that our FTP server is in. This computer needs a FTP client installed (if its a CentOS computer, install one using yum install ftp). Log in to this computer with any account and by typing in the following command that replaces with the IP address of the server running your vsftpd service:
    ftp
  13. On successful connection to the server, the FTP client program will ask you for a username and password. Here, enter a known system user (other than root) from the FTP server. If the login was successful, you will get a 230 login successful message and a ftp> prompt. Now to end our test, type the following FTP command to show all the files in your current ftp directory and check whether you have write-access on the remote server:
    ls
    mkdir test-dir
    rmdir test-dir
  14. Type the following command to end your FTP session:
    exit

How Does It Work?

vsftpd is widely recognized as a fast, lightweight, and reliable FTP server. The purpose of this process was to show you how to build a basic FTP service that is optimized to provide excellent performance for any number of valid system users.

So what did we learn from this experience?

We began the process by installing the necessary YUM package called vsftpd. We then opened the main configuration file located at /etc/vsftpd/vsftpd.conf, after we made a backup copy of it. Next, we disabled anonymous FTP access and thereby secured our FTP service against unknown users. We then restricted users to their home directory by enabling a chroot jail.

Note

The chroot jail represents an essential security feature; once this is done, all the users will be restricted to access the files in their own home directory only.

We then required vsftpd to use local time for our server. Afterwards, we fixed the write permissions for our chrooted FTP users by enabling the allow_writeable_chroot option. Having saved our work, we created a new empty /etc/vsftpd/chroot_list file, which will hold all the user names that can leave their chroot jails. We have to create this file; otherwise, vsftpd will not let us log in to the system. However, you should remember that you must leave it empty all the time because chroot jails are an important protection mechanism for your FTP server.

Next, we added the standard FTP protocol’s port 21 to our firewall configuration to allow incoming connections. Then, we reloaded the firewall to apply these changes. After this, we activated our FTP home directories by setting the appropriate SELinux boolean variable ftp_home_dir to true. This will make the directories valid for SELinux. Please read, Working with SELinux to learn more about SELinux. Next, we enabled vsftpd on boot and started the service within systemd. At this point, vsftpd will now be operational and it can be tested with any regular FTP-based desktop software. Users can log in using a valid system username and password by connecting to the server’s name, domain, or IP address (depending on the server’s configuration).

The purpose of this process was to show you that vsftpd is not a difficult package to install and configure. There is always more to do but, by following this simple introduction, we have quickly enabled our server to run a standard FTP service.

There's more…

Having installed and configured a basic FTP service, you may wonder how to direct users to a specific folder within their home directory. To do this, open the main configuration file in an editor of your choice using /etc/vsftpd/vsftpd.conf.

Scroll down to the bottom of the file and add the following line by replacing the value with something more applicable to your own needs:
local_root=

For example, if this FTP server is mainly for accessing and uploading content for a user’s private web pages hosted on the same server, you may configure Apache to use the user’s home directories in a folder called /home//public_html. For this reason, you may add the following reference at the bottom of your vsftpd configuration file:
local_root=public_html

When finished, save and close the configuration file before restarting the vsftpd service. When testing this new feature make sure that the local_root location exists in the home directory of the user you want to login (for example, ~/public_html).

 

Formatting CentOS and mounting a filesystem

In this process, you will be introduced to the standard CentOS filesystems XFS, Ext4, and Btrfs. Filesystems form one of the most fundamental parts of any operating system and nearly everything depends on them. Here, you will learn how to create different types of standard filesystems available in CentOS 7, and how to link them to your system so that we can access them afterward for reading and writing. These two techniques are called formatting and mounting filesystems; while you do not do this very often, it remains one of the most fundamental Linux system administrator tasks.

To Start With: What Do You Need?

To complete this process, you will require a minimal installation of the CentOS 7 operating system with root access. We will also use virtual block devices instead of real disk devices because it’s better to demonstrate the usage of creating filesystems and formatting disks using “dummy” devices, instead of erasing your real hard disk contents. Therefore, you should have applied the Creating a virtual block device process and created a 1 Gigabyte virtual block device, which will be named /dev/loop0 in this example.

If you want to apply this process for real disk devices, all you have to do is replace /dev/loop0 with your correct partition—for logical volumes (lv) for example, /dev/mapper/myServer/data, for a SATA device /dev/sdX, or for an IDE-based hard disk name /dev/hdX (where X is a character a-z).

The Process

In our example, this block device is labeled at /dev/loop0. Please note that, if you have created more than one block device, your number could be different, so please change the name accordingly:

  1. First, let’s log in as root and show information about all currently available block devices:
    lsblk -io NAME,TYPE,SIZE,MOUNTPOINT,FSTYPE,MODEL
  2. Now, recheck that we have a valid partition table installed on the device:
    parted /dev/loop0 print
  3. The preceding line should print out the following content: Partition Table: gpt. If this is not the case, let’s create a new partition table (confirm the deletion of any data):
    parted /dev/loop0 mklabel gpt
  4. Now, we will create a new partition spanning the complete disk space with an ext4 filesystem label (no filesystem will be installed yet; it’s just a label):
    parted -a optimal /dev/loop0 mkpart primary ext4 2048KiB 100%
  5. Print the partition table again to show the new partition we just created:
    parted /dev/loop0 print
  6. Now, let’s remove the partition:
    parted /dev/loop0 rm 1
  7. We can also create a btrfs-labeled partition:
    parted -a optimal /dev/loop0 unit MB mkpart primary btrfs 2048KiB 100%
  8. Afterward, let’s create an XFS-labeled partition spanning the whole disk:
    parted /dev/loop0 rm 1
    parted -a optimal /dev/loop0 mkpart primary xfs 2048KiB 100%
  9. Now, show the block table again to see what we have changed:
    lsblk -io NAME,TYPE,SIZE,MOUNTPOINT,FSTYPE,MODEL
  10. As we have only defined the partition type label, we still don’t have a valid filesystem on our partition; so, in the next step, we format our disk using the correct type. We use XFS in our example. Please change mkfs -t if you use ext4 or btrfs instead:
    mkfs -t xfs /dev/loop0p1
  11. Next, let’s mount our virtual block device partition on the system, into the directory /media/vbd-1, and please change -t if you use ext4 or btrfs instead:
    mkdir /media/vbd-1
    mount -t xfs /dev/loop0p1 /media/vbd-1
  12. Finally, test if we can read and write to the new filesystem:
    echo "this is a test" > /media/vbd-1/testfile.txt
    cat /media/vbd-1/testfile.txt

How Does It Work?

Here, in this process, we showed the user how to create CentOS 7 standard partitions spanning the whole disk, and then we created some filesystems on them, which is called formatting, using different filesystem types. The standard filesystem available in CentOS 7 is XFS, but as we have learned in this process, there are lots of other ones available as well, including the popular ext4 and btrfs. XFS is a very robust and high-performing file system for large storage configurations; it is considered very mature and stable. Before CentOS 7, the standard file system was ext4, but it had some limitations and not the best performance when working with millions of files and is considered barely suitable for today’s very large filesystems. btrfs is a relatively new filesystem and is included in CentOS 7, but at the time of writing it is still under development and should not be used for production systems. It is considered to be fully supported in later CentOS 7 minor releases and is likely to replace XFS as the standard CentOS filesystem type in the future, as it has a list of very promising features and enhancements, such as copy-on-write, which copies files each time you write to them, and which makes it possible to go back to former file versions.

So, what have we learned from this experience?

We started this process by using the lsblk command to print a list of all available block devices currently attached to the system. We used this command to check if our target block device that we want to use for installing partitions and filesystems on is available. In our example we will use the /dev/loop0 device, please change this name if it’s different on your system (as said before, you could also use a “real” disk block device, such as /dev/sda, but always be careful!). After confirming that we have our device ready, we used the parted command to check the partition table of the disk. A partition table is mandatory for any hard disk to keep track of the partition information on it. As you have seen, our primary tool for creating partition tables and partitions is parted, as it is the officially recommended CentOS 7 tool for these tasks, but there are other programs that do the same as well, such as fdisk or gdisk. If there is no partition table available, we must create one of type gpt using parted’s mklabel gpt parameter.

Next, after we created the partition table, we put some partitions on it. Therefore, we issued parted’s mkpart command with the -a optimal primary ext4 2048KiB 100% options.

Note
Be careful with the parted command all the time and recheck everything before executing, as most of its commands will completely destroy all the data currently stored on the disk.

This will create a new partition starting at 2,048 kilobytes (kb) until the end of the disk. We did not start at the very beginning of the disk (0%) as 2,048 kb is the start of the first sector on the disk to leave some space left to store some additional data. -a optimal aligns the partition to a multiple of the physical block size that will guarantee optimal performance. Next, we removed the partition again using the rm option and number 1, which refers to the first partition we just created. We recreated new partitions of type btrfs and finally xfs. After the disk is partitioned, we need an actual filesystem on it, as parted only labels the partition to a specific type, but does not do the actual formatting. To make the filesystem, we use the mkfs utility. You can either run it with the -t flag, as we did, or use a dot notation, such as mkfs.xfs, to specify the type you want to format it to. The mkfs command gives us a detailed output of what it has done, such as how many blocks have been written and so on.

Finally, after we have created the filesystem on our disk partition, we can use the mount command to make it available and work with it in our current system. mount either attaches or detaches a device’s filesystem to our system’s root filesystem. Therefore, we need to first create a directory to define where we want to attach it to. We use the directory, /media/vbd-1, as a parameter for the actual mount command with the syntax, mount -t

. For almost all standard filesystems, you can skip the -t parameter as it will automatically detect the right type. To detach a filesystem from your system, you can use the umount command with the argument of the device you want to remove (you can also use the folder it’s mounted to; both do work!). In our example, to unmount our loop device’s first partition, type umount /dev/loop0p1.

After mounting our formatted partition device, we can access it like any other component beneath the root folder.

There's more…

In this process, we always use one partition spanning the complete available disk space. Often, you have more than one partition on a disk, so let’s create this kind of layout instead. In this example, we create three 100 MB partitions on /dev/loop0:

  1. First, let’s delete our partition once again using the rm parameter so that we can add new ones:
    parted /dev/loop0 rm 1
  2. Now, let’s create three equal partitions:
    parted -a optimal /dev/loop0 unit MiB mkpart primary ext4 2048KiB 100
    parted -a optimal /dev/loop0 unit MiB mkpart primary ext4 100 200
    parted -a optimal /dev/loop0 unit MiB mkpart primary ext4 300 400
  3. Let’s review our layout:
    parted /dev/loop0 print

Note
Using the gpt partition table, we can create up to 128 primary partitions on any disk; when using the older msdos partition type, there is a maximum of four primary partitions. If you need more, you have to create extended partitions out of primary ones.

 

Configuring journald in CentOS to make it persistent

Journald’s advantages over other logging systems such as rsyslog is that it is very efficient and logs just about everything on your system automatically without the need to configure anything because it is a part of the systemd suite. The main disadvantage is that all journald log information will get lost after a system’s restart. Journald logging can produce huge amounts of data and by default, all logging information is only kept in memory, which is not very practicable if you need to access older log information or analyze causes of system crash reboots. Here, in this process, we show you how to configure journald to make it persistent.

To Start With: What Do You Need?

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 Process

To begin this process, we need to create a location that will hold our persistent journal database:

  1. Log in as the root user and create the following directory:
    mkdir /var/log/journal
  2. Next, add the new directory to journald to use it as a storage location and fix permissions:
    systemd-tmpfiles --create --prefix /var/log/journal
  3. Now, restart journald:
    systemctl restart systemd-journald
  4. Finally, to check whether the log survived the reboot, restart the computer and type the following:
    journalctl --boot=-1

How it works…

We initiated this process by creating the new directory, /var/log/journal. By default, journald writes its log database to /run/log/journal, which is a directory only for runtime information, and its content does not survive system reboots. Afterward, we used the systemd-tmpfiles command to set up our new directory for journald. Finally, we restarted the journald server daemon to apply our changes to the system. To test if persistence is working, restart your server and afterward use journalctl –boot=-1. This will show us all journal information from the last boot. If persistence is not working, it will print out the following error; otherwise, it will correctly show all journal messages before the last boot:
Failed to look up boot -1: Cannot assign requested address

In this fairly simple process, we have shown how to make journald persistent over system reboots. This is really useful if you need to review older log files from the past, which can sometimes help you find out problems, for example, the roots of past hardware failures.

 

Installing CentOS 7 using a kickstart file

While installing CentOS 7 manually using the graphical installer utility is fine on a single server, doing so on multiple numbers of systems can be tedious. Kickstart files can automate the installation process of a server system and here we will show how this can be done. They are simple text-based configuration files which provide detailed and exact instructions on how the target system should be set up and installed (for example, which keyboard layout or additional software packages to install).

To Start With: What Do You Need?

To successfully complete this process, you will need access to an already installed CentOS 7 system to retrieve the kickstart configuration file we want to work with and use for automated installation. On this pre-installed CentOS server, you also need a working Internet connection to download additional software.

Next, we will need to download and create installation media for the DVD or the Everything image (download the latest CentOS-7-x86_64-DVD-XXXX.iso or CentOS-7x86_64-Everything-XXXX.iso file), instead of the minimal iso file shown in another process. Then you need another USB device which must be read and writable on Linux systems (formatted as FAT16, FAT32, EXT2, EXT3, EXT4, or XFS filesystem).

The Process:

In order to implement this process, we first need physical access to an existing kickstart file from another finished CentOS 7 installation, which we will use as a template for a new CentOS 7 installation.

  1. Log in as root on the existing CentOS 7 system and make sure the kickstart configuration file exists by typing the following command and pressing the Return key to execute (this will show you the details of the file):
    ls -l /root/anaconda-ks.cfg
  2. Next, physically plug in a USB device and then type the following command, which will give you a list of all the hard disk devices currently connected to the computer
    fdisk -l
  3. Try to identify the device name by comparing its size, partitions, and identified filesystems with the specifications of your USB device. The device name will be of kind /dev/sdX, where X is an alphabetical character, such as b, c, d, e, … and so on. If you cannot find the right device name for your USB media using the fdisk command, try the following trick: run fdisk -l twice -first with plugged-out and then with plugged-in USB device and compare how the second output changed -it has one device name more than the first output: your device name of interest !
  4. If you have found the right device name in the list, create a directory to mount it to the current filesystem:
    mkdir /mnt/kickstart-usb
  5. Next, actually mount the stick to this folder, assuming that your USB partition of choice is at /dev/sdc1 (change this as required):
    mount /dev/sdc1 /mnt/kickstart-usb
  6. Now we will create our working copy of the kickstart file on the USB device for customizing:
    cp /root/anaconda-ks.cfg /mnt/kickstart-usb
  7. Next, open the copied kickstart file on the USB device with your favorite text editor (here we will use the editor nano, if you have not installed it yet type yum install nano):
    nano /mnt/kickstart-usb/anaconda-ks.cfg
  8. We will now modify the file for installing CentOS on a new target system. In nano, use the up and down arrow keys to go to the line which starts with ( will be the name of the hostname you gave during installation e.g. minimal.home):
    network --hostname=
  9. Now edit the string to give it a new unique hostname. For example, add a -2 to the end of any existing name, as shown next:
    network --hostname=minimal-2.home
  10. Next, move the cursor down using the up and down arrow keys until it stops at the line which says %packages. Append the following lines right below it (you can further customize this and provide additional packages that you want to install automatically):
    mariadb-server
    httpd
    rsync
    net-tools
  11. Now save and close the file, to do this in the nano editor use the key combination Ctrl+o (which means, hold down the Ctrl key on the keyboard and then the o key without releasing the Ctrl key) to write the changes. Then press Return to confirm the filename and Ctrl+x to exit the editor.
  12. Next, install the following CentOS package:
    yum install system-config-kickstart
  13. Now we validate the syntax of our kickstart file using the ksvalidator program, which is included in the package we just installed:
    ksvalidator /mnt/kickstart-usb/anaconda-ks.cfg
  14. Unmount the USB stick now by using the following command:
    cd umount /mnt/kickstart-usb
  15. When you get a new command prompt again, unplug the USB device with the kickstart file for using on the target machine physically from the system.
  16. Now you need physical access to the target machine you want to install CentOS on, using the kickstart file just created. Disconnect any other external file storage(s) that you do not need during the installation.
  17. Power on the computer and put in your prepared CentOS installation media (must be a CentOS DVD or Everything installation disk image prepared on a CD/DVD disc or a USB device installer). Also, connect to the computer the USB stick containing the kickstart file you just created in the earlier steps (if you using a USB drive for installing CentOS then you will need two free USB ports in total to complete this recipe).
  18. Next, start the server and press the correct key during the initial bootup screen, associated with booting the CentOS installation media you just connected.
  19. After the CentOS installer starts loading, the common standard CentOS 7 installation welcome screen will show up and the option Test this media & install CentOS 7 will be pre-selected by the cursor.
  20. Next, press the Esc key on your keyboard once to switch to the boot: prompt
  21. Now we are ready to start the kickstart installation. To do this, you need to know the exact partition name on the USB device where the kickstart file is located. Type the following command, assuming that your partition is at /dev/sdc1 (change this as required), and press the Return key to start the kickstart installation process:
    linux ks=hd:sdc1:/anaconda-ks.cfg
  22. The new system now gets installed automatically using the instructions from the provided kickstart file. You can watch the installation output messages as it is showing the user detailed installation progress.
  23. If the system has finished installing, reboot the system and log in to your new machine to verify that the new system has been set up the way we described using the kickstart file.

How it works...

In this process, you have seen that every server running a CentOS 7 installation keeps the kickstart file in its root directory, which contains detailed information on how the system had been set up during the installation. The kickstart files can be used to automate the installations of multiple systems with the same configuration. This can save a lot of time doing repetitive work as no user interaction during installation is needed. Also, we can use this method if the target machines don’t meet the minimum requirement in RAM for graphically based installations but when needed other features the text mode installer does not provide such as custom partitioning of the system. Kickstart configuration files are simply plain text files which can be created manually from scratch. Because there are quite a number of different commands available to construct your system using the kickstart syntax, we used an existing file as a template and customized it to fit our needs, instead of starting out completely new. We did not use the minimal installation image to drive our kickstart installation because we installed some extra packages not included on the minimal ISO file, such as the Apache web server.

 

Working with SELinux security contexts

As we have learned from the previous process, SELinux is all about labels and policies. In this process, we will show you how to work with these labels, also known as security contexts.

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 chapter process by process, so by now you should have installed the SELinux tools from the previous process and generated all the SELinux man pages for the policies. As you may notice, some of the commands that we will show you in this process have already been applied in other processes. We will explain them here in detail. For using the netstat program, install the package, net-tools, with the YUM package manager.

The Process

As we have learned in a previous process, almost every component in a SELinux system is an object (files, directories, processes, users, and so on). We will begin this process by showing you how to print out the SELinux labels for all kinds of objects using the -Z command-line flag, which a lot of basic Linux commands on a SELinux system support.

  1. To begin with, log in as root and type the following commands to explore SELinux security context information from various kinds of objects:
    id -Z ls -Z ps -auxZ netstat -tulpenZ
  2. Next, to list all available security context names for the files and directories on your system, use the following command (which we filtered for httpd labels only):
    semanage fcontext -l | grep httpd
  3. Next, let’s create a new empty file that we can work with:
    touch /tmp/selinux-context-test.txt
  4. Show the current security context of the new file (should contain the type user_tmp_t):
    ls -Z /tmp/selinux-context-test.txt
  5. Finally, change the user_tmp_t type to a random samba_share_t label name:
    semanage fcontext -a -t samba_share_t /tmp/selinux-context-test.txt restorecon -v /tmp/selinux-context-test.txt
  6. Perform a test to validate your changes:
    ls -Z /tmp/selinux-context-test.txt

How Does It Work?

Here in this process, we have shown you how to display labels (security contexts) of various SELinux object types, how to show all available label names, and how to modify or set them on the example of the file object. Working on a SELinux enhanced system on a daily basis, most administrators would confirm that the most important objects we have to manage security contexts for are files, directories, and processes. Also, you need to remember that every SELinux object can have only one security context.

So, what did we learn from this experience?

As we have have seen, we can use the -Z parameter on a lot of different standard Linux command-line tools to print out their SELinux security context. Here, we have shown you examples to display labels for users, files and directories, processes, and network connections, which we could query with the id, ls, ps, and netstat commands. In the output of these commands, we see that every security context label of every such object consists of three values: user (flagged by _u), role (_r), and type (_t). The type field is used as the main mechanism to do all our access control decisions in the standard SELinux type (which is called targeted), so we often call the whole SELinux access control process type enforcement (TE).

The other values user and role in an object’s label are only necessary for very advanced SELinux configurations not discussed here. In order to show all the available context types for use on our system, use the command-line seinfo -t. These SELinux types are a very important concept that we need to understand. For file and directory objects, they are used to bundle together groups of objects related to each other, and that should be protected or treated the same so that we can define specific policy rules on them. For example, we can assign each file in the standard mail spool directory, /var/spool/mail, of the type mail_spool_t, and then create an access rule policy in which we will use this type to allow specific access. In the context of processes, type values are called domains. Here, types are used as a way to isolate and sandbox processes: any process that has a specified domain name can only communicate and interact with other processes in the same domain (with some exceptions, such as transitions not discussed here). This isolating of processes via domains greatly reduces security risks. When processes get compromised, they can only damage themselves and nothing else.

Note
SELinux is sometimes called a sandboxing system. Starting from the assumption that software will always have bugs, SELinux provides ways to isolate components of the software such that a breach in one component doesn’t compromise another.

If you type in ps -auxZ, you will also see that there are processes that run in a domain called unconfined_t. Processes running with this label are not protected by SELinux policies, which means that, if an unconfined process is compromised, SELinux does not prevent an attacker from gaining access to other system resources and data. Here, security falls back to standard DAC rules, which will be your only and exclusive protection instead.

After we discussed how to display security contexts, next in the process we showed you how you can set and change them. In some older documentation as well as in some SELinux policy man pages, you will encounter examples with a tool called chcon, which is used to modify the security context of your objects. The usage of this tool is not the recommended approach any more, and you should always replace such command line examples with the newer semanage fcontext -a -t command-line in combination with the restorecon program. For semanage, you provide the label type name with -t, and then provide the filename you want to set it for. Then, with restorecon, you provide the filename to which you want to apply the change made by semanage earlier. This is needed because security context can be set on two levels. It can be set to the policy and on a filesystem level. The chcon command sets the new context directly on the filesystem, while the policy context does not get altered. This can be a problem, for example, if you want to reset or change the security context of your filesystem later (this is called relabeling)—which means that all the security context will be applied from the policy to the filesystem, overwriting all your changes made with chcon. So it is better to use semanage, which will write to the policy, and then use restorecon, which will synchronize the policy labels to the filesystem, keeping everything up-to-date. If you want to set labels for directories instead of single files, you can use regular expressions; to see some examples and further command-line options; type man semanage-fcontext and browse to the EXAMPLES section.

 

Configuring a domain-wide mail service with Postfix in CentOS

Postfix is a Mail Transport Agent (MTA) responsible for the transfer of e-mails between mail servers using the SMTP protocol. Postfix is now the default MTA on CentOS 7. Here, as with most other critical network services, its default configuration allows outgoing but does not accept incoming network connections from any host other than the local one. This makes sense if all you need is a local Linux user mailing system and for sending out mails to other external mail servers from localhost too. But if you want to run your own centralized mail server for your own private network and domain, this is quite restrictive. So the purpose of this process is to set up Postfix as a domain-wide mail service to allow e-mails sent from any host in your network and if the recipient is a valid e-mail address within your local domain, deliver them to the correct mailbox on the mail server.

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 to download additional software packages. You need to set up your local network properly and make sure that all the computers that want to send mails through your single-domain mailserver are in the same network and can ping this server. Also, setting your system time correctly is very important for any mail server. Apply the Synchronizing the system clock with NTP and the chrony suite process, Configuring the System before beginning your configuration. Finally, you need to set a Fully Qualified Domain Name (FQDN) for your mail server. Refer to the Setting your hostname and resolving the network process, Configuring the System. It is expected that your server will be using a static IP address and that it maintains one or more system user accounts. It is also assumed that you are working through all the process by process in the order in which they appear.

The Process

Postfix is already installed by default on all CentOS 7 flavors and it should be in a running state. In our example, we want to build a central mail server for our network 192.168.1.0/24 with the local domain name called centos7.home.

  1. First login as root and test if Postfix is already working locally and can send local mails to your system users. Type the following command to send a mail to a Linux user specified by :
    echo "This is a testmail" | sendmail
  2. On CentOS 7, Postfix is also already configured to send out mails to external e-mail addresses (but from localhost only) without any changes to the configuration file. For example, you could use right out-of-the-box:
    echo "This is a testmail" | sendmail contact@example.com

    Note
    If you don’t have a trusted domain and certificate behind your Postfix server, in times of massive spam e-mails most external e-mail servers will reject or put such e-mails directly into the spam folders.

  3. To see if the local mail message has been delivered successfully, show the latest mail log (Press Ctrl+C to exit the log):
    tail -f /var/log/maillog
  4. Next, check if a FQDN for our server is available. This is mandatory, and if not set properly, refer to the process, Configuring the System to set one (in our example, this will output the name mailserver.centos7.home):
    hostname --fqdn
  5. Now create a backup copy of the main Postfix configuration file before opening this file:
    cp /etc/postfix/main.cf /etc/postfix/main.cf.BAK && vi /etc/ postfix/main.cf
  6. First of all, we will want Postfix to listen on all network interfaces instead of only the local one. Activate or uncomment the following line (which means remove the # sign at the beginning of the line) that starts with inet_interfaces to read:
    inet_interfaces = all
  7. Now, some lines below, you will find the line that reads inet_interfaces = localhost. Deactivate it or comment it out by putting a # sign at the start of the line:
    # inet_interfaces = localhost
  8. Next, we need to set the local domain-name of the mail server. For example, if our mailserver’s FQDN is mailserver.centos7.home and this mailserver is responsible for delivering mail for the whole private centos7.home domain, the domain name will be (it’s best to put it below the line that reads #mydomain = domain.tld):
    mydomain = centos7.home
  9. With the intention that this server may become a domain-wide mail server, you should now update the following line that starts with mydestination to read as follows (for example, in the mydestination section, comment out the first mydestination line and uncomment the second line):
    mydestination = $myhostname, localhost.$mydomain, localhost, $mydomain
  10. Next, we need to specify the pathname of a mailbox file relative to a user’s home directory. To do this, scroll down and locate the line that begins with home_mailbox and uncomment the following option (remove the # sign at the line’s beginning):
    home_mailbox = Maildir/
  11. Save and close the file. Now we want to open the correct Postfix server ports in the firewall to allow the incoming SMTP connections to the server:
    firewall-cmd --permanent --add-service=smtp && firewall-cmd --reload
  12. Next, restart the Postfix service as follows:
    systemctl restart postfix
  13. Afterwards, login to a different computer in the same network and install Swiss Army Knife SMTP (swaks) to test out our Postfix server connection remotely. On CentOS, type the following (it needs the EPEL repository to be installed in advance):
    yum install swaks
  14. Now, to test if you can connect to our new Postfix server using the standard SMTP mail port 25, with our Postfix server running on the IP address 192.168.1.100, we are sending a mail remotely to a Linux system user john which has a system user account on our Postfix server:
    swaks --server 192.168.1.100 --to john@centos7.home
  15. Swaks creates output which should give us a hint if the mail transport has been successful. For example (the output has been truncated):
    -> This is a test mailing
    -250 2.0.0 Ok: queued as D18EE52B38
      -> QUIT
    - 221 2.0.0 Bye
  16. You can also test that the last command has been successful by logging in as user john on the Postfix server, then checking and reading your local mailbox’s inbox, which should contain a file with the test mail sent from the swaks tool (the filename will be different on your computer), as follows:
    ls ~/Maildir/new less ~/Maildir/new/14941584.Vfd02I1M246414.mailserver.centos7.home

How Does It Work?

As we have seen, Postfix is installed and running on every CentOS 7 system by default and in its basic configuration the mail server is listening on the localhost address for incoming mails so you can already send out local mails between your server’s local Linux system users without the need to contact an external MTA. It is already running because your system is already using it for a number of local services, such as the crond daemon or for sending out warnings about security breaches (for example, running a sudo command as a non-sudo user).

Before we can explain how this process works, we need to review some more basics about the Postfix MTA system in general. The Postfix MTA service can receive incoming e-mails from mail clients or other remote MTA servers using the SMTP protocol. If an incoming e-mail is destinated for the MTA server’s configured final destination domain (for example, a mail sent with the recipient address john@centos7.home is incoming to the centos7.home configured Postfix MTA server), it will deliver the mail to a local mailbox installed on the server (either in the filesystem or in a database system such as MariaDB). If the incoming mail is not destinated for this server, it will be relayed (forwarded) to another MTA.

Remember that this is all a Postfix server is capable of doing and nothing more: receiving incoming SMTP connections from mail clients or other MTAs, delivering mail to local mailboxes on the server, and forwarding mail to other MTAs using SMTP. Contrary to common belief, Postfix cannot transfer the mails from its local mailboxes to the end users. Here we need another type of MTA called delivery agent, which uses different mail protocols, such as IMAP or POP3.

In this process, we configured our Postfix server so that the other computers and servers in the same network could also send mails to our Postfix server, which is blocked by default (by default only the server itself can send mails). If an incoming e-mail, sent from another computer in our network, has the same domain name in the recipient’s e-mail address as our Postfix server has its FQDN in, then it gets delivered to the appropriate local mailbox defined by the recipient’s part of the e-mail; all external e-mail addresses get relayed to an external MTA.

So what did we learn from this experience?

We began our journey by testing if we could send out local mails to system users. Here we logged in as our root user and sent a mail to a valid local system user using the sendmail program, which is included in the Postfix package. For every mail you send using sendmail, you should be able to see some new lines appearing in the /var/log/maillog file, which contains status information and other important logging text for the mail. If you sent a message from root to the user john and the FQDN of your server is centos7.home, new output lines appended to the log file should contain amongst other things a from=root@centos7.home>,a to=john@centos7.home> and if delivered successfully a status=sent information. If no such logging information shows up, check the status of the Postfix service.

Afterwards, we displayed the FQDN for our server. It is very important to set this up correctly because this information will be used to authenticate the Postfix server when connecting to other MTAs or mail clients. MTAs check the FQDN which has been announced by their partner and some even refuse to connect if it is not provided or if it differs from the real DNS domain name of the server. After our initial test, we then started editing the main Postfix configuration file after we made a backup copy of it first. As said before, by default only the users sitting on the same server the Postfix service is running on can send mails between them as the server defaults to listening on the loopback device only. So first we enabled Postfix to listen to all the available network interfaces instead, using the inet_interfaces = all parameter. This ensured that all our clients in our network could connect to this server. Next, we set the domain name using the mydomain parameter we wanted to have for Postfix. In order for Postfix to work in our network, the domain name defined here in this variable must be the exact same value as the domain name for our server’s network. Afterwards, we changed the mydestination parameter by choosing the line which adds the $mydomain parameter to the list of allowed domains. This will define all domains our Postfix mail server considers as the final destination. If a Postfix mail server is configured as the final destination for a domain, it will deliver the messages to the local mailboxes of the recipient users, which can be found in /var/spool/mail/ (we will change this location in the next step) instead of forwarding the mails to the other MTAs (as we added $mydomain to the list of final destinations in our example, we will deliver all mails sent to the centos7.home domain).

Here, you also need to remember that, by default, Postfix trusts all the other computers (SMTP clients) in the same IP subnetwork as the Postfix server is in to send mails to external e-mail addresses (relay mails to external MTAs) through our centralized server, which could be too relaxed for your network policy. Since e-mail spam is an ongoing problem on the Internet and we don’t want to allow any user to abuse our mail server from sending spam (which an open relay mail server does; it this takes anything from any client and sends it to any mail server), we can further increase security by setting mynetworks_style = host, which only trusts and allows the localhost to send mails to external MTAs. Another way to reduce the spam risk might be to use the mynetworks parameter where you can specify which network or IP address is allowed to connect to our mail server and send e-mails through it; for example, mynetworks = 127.0.0.0/8, 192.168.1.0/24. To learn more about all the available Postfix settings, refer to the Postfix configuration parameter manual using the command man 5 postconf. Afterwards, we changed where the local mail should be stored. By default, all the incoming mails go to a centralized mailbox space located at /var/spool/mail/. In order for local users to receive their mail in their own home directory, we used the Maildir parameter for the home_mailbox option, which changes this system to deliver all the mails to /home//Maildir/ instead. Afterwards, we opened the standard SMTP protocol port in firewalld using the SMPT service, which Postfix uses for communication with the other MTAs or mail clients sending incoming mails through.

Postfix is already configured to start at boot, but to complete this part of the process we restarted the Postfix service for it to accept the new configuration settings. At this stage, the process of configuring Postfix was complete, but to test remote access we needed to log into another computer in the same network. Here we installed a small command line-based mail client called swaks, which can be used to test local or remote SMTP server connections. We ran our test by sending a mail to our remote Postfix mail server and supplied a recipient user and the IP address of our SMTP server. Having done this, you should have received a test message and as a result, you should be happy to know that everything is working correctly. However, if you did happen to encounter any errors, you should refer to the mail server log file located at /var/log/maillog.

There's more…

In this section of the process, we will change your e-mail sender address, encrypt SMTP connections, and configure your BIND DNS server to include our new mailserver’s information.

Changing an e-mail’s appearing domain name

If an MTA sends out an e-mail, Postfix automatically appends the hostname of the sender’s e-mail address by default, if not provided explicitly otherwise, which is a great feature to track down which computer in your network sent the e-mail locally (otherwise it would be hard to find the origin of a mail if you got multiple computers sending out mails by a user called root). Often when sending messages to a remote MTA, you don’t want to have your local hostname appear in the e-mail.

Here it is better to have only the domain name alone. In order to change this, go to the Postfix MTA you want to send mails from, open the Postfix configuration file /etc/postfix/main.cf, and enable this feature by uncommenting (removing the # sign at the beginning of the line) the following line to determine the origin (restart the Postfix service afterwards):
myorigin = $mydomain

Using TLS-(SSL) encryption for SMTP communication

Even if you are running your own Postfix server in a small or private environment, you should always be aware that normal SMTP traffic will be sent in clear text over the Internet, making it possible that anyone could sniff the communication. TLS will allow us to set up an encrypted SMTP connection between the server and the mail client, meaning that the complete communication will be made enciphered and impossible to be read by a third-party. In order to do this, if you have not already bought an official SSL certificate or generated some self-signed certificates for your domain, start by creating one here (read the Generating self-signed certificates process, Providing Security to learn more). First login as root on your server and go to the standard certificate location: /etc/pki/tls/certs. Next, create a TLS/SSL keypair consisting of the certificate and its embedded public key as well as the private key (enter your Postfix’s FQDN as the Common name, for example, mailserver.centos7.home) to do this type make postfixserver.pem. Afterwards, open the main Postfix configuration file /etc/postfix/main.cf with your favorite text editor and put in the following lines at the end of the file:
smtpd_tls_cert_file = /etc/pki/tls/certs/postfix-server.pem
smtpd_tls_key_file = $smtpd_tls_cert_file
smtpd_tls_security_level = may
smtp_tls_security_level = may
smtp_tls_loglevel = 1
smtpd_tls_loglevel = 1

Then save and close this file. Note that setting smtpd_tls_security_level to may will activate TLS encryption if available in the mail client program, otherwise it will use an unencrypted connection. You should only set this value to encrypt (which will enforce SSL/TLS encryption in any case) if you are absolutely sure that all your senders to your mail server are supporting this feature. If any sender (external MTA or mail client) does not support this feature, the connection will be refused. This means that e-mails from such sources will not be delivered into your local mailboxes. We also specified TLS encryption for outgoing SMTP connections from our Postfix server to other MTAs where possible using smtp_tls_security_level = may. By setting both the Postfix’s client and server mode TLS log level to 1 we get more verbose output so we can check if the TLS connections are working. Some very old mail clients use an ancient port 465 for encrypting SMTP over SSL/TLS instead of the standard SMTP port 25.

In order to activate this feature, open /etc/postfix/master.cf and search, then uncomment (remove # at the start of each line) the following lines, so they read:
smtps      inet   n              -               n            -            -          smtpd
-o syslog_name=postfix/smtps
-o smtpd_tls_wrappermode=yes

Save and close the file, and then restart Postfix. Next, we need to open the SMTPS port in the firewall to allow incoming connections to our server. Since no SMTPS firewalld rule is available in CentOS 7, we will create our own service file first using the sed utility:
sed 's/25/465/g' /usr/lib/firewalld/services/smtp.xml | sed 's/Mail
(SMTP)/Mail (SMTP) over SSL/g' > /etc/firewalld/services/smtps.xml
firewall-cmd --reload
firewall-cmd --permanent --add-service=smtps; firewall-cmd --reload

You should now be able to test if an SMTPS connection can be made by using our swaks SMTP command line tool with the -tls parameter from a remote computer to our Postfix server running on IP 192.168.1.100, for example swaks --server 192.168.1.100 --to john@centos7.home -tls. This command line will test if the SMTP server supports TLS encryption (STARTTLS) and exit with an error message if it is not available for any reason. A working output would look as follows (truncated to only show you the most important lines):
    -> STARTTLS
-220 2.0.0 Ready to start TLS
=== TLS started with cipher TLSv1.2:ECDHE-RSA-AES128-GCM-SHA256:128
   ~> This is a test mailing
~ 250 2.0.0 Ok: queued as E36F652B38

You can then also recheck your TLS setup by going to the main mail log file on your Postfix server and watching for the following line corresponding to your swaks test mail from the last step (your output will be different):
Anonymous TLS connection established from unknown[192.168.1.22]: TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)

Configure BIND to use your new mailserver

After our domain-wide Postfix server has been installed and configured, we should now announce this new mail service in our domain using a DNS server. refer to the process, Working with FTP for details on how to set up and configure a BIND server, and especially read the section about the Mail eXchanger (MX) record if you haven’t already. Then add a new MX entry to your BIND forward and corresponding reverse zone file. In your forward zone file, add the following lines for our Postfix server with the IP 192.168.1.100:
IN                MX            10 mailhost.centos7.home.
mailhost                          IN          A            192.168.1.100
In your reverse zone file, you could add the following lines instead:
100                IN         PTR                   mailhost.centos7.local.

 

Securely sharing resources with Samba in CentOS

Samba is a software package that enables you to share files, printers, and other common resources across a network. It is an invaluable tool for any working environment. One of the most common ways to share file resources across a heterogeneous network (meaning different computer systems such as Windows and Linux) is to install and configure Samba as a standalone file server to provide basic file-sharing services through user-level security with the use of the system user’s home directories. Standalone servers are configured to provide local authentication and access control to all the resources they maintain. All in all, every administrator knows that Samba remains a very popular open source distribution, and it is the purpose of this process to show you how to deliver an instant approach to file sharing that provides the seamless integration of any number of users on any type of modern computer across your entire working environment.

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 facilitate the download of additional packages. It is expected that your server will use a static IP address.

The Process

Samba is not installed by default, and for this reason we will begin by downloading and installing the required packages.

  1. To do this, log in as root and type the following command in order to install the required packages:
    yum install samba samba-client samba-common
  2. Having done this, the first step is to rename the original configuration file:
    mv /etc/samba/smb.conf /etc/samba/smb.conf.BAK
  3. Now, create a new configuration file in your preferred text editor by typing the following:
    vi /etc/samba/smb.conf
  4. Begin building your new configuration by adding the following lines, replacing the values shown with values that better represent your own needs:
    [global]
    unix charset = UTF-8
    dos charset = CP932
    workgroup =
    server string =
    netbios name =
    dns proxy = no
    wins support = no
    interfaces = 127.0.0.0/8 XXX.XXX.XXX.XXX/24
    bind interfaces only = no
    log file = /var/log/samba/log.%m
    max log size = 1000
    syslog only = no
    syslog = 0
    panic action = /usr/share/samba/panic-action %d

    Note
    WORKGROUP_NAME is the name of the Windows workgroup. Use the standard Windows name WORKGROUP if you don’t have this value. MY_SERVERS_NAME refers to the name of your server. In most situations, this could be in the form of FILESERVER or SERVER1 and so on. XXX.XXX.XXX.XXX/XX refers to the primary network address that your Samba service is operating at, for example, 192.168.1.0/24. NETWORK_NAME refers to the name of your Ethernet interface. This could be enp0s8.

  5. We will now configure Samba as a standalone server. To do this, simply continue to add the following lines to your main configuration file:
    security = user
    encrypt passwords = true
    passdb backend = tdbsam
    obey pam restrictions = yes
    unix password sync = yes
    passwd program = /usr/bin/passwd %u
    passwd chat = *Enter\snew\s*\spassword:* %n\n
    *Retype\snew\s*\spassword:* %n\n *password\supdated\ssuccessfully* .
    pam password change = yes
    map to guest = bad user
    usershare allow guests = no

  6. For the purpose of this process, we do not intend to configure Samba as a domain master or master browser. To do this, add the following lines:
    domain master = no
    local master = no
    preferred master = no
    os level = 8

  7. We will now add support for home directory sharing by enabling valid users to access their home directories. This feature will support the appropriate read/write permissions and all folders will remain private from other users. To do this, add the following new lines:
    [homes]
         comment = Home Directories
         browseable = no
         writable = yes
         valid users = %S
         create mask =0755
         directory mask =0755

  8. Save and close the file. To test the syntax of the Samba configuration file we just created, use the following:
    testparm

  9. Now, add an existing system user, john, to the Samba user management system (this is for testing later; change it appropriately to a user name on your system):
    smbpasswd -a john

  10. Now, save the file and close it; back on the command line, open the ports in the firewall:
    firewall-cmd --permanent --add-service=samba && firewall-cmd --reload

  11. Configure SELinux to use the Samba home directory:
    setsebool -P samba_enable_home_dirs on

  12. Now, ensure that the samba and nmb services will start up during the boot process and start them right away:
    systemctl enable smb && systemctl enable nmb systemctl start smb && systemctl start nmb

How Does It Work?

It was the purpose of this process to install Samba and configure its file-sharing services, thus providing full connectivity across all modern computer systems in your network.

So, what did we learn from this experience?

Having installed the necessary packages, we renamed the originally installed configuration file to have a backup in place if anything broke later, and then we began setting up Samba from scratch, starting with an empty smb.conf configuration file. Having opened this new file, we began with the global configuration options; the first step was to declare compatibility with Unicode-based character sets. You will need to be aware that the values can vary as a result of your circumstances and network. Read more at man smb.conf.

Having done this, we then proceeded to confirm the name of our workgroup and server, disable WINS, establish a Samba log file, and register the network interface. Then, we elected the following standalone options by choosing a user-based security option, password encryption, and a tdbsam database backend. The preferred mode of security is user-level security, and using this approach implies that each share can be assigned to a specific user. Therefore, when a user requests a connection for a share, Samba authenticates this request by validating the given username and password with the authorized users in the configuration file and the Samba database. Next, we added the master information. In the case of a mixed operating system environment, a known conflict will result when a single client attempts to become the master browser. This situation may not disrupt the file-sharing service as a whole, but it will give rise to a potential issue being recorded by the Samba log files. So by configuring the samba server to not assert itself as the master browser, you will be able to reduce the chance of such issues being reported. So, having completed these steps, the process then considered the main task of enabling the homes directory file-sharing. Of course, you can experiment with the options shown, but this simple set of instructions not only ensures that valid users will be able to access their home directory with the relevant read/write permissions but also, by setting the browseable flag to no, you will be able to hide the home directory from public view and achieve a greater degree of privacy for the user concerned. In our setup, Samba works with your Linux system users, but you should remember that any existing or new user is not added automatically to Samba and must be added manually using smbpasswd -a.

So, having saved your new configuration file, we tested its correctness using the testparm program and opened the Samba related incoming ports in firewalld using the samba service. The next step was to ensure that Samba and its related processes would be made available during the boot process using systemctl. Samba requires two primary processes in order to work correctly: smbd and nmbd. Beginning with smbd, it is the role of this service to provide file-sharing, printing services, user authentication, and resource locking to Windows-based clients using the SMB (or CIFS) protocol. At the same time, it is the role of the nmbd service to listen, understand, and reply to the NetBIOS name service’s requests.

Note
Samba often includes another service call named winbindd, but it has been largely ignored because the intention to provide a Windows Internet Naming Service (WINS)-based service or Active Directory authentication requires additional consideration, which is beyond the scope of this process.

Consequently, our final task was to start both the Samba service (smb) and the associated NetBIOS service (nmb).

You now know how incredibly simple Samba is to install, configure, and maintain. There is always more to learn, and yet this simple introduction has served to illustrate Samba’s relative ease of use and the simplicity of its syntax. It has delivered a solution that has the ability to support a wide variety of different needs and a range of different computer systems, one that will fulfill your file-sharing requirements for many years to come.

There's more…

You can test our Samba server configuration from any client in your network that can ping the server. If it is a Windows-based client, open the Windows Explorer address bar and use the following syntax: \\\
. For example, we use \\192.168.1.10\john (on successfully connecting to it, you need to enter your Samba username’s password). On any Linux client system, (the package, samba-client, needs to be installed on CentOS 7) to list all the available shares of an NFS server, use the following line:
smbclient -L -U

In our example, we would use the following:
smbclient -L 192.168.1.10 -U john

To test, mount a share (this requires the cifs-utils package on CentOS 7) with the following syntax:
mount -t cifs ///
-o "username=
"

In our example, we would use the following:
mkdir /mnt/samba-share
mount -t cifs //192.168.1.10/john /mnt/samba-share -o "username=john"

You can also put this import in the /etc/fstab file for permanent mounting using the following syntax:
/// cifs
0 0

for example: For example, add the following line to the file:
//192.168.1.10/john /mnt/samba-share cifs username=john,password=xyz 0 0

If you don’t want to use passwords in plaintext in this file, read the section about credentials using man mount.cifs, then create a credentials file and protect it with chmod 600 in your home directory so that no other person can read it.

Here in this article, we showed you how to configure Samba as a standalone server and enable home directories, and how to connect to it from a client to get you started. But Samba can do so much more! It can provide printing services or act as a complete domain controller. If you want to learn more, feel free to visit https://www.packtpub.com/ to learn more about other available material.

 

Creating a CentOS virtual block device

In this process, we will create a virtual block device that we will use to simulate real devices and partitions so that we can test-drive concepts and commands used in all later processes. Working with real disks and partitions often involves the risk of losing important data or even having to re-install your complete system. A virtual block device is ideal to learn the techniques and try things out before switching to “production mode”. Later, if you have gained enough experience and feel safe, you can easily replace it with “real” hardware devices, partitions, and logical volumes. All you need to do is substitute your virtual device with “real” block device names.

To Start With: What Do You Need?

To complete this process, you will require a minimal installation of the CentOS 7 operating system with root access. To create a virtual block device, you should have at least one gigabyte of free hard disk space that we will use temporarily to create and make. You can delete this reserved space later (or it will be automatically deleted on reboot). It’s just for testing.

The Process

  1. To begin, log in as root and create an empty file with the exact size of 1 gigabyte:
    dd if=/dev/zero of=/tmp/test-image.dd bs=1M count=1000
  2. Now, let’s create a loop device from the file we just created:
    losetup -fP /tmp/test-image.dd
  3. Next, print the generated loop device name:
    losetup -a
  4. As this will be the first loop device created in the current system, the output will be as follows (loop0 can be a different number if you have created a loop device before):
    /dev/loop0: [0035]:3714186 (/tmp/test-image.dd)
  5. To get a list of all the block devices currently attached to the system, as well as important details, type the following:
    lsblk -io NAME,TYPE,SIZE,MOUNTPOINT,FSTYPE,MODEL
  6.  Now, let’s create a new partition table of the type gpt on our new loop device (confirm the deletion of any data):
    parted /dev/loop0 mklabel gpt
  7. Finally, create device maps from your loop device to make it more similar to real hard disk partitions:
    kpartx -a /dev/loop0

How Does It Work?

In this process, we have learned how to create a virtual block device that acts as a starting point for testing out how to create partitions, logical volumes, and filesystems in later processes can be checked. 

So, what did we learn from this experience?

We started this process by creating a new empty file, which was one gigabyte in size, in the /tmp directory using the dd utility. dd is used to make exact copies of files (which is sometimes called cloning) and expects two parameters: an input file (the if parameter) and an output file (the of parameter). We used the zero devices (/dev/zero) as our input file that returns an endless stream of bytes containing zero. We then limited the stream by defining a block size (bs) and count parameter. The bs defines the amount of data in bytes read at a time, while the count parameter counts how many repetitions of bs will be allowed. So, these arguments can be read as stop the copying process when we reach a block size times count data received. In our example, we used a block size of 1 Megabyte times 1000 = 1 Gigabyte. This zero byte data was written to our output file (of) called /tmp/test-image.dd.

After we created this empty file, we created a temporary loop device with it. A loop device is just a pseudo-device that makes it possible to use a file as a block device. Often, such a file is a CD ISO image, and using it as a loop device will make it accessible as if it were a normal hardware drive. Any device that allows reading or writing data in blocks can be called a block device; in order to get a list of all available block devices in your system, we used the lsblk command, and as you can see, this includes our loop device as well. Standard loop device names start with the number zero, as in /dev/loop0.

Afterward, we created a new partition table on our loop device using the parted command. A partition table is a table maintained on a disk by the operating system describing the partitions on it, and it must be created before we can create them. We used the partition table type gpt, but you can also use the old msdos type here instead.

Normally, when creating a partition table on a virtual block device, we cannot access individual partitions or make filesystems for different partitions on it, because the partitions cannot be addressed individually. Here we used the kpartx command to create device mappings from partition tables, which allows us later to access single partitions for creating filesystems using the notation, /dev/loop0p1, for partition 1 on loop device 0 and /dev/loop0p2 for partition 2 on loop device 0.

Congratulations, you have now created a brand new virtual block device with a standard partition table, which can be used and accessed as if it were a normal disk device.

There's more…

If we want to remove a virtual block device, we first have to unmount it from the filesystem if it is currently mounted (for example, umount /dev/loo0p1). Next, we need to detach the virtual block device file from the loop device using the -d parameter like so: losetup -d /dev/loop0. Afterward, we can delete the block file if we want to: rm /tmp/test-image.dd.

 

Tracking CentOS system resources with journald

Log files contain system messages and output from services, the kernel, and all kinds of running applications. They can be very useful in many situations, for instance, to troubleshoot system problems and monitor services or other system resources, or doing security forensics after a breach of security. In this process, you will learn the basics of how to work with logging services using journald.

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. Also, setting the time and date correctly is very crucial for the whole logging concept, so please apply the Synchronizing the system clock with NTP and the chrony suite process, Configuring the System before using this process. Also, a basic knowledge of systemd and units can be advantageous. Journalctl uses less navigation to show output; please read the Navigating text files with less process for better understanding, Configuring the System if you don’t know how to work with it.

The Process

On CentOS 7, we have a choice between two logging mechanisms called rsyslog and the journald log system, which is a component of the new systemd system manager, for viewing and managing the logging information. Here, we will show you how to work with the journalctl command, which is the controlling client for the journald daemon:

  1. To begin, log in as root and type the following command to view the whole journal log:
    journalctl
  2. Next, we want to show only the messages within a specific time frame (change the date accordingly):
    journalctl --since "2015-07-20 6:00:00" --until "2015-07-20 7:30:00"
  3. Afterward, we want to filter the log system by all messages from the sshd service:
    journalctl -u sshd.service --since "yesterday"
  4.  Now, we want to show only messages with type error:
    journalctl -p err -b
  5. To get the most verbose version of journalctl, use the verbose option:
    journalctl -p err -b -o verbose
  6. Togeta current view on the log output, use the following command (this is not less navigation—use the key combination Ctrl+C to exit this view):
    journalctl -f

How it works…

In CentOS 7, we can use the new journald logging system, which is a part of the systemd system management. It is a centralized tool that will log just about everything on your system including all output from the early boot over kernel to services and all program messages. The main advantage over other logging mechanisms is that you don’t have to configure logging for each of your services or other resources because everything is already set up for all applications that are controlled and running through the centralized systemd system.

So, what have we learned from this experience?

We began our journey by running the journalctl command, which when applied without any parameters show us the complete journal log, which includes everything from starting your system and capturing the first boot log entries to the latest system messages in the order they appeared, appending new messages to the bottom (chronological order). If your system has been running for a while, it can contain hundreds of thousands of lines of logging data, and is very impractical to work within this raw form.

This output is constantly captured by the journald daemon but is not written to text files as other logging systems such as rsyslog do it. Instead, it uses a structured and indexed binary file, which stores a lot of additional meta information such as user Id, timestamp, and so on, and which makes it easy to transform into all kinds of different output formats. This can be very convenient if you want to further process journal information by another tool. As you cannot read binary files, you will need the client journalctl for it, which is used to query the journald database. Since it is almost impossible to parse through this sheer amount of data manually, we then take advantage of journalctl’s rich filtering options. First, we used the --since and --until parameters to extract all log messages within a specific time frame. The syntax for specifying the time and date here is very flexible and understands phrases such as yesterday or now, but we stick with the simple date syntax, YYYY-MM-DD HH:MM:SS. Next, we used journalctl’s -u parameter to filter log messages for a specific unit type. We used it to filter messages coming from the sshd daemon service. We added another filter using the --since parameter, which tightens the result of the -u unit filter even more, outputting only sshd service results that occurred yesterday. The next filter we applied was using the parameter string, -p err -b, which filters the log database by priority or log level. Every log message can have an associated priority that determines the importance of the message. To find out more about different log levels, refer to the manual using the command lineman 3 syslog (if this manual is not available, install it by typing yum install man-pages). Our command will print out all log messages labeled as error or above, which includes: error, critical, alert, or emergency.

Next, we used the same command parameters but added -o verbose, which gives the most verbose output of logging information. Lastly, we presented the -f parameter (for follow), which will give us a live view of the latest log messages and leaves this connection open, appending any new messages to the end of the output when they occur.

This is often useful to see how the system reacts if you are currently testing out settings or starting/stopping services.

Summing up, one can say that, on CentOS 7, two logging systems do coexist: the older rsyslog and the newer journald, with the latter being your primary tool of choice for troubleshooting your system. But remember that on CentOS 7, journald is not a full replacement for rsyslog though. There are some rsyslog features that are missing in journald, and also there are lots of tools and scripts, such as log digesting tools or monitoring suites such as Nagios, that work exclusively with rsyslog.

System administrators often face a big challenge in troubleshooting system errors or unexpected server behaviors. Often, it’s not easy to find the single point of failure by searching through massive amounts of different log file texts while applying regular expression searches or Linux command line kung fu. Journald provides a very convenient alternative by providing a powerful and well-defined centralized querying system to get the log file analysis done quickly and efficiently!