DD-WRT in Repeater Bridge mode


DD-WRT is a third party developed firmware, released under the terms of the GPL for many ieee802.11a/b/g/h/n wireless routers based on a Broadcom or Atheros chip reference design. — DD-WRT wiki

Today we are discussing DD-WRT and specifically how you can do some cool stuff that you would not be able to do with your current wireless router. Chances are that your home router is compatible with DD-WRT. You can find this out by checking the DD-WRT router database. With DD-WRT firmware loaded, your router is able to do some tricks it might not be able to do before. One of these things might involve the repeater bridge mode, which can improve your WiFi range at home. Since devices are automatically switching between WiFi and 3G, especially since the 3G prices (in the Netherlands) are quite high and/or low data traffic limits apply, this mode is a necessity.

So what is the plan? Let’s assume you have a living room with an (non wireless) Internet modem, a server, a printer and a laptop. In your study you have another three PC’s. You need a Mac, a Windows PC and a Linux computer right? Occasionally you bring your laptop from the living room. Let’s assume your wife (or husband) did not allow you to put a nice fast gigabit cable connection between your living room and the study, because he/she feels the cables do not match the interior design. Obviously there is no arguing and you need to go wireless. The fastest wireless connections you get now follow the N standard with a theoretical maximum of 300 Mbps. In reality you will probably only get a fraction of that, because of the distance you need to cover. In my house I get about 25 Mbit with going one floor up and passing a bathroom. But anyway, this would be the network layout you can build using DD-WRT on you router:


The funny poles are actually DD-WRT routers and one is configured as the primary. If your modem has wireless and a switch you can just leave that primary router out, since it is just configured as a standard access point. The secondary is actually a DD-WRT router in repeater bridge mode. This means it connects to the access point by wireless and then announces it’s own SSID (e.g. “wifi-study”) whereas the primary announces the “wifi-living”. Now you can use your laptop in the study as well, and connect the PC’s to the router through wired connections. Note that you can replace the antenna with a Yagi antenna and boost the transmission power to get a better reach and a higher wireless speed.

If you run the router in repeater bridge mode, there are a few settings you need to make sure you set correctly:

  1. You must set your encryption to “WPA2 personal” with “AES” encryption.
  2. You must set your wireless channel to a fixed one, so do NOT put it on “auto”.
  3. Please make sure you follow the instructions carefully.

If you do not yet own a DD-WRT capable router you might consider getting one of these new, very fast routers:

  • Netgear WNDR4300
  • Asus RT-AC66U
  • TP-Link TL-WDR4300
  • Cisco Linksys E4200

These very fast routers have awesome specifications and can run DD-WRT perfectly. I have the older, slower Cisco Linksys E2500 and even older and slower Cisco Linksys WRT54GL routers myself, but they also run DD-WRT fine.


Creating a custom Debian package

You’ve created your own application, it works like a charm and you’re very proud of it. Yet installing this application on a different machine requires you to manually copy over files, a VCS checkout, manual configuration or other operations that are still open human to error.

This post describes a method of creating a simple Debian package using dpkg. The focus will be on the creation of a .deb package containing files (pre-compiled), post-installation and removal script, and dpkg-reconfigure support in combination with debconf. At the end of this brief guide you will have a .deb package that can be installed and reconfigured using ‘dpkg -i mycustompackage.deb’ and ‘dpkg-reconfigure mycustompackage’.

This post does not cover how to build a package using the official Debian way, including sources, documentation and package checking using lintian or piuparts. Please refer to the full how to package for Debian guide if you are looking for that specific information.


Creating packages requires the following packages to be installed:

  • build-essential
  • devscripts
  • debhelper

Preparing your package

The basic idea is that a given directory is built into a .deb package. This directory contains all the files required for the installation, as well as a separate ‘DEBIAN’ folder that contains any scripts or files required for dpkg. Let’s start out with the directory itself before diving in deeper.

The directory needs to follow a certain naming convention. The directory name should start with the package name, followed by a dash and then the version number. For example, “lswhelloworld-1.0”.

This directory should contain the ‘DEBIAN’ folder for dpkg and any other files that you wish the package should contain. Note that all the files will be installed at the same given location. For example, if you create a script at “lswhelloworld-1.0/usr/bin/helloworld”, the file will be located at “/usr/bin/”  after installation. Dpkg will also take care of removing the files when you uninstall the package.

After you have placed all the required files at the correct location, lets move on to the files within the ‘DEBIAN’ folder.


