Configuring CentOS 6 Web Server
27
In 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!
Foundations of CentOS Linux: Enterprise Linux On the Cheap (Books for Professionals by Professionals)
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.
Requirements:
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.
webadmin:x:500:500::/home/webadmin:/bin/bash
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 <strong>your-ip-here</strong> -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):
Static
## all IPs given are for illustrative purposes. Use your own as appropriate. BOOTPROTO="static" BROADCAST="192.168.1.255" DNS1="192.168.1.1" GATEWAY="192.168.1.1" IPADDR="192.168.1.50" NETMASK="255.255.255.0" NM_CONTROLLED="yes" ONBOOT="yes"
Dynamic
BOOTPROTO="dhcp" ONBOOT="yes" NM_CONTROLLED="yes"
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: http://publib.boulder.ibm.com/infocenter/lnxinfo/v3r0m0/index.jsp?topic=%2Fliaai%2Fselinux%2Fliaaiselinuxapache.htm
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.

most helpful, thanks for the tutorial
Definately very helpful. Thank you very much!
Great tutorial. Thanks.
Which one is better, “permitRootLogin no” OR “DenyUsers root
DenyGroups root” ?
Thanks
Honestly, I didn’t know permitRootLogin was an option. I know that DenyUsers root works well for me!
Great guide, thank you. Just one question what would you recommend if you are ssh’ing from a dynamic range of ip addresses?
There’s more than one way to go about this, but one easy way is to goto http://www.whatsmyip.org/ (your IP will be at the very top). Punch that IP into the search field in http://whois.arin.net/ 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.
Useful stuff, thank you!
Very detail, like it a lot.
Thanks for sharing.
BOOTPROTO=none|bootp|dhcp
value static doesn’t present in documentation
Please check: https://access.redhat.com/knowledge/docs/en-US/Red_Hat_Enterprise_Linux/5/html/Installation_Guide/s1-s390info-addnetdevice.html
BOOTPROTO=static is indeed valid in RHEL and CentOS
great article
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
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).
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,
Bodhi
Hi Bodhi. You have to run the visudo command as root.
Perhaps you did not save the file correctly upon exit.
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.
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 :/
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 192.168.1.2(this is my ssh IP too) and my webserver’s IP is 192.168.1.254 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,
Bodhi
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.
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?
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.
How to revert back to the default iptables rules if I have saved the default one
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.
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 — 192.168.1.128 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
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.
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!
Nice article, check this also
http://kfromscratch.blogspot.com/2013/03/how-to-install-lamp-server-on-centos.html