Creating an apache webserver

We understand that needs of website owners are different. For some (like us), keeping it simple is key. Others enjoy a more feature rich environment. We have therefor installed two clusters of webservers on our backends. One runs thttpd (described here) and the other runs apache, described in this setup document.

There are benefits from an administration point of view to apache. It supports scripting languages, like modperl, modpython and of course the famous PHP serverside rendering. It also has an extensive configuration language which allows administrators to build a wide variety of sites with authentication, specific/custom logging, and so on.

Incidentally, we bind port 2080 on the apache server. This is okay because it is not going to be serving traffic directly! It will be a backend to the HA Proxy servers (and they of course do listen to port 80).

A1) Using OpenBSD

We'll install the default port for Apache2 (which is in www/apache-httpd). For PHP5, we'll have to do a bit of work (the port assumes Apache v1 (which is in OpenBSD's base distribution). We'll have to educate the PHP5 port in www/php5 to work with Apache2.
export PKG_PATH=`uname -r`/packages/`uname -m`/
pkg_add -vr apache-httpd

cd /usr/ports/www/php5/
APXS2=`which apxs2`
sed -e "s,--with-apxs=.*apxs,--with-apxs2=$APXS2,g" \
  core/Makefile > core/ && \
  mv core/ core/Makefile
sed -e "s,--with-apxs=.*apxs,--with-apxs2=$APXS2,g" \
  extensions/Makefile > extensions/ && \
  mv extensions/ extensions/Makefile
env FLAVORS="no_dba no_dbase no_mysqli no_ncurses \
  no_pdo_mysql no_pdo_pgl no_pdo_sqlite no_shmop \
  no_snmp no_sybase_ct" make install

cd /etc/apache2
sed -e 's,:80,:2080,g' -e 's,Listen 80,Listen 2080,g' \
  -e 's,Listen 443,Listen 2443,g' httpd2.conf \
  > && mv httpd2.conf

mkdir -p /etc/apache2/paphosting.d /paphosting/apache/
chown paphosting:paphosting /etc/apache2/paphosting.d
chown paphosting:paphosting /paphosting/apache/
echo "NameVirtualHost *:2080" \
  >> /etc/apache2/httpd2.conf

echo "Include /etc/apache2/paphosting.d/" \
  >> /etc/apache2/httpd2.conf

Note: on Apache 2.4+ one needs to remove the NameVirtualHost configuration line as they finally are doing it based on the Listen directive and the Server names provided in the VirtualHost clauses.

A2) Using Ubuntu

We install the default package for Apache2 and PHP5 (and pear). Afterwards we loop over various bits and pieces of config to rewrite the port from the default 80 and 443 to our 2080 and 2443. We also create a config snippet directory in /etc/apache2/paphosting.d/ and a directory for our sites in /www/paphosting/ and chown them to the paphosting user. We also allow the paphosting user to run /usr/sbin/apache2ctl as root using sudo(1).
sudo su -
apt-get install apache2 libapache2-mod-php5 php-pear \
  php5-mysql php5-sqlite php5-imagick php5-gd php5-intl libapache2-mod-rpaf \
cd /etc/apache2
sed -e 's,:80,:2080,g' -e 's,Listen 80,Listen 2080,g' \
  -e 's,Listen 443,Listen 2443,g' ports.conf \
  > && mv ports.conf

cd /etc/apache2/sites-available
sed -e 's,:80,:2080,g' -e 's,:443,:2443,g' default \
  > && mv default

cd /etc/apache2/mods-enabled
ln -sf ../mods-available/rewrite.load
ln -sf ../mods-available/headers.load 
rm alias.conf

mkdir -p /etc/apache2/paphosting.d /paphosting/apache/
chown paphosting:paphosting /etc/apache2/paphosting.d
chown paphosting:paphosting /paphosting/apache/
echo "Include /etc/apache2/paphosting.d/" \
  > /etc/apache2/conf.d/zzz_paphosting.conf

ln -sf /usr/sbin/apache2ctl /usr/local/sbin/apachectl2

cd /etc/php5/apache2/
sed -e 's,memory_limit =.*,memory_limit = 128M,g' php.ini \
  > && mv php.ini
/etc/init.d/apache2 restart
We use zzz_paphosting.conf above to ensure that it is the last configuration snippets loaded overriding all previously set variables. Additionally for SixXS nodes one needs the following packages:
php5-curl php5-mysql php-db mediawiki phpmyadmin
(and don't forget to uninstall the mysql-server related packages that automatically get installed with a:
dpkg --purge `dpkg --list|grep mysql-server | awk '{print $2}'`

A3) Staging Hosts

Staging hosts don't get synced using the normal push method, as such, one needs to check out their svn directory in a useful place and then:
export SVNROOT=/your/path/to/svnroot/paphosting/
mkdir -p /paphosting/apache/
chmod 755 /paphosting
chmod 755 /paphosting/apache
ln -s ${SVNROOT}/apache/sites /paphosting/apache/paphosting
cd /etc/apache2/paphosting.d/
chmod 775 .
ln -s ${SVNROOT}apache/config/host/* .
ln -s ${SVNROOT}apache/config/default/* .
rm *.regtest
This way, the config is actually running out of the live SVN directory instead of being pushed. Of course, when adding files one has to update them there too. Make sure that your SVN repo is reachable also by the apache/www-data user:
cd /; for i in `echo '/home/jeroen/svn/' | sed 's/\// /g'`; do chmod o+x $i; cd $i; done

B) Configuring papapache

1. Add the machine to config/apache{,.$CLUSTER}.hosts

(for the SixXS cluster this is performed with the config update) On your client, add the hostname (any hostname or IPv4 or IPv6 address to which you can connect on the ssh port:
svn update
echo ${HOSTNAME} >> config/apache${CLUSTER}.hosts
mkdir -p files/${HOSTNAME}/etc/logrotate.d
ln -s ../../../common/logrotate.d/apache2-paphosting \
svn commit

2. Ensure you can SSH into the machine as paphosting

From your client, try to SSH as paphosting into the machine. Once you're there, you should make sure that the paphosting user can run the apachectl2 binary as root.
sudo su -
cat << EOF >> /etc/sudoers
paphosting ALL = NOPASSWD: /usr/local/sbin/apachectl2

3. Force a push of the thttpd sites and configs

On your client, try to do an apache push
scripts/ -v -n
# If this looks good, then:
scripts/ -f

4. Check to make sure it works

You can now use the machine to serve Apache2+PHP5 websites, assuming of course that you have verified it actually works, something like:
curl --fail -I -H "Host:" ${HOSTNAME}:2080
[ $? -eq 22 ] && echo "Oops, this failed!!"
You can also hack in /etc/hosts but please make sure to clean up the override when you're done!