Apache Web Server "how to"



Home


When you decide to setup a web server you will find that Apache is one of the most widely used servers on the Internet. It serves the majority of the web because it is powerful and flexible, being able to accommodate many different configurations. it is also open source so the code can be changed or modified without contacting the authors for a "hot fix."

Lets take a look at a sample Apache webserver. It will server up your pages from the document root. We are going to also install some security modules like mod_evasive and mod_security to protect our server from the Internet hordes.

We are going to build is a web cluster front end using Apache v2.2.



Looking at the httpd.conf

Below you will find the link to the Apache server example config file and below that is the same httpd.conf file in a text box. Both formats are available to make it easier for you to review the code. This example is a fully working config file with the exception of setting up a few variables for your environment. The config file is fully commented.

You can download the http.conf here by doing a "save as" or just clicking on the link and choosing download. Before using the config file take a look it below or download it and look at the options.

apache server httpd config file

#######################################################
###  Calomel.org  server httpd.conf   BEGIN
#######################################################
#
# ServerRoot: The top of the directory tree under which the server's
# configuration, error, and log files are kept.
#
# Do not add a slash at the end of the directory path.  If you point
# ServerRoot at a non-local disk, be sure to point the LockFile directive
# at a local disk.  If you wish to share the same ServerRoot for multiple
# httpd daemons, you will need to change at least LockFile and PidFile.
#
ServerRoot "/usr/local/apache2"

#
# Listen: Allows you to bind Apache to specific IP addresses and/or
# ports, instead of the default. See also the 
# directive.
#
# Change this to Listen on specific IP addresses as shown below to 
# prevent Apache from glomming onto all bound IP addresses.
#
Listen 80

#
# Dynamic Shared Object (DSO) Support
#
# To be able to use the functionality of a module which was built as a DSO you
# have to place corresponding `LoadModule' lines at this location so the
# directives contained in it are actually available _before_ they are used.
# Statically compiled modules (those listed by `httpd -l') do not need
# to be loaded here.
#
LoadFile /usr/lib/libxml2.so
LoadModule evasive20_module modules/mod_evasive20.so
LoadModule security2_module modules/mod_security2.so
#


#
# If you wish httpd to run as a different user or group, you must run
# httpd as root initially and it will switch.  
#
# User/Group: The name (or #number) of the user/group to run httpd as.
# It is usually good practice to create a dedicated user and group for
# running httpd, as with most system services.
#
User web_daemon
Group web_daemon


# 'Main' server configuration
#
# The directives in this section set up the values used by the 'main'
# server, which responds to any requests that aren't handled by a
#  definition.  These values also provide defaults for
# any  containers you may define later in the file.
#
# All of these directives may appear inside  containers,
# in which case these default settings will be overridden for the
# virtual host being defined.
#
# ServerAdmin: Your address, where problems with the server should be
# e-mailed.  This address appears on some server-generated pages, such
# as error documents.  e.g. admin@your-domain.com
#
ServerAdmin webmaster@your_hostname.com

#
# ServerName gives the name and port that the server uses to identify itself.
# This can often be determined automatically, but we recommend you specify
# it explicitly to prevent problems during startup.
#
# If your host doesn't have a registered DNS name, enter its IP address here.
#
ServerName your_hostname.com:80

# Timeout: The number of seconds before the daemon receives a request, does not
# get an answer and sends time out.
Timeout 180

##################################################################
#
# Client to server request limitations
LimitRequestBody 102400
LimitRequestFields 40
LimitRequestFieldsize 1000
LimitRequestLine 1000

##################################################################
#
# Mod_Rewrite limits on acceptable characters
RewriteEngine on
RewriteLog /usr/local/apache2/logs/mod_rewrite.log
RewriteLogLevel 0
RewriteRule [^a-zA-Z0-9|\.|/|_|-]  -  [F]
 
##################################################################
#
# Mod_evasive to avoid DDOS
DOSWhitelist 10.10.10.2
DOSLogDir "/usr/local/apache2/logs/mod_evasive.log"

    DOSHashTableSize    314739
    DOSPageCount        2
    DOSPageInterval     1
    DOSSiteCount        30
    DOSSiteInterval     1
    DOSBlockingPeriod   30


