RHCE Series: HTTP

Install apache: yum -y install httpd httpd-manual links

The httpd-manual is a great resource for information, but isn’t needed. The links package is needed for the server-status utilities.

First, let’s create our virtual hosts. We’ll need to create our DocumentRoot directories.

[[email protected] ~]# mkdir /var/www/{server1.example.com,vhost.server1.example.com}
[[email protected] ~]# ls /var/www/
cgi-bin  error  html  icons  manual  server1.example.com  vhost.server1.example.com

Next, you’ll need to edit the /etc/httpd/conf/httpd.conf

[[email protected] ~]# cd /etc/httpd/conf
[[email protected] conf]# vim httpd.conf 
[[email protected] conf]# tail httpd.conf 
#
NameVirtualHost *:80

 DocumentRoot /var/www/server1.example.com
 ServerName server1.example.com


 DocumentRoot /var/www/vhost.server1.example.com
 ServerName vhost.server1.example.com

When you enable virtual hosts in apache, the default website in /var/www/html will not work. You will have to add another virtual host if you want to serve content from that directory. In this configuration, apache will intercept the http headers and look at the destination url and direct traffic based upon that information.

Now that the httpd.conf has been modified, we’ll need to restart apache.

[[email protected] ~]# service httpd restart
Stopping httpd:                                            [  OK  ]
Starting httpd:                                            [  OK  ]
[[email protected] ~]# httpd -S
VirtualHost configuration:
wildcard NameVirtualHosts and _default_ servers:
_default_:8443         server1.example.com (/etc/httpd/conf.d/nss.conf:84)
*:80                   is a NameVirtualHost
         default server server1.example.com (/etc/httpd/conf/httpd.conf:1011)
         port 80 namevhost server1.example.com (/etc/httpd/conf/httpd.conf:1011)
         port 80 namevhost vhost.server1.example.com (/etc/httpd/conf/httpd.conf:1015)
Syntax OK
[[email protected] ~]# apachectl status
                                   Not Found

   The requested URL /server-status was not found on this server.

     ----------------------------------------------------------------------

    Apache/2.2.15 (CentOS) Server at localhost Port 80

You’ll notice that you can use the ‘httpd -S’ command to show the virtual hosts residing on the server. Let’s create some content to view in the virtual hosts.

[[email protected] ~]# echo "server1.example.com" > /var/www/server1.example.com/index.htm
[[email protected] ~]# echo "vhost.server1.example.com" > /var/www/vhost.server1.example.com/index.htm

Now, let’s try to view the content.

[[email protected] ~]# ping -c 1 server1.example.com
PING server1.example.com (192.168.1.1) 56(84) bytes of data.
64 bytes from server1.example.com (192.168.1.1): icmp_seq=1 ttl=64 time=0.042 ms

--- server1.example.com ping statistics ---
1 packets transmitted, 1 received, 0% packet loss, time 0ms
rtt min/avg/max/mdev = 0.042/0.042/0.042/0.000 ms
[[email protected] ~]# ping -c 1 vhost.server1.example.com
PING server1.example.com (192.168.1.1) 56(84) bytes of data.
64 bytes from server1.example.com (192.168.1.1): icmp_seq=1 ttl=64 time=0.028 ms

--- server1.example.com ping statistics ---
1 packets transmitted, 1 received, 0% packet loss, time 0ms
rtt min/avg/max/mdev = 0.028/0.028/0.028/0.000 ms
[[email protected] ~]# curl -I server1.example.com
HTTP/1.1 403 Forbidden
Date: Sun, 28 Oct 2012 02:54:16 GMT
Server: Apache/2.2.15 (CentOS)
Accept-Ranges: bytes
Content-Length: 5039
Connection: close
Content-Type: text/html; charset=UTF-8

[[email protected] ~]# curl -I vhost.server1.example.com
HTTP/1.1 403 Forbidden
Date: Sun, 28 Oct 2012 02:54:24 GMT
Server: Apache/2.2.15 (CentOS)
Accept-Ranges: bytes
Content-Length: 5039
Connection: close
Content-Type: text/html; charset=UTF-8

A quick peak at the error_log shows why we can’t view the page(s).

[[email protected] ~]# tail -f /var/log/httpd/error_log 
[Sat Oct 27 21:48:58 2012] [notice] SELinux policy enabled; httpd running as context unconfined_u:system_r:httpd_t:s0
[Sat Oct 27 21:48:58 2012] [notice] suEXEC mechanism enabled (wrapper: /usr/sbin/suexec)
[Sat Oct 27 21:48:58 2012] [notice] Digest: generating secret for digest authentication ...
[Sat Oct 27 21:48:58 2012] [notice] Digest: done
[Sat Oct 27 21:48:59 2012] [notice] Apache/2.2.15 (Unix) DAV/2 mod_nss/2.2.15 NSS/3.13.1.0 Basic ECC configured -- resuming normal operations
[Sat Oct 27 21:49:06 2012] [error] [client 127.0.0.1] File does not exist: /var/www/server1.example.com/server-status
[Sat Oct 27 21:54:16 2012] [error] [client 192.168.1.1] Directory index forbidden by Options directive: /var/www/server1.example.com/
[Sat Oct 27 21:54:24 2012] [error] [client 192.168.1.1] Directory index forbidden by Options directive: /var/www/vhost.server1.example.com/
[Sat Oct 27 21:54:56 2012] [error] [client 192.168.1.1] Directory index forbidden by Options directive: /var/www/server1.example.com/
[Sat Oct 27 21:55:06 2012] [error] [client 192.168.1.1] Directory index forbidden by Options directive: /var/www/vhost.server1.example.com/