The most important file is the control file and should be located at “lswhelloworld-1.0/DEBIAN/control”.  This file contains all the information that dpkg needs to install your package correctly. This is the place where you should define your package name, version (followed by packaging number), architecture, dependencies and basic description of your package.

Lets look at a small example, which includes the minimum required fields to get it to work. There is an extensive explanation about the control file for binary packages available for people that want to learn more about the control file.

Package: lswhelloworld
Version: 1.0-1
Section: base
Priority: optional
Architecture: all
Depends: debconf (>= 0.2.26)
Maintainer: Rene van Aerle <r.vanaerle@leaseweb.com>
Description: Hello World!
Say hello to the user.

The main thing to look for is the Depends field, this field lets you setup the dependencies for your package. In our case we will depend on debconf version 0.2.26 or higher.

The config file, located at “lswhelloworld-1.0/DEBIAN/config” will be run right after the package has been installed or when it is being pre- or re-configured. In the config script we can ask the user questions that may be used during installation. We could use bash to read user input as described on tldp.org, but in general it is advised to use debconf for asking the user questions.

Debconf offers graphical package configuration and stores all the answers within a database. This database of answers can then be used for future reference and thus the values can be re-used in the pre-installation, post-installation, pre-removal and post-removal scripts without bothering the user with the same questions again. Only the dpkg-reconfigure command will re-ask the user questions.

Everytime you want to ask the user a question, you will need to add a template to the templates file, located at “lswhelloworld-1.0/DEBIAN/templates”.

Template: packagename/question1
Type: [select,multiselect,string,boolean,note,text,password]
Default: [an optional default value]
Description: Blah blah blah?
 Blah blah blah. Blah blah. Blah blah blah. Blah blah? Blah
 blah blah blah. Blah blah blah. Blah blah.
 Blah blah blah. Blah blah. Blah blah blah. Blah blah. Blah blah blah.

Template: packagename/question2

All your questions should be included, each identified with a unique template name (in example above: “packagename/questionX”). The type obviously depends on your question. The available data types include:

  • string  holds any arbitrary string of data
  • select  holds one of a finite number of possible values. These values must be specified in a field named Choices. Separate the possible values with commas and spaces, like this, Choices: yes, no, maybe
  • multiselect  just like the select data type, except the user can choose any number of items from the list. This means that the Default field and the actual value of the question may be a comma and space delimited list of values, just like the Choices field.
  • boolean  holds “true” or “false”
  • note this template is a note that can be displayed to the user. As opposed to text, it is something important that the user really should see. If debconf is not running interactively, it might be saved to a log file or mailbox for them to see later.
  • text  this template is a scrap of text that can be displayed to the user. It’s intended to be used for mostly cosmetic reasons, touching up around other questions that are asked at the same time. Unlike a note, it isn’t treated as something the user should definitely see. Less complex front-ends may refuse to ever display this type of element.
  • password  holds a password. Use with caution. Be aware that the password the user enters will be written to debconf’s database. You should consider clearing that value out of the database as soon as is possible.

After you’ve created your templates, you can use debconf to ask the questions in the config file. Note that it is advised to only ask questions within the config file and to do any other operation within the post/pre-installation or post/pre-removal scripts.

The example config script below asks the user 2 questions using debconf.


# Exit on error
set -e

# Source debconf library.
. /usr/share/debconf/confmodule

# Ask questions
db_input low packagename/question1 || true
db_input low packagename/question2 || true

# Show interface
db_go || true

First we include the debconf library and then prepare the questions using ‘db_input’. The priority is set so that the user can skip some questions according to the priority used with the dpkg command and fallback to the default values. (see: Ubuntu Manpage on dpkg-reconfigure)

Debian preinst, postinst, prerm, postrm scripts

The debian scripts are automatically run before or after a package is installed or removed. Along with the file named control, all these files are part of the control section of a debian archive and should be located in the ‘DEBIAN’ folder. For example, the post-installation script will be located at “lswhelloworld-1.0/DEBIAN/postinst”. The following scripts can be created (make sure the files are executeable, ‘chmod 0755’):

  • preinst – this script executes before that package will be unpacked from its Debian archive (“.deb”) file. Many ‘preinst’ scripts stop services for packages which are being upgraded until their installation or upgrade is completed (following the successful execution of the ‘postinst’ script).
  • postinst this script typically completes any required configuration of the package foo once it has been unpacked from its Debian archive (“.deb”) file. Often ‘postinst’ scripts ask the user for input, and/or warn the user that if they accept the default values, they should remember to go back and re-configure that package as the situation warrants. Many ‘postinst’ scripts then execute any commands necessary to start or restart a service once a new package has been installed or upgraded.
  • prerm this script typically stops any daemons which are associated with a package. It is executed before the removal of files associated with the package.
  • postrm – this script typically modifies links or other files associated with foo, and/or removes files created by the package.

