Setting up a Debian box for development: making a LAMP: apache2

Add a user for the web stuff

# adduser httpd

Choose a simple (but secure) password.

# apt-get install apache2
Reading package lists… Done
Building dependency tree
Reading state information… Done
The following extra packages will be installed:
  apache2-mpm-worker apache2-utils apache2.2-bin apache2.2-common libapr1 libaprutil1 libaprutil1-dbd-sqlite3
Suggested packages:
  apache2-doc apache2-suexec apache2-suexec-custom
The following NEW packages will be installed:
  apache2 apache2-mpm-worker apache2-utils apache2.2-bin apache2.2-common libapr1 libaprutil1
  libaprutil1-dbd-sqlite3 libaprutil1-ldap
0 upgraded, 9 newly installed, 0 to remove and 0 not upgraded.
Need to get 2,155 kB of archives.
After this operation, 7,266 kB of additional disk space will be used.
Do you want to continue [Y/n]? y
Get:1 squeeze/main libapr1 amd64 1.4.2-6+squeeze3 [94.2 kB]
Get:2 squeeze/main libaprutil1 amd64 1.3.9+dfsg-5 [92.3 kB]
Get:3 squeeze/main libaprutil1-dbd-sqlite3 amd64 1.3.9+dfsg-5 [28.1 kB]
Get:4 squeeze/main libaprutil1-ldap amd64 1.3.9+dfsg-5 [25.7 kB]
Get:5 squeeze/main apache2.2-bin amd64 2.2.16-6+squeeze4 [1,439 kB]
Get:6 squeeze/main apache2-utils amd64 2.2.16-6+squeeze4 [164 kB]
Get:7 squeeze/main apache2.2-common amd64 2.2.16-6+squeeze4 [308 kB]
Get:8 squeeze/main apache2-mpm-worker amd64 2.2.16-6+squeeze4 [2,240 B]
Get:9 squeeze/main apache2 amd64 2.2.16-6+squeeze4 [1,396 B]
Fetched 2,155 kB in 5s (423 kB/s)
Selecting previously deselected package libapr1.
(Reading database … 32742 files and directories currently installed.)
Unpacking libapr1 (from …/libapr1_1.4.2-6+squeeze3_amd64.deb) …
Selecting previously deselected package libaprutil1.
Unpacking libaprutil1 (from …/libaprutil1_1.3.9+dfsg-5_amd64.deb) …
Selecting previously deselected package libaprutil1-dbd-sqlite3.
Unpacking libaprutil1-dbd-sqlite3 (from …/libaprutil1-dbd-sqlite3_1.3.9+dfsg-5_amd64.deb) …
Selecting previously deselected package libaprutil1-ldap.
Unpacking libaprutil1-ldap (from …/libaprutil1-ldap_1.3.9+dfsg-5_amd64.deb) …
Selecting previously deselected package apache2.2-bin.
Unpacking apache2.2-bin (from …/apache2.2-bin_2.2.16-6+squeeze4_amd64.deb) …
Selecting previously deselected package apache2-utils.
Unpacking apache2-utils (from …/apache2-utils_2.2.16-6+squeeze4_amd64.deb) …
Selecting previously deselected package apache2.2-common.
Unpacking apache2.2-common (from …/apache2.2-common_2.2.16-6+squeeze4_amd64.deb) …
Selecting previously deselected package apache2-mpm-worker.
Unpacking apache2-mpm-worker (from …/apache2-mpm-worker_2.2.16-6+squeeze4_amd64.deb) …
Selecting previously deselected package apache2.
Unpacking apache2 (from …/apache2_2.2.16-6+squeeze4_amd64.deb) …
Processing triggers for man-db …
Setting up libapr1 (1.4.2-6+squeeze3) …
Setting up libaprutil1 (1.3.9+dfsg-5) …
Setting up libaprutil1-dbd-sqlite3 (1.3.9+dfsg-5) …
Setting up libaprutil1-ldap (1.3.9+dfsg-5) …
Setting up apache2.2-bin (2.2.16-6+squeeze4) …
Setting up apache2-utils (2.2.16-6+squeeze4) …
Setting up apache2.2-common (2.2.16-6+squeeze4) …
Enabling site default.
Enabling module alias.
Enabling module autoindex.
Enabling module dir.
Enabling module env.
Enabling module mime.
Enabling module negotiation.
Enabling module setenvif.
Enabling module status.
Enabling module auth_basic.
Enabling module deflate.
Enabling module authz_default.
Enabling module authz_user.
Enabling module authz_groupfile.
Enabling module authn_file.
Enabling module authz_host.
Enabling module reqtimeout.
Setting up apache2-mpm-worker (2.2.16-6+squeeze4) …
Starting web server: apache2.
Setting up apache2 (2.2.16-6+squeeze4) …

