How to create a new ansible role

I’ve recently started playing with ansible so I’ve just barely got the basics of this automation technology. I’ve previously used Chef or Saltstack but, this is something new for me. In today’s article I’ll show you how to create a new ansible role. Roles are somehow like Chef cookbooks because they provide all the needed information such as attributes, handles, tasks, etc. to install and configure a particular application.

To create a new role with ansible simply use the ansible-galaxy init role_name command. Note that if you are behind a firewall and cannot access the ansible api server from within your network, you can use the –offline option to create the role locally:

ansible-galaxy init apache –offline

ansible-galaxy command

ansible-galaxy command

Note that right now a directory tree has been created in the specified role. I’ve used  the find command to list all dirs:

[root@chefserver apache]# find -type d -exec ls -d1 {} \;

You can also use the tree command which must be installed if you are using the CentOS minimal image:

[root@chefserver roles]# tree apache/
├── defaults
│   └── main.yml
├── files
├── handlers
│   └── main.yml
├── meta
│   └── main.yml
├── tasks
│   └── main.yml
├── templates
├── tests
│   ├── inventory
│   └── test.yml
└── vars
└── main.yml

8 directories, 8 files

Each directory has a specific functionality within the role as follows:

defaults – location for the default variable for your role. I’m still new with ansible variable precedence but, I’ve learned so far that variable defined in the defaults directory of a role can be easily overwritten because they have the lowest priority. This is where you define a variable value just in case there is none defined when the role is called.
files – this is where you store any file that must be copied on the destination machine. Within this directory you can store any files such as configuration files, rpm packages. Note that files stored within this directory cannot be modified as templates so usually they are just copied to the destination machines.
handlers – notify directives within ansible tasks usually interact with system services. Within the handlers directory you store any definition for System services.
meta – role dependencies are stored within the meta directory. It also hosts other information for a specific role such as the author of the role, the description, company name, license, minimum ansible version, supported platforms, categories.
tasks – installation and configuration actions for that specific role
templates – location for ansible templates. These are files that are written in Jinja2 templating language and can be modified as the machine is provisioned. Note that you can customize a template for any structure or configuration needed.
teststhis is where you would place any verification mechanism for the results of your role
vars – directory used to store variables for the role. Variable stored here have higher priority than those stored on the defaults directory.

Changing timezone on CentOS7

CentOS7 gets shipped with the timedatectl tool which can be used to display/modify timezone settings on the server. There are several options available with this command and you can explore its man page to find out more information.

To list all available timezones, use the timedatectl list-timezones command

Since there are a lot of timezones available, you can use grep command and further filter them: timedatectl list-timezones | grep Europe

Once you’ve chosen a timezone, use timedatectl with the set-timezone parameter to set a particular timezone on your machine:

timedatectl set-timezone Europe/Bucharest

You can view timezone information by typing timedatectl:


Get timezone information on CentOS7

Now if you check out the /etc/localtime file, you will see that it’s actually a symbolic link pointing to the new configured  timezone:

ls -l /etc/localtime 


CentOS timezone

As you can see from the image above, the symlink is pointing to /usr/share/zoneinfo/. If you explore this folder you will see that it contains a directory structure for each locale:


Linux timezone

timedatectl set-timezone command actually creates a that specific symbolic link so you can simply create it manually instead of using this command. So first remove the localtime file and then execute the following command:

ln -s /usr/share/zoneinfo/US/Eastern localtime

In this case the timezone will be changed to US/Eastern so now if we execute timedatectl, you’ll see that the change was made successfully:


How to change timezone on CentOS

TZ environment variable is used to determine local timezone on a machine. If a system is well configured and the timezone is correctly set, it would not be necessary to manually configure this environment variable. If you have applications that use it specifically or you have an environment which requires TZ to be set, then, you would need to export it.

Note that tzselect command is available in Centos7 so if you want to change the TZ environment variable you can use this command or export directly the desired value as seen in the following example:

export TZ=:/usr/share/zoneinfo/Europe/London

Changing System locales:

Locales are a method in which a computer is assigned the language, country and codeset for its System.


Linux system locales

With locale -a command you can view all locales that are available to you. If you want to change your locale you can export the following two environment variables with the desired locales:

$ export LANG=en_GB.UTF-8
$ export LC_ALL=en_GB.UTF-8