Notice, that I labeled the index files index.htm. Be default, index.html and index.html.var are the default index pages AND apache, by default, doesn’t print a directory listing as a default index page if a index.html or index.html.var page doesn’t exist. So, to fix this, I had to add index.htm to the “DirectoryIndex” directive in the httpd.conf

#
# DirectoryIndex: sets the file that Apache will serve if a directory
# is requested.
#
# The index.html.var file (a type-map) is used to deliver content-
# negotiated documents.  The MultiViews Option can be used for the 
# same purpose, but it is much slower.
#
DirectoryIndex index.html index.html.var index.htm

Now, let’s try this again.

[[email protected] ~]# vim /etc/httpd/conf/httpd.conf 
[[email protected] ~]# service httpd restart
Stopping httpd:                                            [  OK  ]
Starting httpd:                                            [  OK  ]
[[email protected] ~]# 
[[email protected] ~]# 
[[email protected] ~]# curl -I server1.example.com
HTTP/1.1 200 OK
Date: Sun, 28 Oct 2012 03:05:43 GMT
Server: Apache/2.2.15 (CentOS)
Last-Modified: Sun, 28 Oct 2012 02:52:13 GMT
ETag: "4d12-14-4cd15a3d274c1"
Accept-Ranges: bytes
Content-Length: 20
Connection: close
Content-Type: text/html; charset=UTF-8

[[email protected] ~]# curl -I vhost.server1.example.com
HTTP/1.1 200 OK
Date: Sun, 28 Oct 2012 03:05:54 GMT
Server: Apache/2.2.15 (CentOS)
Last-Modified: Sun, 28 Oct 2012 02:52:26 GMT
ETag: "4d32-1a-4cd15a49dd342"
Accept-Ranges: bytes
Content-Length: 26
Connection: close
Content-Type: text/html; charset=UTF-8

[[email protected] ~]# curl vhost.server1.example.com
vhost.server1.example.com
[[email protected] ~]# curl server1.example.com
server1.example.com
[[email protected] ~]# ls -Z /var/www/
drwxr-xr-x. root root system_u:object_r:httpd_sys_script_exec_t:s0 cgi-bin
drwxr-xr-x. root root system_u:object_r:httpd_sys_content_t:s0 error
drwxr-xr-x. root root system_u:object_r:httpd_sys_content_t:s0 html
drwxr-xr-x. root root system_u:object_r:httpd_sys_content_t:s0 icons
drwxr-xr-x. root root system_u:object_r:httpd_sys_content_t:s0 manual
drwxr-xr-x. root root unconfined_u:object_r:httpd_sys_content_t:s0 server1.example.com
drwxr-xr-x. root root unconfined_u:object_r:httpd_sys_content_t:s0 vhost.server1.example.com
[[email protected] ~]# ls -Z /var/www/*example.com/
/var/www/server1.example.com/:
-rw-r--r--. root root unconfined_u:object_r:httpd_sys_content_t:s0 index.htm

/var/www/vhost.server1.example.com/:
-rw-r--r--. root root unconfined_u:object_r:httpd_sys_content_t:s0 index.htm

Now, the sites are working. So, let’s go on to the next objective of configuring private directories.

We’ll set up vhost.server1.example.com to create a private directory with.

[[email protected] ~]# htpasswd -cm /var/www/vhost.server1.example.com/.htpasswd james
New password: 
Re-type new password: 
Adding password for user james
[[email protected] ~]# cat /var/www/vhost.server1.example.com/.htpasswd 
james:$apr1$dTUr3R1T$l77COVCwfP0ZKoF05Vq081
[[email protected] ~]# vim /etc/httpd/conf/httpd.conf 
[[email protected] ~]# tail -6 /etc/httpd/conf/httpd.conf 

 AuthType Basic
 AuthName "Private"
 AuthUserFile /var/www/vhost.server1.example.com/.htpasswd
 Require valid-user

[[email protected] ~]# service httpd restart
Stopping httpd:                                            [  OK  ]
Starting httpd:                                            [  OK  ]
[[email protected] ~]# curl -I vhost.server1.example.com
HTTP/1.1 401 Authorization Required
Date: Sun, 28 Oct 2012 03:42:59 GMT
Server: Apache/2.2.15 (CentOS)
WWW-Authenticate: Basic realm="Private"
Connection: close
Content-Type: text/html; charset=iso-8859-1

[[email protected] ~]# curl --user james:testuser vhost.server1.example.com
vhost.server1.example.com