##################################################################
#
# Mod_Security settings
Include conf/modsecurity/*.conf
SecAuditLog /usr/local/apache2/logs/modsec_security.log
SecServerSignature your_hostname.com

##################################################################
#
# Mod_Expires to tell clients to cache files 
ExpiresActive On
ExpiresDefault "access plus 2 hours"

##################################################################

#
# EnableMMAP and EnableSendfile: On systems that support it, 
# memory-mapping or the sendfile syscall is used to deliver
# files.  This usually improves server performance, but must
# be turned off when serving from networked-mounted 
# filesystems or if support for these functions is otherwise
# broken on your system.
#
EnableMMAP on
EnableSendfile on

#
# ErrorLog: The location of the error log file.
# If you do not specify an ErrorLog directive within a 
# container, error messages relating to that virtual host will be
# logged here.  If you *do* define an error logfile for a 
# container, that host's errors will be logged there and not here.
#
ErrorLog logs/error_log
## Send the error logs to a remote log server
#ErrorLog syslog:local6

#
# LogLevel: Control the number of messages logged to the error_log.
# Possible values include: debug, info, notice, warn, error, crit,
# alert, emerg.
#
#LogLevel debug
LogLevel notice


    #
    # The following directives define some format nicknames for use with
    # a CustomLog directive (see below).
    #
    LogFormat "%h %l %u %t \"%r\" %>s %b \"%{Referer}i\" \"%{User-Agent}i\"" combined
    LogFormat "%h %l %u %t \"%r\" %>s %b" common

    
      # You need to enable mod_logio.c to use %I and %O
      LogFormat "%h %l %u %t \"%r\" %>s %b \"%{Referer}i\" \"%{User-Agent}i\" %I %O" combinedio
    

    #
    # The location and format of the access logfile (Common Logfile Format).
    # If you do not define any access logfiles within a 
    # container, they will be logged here.  Contrariwise, if you *do*
    # define per- access logfiles, transactions will be
    # logged therein and *not* in this file.
    #
    CustomLog logs/access_log combined
    ## Send the access logs to a remote log server
    #CustomLog "|/usr/bin/logger -p local6.info" combined

    #
    # If you prefer a logfile with access, agent, and referer information
    # (Combined Logfile Format) you can use the following directive.
    #
    #CustomLog logs/access_log combined


#
# Customizable error responses come in three flavors:
# 1) plain text 2) local redirects 3) external redirects
# NOTE: using streight text is small and efficient.
#
ErrorDocument 505 "your_custom_error_message_here"
ErrorDocument 504 "your_custom_error_message_here"
ErrorDocument 503 "your_custom_error_message_here"
ErrorDocument 502 "your_custom_error_message_here"
ErrorDocument 501 "your_custom_error_message_here"
ErrorDocument 500 "your_custom_error_message_here"
ErrorDocument 417 "your_custom_error_message_here"
ErrorDocument 416 "your_custom_error_message_here"
ErrorDocument 415 "your_custom_error_message_here"
ErrorDocument 414 "your_custom_error_message_here"
ErrorDocument 413 "your_custom_error_message_here"
ErrorDocument 412 "your_custom_error_message_here"
ErrorDocument 411 "your_custom_error_message_here"
ErrorDocument 410 "your_custom_error_message_here"
ErrorDocument 409 "your_custom_error_message_here"
ErrorDocument 408 "your_custom_error_message_here"
ErrorDocument 407 "your_custom_error_message_here"
ErrorDocument 406 "your_custom_error_message_here"
ErrorDocument 405 "your_custom_error_message_here"
ErrorDocument 404 "your_custom_error_message_here"
ErrorDocument 403 "your_custom_error_message_here"
ErrorDocument 402 "your_custom_error_message_here"
ErrorDocument 401 "your_custom_error_message_here"
ErrorDocument 400 "your_custom_error_message_here"
#
## Other example error pages
#ErrorDocument 500 "The server has made a mistake."
#ErrorDocument 404 /missing.html
#ErrorDocument 404 "/cgi-bin/missing_handler.pl"
#ErrorDocument 402 http://www.example.com/subscription_info.html
#
#######################################################
###  Calomel.org server  httpd.conf   END
#######################################################


Building the binaries

First, we need to install the following packages from source: Apache 2.2 or higher, mod_security, and mod_evasive. We will be building from source because we can setup exactly what we need and no more. There is no need for most of the packages or modules Apache comes with to be installed on our server. Let's keep it to a minimum.

The packages will be installed into the default directory /usr/local/apache2/ . The config files are in /usr/local/apache2/conf and the logs are in /usr/local/apache2/logs .

To build Apache 2.2 from source make a working directory any where you want and download the source to that directory. Untar the package and change to the untared directory. Execute the following line to make Apache with the modules we need for the server. The install will be put into /usr/local/apache2/

This line will:

killall httpd;rm -rf /usr/local/apache2/bin;make clean; ./configure --disable-cgi --disable-negotiation --disable-autoindex --disable-status --disable-userdir --enable-rewrite --enable-unique-id --enable-expires && make && make install

For security and to reduce the change that a DDOS will affect our new server we are going to also install a the modules mod_evasive and mod_security.

To build mod_evasive download the latest source code here and put it into the working directory. Untar the package and execute the following line to build it. Copy the mod_evasive20.so file to the apache2 modules directory /usr/local/apache2/modules/

/usr/local/apache2/bin/apxs -i -a -c mod_evasive20.c

To build mod_security download the latest source code here and put it into the working directory. Untar the package and execute the following line to build it. Copy the mod_security2.so file to the apache2 modules directory /usr/local/apache2/modules/

make && make install



Need help setting up an Apache reverse proxy in front of a cluster? Make sure to check out the Apache Cluster Reverse Proxy.



Editing the httpd.conf

Now that the install is finished and the security modules are built and copied to the correct directory, it is time to download the config file httpd.conf from above. Save the calomel.org httpd.conf file to /usr/local/apache2/conf/httpd.conf . It is time to take a look at some of the directives that need your attention.

The "user" and "group" need to be a valid non-privileged user. You may want to avoid using generic system users like "nobody" "or daemon" and make your own user. For the example we used "web_daemon".

Check the ServerName and ServerAdmin directives to make sure they reflect the name of your server and the contact information in case someone has any problems.

The settings for Mod_evasive are to avoid DDOS attacks. The directive DOSWhitelist can be a single ip or network you wish to exclude like a local LAN from the evasive limitations.

The Mod_Security settings set the directory where the default security rules can be found and you need to make sure the directive SecServerSignature is set to your hostname.

Mod_Expires to tell clients to cache files so you can save bandwidth. If a client is going from one page to another on your site. You can ask them to keep a cached copy of objects like pictures and buttons so they do not download the same data over and over again.

Customizable error responses allow you to customize how a remote client is treated when they encounter an error. Here you can specify a 1) plain text, 2) local redirects or 3) external redirects to help error-ed clients find your content. In the example we set all errors to the simple text string "your_custom_error_message_here".



Want more speed? Make sure to also check out the Network Speed and Performance Guide. With a little time and understanding you could easily double your firewall's throughput.



Starting the server

The last step is to make sure the server will start without error. The following will start, stop or do a graceful restart of the apache server:

/usr/local/apache2/bin/apachectl -k start
/usr/local/apache2/bin/apachectl -k stop
/usr/local/apache2/bin/apachectl -k graceful

If you get an error make sure to check the access_log and error_log in the /usr/local/apache2/log/ directory. All of the modules that we built will also log to the same directory.



SECURITY NOTE: We highly recommend using a reverse proxy like Pound to front end your web servers. Pound offers an added layer of security and can be used to filter most malicious requests from ever hitting the web server. Use Pound to stop the bad bots and allow your web server to focus on good clients. For a complete explanation and examples check out the Calomel.org Pound reverse proxy "how to".


Questions?

Do you have an Apache log analyzer I can use to send out reports by email?

Yes, we do. Take a look at Apache Log Reporter for apache, lighttpd, and thttpd style logs. It will send a text based report that is less than 2.5 kilobytes and summarizes your web logs for the last few days?

I am interested in setting up a SSL encrypted server (https port 443). Can your help me?

Yes. Please check out our Guide to Webserver SSL Certificates. Setting up SSL through Apache is quite easy. What is most important is understanding how SSL encryption works and what your expectations should be.

How can I test if the server is returning the correct headers?

You can use telnet to connect to port 80 of the web server. Then you can send a request for a GET, HEAD, or POST and see what the server returns. Here we sent a "HEAD / HTTP/1.1" request and we were denied like we were supposed to be.
## Test using telnet
username@machine:~$ telnet your_hostname.com 80 
Trying 10.20.30.40...
Connected to your_hostname.com (10.20.30.40).
Escape character is '^]'.
HEAD / HTTP/1.1

HTTP/1.1 400 Bad Request
Date: Mon, 10 Jan 2010 10:20:30 GMT
Server: your_hostname.com 
Connection: close
Content-Type: text/html; charset=iso-8859-1

Connection closed by foreign host.

How can I see what modules are loaded on my custom built Apache binary?

Using the "-M" argument will show all of the modules statically built into the binary. Your modules may look something like this. If you see a module listed and you do not need it or do not want it then re-build apache with "--disable-" and the name of the module.
[user@webserver ~]# /usr/local/apache2/bin/apachectl -M
Loaded Modules:
 core_module (static)
 authn_file_module (static)
 authn_default_module (static)
 authz_host_module (static)
 authz_groupfile_module (static)
 authz_user_module (static)
 authz_default_module (static)
 auth_basic_module (static)
 include_module (static)
 filter_module (static)
 log_config_module (static)
 env_module (static)
 expires_module (static)
 unique_id_module (static)
 setenvif_module (static)
 mpm_prefork_module (static)
 http_module (static)
 mime_module (static)
 asis_module (static)
 cgi_module (static)
 dir_module (static)
 actions_module (static)
 alias_module (static)
 rewrite_module (static)
 so_module (static)
 perl_module (shared)
 evasive20_module (shared)
 security2_module (shared)
Syntax OK

How do I send the Apache access_log and error_log to a remote log server (loghost) and locally?

Sending all of your logs to an independent and highly secure log server is an excellent way to keep a forensic copy of you logs in case you webserver is compromised. There are four(4) steps, lets get started...

First, edit the apache config file "/usr/local/apache2/conf/httpd.conf" and replace the ErrorLog and CustomLog directives with the following examples. This will send all apache logs to the syslog facility local6.

root@webserver$ vi /usr/local/apache2/conf/httpd.conf

### error_log
 # ErrorLog: The location of the error log file.
 #ErrorLog logs/error_log
  ErrorLog "|/usr/bin/logger -p local6.error"

### access_log
  
   #CustomLog logs/access_log combined
    CustomLog "|/usr/bin/logger -p local6.info" combined
  

Second, edit the syslog config "/etc/syslogd.conf" on the webserver to send all logs tagged as "local6.*" to our log server loghost.domain.lan. We also need to make sure that the web logs do not goto /var/log/messages on the local system. Make sure to add ";local6.!*" to filter the error and access logs from /var/log/messages. Remeber to seperate to seperate your logfacility and log destination with tabs.

root@webserver$ vi /etc/syslogd.conf
  # Log anything (except mail) of level info or higher.
  # Don't log private authentication messages!
  *.info;mail.none;authpriv.none;cron.none;local6.!*      /var/log/messages
  *.info;mail.none;authpriv.none;cron.none;local6.!*      @loghost.domain.lan
  ## Apache logs
  local6.*                                                @loghost.domain.lan
  local6.error                                            /usr/local/apache2/logs/error_log

Third, edit the "/etc/syslog.conf" on the loghost to accept all messages tagged as local6 and save them to the a apache weblogs file.

root@loghost$ vi /etc/syslog.conf
  *.notice;auth,authpriv,cron,ftp,kern,lpr,mail,user.none,local6.!*  /var/log/messages
  ## Apache logging
  local6.*                                                           /var/log/apache_weblogs

The last step is to restart the Apache webserver and the syslogd daemons on both the webserver and the loghost boxes. You should then be able to "tail -f /var/log/apache_weblogs" as see all of the error_log and access_log from your webserver.

If you need to test the logging facility manually you can execute the following:

logger -p local6.crit "Calomel.org remote logging test"





Questions, comments, or suggestions? Contact Calomel.org