Note that these will not be persistent changes and you’ll have to add them to your
~/.bashrc or /etc/profile files to make them permanent.

Working with SElinux booleans

SElinux booleans are on/off switches that can be easily disabled or enabled if required. I’ll try to show you in this article how you can interact with SElinux booleans on a Linux machine. Note that for this demonstration I will be using a CentOS 6 Virtual Machine.

To view a detailed list of available selinux booleans you would type getsebool -a command, which will display something like:


SElinux booleans

Let’s say you have an Apache web server and you want to check out what SElinux modules are available within the OS. Since there are a lot of available booleans, we can refine this search by typing getsebool -a | grep httpd to list only the available Apache booleans. Each boolean has a distinctive role within the OS and will enable a particular access for the Apache web server. I’m not going to discuss about them now but, you can read further here.

To enable a SElinux boolean simply execute the  setsebool boolean_name on/off command, just like in the following example:

setsebool httpd_enable_homedirs on

Using the same command but with the off switch will disable the boolean:

setsebool httpd_enable_homedirs off

Note that these changes are not persistent unless you use the -P parameter and will disappear once you reboot the machine. So this is how you would make a persistent change:

setsebool -P httpd_mod_auth_pam on
setsebool -P httpd_enable_homedirs on
The first time you activate a boolean that’s not enabled by default, a file named booleans.local will be created on the machine, which contains the enabled booleans. You can view the content of this file in  /etc/selinux/targeted/modules/active/booleans.local .Note that if you modify this file manually,  you will not create any changes to SElinux since this file is created for users and it’s not used to enable/disable booleans:

Selinux enabled booleans file

SElinux will normally point you to the right command if there are some issues logged in the audit file. Literally, it will actually show you the exact command that you have to execute to fix your issues. So if you have any booleans that needs enabled, just check out the audit or the messages files to get an idea on what needs to be configured.

How to create SElinux policy

SElinux is a security mechanism introduced in Linux OS as an extra security layer. There are probably many things to be mentioned about selinux so I’m not going to discuss about the main concepts that make up selinux such as labeling and targeting. I’ll show you in this article how to create a new selinux policy (also known as module) and install it on a machine.

You can check the selinux status by typing getenforce without any parameters. You can then use setenforce 0 command to change it to permissive or setenforce 1 again to enforce it:


selinux status

All SElinux messages are logged in /var/log/audit/audit.log, you can inspect this file to determine what applications are blocked from interacting with the Operating System. /var/log/messages is another location in which you can find useful information about selinux logs. As you will probably see, the log file contains a bunch of information that is hard to read, you can use the audit2allow -w -a command to display a more friendlier output. This command will parse the audit.log file ( -a parameter) and then will create a friendlier output (-w parameter) that looks something like:


selinux policy

In SElinux context all log messages are named AVC so you will see them everywhere in the audit log file.

You can view all SElinux  rejected accesses using the audit2allow -a command:


How to create SElinux policy

This command can also be used to parse the log file then create a module that can be imported by SElinux to allow access. Execute audit2allow -a -M module_name to create a new SElinux module. I’ve named mine zabbixdiamond and placed it in my home directory. The command will create two files, one with .pp and another one with .te extension:

audit2allow -a -M zabbixdiamond

SElinux module

selinux policy files

You can view the content of the selinux module by executing cat zabbixdiamond.te command. As you can see from the image below, the module contains all the rules that are needed by SElinux to allow this particular AVC :

How to create SElinux policy

how to create selinux module

All that’s left now is to install the module using the following command: semodule -i zabbixdiamond.pp. If you encounter an error saying something that “global requirements are not met” it means that SElinux already has a module with a similar name installed on the machine so you’ll need to change its name:

How to create SElinux policy

how to install selinux module

In this case you will have to restart the procedure and create a new SElinux module with a different name. To check what modules are installed on the server use semodule -l. You can expand this command and search for a particular SElinux module with semodule -l | grep zabbixdiamond . In this way you also verify if a SElinux module has been successfully loaded in the OS.

Execute again audit2allow -a and see if the AVCs are now allowed in SElinux:

How to create SElinux policy

audit2allow command with selinux

That’s about it for this article folks, hope it will serve you well in creating SElinux policies. Wish you all the best!

Using find command to interact with files