Now, let’s go ahead and set up group managed content, then we’ll deploy a cgi application.

[[email protected] ~]# echo "sysadmin: james user1 user2" > /var/www/vhost.server1.example.com/.htgroup 
[[email protected] ~]# cat /var/www/vhost.server1.example.com/.htgroup 
sysadmin: james user1 user2
[[email protected] ~]# vim /etc/httpd/conf/httpd.conf 
[[email protected] ~]# tail -7 /etc/httpd/conf/httpd.conf 

 AuthType Basic
 AuthName "Private"
 AuthUserFile /var/www/vhost.server1.example.com/.htpasswd
 AuthGroupFile /var/www/vhost.server1.example.com/.htgroup
 Require group sysadmin

[[email protected] ~]# service httpd restart
Stopping httpd:                                            [  OK  ]
Starting httpd:                                            [  OK  ]
[[email protected] ~]# curl -I vhost.server1.example.com
HTTP/1.1 401 Authorization Required
Date: Sun, 28 Oct 2012 03:49:50 GMT
Server: Apache/2.2.15 (CentOS)
WWW-Authenticate: Basic realm="Private"
Connection: close
Content-Type: text/html; charset=iso-8859-1

[[email protected] ~]# curl --user james:testuser vhost.server1.example.com
vhost.server1.example.com

This time, the user ‘james’ was allowed because the user was in the ‘sysadmin’ group. Now the cgi application.

[[email protected] ~]# vim /var/www/cgi-bin/hello.cgi
[[email protected] ~]# chmod +x /var/www/cgi-bin/hello.cgi 
[[email protected] ~]# cat /var/www/cgi-bin/hello.cgi 
#!/usr/bin/perl

print "Content-type: text/html\r\n\n";

print "Hello!\n";
[[email protected] ~]# curl -I server1.example.com/cgi-bin/hello.cgi
HTTP/1.1 200 OK
Date: Sun, 28 Oct 2012 04:01:36 GMT
Server: Apache/2.2.15 (CentOS)
Connection: close
Content-Type: text/html; charset=UTF-8

[[email protected] ~]# curl server1.example.com/cgi-bin/hello.cgi
Hello!

The last and final objective, though not on the RHCE offical list, it’s a useful tool for working with httpd servers. Setting up the server-status tool.

First, you’ll need to edit the httpd.conf.

#
# Allow server status reports generated by mod_status,
# with the URL of http://servername/server-status
# Change the ".example.com" to match your domain to enable.
#
ExtendedStatus On

    SetHandler server-status
    Order deny,allow
    Deny from all
    Allow from 127.0.0.1 

[[email protected] ~]# service httpd restart
Stopping httpd:                                            [  OK  ]
Starting httpd:                                            [  OK  ]
[[email protected] ~]# apachectl fullstatus
                       Apache Server Status for localhost

   Server Version: Apache/2.2.15 (Unix) DAV/2 mod_nss/2.2.15 NSS/3.13.1.0
   Basic ECC

   Server Built: Feb 13 2012 22:31:42

     ----------------------------------------------------------------------

   Current Time: Saturday, 27-Oct-2012 23:07:09 CDT

   Restart Time: Saturday, 27-Oct-2012 23:06:51 CDT

   Parent Server Generation: 0

   Server uptime: 18 seconds

   Total accesses: 1 - Total Traffic: 2 kB

   CPU Usage: u.08 s.01 cu0 cs0 - .5% CPU load

   .0556 requests/sec - 113 B/second - 2048 B/request

   1 requests currently being processed, 7 idle workers

 __W_____........................................................
 ................................................................
 ................................................................
 ................................................................

   Scoreboard Key:
   "_" Waiting for Connection, "S" Starting up, "R" Reading Request,
   "W" Sending Reply, "K" Keepalive (read), "D" DNS Lookup,
   "C" Closing connection, "L" Logging, "G" Gracefully finishing,
   "I" Idle cleanup of worker, "." Open slot with no current process

Srv PID   Acc  M CPU  SS Req Conn Child Slot  Client          VHost           Request     
                                                                           GET            
0-0 3474 0/1/1 _ 0.09 4  5   0.0  0.00  0.00 127.0.0.1 server1.example.com /server-status 
                                                                           HTTP/1.1       
                                                                           GET            
2-0 3476 0/0/0 W 0.00 0  0   0.0  0.00  0.00 127.0.0.1 server1.example.com /server-status 
                                                                           HTTP/1.1       

     ----------------------------------------------------------------------

    Srv  Child Server number - generation                            
    PID  OS process ID                                               
    Acc  Number of accesses this connection / this child / this slot 
     M   Mode of operation                                           
    CPU  CPU usage, number of seconds                                
    SS   Seconds since beginning of most recent request              
    Req  Milliseconds required to process most recent request        
   Conn  Kilobytes transferred this connection                       
   Child Megabytes transferred this child                            
   Slot  Total megabytes transferred this slot                       

     ----------------------------------------------------------------------

    Apache/2.2.15 (CentOS) Server at localhost Port 80


You can use apachectl status|fullstatus to get real time statistics of the web server utilization.