Setting up an Apache 2 (httpd) Web Server

This is a set of emerging instructions I am putting together as I knit my web server together. Until recently, and for many years, it was powered by NetWare 6.5. I have chosen SuSE Linux 10.2 because I’ve long used this OS which is now produced by my friends back at Novell.

When you install your Linux host, be sure to include the following components, or go get them using Yast2 Software:


Location of content

There are several places you can place your content, one example being /srv/www/httpdocs, a generic place. However, the best and most easily manageable place is to create a user for each supported domain, then place that domain’s content under a subdirectory, public_html (this name isn’t invented, but was conceived for this purpose), of that user’s home directory. For example, files for http://www.bullheadranch.com/ should be copied to (and maintained on) the path

	/home/bullheadranch/public_html/index.html, etc.

Preparation of server for content

In Yast2, which can be invoked from the command-line (difficult TUI) if logged in as root, or using the GUI interface (much easier), is used to ensure one setting. Follow this path:

System -> sysconfig editor -> Network -> WWW -> Apache2 -> Apache Modules

Ensure that userdir is included in the line to edit. Take time and scrutinize, especially the TUI environment, the screen to see where this happens. On my freshly set-up server, this was already done.

Then go to /etc/apache2 and copy mod_userdir.conf from this directory to /etc/apache2/conf.d. Then edit this file, search for “public_html” until you see “#UserDir public_html’ and uncomment the line just as it is (remove the #).


Creating virtual hosts

A virtual host anchors a domain and, at the same time, points to the file content of the pages. In theory, you can best manage these by means of Yast2, but I’ve never so far been able to make it work. Instead, I do the following:

Copy /etc/apache2/vhosts.d/vhost.template to a new name corresponding to the first domain my web server will host. For our example, we’ll call it windofkeltia.conf.

Edit your new Apache 2 virtual hosts configuration file using your favorite text editor, vim.

Search for dummy-host.example.com. Everywhere this string occurs, you will replace it with your own domain name, in our example, windofkeltia.com.

Near the top of this file, change webmaster@dummy-host.example.com to your e-mail address (or the e-mail address of the webmaster). In my case, I’m russ@windofkeltia.com. Change also the server name to the domain name.

<VirtualHost *:80>
	ServerAdmin russ@windofkeltia.com
	ServerName  www.windofkeltia.com
	...

As I’m advising you to create one user per domain and to place the content on /home/domain/public_html, you will need to specify this in the places you find other paths including the sample name, dummy-host.example.com. The following places in this file will need to be changed therefore. I have included sufficient context in this file so that you will have no trouble finding the location to modify.

<VirtualHost *:80>
	ServerAdmin webmaster@dummy-host.example.com
	ServerName  dummy-host.example.com
	...
	# DocumentRoot: The directory out of which you will server your
	# documents. By default all requests are taken from this directory, but
	# symbolic links and aliases may be used to point to other locations.
	DocumentRoot /srv/www/vhosts/dummy-host.example.com
	...
	ErrorLog /var/log/apache2/dummy-host.example.com-error_log
	CustomLog /var/log/apache2/dummy-host.example.com-access_log combined
	...
	# The same rules about trailing "/" apply to ScriptAlias directives as to
	# Alias.
	#
	ScriptAlias /cgi-bin/ "/srv/www/vhosts/dummy-host.example.com/cgi-bin/"
	...
	# "/srv/www/cgi-bin" should be changed to wherever your ScriptAliased
	# CGI directory exists, if you have one, and where ScriptAlias points to.
	#
	<Directory "/srv/www/vhosts/dummy-host.example.com/cgi-bin/">
	    AllowOverride None
	    Options +ExecCGI -Includes
	    Order allow,deny
	    Allow from all
	<Directory>
	...
	#This should be chnage to whatever you set DocumentRoot to.
	#
	<Directory "/srv/www/vhosts/dummy-host.example.com">
	...