# a2enmod rewrite
Enabling module rewrite.
Run '/etc/init.d/apache2 restart' to activate new configuration!

# nano /etc/apache2/envvars

export APACHE_RUN_USER=httpd
export APACHE_RUN_GROUP=httpd

We will activate the Mass Hosting module for Apache so we can develop a bunch of projects at the same time

We need a file to correct the value of DOCUMENT_ROOT when using such module:


// Let's fix the document root because of a bug in Apache's mod_vhost_alias not
// setting up the correct $_SERVER[‘DOCUMENT_ROOT’] env variable.
$__mod_vhost_alias_fix_doc_root = dirname(__FILE__) . DIRECTORY_SEPARATOR . 'domains' . DIRECTORY_SEPARATOR . $_SERVER[‘HTTP_HOST’] . DIRECTORY_SEPARATOR . 'html';

if (is_dir($__mod_vhost_alias_fix_doc_root)) {
    $_SERVER[‘DOCUMENT_ROOT’] = $__mod_vhost_alias_fix_doc_root;


We create a configuration file for virtual hosts:

nano /etc/apache2/sites-available/vhosts
# get the server name from the Host: header
UseCanonicalName Off

# splittable logs
LogFormat "%{Host}i %h %l %u %t \"%r\" %s %b" vcommon
CustomLog ${APACHE_LOG_DIR}/access_log vcommon

<Directory /home/httpd/domains/portnumber53.local/html>
# ExecCGI is needed here because we can't force
# CGI execution in the way that ScriptAlias does
Options FollowSymLinks ExecCGI

# now for the hard bit

RewriteEngine On

# a ServerName derived from a Host: header may be any case at all
RewriteMap lowercase int:tolower

## deal with normal documents first:
# allow Alias /icons/ to work – repeat for other aliases
RewriteCond %{REQUEST_URI} !^/icons/
# allow CGIs to work
RewriteCond %{REQUEST_URI} !^/cgi-bin/
# do the magic
RewriteRule ^/(.*)$ /home/httpd/domains/${lowercase:%{SERVER_NAME}}/html/$1

## and now deal with CGIs – we have to force a MIME type
RewriteCond %{REQUEST_URI} ^/cgi-bin/
RewriteRule ^/(.*)$ /home/httpd/domains/${lowercase:%{SERVER_NAME}}/cgi-bin/$1 [T=application/x-httpd-cgi]

# that's it!
a2ensite vhosts
a2dissite default
mkdir -p /home/httpd/domains/portnumber53.local/html
echo "PortNumber53.local<?php phpinfo(); ?>" > /home/httpd/domains/portnumber53.local/html/index.php

mkdir -p /home/httpd/domains/example.local/html
echo "Example.local<?php phpinfo(); ?>" > /home/httpd/domains/example.local/html/index.php

Let's restart Apache:
service apache2 restart

As long as your windows box solves portnumber53.local and example.local to the IP of your debian web box, try opening these domains in your browser.


Intranet: setup DJBDNS to respond for *.local to help development


0. Follow instructions to setup a DNS Cache


1. Create an alias for eth0:

# nano /etc/network/interfaces

auto eth0:0
iface eth0:0 inet static

2 . restart networking

# /etc/init.d/networking restart


3. Use tinydns-conf to setup djbdns 

# tinydns-conf dnscache dnslog /etc/tinydns


# ln -svf /etc/tinydns /etc/service

# cd /etc/service/tinydns/root/



4. Setup the "local" domain name:

# ./add-ns local

#./add-host a.ns.local


5. Create the data file for tinydns

# cd /etc/service/tinydns/root/

# nano data



In the sample file above:
– is the IP address of the DNS server, so it is the one responsibe for domain name responses
– is the IP address of your future Web server
Save and update data/cdb
# make
6. Edit /etc/resolv.conf
search portnumber53.local



7. Let dnscache know about your *.local domain names:

# cd /etc/service/dnscache

# echo > root/servers/local

# chmod 644 root/servers/local


8. Restart dnscache

# svc -t .




Code:: css-message-box

I just started a Google Code hosted project since I’m always in need of pretty message boxes for my HTML things.

Let me know if you want/can contribute to it. It’s currently licensed under GPL 2.0

Here’s the address:




Center a unordered UL/LI based menu

I lost count of how many times I broke my head trying to do this….

so taking a note will hurt less for sure:


#footer li{display:inline}


<ul id=”footer”>
<li><a href=”1.php”>Link 1</a></li>
<li><a href=”2n.php”>Link 2</a></li>
<li><a href=”3.php”>Link 3</a></li>

Really simple in the end

  • IGlr