In this short article I want to show you how you can use find to interact with files within Linux. I’ll also try to cover some of the aspects when using find with xargs command and we’ll see the difference between these two. So we’ll start by playing with some of the parameters available with the find command.

Getting files older than a X number of days and remove those

find /path/to/files -mtime +60 -exec rm {} \;

You can also use the -delete option that’s available with the find command:

find . -mtime +1 -delete

If you want to search on multiple directories but want to limit the maximum depth for the search, you would use the –maxdepth parameter, just like in the following example:

find . -maxdepth 1 -mtime +1 -exec ls {} \;

Find command allows you to search for a particular type of file, such as regular files (f), directories (d), symbolic lynk (l), character devices (c) and block devices (b):

find . -type f -maxdepth 1 -mtime +30

find . -type d -maxdepth 1 -mtime +30

You can also pipe the xargs command and achieve similar results to the ones we’ve seen in the previous examples:

find . -type f -maxdepth 1 -mtime +30 | xargs ls -al

So what’s the difference between using find . -type f -maxdepth 1 -mtime +30 -exec ls -al {} \; and find . -type f -maxdepth 1 -mtime +30 | xargs ls -al  since they both seem to have similar results:


find with -exec parameter vs find with xargs command

When using find with the -exec parameter, the command will actually run the rm command for each occurrence thus creating an overhead of the whole remove process. What’s important is that when interacting with a lot of files xargs is the preferred method. Why? because when executing a command with xargs, it will actually try to run a single remove command with as much files as possible as attributes. That being said, the find with -exec parameter is much slower than find piped with xargs:

find . -exec rm \{}

find . -print0 | xargs -0 rm

So how much parameters can you fit into a single xargs command? Execute the xargs –show-limits command to view the command’s limits:


Xargs command limits

Using find command with the -exec parameter:

find /path/to/junk/files -type f -mtime +30 -exec rm -f {} \;

Using find command with the xargs command:

find /path/to/junk/files -type f -mtime +30 -print0 | xargs -0 -r rm -f

How to install and configure a DHCP Server on a Linux machine

Hello dear readers,
In today’s article I will show you how to create your Linux DHCP server. DHCP or Dynamic Host Control Protocol is a service which provides IP addressing to your network devices. The difference between assigning static IPs and using a DHCP server is that the IP assignment is made without the interference of System Administrators. Using such service you also have a centralized administration point to your whole infrastructure offering an easy way to assign/change or remove an IP address from your hosts. Every network parameter can be automatically configured by the DHCP server: IP address, network mask, gateway, DNS servers, WINS server address, etc. This service works using the client-server model: the server sends messages using 67 (source) and 68 (destination) UDP port numbers while the client uses port 68 as source and port 67 as destination.
One of the main principles behind this technology is the use of “leased” addresses. This means that each client will be able to use a certain IP address only in the allotted time. Once an IP address has been assigned to a DHCP client, a lease-time duration is set. The client will contact the DHCP server periodically to “renew” it’s IP address. If for whatever reason, the DHCP server does not respond in time, the client will try to contact other DHCP servers by broadcasting a message throughout the network.
Before an IP is assigned to a workstation, several messages are exchanged between the DHCP client and the server. The following picture displays a typical DHCP process:

DHCP Client-Server model

We’ve talked previously about DHCP in this article when we’ve talked about Windows Server. From above, the whole DHCP IP assignment method looks something like this:
 1. client sends a DISCOVER message in which he tries to contact any DHCP server available on the network. This is a broadcast message that uses the UDP port 67 as destination. Unless there is DHCP-Relay configured on the network, this message will be blocked from any edge device (a router). This message can contain an IP address, the last used IP address and/or the lease time.
2. server will respond with an OFFER message that contains all the network parameters. This is also a broadcast message that uses the UDP port 68 as destination.
3. when the client chooses a certain IP configuration, it will send a REQUEST message to the DHCP server to inform that the specified IP address has been chosen. This message is received by all DHCP servers and thus, all will know that the client has received its reservation.
4. server will respond with an ACK (Acknowledge) message and the network parameters will be sent to the client.
Other types of DHCP messages that can be exchanged between the client and the server are:
Decline – the client will refuse to accept the IP allocation because this network address is used by another workstation
NACK – this type of message is sent when the server refuses to lease an IP address
Inform – when certain network parameters must be changed, the client will send an inform message to the server
Release – the client will inform the server that he doesn’t need the reservation anymore
For this example, I will install the DHCP server on a CentOS machine, you can choose whatever distribution you like because the config is similar. You’ll need an active Internet connection if you choose to install the DHCP service using the yum tool. To install this service from sources the story is a bit complicated and I will not talk about it right now.
To configure the network parameters, use ifconfig or ip commands:
ifconfig eth0 network
ip address add dev eth0