Note that you should comment out, using the pound sign (#) the ScriptAlias and CGI-related syntax unless and until you know what you doing. You should end up with, allowing for our present example, the following changes, including lines commented out. There is one additional section to comment out that doesn’t present the dummy-host.example.com string. Why we comment that section out is explained in a comment there. All th comments I have inserted are in the first column; any original ones I show here are entabbed.

<VirtualHost *:80>
	ServerAdmin russ@windofkeltia.com
	ServerName  windofkeltia.com
	...
	# DocumentRoot: The directory out of which you will server your
	# documents. By default all requests are taken from this directory, but
	# symbolic links and aliases may be used to point to other locations.
	DocumentRoot /home/windofkeltia/public_html/windofkeltia.com
	...
#	ErrorLog /home/windofkeltia/public_html/windofkeltia.com-error_log
#	CustomLog /home/windofkeltia/public_html/windofkeltia.com-access_log combined
	...
	# The same rules about trailing "/" apply to ScriptAlias directives as to
	# Alias.
	#
#	ScriptAlias /cgi-bin/ "/home/windofkeltia/public_html/cgi-bin/"
	...
	# "/srv/www/cgi-bin" should be changed to wherever your ScriptAliased
	# CGI directory exists, if you have one, and where ScriptAlias points to.
#	<Directory "/home/windofkeltia/public_html/cgi-bin/">
#	  AllowOverride None
#	  Options +ExecCGI -Includes
#	  Order allow,deny
#	  Allow from all
#	<Directory>
	...
#	I comment out this section because it is already configured on a global
#	level (see mod_userdir instructions elsewhere in this web page how-to).
#	<IfModule mod_userdir.c>
#	  # Note that the name fo the user directory ("publi_html") cannot simply be
#	  # changed here, since it is a compile-time setting. The apache package
#	  # would have to be rebuilt. You could work around by deleting
#	  # /usr/sbin/suexec, but then all scripts from the directories would be
#	  # executed with the UID of the webserver.
#	  UserDir public_html
#	  # The actual configuration of the directory is in
#	  # /etc/apache2/mod_userdir.conf
#	  Include /etc/apache2/mod_userdir.conf
#	  # You can, however, change the ~ if you find it awkward, by mapping e.g.
#	  # http://www.example.com/users/karl-heinz/ --> /home/karl-heinz/public_html
#	  # AliasMatch ^/users/([a-zA-Z0-9-_.])/?(.*) /home/$1/public_html/$2
#	<IfModule>
	...
	# This should be changed to whatever you set DocumentRoot to.
	#
	<Directory "/home/windofkeltia/public_html">
	...

Not only does this approach work, but it actually shows up in Yast. Unfortunately, a file, yast2_vhosts.conf gets created the first time you click on the Hosts tab in Yast and, each subsequent time, that file is appended to and gets bigger and bigger. In the Hosts tab in Yast, the domains show up duplicated each time as well. This appears not to harm anything, but it’s very annoying to an obsessive-compulsive sufferer like me. The solution is to delete this file whenever this problem gets on your nerves:

	windofkeltia:/etc/apache2/vhosts.d # rm yast2_vhosts.conf

Having separate configuration files in the /etc/apache2/vhosts.d directory is perhaps a better way to go than trying to get it working via Yast as I’ve already said. You have explicit files for each host you setup and each contains additional configuration parameters if you wish to add more fancy functionality to without having to lookup the Apache docs. By this I am referring to some of the lines we commented out in the above procedure

The default host (where the server goes to if it cannot find a virtual host setting) can be kept in /srv/www/htdocs, which might be where I should keep windofkeltia instead of under its own user since this is in essence the root page of my server. However, I am so enthralled by how this works that I may just put a link to /home/windofkeltia/public_html or some such thing.

Finally, I have in this directory numerous configuration files, one for each domain I host on my server.


Redirecting partial expressions of URL to the right place...

Typing silvertipexpress.com and pressing return will not reach this domain’s page as will www.silvertipexpress.com or http://www.silvertipexpress.com. This is by lack of providing for the missing www.. This is easily fixed by creating, before or after the VirtualHost tag we’ve just discussed, the following paragraph (in /etc/apache2/vhost.d/silvertipexpress.conf):

<VirtualHost *:80>
	ServerAdmin russ@windofkeltia.com
	ServerName  silvertipexpress.com
	Redirect  / http://www.silvertipexpress.com
</VirtualHost>

Another Yast duty...

You need to select, from among all your content, a default set of pages for the server as a whole. This is indicated in Yast->Network Services->HTTP Server->Hosts (tab)->Set as Default. Select which one and put its pages on the path srv/www/htdocs or, better yet, put a symbolic link there to the index.html of the pages you want as default and leave the pages on the path already suggested.

In fact, I have trouble with the whole Yast thing when it comes to clicking on the Hosts tab. Clicking there seems to add up all my individual domain.conf files, described above, over and over again. The solution is to delete /etc/apache2/vhosts.d/yast2_vhosts.conf every time you make the mistake of clicking on that tab, but where does that leave your Set as Default value? I’ve never been able to get the interfaces of this tab to work properly (hence the rather lengthy instructions above) so that Yast manages the problem itself. This is borked and I’ll have to come back to this as soon as I get an answer.

Part of that answer is to fix the default location by renaming it to sort first. I was getting alfredbateman.org at first when I went to my server.

Copy and rename /etc/apache2/vhosts.d/wincofkeltia.conf to _windofkeltia.comf so that it will sort first alphabetically. The first virtual host configuration is the winner when it comes to serving up the default when a no HTTP Host header is given on the remote request. In this way, http://66.7.114.165 gets served by the windofkeltia configuration because _windofkeltia.conf sorts first.


Protecting the Linux host

To protect the Linux host against intrusion I do the following things:


Enforcing good passwords

This is simply to enforce that users get passwords that have:

For example, user bob should not have a password bob or gandalf or bob-19550118, etc. However, Gandalf-19550118 might be a reasonable password if 19550118 were not Bob’ birthdate and if Gandalf were’t in such recent popularity.

The best password is a longish and completely meaningless string of mixed characters, one that has no connection to the user. The string should not be an obvious keyboard pattern like asdf1234.


Setting up and securing sshd

To secure sshd, edit /etc/ssh/sshd_config and remove the ability for root to log in and change to protocol 2:

Using Yast->Security and Users->Firewall->Allowed Services, click on Service to Allow, scroll down, select, then add SSH to the list of services allowed through the firewall. HTTP Server should already be in this list. Do not add FTP or other, less secure services. In fact, don’t add any services unless you know you want them.


Set up sudo

As already discussed elsewhere in this document, do not permit anyone to log in through ssh as root. This is a bad practice. Do permit someone to log in under a user you create for them with a secure password and, if you deem necessary, permit them to use su or sudo to accomplish root work you want them to perform. The reasons this is more secure are:

Using Yast->Security and Users->Sudo->User Aliases, create an alias group ADMIN and add users to it whom you agree can access your hardware with root privileges.

Then, add the following line to the bottom of /etc/sudoers:

	ADMINS  ALL = NOPASSWD: ALL

(No, I don’t know what this means either.)


Troubleshooting

If you watch closely as your system comes up, you may get some nastygrams from Apache similar to:

Starting httpd2 (prefork)
(long date/timestamp) [warn] _default_ VirtualHost overlap on port 80, the first has precedence
(long date/time stamp) [warn] _default_ VirtualHost overlap on port 80, the first has precedence
...

...repeated once for each domain you have. The solution is to uncomment

	NameVirtualHost *:80

in /etc/apache1/listen.conf. This line tells the server that you are doing name-based virtual hosting on this host.

Bouncing Apache

For some reason, while the Apache dæmon is named httpd, there is no corresponding script on the path /etc/init.d. Instead, use /etc/init.d/apache2. Actually, the real way to do it is:

	windofkeltia:/home/msimpson:~> rcapache2 restart

The browser cache

In working with changing web pages and configurations, it is sometimes necessary to flush the browser cache to be certain a page is really visible or not. In Firefox, this is done by holding down F5 while clicking on the reload button.