Any of the above scripts can query the debconf database and take the appropriate action. To read the answers from the debconf database, you can use the following example code:


# Source debconf library.
. /usr/share/debconf/confmodule

# Fetching configuration from debconf
db_get packagename/question1

db_get packagename/question2

Again we include the debconf library and then use ‘db_get’ to fetch the answer from the debconf database. The value is then stored with the $RET variable. After creating your scripts, it is possible to build the package.

Building the package

To build the package, make sure the debian scripts (config, preinst, postinst, prerm, postrm) have the correct permissions (0755) and make sure the control and templates files are present within the ‘DEBIAN’ folder.


    • control (required)
    • templates (optional)
    • preinst (optional, chmod 0755)
    • postinst (optional, chmod 0755)
    • prerm (optional, chmod 0755)
    • postrm (optional, chmod 0755)
  • (files to be installed at specified location)

If you have all the files in place, you can build the package using ‘dpkg-deb –build’.

rene@ubuntu:~# dpkg-deb --build lswhelloworld-1.0/
dpkg-deb: building package `lswhelloworld' in `./lswhelloworld-1.0.deb'.

This will generate a .deb package that can be installed using ‘dpkg -i lswhelloworld-1.0.deb’ and will run the config and scripts accordingly. You can re-run the config by using ‘dpkg-reconfigure lswhelloworld’ or completely remove it ‘dpkg -r lswhelloworld’.


If you need help in building any of these packages, please leave your comment below.


Symfony2 under Nginx on Ubuntu 12.04

Here at LeaseWeb we use the Symfony2 framework a lot. While many people run Apache2 as their web server, some prefer running Symfony2 under Nginx. At this moment Nginx is very popular among high traffic websites. It is actually the second most popular web server on the internet. Unfortunately the default Nginx configuration will not work with Symfony2 since it does not support the .htaccess format. However, with some small tweaks to the configuration you can make  your server run Symfony2 under Nginx.

For this guide, we used a fresh Ubuntu 12.04 installation, downloaded Symfony Standard 2.2.1 (latest) and installed Nginx 1.1.19 and PHP-FPM 5.3.10 from the standard repositories.

Install Nginx

Firstly, you must install Nginx and start the service.

sudo apt-get install nginx
sudo service nginx start

Install PHP5

Since Symfony2 is a PHP framework, you need to install that as well. To make PHP work with Nginx you must install the PHP-FPM package.

sudo apt-get install php5-fpm

Configure Nginx virtual host

Create a new file at /etc/nginx/sites-available with the name of your domain or project, this will be the Nginx configuration for your Symfony2 project. Edit the file as required.