How to configure Linux IP address

If you need to remove an IP address type ip address del dev eth0 or ifconfig eth0 delete
The default route/gateway address can be configured by typing:
route add default gw oip route add default  via

How to configure gateway IP in Linux

 Once the network parameters have been set, we’ll need to enable the network interface by typing ifconfig eth0 up

How to enable network interface in Linux

 To disable a network interface, type ifconfig eth 0 down
We’ll need to add the DNS servers used by our DHCP server. Navigate to /etc/resolv.conf and edit the file using your favorite editor. Once you’ve opened the file, type in the following:
Add one entry per line for each DNS server’s IP address

How to configure local DNS servers in Linux

Now you should be able to ping any website and we are ready to install the DHCP service. There are several things that you’ll need to know before we can proceed with the installation:
  • the DHCP service is called dhcpd (DHCP Daemon) and once we’ve configured it, we’ll see this process running on the server.
  • In CentOS, the DHCP config file in stored under /etc/dhcp/dhcpd.conf. We’ll need to modify this file to successfully configure our server. Note that if the installation is made from sources, this file will have to be created manually:

DHCP configuration file

 As you can see from the output, in CentOS, the configuration file is empty so we need to enter all configuration parameters manually. An example can be seen in /usr/share/doc/dhcp*/dhcpd.conf.sample. Once the configuration is finished, we can validate it using the dhcpd -t command.
To install the DHCP service, type yum install dhcp and wait for the installation to finish. If you don’t know weather your server has this service installed or not, try to install it and you’ll receive the following message:

How to install DHCP in Linux

