Server:apache
From Linux How-To Repository
Contents |
Basic Apache Configuration
Other Resources: Basic Configurations
It all depends on what you want but there are some basics to include in configuration files apache2.conf and httpd.conf.
Enable CGI
In apache2.conf you may need to find the AddHandler section and enable cgi:
# AddHandler allows you to map certain file extensions to "handlers":
# actions unrelated to filetype. These can be either built into the server
# or added with the Action directive (see below)
#
# To use CGI scripts outside of ScriptAliased directories:
# (You will also need to add "ExecCGI" to the "Options" directive.)
#
AddHandler cgi-script .cgi .pl
Configure httpd.conf
Most custom stuff is really best done in the httpd.conf file. Here are a couple of things to include.
# This is so your index pages load automatically
DirectoryIndex index.html index.htm index.shtml index.cgi index.php index.php3 index.pl index.xhtml
#
# The following lines prevent .htaccess and .htpasswd files from being
# viewed by Web clients.
#
<Files ~ "^[\._]ht">
Order allow,deny
Deny from all
Satisfy All
</Files>
<Directory />
AllowOverride None
</Directory>
# Something like this is so you can show your own error pages
<Directory "/home/www">
AllowOverride All
Options -Indexes +Includes
ErrorDocument 403 /403.html
ErrorDocument 404 /404.html
ErrorDocument 500 /500.html
</Directory>
# Something like this prevents access to certain directories
<Directory "/home/www/private_stuff">
Order allow,deny
Allow from all
Options Indexes Includes
AuthType Basic
AuthName "PRIVATE ACCESS"
AuthUserFile "/home/username/.htpassword_file"
require valid-user
</Directory>
# Or, like this
<Directory "/home/www/private_stuff">
Order allow,deny
Deny from all
Allow from 127.0.0.1
</Directory>
Enhanced Logging
Since logging is controlled in apache2.conf, any customizing can be done there. You can find the log section by looking for the following:
ErrorLog /var/log/apache2/error.log # # LogLevel: Control the number of messages logged to the error_log. # Possible values include: debug, info, notice, warn, error, crit, # alert, emerg. # LogLevel warn
I found this wasn't enough for me because I wanted to see a history of web pages being accessed. So, I added a file to /var/logs/apache2 called custom.log, making sure it had the same user:group and permissions as access.log. Then in apache2.conf I put this after the LogLevel section.
# Added to get more verbose logging # just catch everything except images SetEnvIf Request_URI "(\.gif|\.png|\.jpg)$" images CustomLog /var/log/apache2/custom.log common env=!images
The SetenvIf parameter is where you put the things you want to include. Another example is like this:
SetEnvIf Request_URI "(\.html|\.shtml|\.php)$" html
For this to work, you would then put env=html at the end of Customlog. However, what I did is to set an environment to included images, then in the CustomLog, I set the env parameter to exclude all images (with the extensions I had specified). The ! before "images" is equivalent to save "not" or "everything except."
Lastly, I added custom.log to my System Log Viewer and to my Conky output, so that I could see at a glance what was being accessed and when.
Add Virtual Hosts
UPDATE: further below is the old way of doing it. Another way is to put details for each virtual host info (like the details for each host below) in separate files in /etc/apache2/sites-available. The main server info will be in "default." A virtual host's info would be in a file named, for example, www.second_website.com. A link to it would then go in sites-enabled, like this.
sudo ln -s /etc/apache2/sites-available/www.second_site.com /etc/apache2/sites-enabled/www.second_site.com
Note that this file would not have "NameVirtualHost" at the top. That only goes in "default".
I prefer this way of keeping everything in separate files now. But there is the old way of adding virtual hosts to httpd.conf might suit. In the examples here, the one machine with a local address of 192.168.0.1 is host to 2 websites, each using port 80. The same thing can be used for subdomains. Of course, if you had a setup like this, the "Directory" directive above would not be needed because each site has its own in the "VirtualHost" directives.
NameVirtualHost 192.168.0.1:80
<VirtualHost 192.168.0.1:80>
ServerAdmin webmaster@example.com
ServerName www.first_website.com
DocumentRoot /home/www/first_website
<Directory "/home/www/first_website">
Options Indexes FollowSymLinks Includes
AllowOverride AuthConfig FileInfo Indexes Limit
Order allow,deny
Allow from all
</Directory>
ErrorLog /logs/first_website/error_log
CustomLog /logs/first_website/access.log combined
</VirtualHost>
<VirtualHost 192.168.0.1:80>
ServerAdmin webmaster@example.com
ServerName www.second_website.com
DocumentRoot "/home/www/second_website"
<Directory "/home/www/second_website">
Options Indexes FollowSymLinks Includes
AllowOverride AuthConfig FileInfo Indexes Limit
Order allow,deny
Allow from all
</Directory>
ErrorLog /logs/second_website/error_log
CustomLog /logs/second_website/access.log combined
</VirtualHost>
Troubleshooting
Web Pages Aren't Showing
If web pages are no longer showing, check file permissions:
Try this
Mod_Include Error
You may see an error like this:
mod_include: Options +Includes (or IncludesNoExec) wasn't set, INCLUDES filter removed
That means you need to add these to either apache2.conf or your mods-available/mime.conf file:
AddType text/html .shtm .shtml AddOutputFilter INCLUDES .shtm .shtml
AddHandler server-parsed .shtm .shtml
Tuning Apache
Source: http://virtualthreads.blogspot.com/2006/01/tuning-apache-part-1.html
Source: http://httpd.apache.org/docs/2.0/misc/perf-tuning.html
Other Resources: Optimizing Apache
In theory, keep-alives allow web clients and servers to fully utilize their available bandwidth, and reduces latency by eliminating the overhead of frequently opening new connections.
Apache has several keep alive settings:
- KeepAlive: either On or Off, depending on whether Apache should allow connections to be used for multiple requests
- KeepAliveTimeout: how long, in seconds, Apache will wait after a request has been answered for another request before closing the connection
- MaxKeepAliveRequests: how many total requests a client can issue across a single connection
- MaxClients: the total number of worker processes that Apache will allow at any given time
The default Apache configuration file sets KeepAlive as on, with a KeepAliveTimeout of 15 seconds, MaxKeepAliveRequests of 100, and MaxClients is at 150.
But if you get 1,000 clients trying to access your web site, the first 150 clients will be successful. Some may not leave straight away, after their page has downloaded, and will hold open their connections for 15 seconds until your server forces their connection to close. That means the next 850 clients can't access the web server, as all of the available Apache processes will be used up.
You could increase Apache's MaxClients, but each Apache process consumes a bit of memory and it could run out, leaving you with an unresponsive server.
Tune Up Tips:
1. Divide your total RAM by 5 megabytes to see what you need for the traffic you get;
for example, a server with 512 megabytes of RAM could handle a MaxClients of 100.
2. Reduce the KeepAliveTimeout to 2 seconds, or simply turn KeepAlive off.
3. Disable ExtendedStatus unless you're debugging. Same goes for mod_info.
4. Keep HostnameLookups off (particularly if you're not running a local DNS server)
5. Setting the Options -Indexes FollowSymLinks saves a few io reads
(apache doesn't have to check if its a symlink)
6. Set a timeout value of 30 seconds will help save you RAM when a slow modem user is tying up the system.
Benchmark Apache
From http://www.cyberciti.biz/tips/linux-hard-drive-speed-benchmark-software-howto.html
What is important in benchmarking is the average time it will take when you have a maximum number of users on your site simultaneously. Another important thing is how much more time it will take when there are 2 times more users.
Here are few tips to carry out procedure along with an example: Procedures
* You need to use same hardware configuration and kernel (OS) for all tests
* You need to use same network configuration. For example, use 100Mbps port for all tests
* First record server load using top or uptime command
* Take at least 3-5 readings and use the best result
* After each test reboot the server and carry out test on next configuration (web server)
* Again record server load using top or uptime command
* Carry on test using static html/php files and dynamic pages
* It also important to carry out test using the Non-KeepAlive and KeepAlive (the Keep-Alive extension to provide long-lived HTTP sessions, which allow multiple requests to be sent over the same TCP connection) features
* Also don’t forget to carry out test using fast-cgi and/or perl tests
Example: Benchmark a Apache 2.2 and lighttpd 1.4.xx web server.====
Static Non-KeepAlive test for Apache web server
i) Note down server load using uptime command
$ uptime
ii) Create a static (small) html page as follows (snkpage.html) (assuming that server IP is 202.54.200.1) in /var/www/html (or use your own webroot):
<!DOCTYPE HTML PUBLIC “-//W3C//DTD HTML 4.0 Transitional//EN”> <html> <head> <title>Webserver test</title> </head> <body> This is a webserver test page. </body> </html>
Login to Linux/bsd desktop computer and type following command:
$ ab -n 1000 -c 5 http://202.54.200.1/snkpage.html
Where,
* -n 1000: ab will send 1000 number of requests to server 202.54.200.1 in order to perform for the benchmarking session * -c 5 : 5 is concurrency number i.e. ab will send 5 number of multiple requests to perform at a time to server 202.54.200.1
For example if you want to send 10 request, type following command:
$ ab -n 10 -c 2 http://www.somewhere.com/
Output:
This is ApacheBench, Version 2.0.41-dev <$Revision: 1.141 $> apache-2.0
Copyright (c) 1996 Adam Twiss, Zeus Technology Ltd, http://www.zeustech.net/
Copyright (c) 1998-2002 The Apache Software Foundation, http://www.apache.org/
Benchmarking www.cyberciti.biz (be patient)…..done
Server Software:
Server Hostname: www.somewhere.com
Server Port: 80
Document Path: /
Document Length: 16289 bytes
Concurrency Level: 1
Time taken for tests: 16.885975 seconds
Complete requests: 10
Failed requests: 0
Write errors: 0
Total transferred: 166570 bytes
HTML transferred: 162890 bytes
Requests per second: 0.59 [#/sec] (mean)
Time per request: 1688.597 [ms] (mean)
Time per request: 1688.597 [ms] (mean, across all concurrent requests)
Transfer rate: 9.59 [Kbytes/sec] received
Connection Times (ms)
min mean[+/-sd] median max
Connect: 353 375 16.1 386 391
Processing: 1240 1312 52.1 1339 1369
Waiting: 449 472 16.2 476 499
Total: 1593 1687 67.7 1730 1756
Percentage of the requests served within a certain time (ms)
50% 1730
66% 1733
75% 1741
80% 1753
90% 1756
95% 1756
98% 1756
99% 1756
100% 1756 (longest request)
Repeat above command 3-5 times and save the best reading.
Static Non-KeepAlive test for lighttpd web server
First, reboot the server. Stop Apache web server. Now configure lighttpd and copy /var/www/html/snkpage.html to lighttpd webroot and run the command (from other linux/bsd system):
$ ab -n 1000 -c 5 http://202.54.200.1/snkpage.html
How do I carry out Web server Static KeepAlive test?
Use -k option that enables the HTTP KeepAlive feature using ab test tool. For example:
$ ab -k -n 1000 -c 5 http://202.54.200.1/snkpage.html
Use the above procedure to create php, fast-cgi and dynmic pages to benchmarking the web server.
Please note that 1000 request is a small number you need to send bigger (i.e. the hits you want to test) requests, for example following command will send 50000 requests :
$ ab -k -n 50000 -c 2 http://202.54.200.1/snkpage.html
How do I save result as a Comma separated value?
Use -e option that allows to write a comma separated value (CSV) file which contains for each percentage (from 1% to 100%) the time (in milliseconds) it took to serve that percentage of the requests:
$ ab -k -n 50000 -c 2 -e apache2r1.cvs http://202.54.200.1/snkpage.html
How do I import result into excel or gnuplot programs so that I can create graphs?
Use above command or -g option as follows:
$ ab -k -n 50000 -c 2 -g apache2r3.txt http://202.54.200.1/snkpage.html
Put following files in your webroot (/var/www/html or /var/www/cgi-bin) directory. Use ab command.
Sample test.php file
<html> <head><title>Php test with phpinfo()</title></head> <body> <? phpinfo(); ?> </body> </html>
Run ab command as follows:
$ ab -n 500 -c 5 http://202.54.200.1/test.php
Sample test.pl (perl) file
#!/usr/bin/perl $command=`perl -v`; $title = “Perl Version”; print “Content-type: text/html\n\n”; print “<html><head><title>$title</title></head>\n<body>\n\n”; print “<h1>$title</h1>\n”; print $command; print “\n\n</body></html>”;
Run ab command as follows:
$ ab -n 3000 -c 5 http://202.54.200.1/cgi-bin/test.pl
Sample psql.php (php+mysql) file
<html>
<head><title>Php+MySQL</title></head>
<body>
<?php
$link = mysql_connect(“localhost”, “USERNAME”, “PASSWORD”);
mysql_select_db(“DATABASE”);
$query = “SELECT * FROM TABLENAME”;
$result = mysql_query($query);
while ($line = mysql_fetch_array($result))
{
foreach ($line as $value)
{
print “$value\n”;
}
}
mysql_close($link);
?>
</body>
</html>
Run ab command as follows:
$ ab -n 1000 -c 5 http://202.54.200.1/psql.php
<h1>$title</h1>\n”; print $command; print “\n\n</body></html>”;
Run ab command as follows:
$ ab -n 3000 -c 5 http://202.54.200.1/cgi-bin/test.pl
Sample psql.php (php+mysql) file
<html>
<head><title>Php+MySQL</title></head>
<body>
<?php
$link = mysql_connect(“localhost”, “USERNAME”, “PASSWORD”);
mysql_select_db(“DATABASE”);
$query = “SELECT * FROM TABLENAME”;
$result = mysql_query($query);
while ($line = mysql_fetch_array($result))
{
foreach ($line as $value)
{
print “$value\n”;
}
}
mysql_close($link);
?>
</body>
</html>
Run ab command as follows:
$ ab -n 1000 -c 5 http://202.54.200.1/psql.php
<h1>$title</h1>\n”; print $command; print “\n\n</body></html>”;
Run ab command as follows:
$ ab -n 3000 -c 5 http://202.54.200.1/cgi-bin/test.pl
Sample psql.php (php+mysql) file
<html>
<head><title>Php+MySQL</title></head>
<body>
<?php
$link = mysql_connect(“localhost”, “USERNAME”, “PASSWORD”);
mysql_select_db(“DATABASE”);
$query = “SELECT * FROM TABLENAME”;
$result = mysql_query($query);
while ($line = mysql_fetch_array($result))
{
foreach ($line as $value)
{
print “$value\n”;
}
}
mysql_close($link);
?>
</body>
</html>
Run ab command as follows:
$ ab -n 1000 -c 5 http://202.54.200.1/psql.php
<h1>$title</h1>\n”; print $command; print “\n\n</body></html>”;
Run ab command as follows:
$ ab -n 3000 -c 5 http://202.54.200.1/cgi-bin/test.pl
Sample psql.php (php+mysql) file
<html>
<head><title>Php+MySQL</title></head>
<body>
<?php
$link = mysql_connect(“localhost”, “USERNAME”, “PASSWORD”);
mysql_select_db(“DATABASE”);
$query = “SELECT * FROM TABLENAME”;
$result = mysql_query($query);
while ($line = mysql_fetch_array($result))
{
foreach ($line as $value)
{
print “$value\n”;
}
}
mysql_close($link);
?>
</body>
</html>
Run ab command as follows:
$ ab -n 1000 -c 5 http://202.54.200.1/psql.php
Chroot Apache
I don't know whether this will ever be useful, but anyway, directly copied from here: http://www.haught.org/howto/chroot_apache
Introduction
Chrooting makes a process believe that the root of the file system is higher up in the hierarchy. For example, if a process was chrooted in /home/www, the process would see it's root, /, as whatever was in /home/www. Everything else in the file hierarchy is nonexistent as far as the chrooted process is concerned. Chrooting is not a magic bullet, solving all your security needs. It instead puts up a road block from the hacked and exploited process from taking over an entire system. If anything, it slows down an attack and keeps an administrator from having to blow out an entire server when a hack occurs. This is important for apache running modules like PHP where a bad coding could compromise the entire server. Chrooting apache or other programs are just small steps to having a more secure server. It is not impossible to break out, just like with road blocks, there is always some way around them. In addition to chroot, FreeBSD's jail should also be looked at as an option. A jailed process has certain system calls restricted and can only bind to a single IP address. Planning
In order to chroot apache, you will need to decide where everything will reside. For this example I will place apache into /home/www/ which will look like / to apache. In addition I must create a /home/www/sbin, /home/www/tmp, /home/www/var, /home/www/usr, /home/www/usr/lib, etc... I will also need my own devices, so I will cd into /home/www/dev and use mknod to create null, random, urandom, and zero as such:
- mknod null c 2 2
- mknod random c 2 3
- mknod urandom c 2 4
- mknod zero c 2 12
These are just some basic ones that will probably be needed, I will find out later if any others are needed. I will also need to add a user "www" to our chroot so that apache can hand off the process to this user. In /home/www/etc I created the file passwd with only the single www user and also create the group file and add the single "www" group to it.
- echo "www:*:80:80::::::" > /home/www/etc/passwd
- echo "www:*:80:" > /home/www/etc/group
Now I just need to create a password database using pwd_mkdb as such:
- pwd_mkdb -d /home/www/etc /home/www/etc/passwd
Configuration
To make things easier I append my own "chroot" layout to config.layout in the main directory of the apache source as such:
<Layout chroot>
prefix: /home/www
exec_prefix: ${prefix}
bindir: ${exec_prefix}/bin
sbindir: ${exec_prefix}/sbin
libdir: ${exec_prefix}/usr/lib
libexecdir: ${exec_prefix}/usr/libexec/apache2
mandir: ${prefix}/usr/man
sysconfdir: ${prefix}/etc/apache2
datadir: ${prefix}/websites
installbuilddir: ${prefix}/usr/share/apache2
errordir: ${datadir}/error
iconsdir: ${datadir}/icons
htdocsdir: ${datadir}/htdocs
manualdir: ${prefix}/usr/share/doc/apache2
cgidir: ${datadir}/cgi-bin
includedir: ${prefix}/usr/include/apache2
localstatedir: /var
runtimedir: ${localstatedir}/run
logfiledir: ${localstatedir}/log
proxycachedir: ${datadir}/proxy
infodir: ${exec_prefix}/usr/share/info
</Layout>
And I compile and install as usual but add the --with-layout=chroot option to configure. I then move /etc/apache2 to /home/www/etc/apache2 and create a symbolic link from it's current location to its old. Libraries
To see which libraries httpd need I will use ldd:
- ldd /home/www/sbin/httpd
This will give me a nice starting point to copy libs into our chroot. For further testing, I will start up httpd with the -t option:
- chroot /home/www/ /sbin/httpd -t
Apache is nice enough to print out what libraries it needs. I will also use truss to see that files and devices httpd is trying to access and what failures occur.
- truss chroot /home/www /sbin/httpd -k start -d /
Truss will give me exactly what httpd is looking for and where it's looking. My httpd.conf needed to be edited to reflect the new file hierarchy. Anywhere there was a "/home/www", I replaced it with a "/". Truss will again come in handy for telling me where httpd is looking especially for files and directories in the chrooted /var that I always forget about. With everything in place, we just need to start and stop apache. Starting & Stopping
To start and stop the chrooted apache server I created the file apache2.sh in /usr/local/etc/rc.d/ which contains the following:
#!/bin/sh
PREFIX=
CHROOT=/home/www
case "$1" in
start)
[ -x ${CHROOT}${PREFIX}/sbin/httpd ] &&
chroot ${CHROOT} ${PREFIX}/sbin/httpd -k start -d / > /dev/null &&
echo -n ' apache2'
;;
stop)
[ -r ${CHROOT}/var/run/httpd.pid ] &&
chroot ${CHROOT} ${PREFIX}/sbin/httpd -k stop -d / > /dev/null &&
echo -n ' apache2 stopped'
;;
restart)
[ -r ${CHROOT}/var/run/httpd.pid ] &&
chroot ${CHROOT} ${PREFIX}/sbin/httpd -k restart -d / > /dev/null &&
echo -n ' apache2 restarted'
;;
test)
[ -x ${CHROOT}${PREFIX}/sbin/httpd ] &&
chroot ${CHROOT} ${PREFIX}/sbin/httpd -t -d /
;;
*)
echo "Usage: `basename $0` {start|stop|restart|test}" >&2
;;
esac
exit 0
I also created a symbolic link from /usr/local/etc/rc.d/apache2.sh to /usr/local/sbin/apachectl which makes it easier to start and stop apache manually.
Modules
The apache modules such as php can be installed just as they would otherwise. Just use apxs installed at /home/www/sbin/apxs and you are all set. The only difference is that you will need to use truss once again to see what the new module needs. Php for example has its own modules that all can have their own requirements as far as libraries are concerned. Follow the same procedure as before to get the system libraries into the chroot.
