How to Install and Configure ‘Cache Only DNS Server’ with ‘Unbound’ in RHEL/CentOS 7

from here

Caching name servers using ‘Unbound‘ ( is a validating, recursive, and caching DNS server software ), back in RHEL/CentOS 6.x (where x is version number), we used bind software to configure DNS servers.

Here in this article, we are going to use ‘unbound‘ caching software to install and configure a DNS Server in RHEL/CentOS 7 systems.

Setup Cahing DNS Server in CentOS 7

Setup Cahing DNS Server in RHEL/CentOS 7

DNS cache servers are used to resolve any DNS query they receive. If the server caches the query and in future the same queries requested by any clients the request will be delivered from DNS ‘unbound‘ cache, this can be done in milliseconds than the first time it resolved.

Caching will only act as a agent to resolve the query of client from any one of the forwarders. Using caching server, will reduce the loading time of webpages by keeping the cache database in unbound server.

My Server and Client Setup

For demonstration purpose, I will be using two systems. The first system will act as a Master (PrimaryDNS server and the second system will act as a local DNS client.

Master DNS Server
Operating System   :    CentOS Linux release 7.0.1406 (Core)
IP Address	   :
Host-name	   :
Client Machine
Operating System   :	CentOS 6
IP Address	   :
Host-name	   :

Step 1: Check System Hostname and IP

1. Before setting up a caching DNS server, make sure that you’ve added correct hostname and configured correct static IP address for your system, if not set the system static IP address.

2. After, setting correct hostname and static IP address, you can verify them with the help of following commands.

# hostnamectl
# ip addr show | grep inet

Check IP Address in CentOS 7

Check IP Address

Step 2: Installing and Configuring Unbound

3. Before installing ‘Unbound’ package, we must update the our system to latest version, after that we can install the unbound package.

# yum update -y
# yum install unbound -y

Install Unbound DNS Package in CentOS 7

Install Unbound DNS Package

4. After package has been installed, make a copy of the unbound configuration file before making any changes to original file.

# cp /etc/unbound/unbound.conf /etc/unbound/unbound.conf.original

5. Next, use any of your favorite text editor to open and edit ‘unbound.conf‘ configuration file.

# vim /etc/unbound/unbound.conf

Copy Unbound DNS Configuration

Copy Unbound DNS Configuration

Once the file is opened for editing, make the following changes:


Search for Interface and enable the interface which we going to use or if our server have multiple interfaces we have to enable the interface

Here Our server IP was, So, i’am going to use unbound in this interface.

Enable IPv4 and Protocol Supports

Search for the following string and make it ‘Yes‘.

do-ip4: yes
do-udp: yes
do-tcp: yes
Enable the logging

To enable the log, add the variable as below, it will log every unbound activities.

logfile: /var/log/unbound
Hide Identity and Version

Enable following parameter to hide id.server and hostname.bind queries.

hide-identity: yes

Enable following parameter to hide version.server and version.bind queries.

hide-version: yes
Access Control

Then search for access-control to allow. This is to allow which clients are allowed to query this unbound server.

Here I have used, that means anyone send query to this server. If we need to refuse query for some range of network we can define which network need to be refuse from unbound queries.

access-control: allow

Note: Instead of allow, we can replace it with allow_snoop this will enable some additional parameters like dig and it support both recursive and non recursive.

Domain Insecure

Then search for domain-insecure. If our domain is works with DNS sec keys, we need to define our server available for domain-insecure. Here our domain will be treated as insecure.

domain-insecure: "
Forward Zones

Then change the forwarders for our requested query not fulfilled by this server it will forward to root domain (. ) and resolve the query.

        name: "."

Finally, save and quit the configuration file using wq!.

6. After making the above configuration, now verify the unbound.conf file for any errors using the following command.

# unbound-checkconf /etc/unbound/unbound.conf

Check Unbound DNS Configuration

Check Unbound DNS Configuration

7. After file verification over without any errors, you can safely restart the ‘unbound’ service and enable it at system startup.

# systemctl start unbound.service
# sudo systemctl enable unbound.service

Start Unbound DNS Service

Start Unbound DNS Service

Step 3: Test DNS Cache Locally

8. Now it’s time to check our DNS cache, by doing a ‘drill’ (query) one ‘‘ domain. At first the ‘drill‘ command results for ‘‘ domain will take some milliseconds, and then do a second drill and have a note on Query time it takes for both drills.

drill @

Check DNS Cache Locally

Check DNS Cache Locally

Did you see in the above output, the first query taken almost 262 msec to resolve and the second query takes 0 msec to resolve domain (

That means, the first query gets cached in our DNS Cache, so when we run ‘drill’ second time the query served from our local DNS cache, this way we can improve loading speed of websites.

Step 4: Flush Iptables and Add Firewalld Rules

9. We can’t use both iptables and firewalld at same time on same machine, if we do both will conflict with each other, thus removing ipables rules will be a good idea. To remove or flush the iptables, use the following command.

# iptables -F

10. After removing iptables rules permanently, now add the DNS service to firewalld list permanently.

# firewall-cmd --add-service=dns
# firewall-cmd --add-service=dns --permanent

11. After adding DNS service rules, list the rules and confirm.

# firewall-cmd --list-all

Add DNS to Firewalld

Add DNS to Firewalld

Step 5: Managing and Troubleshooting Unbound

12. To get the current server status, use the following command.

# unbound-control status

Check Unbound DNS Status

Check Unbound DNS Status

Dumping DNS Cache

13. If in-case you would like to have a dump of a DNS cache information in a text file, you can redirect it to some file using below command for future use.

 # unbound-control dump_cache > /tmp/DNS_cache.txt

Backup DNS Cache

Backup DNS Cache

14. To restore or import the cache from the dumped file, you can use following command.

# unbound-control dump_cache < /tmp/DNS_cache.txt

Restore DNS Cache

Restore DNS Cache

Flushing DNS Records

15. To check whether the specific address was resolved by our forwarders in unbound cache Server, use the below command.

# unbound-control lookup

Check DNS Lookup

Check DNS Lookup

16. Some times if our DNS cache server will not reply our query, in mean time we can use to flush the cache to remove information such as AAAANSSOCNAMEMXPTR etc.. records from DNS cache. We can remove all information using flush_zone this will remove all informations.

# unbound-control flush
# unbound-control flush_zone

17. To check which forwards are currently used to resolve.

# unbound-control list_forwards

Check Current DNS Forwards

Check Current DNS Forwards

Step 6: Client Side DNS Configuration

18. Here I’ve used a CentOS 6 server as my client machine, IP for this machine is and I’m going to use my unbound DNS server IP (i.e Primary DNS) in it’s interface configuration.

Log-into the Client machine and set the Primary DNS server IP to our unbound server’s IP.

Run the setup command and choose network configuration from TUI network manager.

Then choose DNS configuration, insert the unbound DNS server’s IP as Primary DNS, but here i have used both in Primary and Secondary because I don’t have any other DNS server.

Primary DNS	:
Secondary DNS	:

Select Network Configuration

Select Network Configuration

Select DNS Configuration

Select DNS Configuration

Enter DNS IP Address

Enter DNS IP Address

Click OK –> Save&Quit –> Quit.

19. After adding Primary and Secondary DNS IP addresses, now it’s time to restart the network using following command.

# /etc/init.d/network restart

Restart Network in CentOS 6

Restart Network

20. Now time to access any one of the website from client machine and check for the cache in unbound DNS server.

# elinks
# dig

Check Website

Check Website

Query Website

Query Website

Setup DNSSEC support

Next, we instruct Unbound DNS server to generate RSA keys in order to provide DNSSEC support:

# unbound-control-setup 
setup in directory /etc/unbound
generating unbound_server.key
Generating RSA private key, 1536 bit long modulus
e is 65537 (0x10001)
generating unbound_control.key
Generating RSA private key, 1536 bit long modulus
e is 65537 (0x10001)
create unbound_server.pem (self signed certificate)
create unbound_control.pem (signed client certificate)
Signature ok
Getting CA Private Key
Setup success. Certificates created. Enable in unbound.conf file to use

All what remains is to check Unbound’s configuration:

# unbound-checkconf
unbound-checkconf: no errors in /etc/unbound/unbound.conf


Earlier we were used to setup DNS cache server using bind package in RHEL and CentOS systems. Now, we have seen how to setup a DNS cache server using unbound package. Hope this will resolve your query request quicker than the bind pacakge.

ISPConfig: replace apache with nginx

from here
In this tutorial i show you how to replace apache with nginx using ISPConfig I performed the migration for serveral sites running Joomla 2.x, Joomla 3.x, WordPress and some static / self-written pages.The server runs ISPConfig installed using the Perfect Server Howto from

There are some differents between apache and nginx so you may have to adjust some settings for your web-sites.
nginx does not support .htaccess
nginx does not use different apache-modules like mod_rewrite

You can use different online-converters like to move the configs from apache to nginx. But keep in mind, that it´s not guranteed, that the convert works with out any errors. I used for different (very simple) htaccess without any problems

If you change the webserver in ISPConfig from apache to nginx, you can´t see your additional apache directives in the interface (but they are still in the database). You can browse through all you websites and write down the directives or you can grab them from the databse using phpmyadmin or mysql with this sql-command:
SELECT domain, apache_directives FROM web_domain WHERE apache_directives != '';

To find all .htaccess files, you ran run find /var/www/clients/ -name .htaccess -not -path "*/stats/*".

1. install nginx
apt-get install nginx

2. install php-fpm
apt-get install php5-fpm
and make sure, that /etc/php5/fpm/php.ini contains:


Restart php-fpm with /etc/init.d/php5-fpm reload.

Now nginx is installed but apache is still your active webserver.

3. enable Maintaince mode
Enable the Maintenance Mode in ISPConfig under System / Mainconfig on the tab Misc to prevent changes during the migration.

4. switch to nginx in ISPConfig
Login as root into phpmyadmin, open the database dbispconfig, select the table server and edit the server.

Scroll down to config and find the line [global] finden. In the next line replace




Scroll futher down to the line [web] And change the next line from





6. Create ispconfig.vhost in /etc/nginx/sites-available:
vi /etc/nginx/sites-avaliable/ispconfig.vhost
and paste one of the following contents:

with SSL:

server {
listen 8080;
ssl on;
ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
ssl_certificate /usr/local/ispconfig/interface/ssl/ispserver.crt
ssl_certificate_key /usr/local/ispconfig/interface/ssl/ispserver.key;
server_name _;

root /usr/local/ispconfig/interface/web/;

client_max_body_size 20M;

location / {
index index.php index.html;

# serve static files directly
location ~* ^.+.(jpg|jpeg|gif|css|png|js|ico|html|xml|txt)$ {
access_log off;

location ~ \.php$ {
try_files $uri =404;
include /etc/nginx/fastcgi_params;
fastcgi_pass unix:/var/lib/php5-fpm/ispconfig.sock;
fastcgi_index index.php;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
#fastcgi_param PATH_INFO $fastcgi_script_name;
fastcgi_buffer_size 128k;
fastcgi_buffers 256 4k;
fastcgi_busy_buffers_size 256k;
fastcgi_temp_file_write_size 256k;

location ~ /\. {
deny all;

without SSL:

server {
listen 8080;
ssl off;
server_name _;

root /usr/local/ispconfig/interface/web/;

client_max_body_size 20M;

location / {
index index.php index.html;

# serve static files directly
location ~* ^.+.(jpg|jpeg|gif|css|png|js|ico|html|xml|txt)$ {
access_log off;

location ~ \.php$ {
try_files $uri =404;
include /etc/nginx/fastcgi_params;
fastcgi_pass unix:/var/lib/php5-fpm/ispconfig.sock;
fastcgi_index index.php;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
#fastcgi_param PATH_INFO $fastcgi_script_name;
fastcgi_buffer_size 128k;
fastcgi_buffers 256 4k;
fastcgi_busy_buffers_size 256k;
fastcgi_temp_file_write_size 256k;

location ~ /\. {
deny all;

And create the symlink with
ln -s /etc/nginx/sites-available/ispconfig.vhost /etc/nginx/sites-enabled/000-ispconfig.vhost

7. adjust websites
Disable the Maintaince Mode and convert existing htaccess-file and apache-directives and insert the new values in the webinterface for each website.

If you did not change all websites, run the resyn-tool for the websites.

8. disable apache and start nginx
/etc/init.d/apache2 stop
update-rc.d -f apache2 remove
/etc/init.d/nginx start


If you need to switch-back to apache, just revert the steps 4. and 8.

How Does a Virtual Environment Work?

post from here

Using Virtual Environments

To get started, if you’re not using Python 3, you’ll want to install the virtualenv tool with pip:

$ pip install virtualenv

If you are using Python 3, then you should already have the venv module from the standard library installed.

Start by making a new directory to work with:

$ mkdir python-virtual-environments && cd python-virtual-environments

Create a new virtual environment inside the directory:

# Python 2:
$ virtualenv env

# Python 3
$ python3 -m venv env

The Python 3 venv approach has the benefit of forcing you to choose a specific version of the Python 3 interpreter that should be used to create the virtual environment. This avoids any confusion as to which Python installation the new environment is based on.

From Python 3.3 to 3.4, the recommended way to create a virtual environment was to use the pyvenv command-line tool that also comes included with your Python 3 installation by default. But on 3.6 and above, python3 -m venv is the way to go.

In the above example, this command creates a directory called env, which contains a directory structure similar to this:

├── bin
│   ├── activate
│   ├── activate.csh
│   ├──
│   ├── easy_install
│   ├── easy_install-3.5
│   ├── pip
│   ├── pip3
│   ├── pip3.5
│   ├── python -> python3.5
│   ├── python3 -> python3.5
│   └── python3.5 -> /Library/Frameworks/Python.framework/Versions/3.5/bin/python3.5
├── include
├── lib
│   └── python3.5
│       └── site-packages
└── pyvenv.cfg

Here’s what each folder contains:

  • bin: files that interact with the virtual environment
  • include: C headers that compile the Python packages
  • lib: a copy of the Python version along with a site-packages folder where each dependency is installed

Further, there are copies of, or symlinks to, a few different Python tools as well as to the Python executables themselves. These files are used to ensure that all Python code and commands are executed within the context of the current environment, which is how the isolation from the global environment is achieved. We’ll explain this in more detail in the next section.

More interesting are the activate scripts in the bin directory. These scripts are used to set up your shell to use the environment’s Python executable and its site-packages by default.

In order to use this environment’s packages/resources in isolation, you need to “activate” it. To do this, just run the following:

$ source env/bin/activate
(env) $

Notice how your prompt is now prefixed with the name of your environment (env, in our case). This is the indicator that env is currently active, which means the python executable will only use this environment’s packages and settings.

To show the package isolation in action, we can use the bcrypt module as an example. Let’s say we have bcrypt installed system-wide but not in our virtual environment.

Before we test this, we need to go back to the “system” context by executing deactivate:

(env) $ deactivate

Now your shell session is back to normal, and the python command refers to the global Python install. Remember to do this whenever you’re done using a specific virtual environment.

Now, install bcrypt and use it to hash a password:

$ pip -q install bcrypt
$ python -c "import bcrypt; print(bcrypt.hashpw('password'.encode('utf-8'), bcrypt.gensalt()))"

Here’s what happens if we try the same command when the virtual environment is activated:

$ source env/bin/activate
(env) $ python -c "import bcrypt; print(bcrypt.hashpw('password'.encode('utf-8'), bcrypt.gensalt()))"
Traceback (most recent call last):
  File "<string>", line 1, in <module>
ImportError: No module named 'bcrypt'

As you can see, the behavior of the python -c "import bcrypt..." command changes after the source env/bin/activate call.

In one instance, we have bcrypt available to us, and in the next we don’t. This is the kind of separation we’re looking to achieve with virtual environments, which is now easily achieved.


To explain how this works, let’s first check out the locations of the different python executables. With the environment “deactivated,” run the following:

$ which python

Now, activate it and run the command again:

$ source env/bin/activate
(env) $ which python

After activating the environment, we’re now getting a different path for the python executable because, in an active environment, the $PATH environment variable is slightly modified.

Notice the difference between the first path in $PATH before and after the activation:

$ echo $PATH

$ source env/bin/activate
(env) $ echo $PATH

In the latter example, our virtual environment’s bin directory is now at the beginning of the path. That means it’s the first directory searched when running an executable on the command line. Thus, the shell uses our virtual environment’s instance of Python instead of the system-wide version.

The commands to check CentOS version

The following table contains most common and recommended ways on how to check CentOS version on your CentOS Linux server or desktop.

$ rpm -q centos-releaseCentOS version valid for CentOS 6 and higher. Causes to reveal major, minor and asynchronous CentOS version.
$ lsb_release -dRequires redhat-lsb package to be installed before execution.
$ rpm -E %{rhel}RPM macro to reveal a major CentOS version
$ rpm –eval %{centos_ver}RPM macro to display a major version of CentOS
$ cat /etc/centos-releaseLinux cat command to output content of the /etc/centos-release to query CentOS version. Works with CentOS 6 and higher.

In case the above-provided commands did not help you to obtain the CentOS version number you may try the following alternative commands.

Although available only for CentOS version 7 and above the hostnamectl command might provide you with a significant clue about your OS version number:

$ hostnamectl 
   Static hostname: localhost.localdomain
         Icon name: computer-vm
           Chassis: vm
        Machine ID: fe069af6a1764e07be909d7cf64add99
           Boot ID: b81bb73dc549484c8927e830e149eb55
    Virtualization: kvm
  Operating System: CentOS Linux 7 (Core)
       CPE OS Name: cpe:/o:centos:centos:7
            Kernel: Linux 3.10.0-862.6.3.el7.x86_64
      Architecture: x86-64

For more answers try to query all release files within the /etc directory:

$ cat /etc/*elease
CentOS Linux release 7.5.1804 (Core) 
NAME="CentOS Linux"
VERSION="7 (Core)"
ID_LIKE="rhel fedora"
PRETTY_NAME="CentOS Linux 7 (Core)"


CentOS Linux release 7.5.1804 (Core) 
CentOS Linux release 7.5.1804 (Core)

Bash Script to check CentOS version

The following bash script can be used to obtain the CentOS version number given that the /etc/centos-release file exists and is populated.

The below script serves as an example, feel free to modify wherever appropriate. For more information about Bash Scripting visit our bash scripting tutorial:


full=`cat /etc/centos-release | tr -dc '0-9.'`
major=$(cat /etc/centos-release | tr -dc '0-9.'|cut -d \. -f1)
minor=$(cat /etc/centos-release | tr -dc '0-9.'|cut -d \. -f2)
asynchronous=$(cat /etc/centos-release | tr -dc '0-9.'|cut -d \. -f3)

echo CentOS Version: $full
echo Major Relase: $major
echo Minor Relase: $minor
echo Asynchronous Relase: $asynchronous


$ ./ 
CentOS Version: 7.5.1804
Major Relase: 7
Minor Relase: 5
Asynchronous Relase: 1804

Python program to check CentOS version

The following python script will output the distribution name along with the OS version number:


import platform
print platform.linux_distribution()

Alternatively, one can execute python code directly from the shell:

$ python -c 'import platform; print platform.linux_distribution()'


$ python 
('CentOS Linux', '7.5.1804', 'Core')