server {

    # Listen on port 80
    listen 80;

    # Server name being used (exact name, wildcards or regular expression)
    server_name *.website.com;

    # Document root, make sure this points to your Symfony2 /web directory
    root /var/www/website.com/web;

    # Logging
    error_log /var/log/nginx/website.com-error.log;
    access_log /var/log/nginx/website.com-access.log;

    # Handle static files, redirect to app.php if not found
    location / {
        try_files $uri /app.php;

    # Pass the PHP scripts to FastCGI server
    location ~ ^/(app|app_dev|config)\.php(/|$) {
        fastcgi_pass unix:/var/run/php5-fpm.sock;
        fastcgi_split_path_info ^(.+\.php)(/.*)$;
        include fastcgi_params;
        fastcgi_param  SCRIPT_FILENAME $document_root$fastcgi_script_name;
        fastcgi_param  HTTPS off;

Now test the configuration.

sudo nginx -t
nginx: the configuration file /etc/nginx/nginx.conf syntax is ok
nginx: configuration file /etc/nginx/nginx.conf test is successful

Add website.com to your hosts file

If you are following this guide for production you can skip this step. For development you need to add the domain to the hosts file to make sure the current machine reacts when you type in the address. You can do that by running this command:

echo " www.website.com" | sudo tee -a /etc/hosts

Enable site and reload the Nginx configuration

sudo ln -s /etc/nginx/sites-available/website.com /etc/nginx/sites-enabled/website.com
sudo service nginx reload

That should do the trick! Check your http://www.website.com/app_dev.php/, http://www.website.com/app.php/ and http://www.website.com/ locations to verify that everything works correctly.

Using TCP/IP for FPM (optional)

If you prefer using TCP/IP for FPM, open the PHP-FPM pool config file: /etc/php5/fpm/pool.d/www.conf


listen = /var/run/php5-fpm.sock

By line:

listen =

Then change your Nginx site configuration.


fastcgi_pass unix:/var/run/php5-fpm.sock;

By line:


You must reload php-fpm and nginx for the changes to take effect. Note that with TCP/IP you can build a more scalable setup where you have multiple FPM machines and one Nginx as the load balancer in front of them.


UTF-8 in PHP and MySQL under Ubuntu 12.04

UTF-8 is the de facto standard character set for PHP websites and there are but a few reasons not to use UTF-8 (utf_general_ci) as the default MySQL database collation. However, anyone arguing that UTF-16 is a better standard would probably be right, but because UTF-8 is more popular, nobody cares. Unfortunately, the guys at Ubuntu (or upstream at Debian, PHP and MySQL) still have some strange defaults configured in their software, as follows:

  1. PHP connects explicitly to MySQL with an “Latin 1” character set unless you send the “set names utf8” query.
  2. Apache does not specify a character set by default (nor does PHP), letting the browser determine which character set is used.
  3. MySQL sets the “latin1” as default character set and “latin1_swedish_ci” as default collation (for string comparison).

This is a longstanding issue. The reason for these western/Swedish defaults is that MySQL AB has a Swedish origin. Now that MySQL is the world’s most popular web database, and has been bought by Oracle (based in California/US), it seems like a strange choice. These days you would expect the following defaults:

  1. PHP connects to the server and uses the character set of the server, unless specified.
  2. Apache should assume all text content to be UTF-8 encoded.
  3. MySQL should have UTF-8 as the default character set and “utf_general_ci” as the default collation.

It is easy to make Apache/MySQL/PHP (under Ubuntu 12.04) behave the way you like. First we add the character set to Apache:

sudo echo "AddDefaultCharset utf-8" >  /etc/apache2/conf.d/utf8.conf

Now for MySQL, we open “/etc/mysql/my.cnf” and under the “[mysqld]” section we add the following 3 lines:

init-connect='SET NAMES utf8'

For a default of UTF-8 in the MySQL command line client (optional) you must add the following line in the “/etc/mysql/my.cnf” file under the “[client]” section:


Now restart the Apache and MySQL servers with the following commands:

sudo service mysql restart
sudo service apache2 restart

This is really all you have to do on a default Ubuntu 12.04. To check whether or not everything works correctly put the following “utf8.php” file on your website:

mysql_connect('localhost', 'username', 'password');
$re = mysql_query('SHOW VARIABLES LIKE "c%";')or die(mysql_error());
while ($r = mysql_fetch_assoc($re))
{ echo $r&#91;"Variable_name"&#93;.': '.$r&#91;"Value"&#93;; echo "<br />";

The output should be:

character_set_client: utf8
character_set_connection: utf8
character_set_database: utf8
character_set_filesystem: binary
character_set_results: utf8
character_set_server: utf8
character_set_system: utf8
character_sets_dir: /usr/share/mysql/charsets/
collation_connection: utf8_general_ci
collation_database: utf8_general_ci
collation_server: utf8_general_ci
completion_type: NO_CHAIN
concurrent_insert: AUTO
connect_timeout: 10

Let me know if you still have any trouble making it work. Good luck!


Turn off reverse DNS lookups for Apache access logging

If reverse DNS lookups are shown in your Apache access log, while you were expecting (and needing) IP addresses, this post may help.

htaccess ip address block
Figure 1: Example “.htaccess” file for blocking IP addresses

By default IP addresses are logged in the Apache access log “/var/log/apache2/access.log” unless you specify “HostnameLookups On” in “/etc/apache2/apache2.conf” (it is off by default). But if you are restricting access to specific content using an “.htaccess” file with an “allow from” or “deny from” construction this changes. If you have this in your “.htaccess” file IP addresses are logged:

deny from

But if you add a comment to the line like this reverse DNS lookups are logged:

deny from # my home ip address

Cause and work-around

This is caused by “mod_authz_host” (which is enabled by default) that kicks in and converts the IP addresses to hostnames. The work-around is to put the comment on the previous line:

# my home ip address:
deny from

It also happens when you use a regular expression or a host name (which is more obvious). Plain IP addresses and CIDR notation do not trigger the conversion. Hopefully this post can save you some time.