Configuring CentOS 6 Web Server

by on May 9, 2012 at 7:07 pm

Centos 6 in 3DIn this article, I’m going to be outlining the steps to install and configure a complete web server on a base install of CentOS 6.  (Which should be compatible with Scientific Linux 6 as well as Red Hat Enterprise Linux 6)

I personally don’t prefer to install package groups relating to “LAMP” or similar during initial installation because I’m simply too lazy to review each and every package that is included in those groups, and what the dependencies are. By installing the required packages using yum, this allows you to install just the software you’re looking for, without worrying about dependencies. This software stack is time tested; we’ll install on CentOS’s latest release, and test a few popular applications while we’re at it!

For a more in-depth covering of Apache, php, and MySQL, see my previous post about setting up a web server in Ubuntu 12.04; in this guide, I’m going to focus on CentOS / Red Hat specific requirements to get your server up and running in no time.


A newly installed CentOS 6 (or similar distro) with absolute minimum base install (we like a challenge!).

Internet connection, or at least a connection to a local repository.

Your command-line A-game.

Tasks to completion:

The minimal install in CentOS is very bare, includes some things other distros don’t, and doesn’t include some things other distros do.

Create new administrative user and add that user to sudoers.

Configure ssh settings.

Configure iptables.

Configure network settings. (because by default, you’ll have no network connection!)

Install web server packages: <packages here>

Configure selinux contexts.  (Don’t be scared, it’s easy!)

 Step 1: Create administrative user

For security reasons, it’s not desirable to log in directly as root.  By default, root is the only account created during a minimal install of CentOS, therefore we must create a new administrative account.

First, log in as root via the terminal.  Now, let’s create a new user (the user name can be whatever you wish).

 useradd webadmin

When you run cat /etc/passwd your output  show contain the following at the bottom.


Set the password for that user as follows:

 passwd webadmin

Followed by entering the password at the prompt (your text will be hidden).

 Step 2:  Add user to sudoers

sudo should be installed by default on CentOS 6, but there will be no users (other than root) configured.  Let’s edit the sudoers file using the command “visudo”  This will launch a special vi/vim editor that allows you to add users.  Locate the following line:

 root   ALL=(ALL)     ALL

Now, copy that line, and change ‘root’ to your new user’s name, in our case webadmin.  Save and exit the program.

Let’s test this user’s permissions in another terminal, by pressing alt+f2;  Log in and use sudo as normal.  Everything should work without error.  If everything is working, log out, switch back to tty1, log out of root, and log in as the newly created user.

Step 3:  Configure sshd

We’re going to prevent root from accessing the system via ssh.  This is a best-practice in Linux security, and while completely optional, is highly recommended.

Add the following lines to the file /etc/ssh/sshd_config

DenyUsers root
DenyGroups root

Then restart sshd.

We don’t have networking up yet, and ssh client isn’t installed on the local system, so we won’t be able to test this just yet.  After you have set up networking in the steps below, try to ssh in as webadmin (or the user you created); it should work just fine. Now try as root, you should get an error about the wrong username / password.  Another option is to white-list which users can log in by adding:  AllowUsers <username> though blocking root is adequate for most situations.

 Step 4: Configure iptables

Unlike other distros, such as Debian and Ubuntu, CentOS has iptables rules and policies in place from the start.  If your system is going to be sitting behind a properly configured firewall, then it’s safe (and quite common) to disable iptables all together with the following command:

## first, let\'s save a copy in case we change our minds later
iptables-save > /root/default.iptables
## only perform this step if you don\'t want to use iptables (not recommended)
iptables -F
## make these rules (or lack thereof) persistent (will survive reboot)
/etc/init.d/iptables save

However, we’re going to assume you want iptables to be fully configured, and only white-listed traffic will be getting through.

First, if you’re administering this system remotely, you need to allow for ssh, otherwise you’ll lose your connection and lock yourself out of your system:

iptables -A INPUT -s your-ip-here -j ACCEPT
iptables -A OUTPUT -p tcp -m tcp --sport 22 -j ACCEPT

Keep in mind your settings may vary; this will leave open all inbound ports for your desktop/network’s IP, and allow ssh traffic out of the firewall.

Next, I like to completely lock the system down by setting the default policy to DROP.  Anything that does not match an ACCEPT rule will be dropped.

iptables -P INPUT DROP
iptables -P FORWARD DROP
iptables -P OUTPUT DROP

Now that the system is locked down, let’s go ahead and open up our ports.

iptables -A INPUT -p tcp -m tcp --dport 80 -j ACCEPT
iptables -A INPUT -p tcp -m tcp --dport 443 -j ACCEPT
iptables -A OUTPUT -p tcp -m tcp --sport 80 -j ACCEPT
iptables -A OUTPUT -p tcp -m tcp --sport 443 -j ACCEPT

That’s it.  Let’s go ahead and save our configuration, as well as make a backup copy of our rules in case we overwrite what we’ve done at a later date, and need to fall back.

