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:
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
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-mysqlThen 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.soIf 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