Up one level
A simple Apache Webserver over a DSL connection in Debian Linux
Spencer Stirling

First, let the world in: forward port 80 through your router/firewall
If you are like me then you have a regular DSL or Cable modem connection, and you are probably sitting behind a firewall (perhaps you set it up yourself). Since your web server probably sits on your LAN *behind* your router/firewall you will need to "punch a hole" so that the outside world can get IN!!! If this sounds risky, then you are right! There is risk to everything.

This is called "port forwarding", and the details of how to do this depend highly on your router and firewall (so I cannot go into detail). Sometimes it's trivial, sometimes it's a pain in the back-end. The only thing to do is to "forward" port 80 from your router/firewall to the internal address of your computer (on which the webserver will be installed). This just means that when somebody makes a request to port 80 (an http:// request) on the PUBLIC IP address of your router, then the router will take this request and FORWARD it to the specified computer that sits safely inside the LAN (this computer has an internal PRIVATE IP address - not directly accessible from the outside).

To find out your PUBLIC IP address go to www.whatismyip.com - that'll tell you what it currently is. Since you have a regular DSL/Cable Modem this will probably CHANGE sometimes - maybe every couple of weeks, maybe daily. Hence, your IP is "dynamic". This dynamic nature of your IP will force you to jump through some hoops. If you have a "static" IP address then things will be much simpler for you, but you'll have to work that out for yourself. For tips concerning how to deal with these problems check out my article about Dynamic DNS and my article about forwarding through a gateway.

Install and configure the Apache server
Now to set up the Apache webserver (version 1.3 OBVIOUSLY THIS DOCUMENT IS A BIT OUTDATED WITH APACHE 2 AROUND). This is REALLY EASY!!! Just install the package "apache-perl" (this has Perl supported included. You can install "apache" instead and mess around with the separate Perl *module* - in that case replace "apache-perl" in the following with "apache"). Later on, we'll see how to set up CGI, PHP, and SSL. For now let's keep it simple. You can configure the Apache server by editing the file /etc/apache-perl/httpd.conf.

Most of the defaults in there are fine... you can add your domain(s) to be served by using so-called "Named Virtual Hosts". Let's say that I have my webpage in the directory "/var/www/spencerstirling.com". Then I could serve this out by adding the following stanzas in /etc/apache/httpd.conf (near the end - it will be obvious where these go)

NameVirtualHost*

<VirtualHost *>
    ServerName spencerstirling.com
    <IfModule mod_rewrite.c>
        RewriteEngine on
        RewriteRule ^(.*) http://www.spencerstirling.com$1 [R,L]
    </IfModule>
</VirtualHost>
<VirtualHost *>
  DocumentRoot /var/www/spencerstirling.org
  ServerName	www.spencerstirling.com
  # for SSI parsing (server side includes - e.g. CGI scripts)
  <IfModule mod_include.c>
    AddType text/html .html
    AddHandler server-parsed .html
  </IfModule>
  # anti-hotlinking
  <IfModule mod_rewrite.c>
     RewriteEngine on
     RewriteCond %{HTTP_REFERER} !^$
     RewriteCond %{HTTP_REFERER} !^http://(www\.)?spencerstirling\.com/ [NC]
     RewriteRule .*\.(gif|jpe?g|png)$ - [F,L]
  </IfModule>
</Virtualhost>

I could serve out a completely different webpage located in "/var/www/birdlist.org" by adding these stanzas as well:

<VirtualHost *>
    ServerName birdlist.org
    <IfModule mod_rewrite.c>
        RewriteEngine on
        RewriteRule ^(.*) http://www.birdlist.org$1 [R,L]
    </IfModule>
</VirtualHost>
<VirtualHost *>
  ServerName	www.birdlist.org
  DocumentRoot /var/www/birdlist.org
</Virtualhost>

Notice that I only put in "NameVirtualHost *" once. Also, it's worth noting that the first "VirtualHost" stanza with the "Rewrite" stuff is just for a pleasant browsing experience. If somebody types in "spencerstirling.com" I want it to be automatically rewritten "www.spencerstirling.com". You will need to make sure that the "mod_rewrite" module is being loaded (it probably is, but see below in the SSL section if you are unsure). The "www.spencerstirling.com" stanza contains some extra pieces (such as server parsing for CGI scripts and an anti-hotlinking rewrite rule). After these changes have been made then its time to restart the Apache webserver by typing

/etc/init.d/apache-perl restart

A little commentary is in order. There was a reason that I put my webpages under "/var/www". That's because Apache determines "permissions" for accessing directories in a top-down fashion. Far above in "/etc/apache-perl/httpd.conf" you'll see the following stanza:

<Directory />
    Options SymLinksIfOwnerMatch
    AllowOverride None
</Directory>

This basically sets up some strict rules from the root directory / on down. From then on every piece of access must be explicitly opened. Not much further down you'll see a similar "Directory" stanza for "/var/www", like this:

<Directory /var/www>
    Options Indexes Includes FollowSymLinks MultiViews
    AllowOverride None
    Order allow,deny
    Allow from all
</Directory>
This will open up some permissions so that your webpages under that directory can be accessed. For example, notice the "FollowSymLinks" directive. This means that you can have symbolic links to your pages from there and Apache will follow them! Obviously I don't need to put my webpages under /var/www AT ALL! I could put similar "Directory" stanzas for any directory that I WANT! However, I'm lazy, so I just put my webpages wherever I want and add a symbolic link in "/var/www".

In general there are several places where access can be granted using so-called directives such as "FollowSymLinks" as above. First, most (maybe all?) directives make sense in a "Directory" stanza, as above.

Second, you can place *some* directives in the "VirtualHost" stanza already discussed - such settings will apply to the "DocumentRoot" directory specified there.

Third, directives can be specified in a separate ".htaccess" files placed in directories in the website itself. This is useful for many reasons - for example if you want to give users control over their own access permissions. NOTE that the ".htaccess" file will ONLY take effect if, somewhere in "httpd.conf", that directory has already been given (for example) "AllowOverride All" permission. This means that the administrator must grant "override" access before users can configure their own access permissions via ".htaccess" files. You should check the official Apache 1.3 documentation for information concerning which directives apply where.

One neat feature of Apache is that each USER can automatically have his/her OWN private webpage. What I mean is THIS: I have a user named "sonja", and in her home directory she can create a subdirectory called "public_html" (i.e. /home/sonja/public_html). In there she has her own index.html and full private webpage. This webpage can be viewed from the internet by going to

www.spencerstirling.com/~sonja

Pretty NEAT!!! Huh?

Setting up an Apache server using SSL
Now there will probably come a time in your life when you'll need to serve up some data that is of a more "sensitive" nature. Maybe you'll have users logging in to some part of your website, or whatever. You will be doing them (and yourself) a HUGE disservice if you don't encrypt the session using SSL. In fact, you might get sued over the deal. So let's figure out how to get this part done.

Before we begin, let me say that it IS possible to use the mod_ssl module with Apache. I NEVER got the thing to work. Instead, I'm going to install a COMPLETELY SEPARATE Apache SSL-enabled server! Once you know how to use the regular Apache server, there's nearly nothing new to learn. To begin, install the package "apache-ssl". This will configure a server that listens on port 443 (the regular server listens on port 80, of course!). During the setup you'll need to generate your own SSL certificate. I'll trust you to figure that out yourself (or buy one if you really want to be legit).

The setup is NEARLY identical. For example, to add my website (viewable over SSL using https://) I added this stanza to "/etc/apache-ssl/httpd.conf" (notice that apache-perl and apache-ssl have completely separate configuration files)

NameVirtualHost *

<VirtualHost *>
  SSLEnable
  ServerName www.spencerstirling.com
  DocumentRoot /var/www/spencerstirling.com
</VirtualHost>

Notice the extra "SSLEnable" directive. But, of course, you are not interested in looking at my website encrypted! It's already slow enough!!! (crappy middle-of-forest DSL provider). Let's do a real example - granting a certain individual access (via a custom password) to a section of your site. This is very simple... consider the following stanza (placed in "/etc/apache-ssl/httpd.conf")

Alias /easytoremember /disks/raid/backup/privatedirectory
<Directory /disks/raid/backup/privatedirectory>
  Options Indexes Includes FollowSymLinks MultiViews
  AuthName "Please login"
  AuthType Basic
  AuthUserFile /etc/apache-ssl/passwords
  AuthGroupFile /dev/null
  require user jimmy
  order allow,deny
  allow from all
</Directory>
This sets up password-guarded access to "/disks/raid/backup/privatedirectory" (which is accessible by the easy name "www.spencerstirling.com/easytoremember"). Here usernames and passwords are stored in a special file (I chose "/etc/apache-ssl/passwords"). Clearly I am allowing only the user "jimmy". I can set up my "/etc/apache-ssl/passwords" file with the following commands:

htpasswd -c /etc/apache-ssl/passwords jimmy

(the -c switch creates the file. To add users to an existing file leave -c OUT). That's IT!!!

Well, not quite. Most of the time your users will just type in the webpage. They won't even think about the "http://". Every browser will guess that they mean "http://" and tack it on for them. Unfortunately, here we REALLY need "https://" since we are going over port 443, not port 80! To make things nice you need to have your REGULAR Apache webserver REDIRECT the request to you SSL-enabled webserver. You can do this (using the above example) by placing the following stanza in "/etc/apache-perl/httpd.conf" (the configuration file for the REGULAR apache-perl webserver!)

# Redirect to the SSL enabled server
Alias /easytoremember /disks/raid/backup/privatedirectory
<IfModule mod_rewrite.c>
    <Location /easytoremember>
      RewriteEngine on
      RewriteCond %{HTTPS} !=on [NC]
      RewriteRule . https://%{HTTP_HOST}%{REQUEST_URI}  [R,L]
    </Location>
</IfModule>
This tells the regular Apache server to rewrite the URL, effectively passing the request off to the SSL-enabled Apache server. Note that you will need the "mod_rewrite" module loaded... check your "/etc/apache-perl/modules.conf" file for the line

LoadModule rewrite_module /usr/lib/apache/1.3/mod_rewrite.so

If it's not there then add it manually into your "httpd.conf" file.

Special note: I have had bad luck and quirky behavior trying to mix/match HTTP -> HTTPS rewrite directives and login authentication stanzas in .htaccess (even if "AllowOverride All" is set up for the appropriate directories in both the apache-perl and apache-ssl httpd.conf files). I have finally given up and I just keep all of the appropriate stanzas in the httpd.conf files.

VERY SPECIAL NOTE: I almost always keep secure parts of the site in a separate directory out of the regular site's "DocumentRoot" directory. I just refer to it by an "Alias" as above. This makes it so that people HAVE to go through SSL to get to that part of the site.

Other methods to authenticate
This whole "htpasswd" special password file bit is OK for some things, however my users want to log in using their usual system password. There are several ways to do this.

First, there is a module "libapache-mod-auth-pam" that supposedly allows Apache to use the usual PAM interface. The setup seemed simple enough, however I COULD NOT GET THE THING TO WORK after several hours of checking and rechecking. My logs kept telling me that the PAM module wasn't loading, but IT WAS! Frustrated, I gave up.

It just so happens that I keep my users in a MySQL database rather than having them in the usual /etc/passwd file. See my MySQL authentication page for details concerning that.

In that case, I can directly use the MySQL database. So I first installed the module

libapache-mod-auth-mysql
Then I added the following stanza in "/etc/apache-ssl/httpd.conf" (the SSL server, of course).
Alias /easytoremember /disks/raid/backup/privatedirectory
<Directory /disks/raid/backup/privatedirectory>
  Options Indexes Includes FollowSymLinks MultiViews
  Auth_MySQL on
  AuthMySQL_Host localhost
  AuthMySQL_User nss-shadow
  Auth_MysQL_Password PUTYOURPASSWORDHERE
  Auth_MySQL_DB nss_mysql
  Auth_MySQL_Password_Table user
  Auth_MySQL_Username_Field user_name
  Auth_MySQL_Password_Field password
  Auth_MySQL_Empty_Passwords off
  Auth_MySQL_Encryption_Types Crypt
  AuthName "Please login"
  AuthType Basic
  AuthGroupFile /dev/null
  require user jimmy
  order allow,deny
  allow from all
</Directory>
This accomplishes the authentication. Be careful!!!!! Apache is CASE SENSITIVE!!! Those capital and lowercase letters are IMPORTANT (a fact that cost me a good hour)!!!

A note about security: notice that you are putting the password for the "nss-shadow" user in here. That's bad! You should

chmod 600 /etc/apache-ssl/httpd.conf
at LEAST! I don't know what further security risks are here. Probably somebody could force Apache to dump its configuration file, which would also be bad. You should check these things out (I'm too busy right now).

Enabling CGI and PHP on your webserver
If you've been following my examples so far then you are in luck: you probably already have CGI enabled on your webserver! To check this, look for the following line in "modules.conf"

LoadModule cgi_module /usr/lib/apache/1.3/mod_cgi.so

You can enable PHP support by installing the Debian package "libapache-mod-php5". Check in "modules.conf" for the line

LoadModule php5_module /usr/lib/apache/1.3/libphp5.so

If these lines don't show up in "modules.conf" but you KNOW that those modules are installed on the system then you can put these lines manually in "httpd.conf".

Remember that each Apache webserver has a completely independent configuration (SSL or not). Now that you have CGI enabled, you need to know how to use it. I give up: CGI+Apache 1.3 is documented MUCH better elsewhere, for example try the official Apache docs. It's important to remember that Apache runs as the user "www-data", hence if your CGI programs will be reading/modifying any files then the permissions must be set to allow "www-data" to do these things!

The only thing that I have to add concerns so-called Server-Side Includes. This can be a great way to add *small* snippets of CGI dynamic content in your webpages (for example, a counter). As usual, there is no reason to reinvent the wheel - check out the official docs. Before you do, however, please read the following caveat!!!

I found that the "Includes" module wasn't loading properly. Check your "modules.conf" file for the line

LoadModule includes_module /usr/lib/apache/1.3/mod_include.so
If it's not there, then you can load the module MANUALLY by adding that line to your "httpd.conf".

Web Statistics using Awstats
You will likely want to keep web statistics around (and your users will likely want them, too). For that you can install "Awstats". Thank the gods (yes, I've been watching Battlestar Galactica) for this link http://www.dotvoid.com/view.php?id=29. I especially agree with the author that documentation written by the developer is usually not the best. Obviously, they MUST do it, but then it's the job of somebody with technical skill to unravel what they said and make it more presentable. It takes two to tango I guess.

This page has been visited   times since December 28, 2005