service iptables save
iptables-save > /root/iptables.saved

Step 5: Configure network settings

You may be asking yourself why you have no network connectivity after installation.  I join you in this questioning; I’m sure someone, somewhere decided that this was the best approach to take.  This is a minimum-install we’re working with, after all.

If you have jumped the gun, and ran ifconfig eth0  I applaud your efforts; however if simple command was adequate you wouldn’t be reading this section right now, would you?  Anyway..

CentOS and related distros store a lot of system configuration settings in the /etc/sysconfig directory.  We’re going to make a few changes.

First, we want to set our system’s hostname .  Edit the file /etc/sysconfig/network .  This file should be self explanatory, changes to hostname will take effect after system reboot.

Next, we want to  configure our primary network interface.  On 99% of systems, this will be called eth0.  If you want to see what network adapters were found during system boot, run the command: ifconfig -a

We’re going to assume eth0 is the adapter in question.   If this is the case, there should be a corresponding configuration file: /etc/sysconfig/network-scripts/ifcfg-eth0 .  Edit this file, adding or changing entries as follows (leave everything else in the file intact, including the HWADDR entry):


## all IPs given are for illustrative purposes.  Use your own as appropriate.



Now, restart networking: service network restart

Next: ifup eth0

If everything went correctly, you should now have network connectivity.  If you selected are getting your IP from dhcp, ifconfig should now show an IP for the adapter eth0.

 Step 6: Install web server packages

Okay, with the above setup, you’re clear to start installing packages.  I highly recommend running yum update before continuing.  It’s important to keep your system’s security patches up to date.

 yum install httpd php mysql-server php-mysql

Unlike Debian and Ubuntu, apache is not automatically started after installation on CentOS 6.

Before starting httpd (apache), peform the following:

chown apache:apache /var/www/html -R
chcon -R -u system_u -t httpd_sys_content_t -r object_r /var/www/html

Now, start apache, MySQL, and configure them to turn on at system boot:

service httpd start
service mysqld start
chkconfig httpd on
chkconfig mysqld on

We can create a “hello world” style index.php file in the /var/www/html directory to test our server.  Remember, each new file that is created or moved into /var/www needs to have the appropriate SElinux context set.

In-depth  reference for apache+SELinux:

Also be sure to check out man httpd_selinux for more SELinux contexts that might suite your specific needs.

 Important config file locations:

Apache/httpd:    /etc/httpd/conf/httpd.conf

php:    /etc/php.ini 

MySQL:    /etc/my.cnf

, , , , , , , , , , , , , , , ,