After the installation has been successfully completed, it’s time to configure our DHCP server by editing the configuration file. Simply copy the content from /usr/share/doc/dhcp*/dhcpd.conf.sample to /etc/dhcp/dhcpd.conf. To achieve this result, type in cat /usr/share/doc/dhcp*/dhcpd.conf.sample > /etc/dhcp/dhcpd.conf
Now open the dhcpd.conf file using your favorite editor. I’ve edited the file and kept only the information that we require for this config. The file should look similar to:
ddns-update-style none;
option domain-name “”;
option domain-name-servers;
option routers
default-lease-time 600;
max-lease-time 7200;
subnet netmask {
Note that the bold lines are the ones that must appear in the config. The # sign is used to comment lines so whatever is written after this character is not executed. It’s important to put the ; character at the end of each line.
I will try to explain each parameter used in our configuration file:
  • authoritative – an authoritative server will respond to requests coming from clients that are part of the same subnet. Simply put, if a client from a subnet that was not configured on the DHCP server requests a renew, the DHCP server will send DHCP NACK messages forcing the client to release its IP configuration.
  • ddns-update-style none – disables dynamic DNS
  • option domain-name “” – sets the domain name of the DHCP clients
  • option domain-name-servers – sets the DNS servers used by clients
  • option routers – sets the network routers
  • default-lease-time 600; and max-lease-time 7200; – the number of seconds a client can hold its IP allocation before submitting a renew
Note that if we include these settings in the subnet config, the settings will only be applied to that particular subnet. In this example we’ve configured the settings for the whole server thus all subnets configured on this machine will carry the same config.
  • subnet netmask  – the subnet of the DHCP server
  • range; – the pool of IP addresses used by DHCP clients
After we’ve finished our configuration, it’s time to test the config file for errors by typing dhcpd -t. If there are no errors received, the dhcp daemon can be started. You can verify it’s status by typing service –status-all | grep dhcpd

Get DHCP service status 

Start the DHCP daemon by typing /sbin/service dhcpd start .You can stop it by typing: /sbin/service dhcpd stop
If you type ps -el | grep dhcpd, you should be able to see the daemon running on your server. If you have any problems with the server at this point, type service dhcpd restart to restart the DHCP daemon:

How to restart DHCP daemon

We can also check if the server listens on UDP port 67 by typing netstat -paun

how to verify DHCP port in Linux

p = display PID/Program name for sockets ; a – all ; u – show only UDP ports ; n – numeric

On the client side, you will need to type dhclient [interface name] to instruct the DHCP client to listen on the specified interface. After this step is complete, if you type ifconfig or ip addr show, you should be able to see the leased IP address:

how to display IP address in Linux

 The dhclient config file is stored in /etc/dhcp/dhclient.conf. By editing this file, we can set custom settings for the DHCP client:

How to configure DHCP client

 The database of the DHCP client is stored under /var/lib/dhcp/dhclient.leases
If we return on the server, we can check out the DHCP database in which leased IP addresses are stored. In CentOS, the database can be found in /var/lib/dhcpd/dhcpd.leases and looks something similar to:

DHCP database

This way we can verify what IP addresses have been leased to DHCP clients. The number of leased IP addresses can be easily viewed by typing dhcpd once the daemon has been started:

Verify DHCP leased IP addresses

If we want to reserve a specific IP for a DHCP client, we’ll need to type in the following (I’ll add comments on each line):

host ubuntu1 {   host identification within the dhcpd.conf file
        hardware ethernet 00:0c:29:bd:5b:69;   – MAC address of the host
        option domain-name-servers;   – specific DNS servers used by this host (optional)
        option routers;   – specific gateway used by the host (optional)
        fixed-address;   – host’s reserved IP address
Once you’ve made this configuration, restart the dhcp daemon. On the client side, we will need to disable/enable the network interface by typing ifconfig eth0 down followed by ifconfig eth0 up.
Another method of renewing the leased IP address is by typing: sudo dhclient -r eth0 followed by sudo dhclient eth0
 If there are no problems on the server, the DHCP client will renew it’s IP address:

DHCP client renew

We can further modify our dhcpd.config file to set custom settings for a group of DHCP clients by typing:
group {
option domain-name-servers; -global settings applied to this groups of hosts
option routers;
         host ubuntu1      { 00:0c:29:bd:5b:69; }   each DHCP client with it’s corresponding MAC address
         host ubuntu2      { 00:0c:29:bd:5b:70; }
         host ubuntu3      { 00:0c:29:bd:5b:71; }
 I’ve tried to cover all main steps that you need to take in order to install and configure DHCP on your infrastructure. We’ve seen how to deploy the DHCP server and configure a client to obtain its IP automatically. Hope I’ve managed to explain all the important steps and you now have a clear understanding of the DHCP protocol how its implemented in Linux distributions. If you have any questions don’t hesitate to post a comment and I’ll respond asap. Wish you all the best!

Running Docker images

In this article I’ll show you how to manipulate docker images and run them locally on your workstation. To pull an image from the official docker hub repository use the command docker pull image_name just like in the following example:


how to pull docker images

Now that the image has been stored locally, you can type docker images to visualize all available local images:


listing docker images

You are probably wondering where are the docker images stored. Well, they are encoded in the docker application in /var/lib/docker/devicemapper/devicemapper/data and /var/lib/docker/devicemapper/devicemapper/metadata. Note that these locations can be seen if you execute docker info command:


get docker information

By default, the docker pull command will only download a single image so, if you need to download everything from a repository, use docker pull –all-tags rabbitmq

Now you can simply execute docker run -d rabbitmq and verify the container has been started by typing docker ps command. Remember that if you don’t use the -d parameter, the container will end its execution once you exit the terminal.

You can pull a specific docker image tag by using the same pull command just like in the following example: docker pull rabbitmq:3.6.5-management


pull docker image tag

Note that because I’ve previously downloaded the rabbitmq base image, the download was much faster since I already had some pieces of the docker image. I’ve downloaded this specific image because it contains the rabbitmq management interface and I wanted to show you how to forward a port from a docker container to your host. This can be achieved by using the -p IP:host_port:container_port parameter. For this example I don’t need to bind that port on a specific interface so I’ll simply use the following command:

docker run -d -p 15672:15672 rabbitmq:3.6.5-management

You can then verify that the port has been opened with the netstat command:

netstat -tupln | grep 15672docker-portforwardingYou can now open a browser and check the rabbitmq management interface on the specified port:


rabbitmq on docker

Manipulating images with docker is pretty simple as you’ve seen in this article. In a future article I want to cover the topic on how images are built for docker. In the meantime don’t hesitate to post a comment in the dedicated section and share it to others. Wish you all the best!