You can skip to the end and leave a response. Pinging is currently not allowed.

  • Jared Coal

    most helpful, thanks for the tutorial

  • http://localhost Jay Ell III

    Definately very helpful. Thank you very much!

  • EdUp

    Great tutorial. Thanks.

    Which one is better, “permitRootLogin no” OR “DenyUsers root
    DenyGroups root” ?


    • Mike

      Honestly, I didn’t know permitRootLogin was an option. I know that DenyUsers root works well for me!

  • Tony C

    Great guide, thank you. Just one question what would you recommend if you are ssh’ing from a dynamic range of ip addresses?

    • Mike

      There’s more than one way to go about this, but one easy way is to goto (your IP will be at the very top). Punch that IP into the search field in Next, it will tell you your ISP Range. Use the info from the CIDR row to create your rule. That will allow you to connect on any IP that your ISP may be providing to you, as your block is not generally going to change.

  • Ryan

    Useful stuff, thank you!

  • Lambert

    Very detail, like it a lot.
    Thanks for sharing.

  • Willydddddddddwww

    value static doesn’t present in documentation

  • jason

    great article

  • D1mOs

    Useful stuff, but could you explain the necessity of the following lines ??

    chown apache:apache /var/www/html -R
    chcon -R -u system_u -t httpd_sys_content_t -r object_r /var/www/html

    • Mike

      Certain files have to be writeable in order for WordPress to install and operate successfully, thus chown. Some people will tell you not to do this for one reason or another. The alternative is making certain files and directories within your document root world-writeable. Since SELinux is in enforcing mode in this tutorial, httpd is a targeted service. This means the httpd process can only access files with the appropriate file context, which brings us to the chcon command. Sometimes when files are copied or moved (I cannot remember which) from one directory to another, the wrong SELinux file context is applied. Using the chcon command as described above will temporarily relabel those file contexts. You could also run restorecon in a similar manner to restore default file contexts for the /var/www directory (which is probably the more correct way of doing it, but I didn’t know about the restorecon command at the time).

  • Bodhisatwa Ghosh

    Sorry the “visudo” method you have mentioned over here did not work for me. I followed that but after I tried to do sudo from the webadmin user, I go this error

    webmin is not allowed to run sudo on localhost. This incident will be reported.

    Then after some searching I got another command and it worked for me.

    echo ‘weadmin ALL=(ALL) ALL’ >> /etc/sudoers

    Can you please explain me what happened. I am not very familiar with linux. Please help.

    Thanks & Regards,

    • Mike

      Hi Bodhi. You have to run the visudo command as root.
      Perhaps you did not save the file correctly upon exit.

      • Bodhisatwa Ghosh

        Hi Mike,

        I did run the visudo as root. I also opened the filed later and saw that the lines are already there as I have saved last time. :(

        • Mike

          I’m not sure why you are having this problem if you performed the steps as you said. I have used visudo for years. There must be something you’re missing :/

  • Bodhisatwa Ghosh

    Hi Mike,

    I am facing 2 issues regarding this configuration,

    1) After configuring the iptables, in the last step, the command
    iptables-save > /root/iptables.saved
    did not work, it gave me, Permission Denied. I had to login as root and do it as root. But I used sudo in all the last configuration which worked fine except this last one.

    2) I was trying to load the the webserver from another machine in the LAN with the IP is my ssh IP too) and my webserver’s IP is by typing in the address bar of the browser. But it does not load the default Apache page. But when I stop the iptables using
    sudo service iptables stop
    it loads perfectly but starting the service iptables with
    sudo service iptables start
    again stops the page from loading. I am using Centos 6.3. Please help

    Thanks & Regards,

    • Mike

      Most of my tutorials assume you are logged in as root. You can save the iptables-save output command to any directory of your choosing.
      Make sure you have your port 80 open to incoming connections on the web server. Please see Step 4 for the necessary details.

  • JR

    I’m trying to use your guide. However I’m stuck at step 4.

    iptables-save > /root/default.iptables

    Doesn’t do the trick for me. Im getting an permission denied error. Even when I’m trying to use it with sudo. Could you help me out?

    • Mike

      iptables-save command saves the current config of IP tables to a text file.
      You cannot save to /root/default.iptables by using sudo iptables-save because the redirection is not being executed as su. You must be logged in as root to save the file in /root directory. Alternatively, you can save the output of iptables-save to any location you wish.

  • Bodhisatwa Ghosh

    How to revert back to the default iptables rules if I have saved the default one

    • Mike

      First, I would suggest saving your current config with iptables-save > /some/file as before.
      Then, you just run iptables-restore < /root/iptables.out
      Don’t forget to use service iptables save to ensure your changes survive a reboot.

  • Karl

    Hi, thank you so much for your tutorial! II thought I followed along exactly, but II am having problems accessing thee machine when iptables is started. When I turn it off, no problem, I get the default page.

    I was wonderiing if you could take a look and tell me if you see any glaring mistakes in my iptables configuration:

    Chain INPUT (policy DROP)
    target prot opt source destination
    ACCEPT all — anywhere anywhere state RELATED,ESTABLISHED
    ACCEPT icmp — anywhere anywhere
    ACCEPT all — anywhere anywhere
    ACCEPT tcp — anywhere anywhere state NEW tcp dpt:ssh
    REJECT all — anywhere anywhere reject-with icmp-host-prohibited
    all — anywhere anywhere
    ACCEPT all — anywhere
    ACCEPT tcp — anywhere anywhere tcp dpt:http
    ACCEPT tcp — anywhere anywhere tcp dpt:https
    ACCEPT tcp — anywhere anywhere tcp spt:http
    ACCEPT tcp — anywhere anywhere tcp spt:https

    Chain FORWARD (policy DROP)
    target prot opt source destination
    REJECT all — anywhere anywhere reject-with icmp-host-prohibited

    Chain OUTPUT (policy DROP)
    target prot opt source destination
    ACCEPT tcp — anywhere anywhere tcp spt:ssh

    • Mike

      IPtables work in ‘chains.’ So, when in incoming connection matches a rule on the INPUT column, that rule is immediately applied.
      In your case, the line ‘REJECT all’ is above the ACCPEPT http rules. Since you changed your default policy to drop, this rule is redundant and is also prohibiting any rules being followed below it.

      • Karl

        Thanks, you’re a genius! When I initially entered the rules, it did not accept one of them due to a typo. I went back afterwards and entered it correctly. I never considered that the rules would be applied in the order I entered them. I fixed it and it works now. Thanks again!

  • Bob
  • Francesco

    the way you have configured iptables block dns resolution

    • Mike

      I have not experienced this. I’ll take a look and update the post if necessary.

  • Akash Chauhan

    I’ve tried all what you said but the same error service httpd start Starting httpd: no listening sockets available, shutting down Unable to open logs [FAILED]

    • Mike

      Do you have another process bound to port 80?

      • Arabinda Ghosh

        yes.. That is in port 88

  • Arabinda Ghosh

    My comment is……

    Nothing to say. Its outstanding.

  • Secure Cloud

    I just wanted to reach out and let you know that I included your article “How to set up and secure Apache web server under CentOS” in the InterWorx roundup of April’s best SysAdmin content.

    • Mike

      Thanks, but that is not the title of my article.