Installing OpenWrt Kamikaze on the ASUS WL500GPV2

I'm a big fan of OpenWrt for more than a year when I got to know it.  I daydreamed about a powerful router that is fully controllable and runs Linux.  Little did I know in those times about specialized Linux distributions running on routers. I can remember when I started to chat with my good friend, Dömi about this topic and he immediately mentioned OpenWrt. Fast forward one month and an ASUS WL500GPV2 was sitting on my desk running OpenWrt Kamikaze.

I'd like to mention that although I'll talk about the V2, I wish I would have bought the V1 because that's much more hackable. You can upgrade its memory and/or replace its Mini PCI WiFi card, but you can't do that with the V2, unfortunately.

The reason I put this guide together is that I wanted a detailed configuration guide on the topic because it's quite demanding to rebuild my mental model of how things work after some months. Be aware that that this HOWTO is not for the faint of heart. I assume you know what you're doing.

1) Download the firmware

wget http://downloads.openwrt.org/snapshots/trunk/brcm-2.4/openwrt-brcm-2.4-squashfs.trx

2) Set up localhost to hang on the 192.168.1.x subnet

sudo ifconfig br0 down  # in case you use VirtualBox host networking
sudo brctl delbr br0  # also for VirtualBox
sudo ifconfig eth1 192.168.1.2

3) Flash the router firmware

# Boot the router into diagnostic mode by pressing the reset button right after restart. Wait until the power LED starts blinking.
atftp --trace --option "timeout 1" --option "mode octet" --put --local-file openwrt-brcm-2.4-squashfs.trx 192.168.1.1
# Wait at least half a minute otherwise the router won't get flashed properly and boots into diagnostic mode.

4) Set up SSH public key authentification

# Disable and enable router and wait for the boot that takes about half minutes.
telnet 192.168.1.1
passwd
# At this point telnetd gets stopped and the dropbear sshd gets started.
exit
scp ~/.ssh/id_rsa.pub [email protected]:/etc/dropbear/authorized_keys
ssh [email protected]

5) Set up WAN connection

# Use this for cable modem connections:
uci set network.wan.proto=dhcp

# Use this for ADSL connections:
uci set network.wan.proto=pppoe
uci set network.wan.username=yourusername
uci set network.wan.password=yourpassword

# Let's commit the changes finally:
uci commit network
ifup wan
reboot  # If the WAN connection is still down at this point.

6) Set up WiFi connection

uci set wireless.wl0.disabled=0
uci set [email protected][0].ssid=yourssid
uci set [email protected][0].encryption=psk2
uci set [email protected][0].key=yourpassword
uci commit wireless
wifi

7) Install packages

opkg update
opkg install mc ndyndns etherwake ntpclient openvpn kmod-fs-ext2 fdisk e2fsprogs kmod-usb2 kmod-usb-storage nmap
# Here you can remove every luci related packages if you don't need the web interface.

8) Restore configuration

# It's pretty easy to restore configuration from a backup once you made a backup like this:
ssh your-router 'tar czf - /etc /root' > kamikaze-backup-`date +%Y-%m-%d_%H-%M-%S`.tar.gz

9) Supercharge storage space

# Plug in the pendrive.
mkfs.ext2 /dev/scsi/host0/bus0/target0/lun0/part1
mount /dev/scsi/host0/bus0/target0/lun0/part1 /mnt
cp -a /bin /etc /home /lib /root /sbin /usr /www /mnt
mkdir /mnt/dev /mnt/jffs /mnt/mnt /mnt/proc /mnt/rom /mnt/sys /mnt/tmp /mnt/var
umount /mnt

cat < /etc/config/bootfromexternalmedia
config bootfromexternalmedia
    option target   '/mnt'
    option device   '/dev/scsi/host0/bus0/target0/lun0/part1'
    option modules  'usbcore ehci-hcd scsi_mod sd_mod usb-storage jbd ext2'
    option enabled  '1'
END
cat < /sbin/init.new
#!/bin/sh
. /etc/functions.sh
config_load "bootfromexternalmedia"
local section=\$CONFIG_SECTION
config_get      "target"   "\$section" "target"
config_get      "device"   "\$section" "device"
config_get      "gpiomask" "\$section" "gpiomask"
config_get      "modules"  "\$section" "modules"
config_get_bool "enabled"  "\$section" "enabled" '1'
[ "\$enabled" -gt 0 ] && {
    [ -n "\$gpiomask" ] && {
        echo "\$gpiomask" > /proc/diag/gpiomask
    }
    for module in \$modules; do {
        insmod \$module
    }; done
    sleep 5s
    mount -o rw "\$device" \$target
    [ -x \$target/sbin/init ] && {
        . /bin/firstboot
        pivot \$target \$target
    }
}
exec /bin/busybox init
END

chmod a+x /sbin/init.new
ln -f -s /sbin/init.new /sbin/init
reboot

Standardizing the command line interface

Few days ago I've tried to do some scripting with the s3cmd.rb utility and I couldn't find a way to carry out the task because of the interactive nature of s3cmd.rb. I've made some search on the s3sync forum and finally found the solution:

yes | s3cmd.rb list mybucket | grep -v 'More? Y/n:'

I was surprised to find out that the "yes" utility is part of GNU Coreutils and I didn't know about it. I also find funny the hacky nature of the solution. It's not bulletproof because if your bucketname / keyname contains the "More? Y/n:" string then you're screwed, but that's a highly unlikely case and I admit that the above script should work in practice.

I was thinking on how command line applications could be standardized so they'd become more usable, less of a pain. Here are my suggestions:

  • If the default interactive mode makes sense, then provide a -y, –yes option to make scripting easy.
  • If recursion makes sense, provide the -r, –recursive option. Please don't use -R with capital "r", like chown does! I don't wanna look up the manual every time in such trivial cases.
  • Make your utility accept – as the ending of your arguments so filenames starting with a dash won't be misinterpreted.
  • Don't add the scripting language related extension, like .py, .rb, .pl to your utility, please! I want to type it as fast as it's possible and I don't care what language you use unless I have to hack your crappy script which shouldn't be the case.

I could probably come up with dozens like the above, but these are my initial thoughts.

MediaWiki on SourceForge – The HOWTO

This is my third and last post regarding the installation of MediaWiki on SourceForge.

In my first post, I concluded that it's not possible to install MediaWiki on SourceForge. In my second post, I acknowledged that it's doable and in this post of mine, in my third post on the subject, I'm gonna actually describe how to do it in a way that will make you understand what are you doing and why.

Just to let you know, what you're reading now is probably the most complete and clear HOWTO ever written on the subject. It's not that there aren't any resources out there, but they're not very usable or clear in my experience.
As an additional note, it wasn't fun to compile all this information into a quality document like this, but I was so pissed off by this issue and I wasted so much time with it, that I really don't wanna anyone out there to suck days with this process like I did. So if you're eager to install MediaWiki into your project web space on SourceForge, this guide will worth you pure gold. I should probably charge you, but I'm such a nice person…

Throughout this HOWTO, i'll mark text regions with bold formatting that are supposed to be replaced by your installation settings.

Here are the steps to make the thing happen:

  1. Deploy MediaWiki source on SourceForge:
    1. Download MediaWiki to your local machine.
    2. scp the tarball to your project web space, since outbound connections are forbidden from the SourceForge shell:
      $ scp mediawiki-version.tar.gz username@shell.sf.net:/home/groups/p/pr/projectname/htdocs
    3. Extract the tarball on SourceForge:
      $ ssh username@shell.sf.net
      $ cd /home/groups/p/pr/projectname/htdocs
      $ tar xzvf mediawiki-version.tar.gz
    4. Symlink the wiki directory, so we'll have less burden when upgrading to a more recent version of MediaWiki:
      $ ln -s mediawiki-version wiki
  2. Set up persistent directories. Since project directories on SourceForge are not writable by Apache, we need to create writable directories for storing volatile data and modify some configuration details accordingly:
    1. Create a persistent directory for your project in /tmp/persistent/tmpname. tmpname should be the same as your projectname. In case /tmp/persistent/projectname is already created by someone else, you need to choose another name.
      $ mkdir /tmp/persistent/tmpname
    2. Create writable directories for initial configuration, session management and image data:
      $ cd /tmp/persistent/tmpname
      $ mkdir config sessions images
      $ chmod a+w *
    3. Symlink the config and images MediaWiki directories to your persistent directory:
      $ cd /home/groups/p/pr/projectname/htdocs/wiki
      $ cp config/index.php /tmp/presistent/tmpname/config
      $ rm -f config/index.php
      $ rmdir config
      $ ln -s /tmp/persistent/tmpname/config
      $ rm -f images/.cvsignore images/README
      $ rmdir images
      $ ln -s /tmp/persistent/tmpname/images
  3. Prepare the source for installation. /home/groups/p/pr/projectname/htdocs/wiki/config/index.php needs to be hacked in order to work correctly with the persistent directory setup:
    1. Point to the correct wiki root directory by replacing line 117:
      $IP = dirname( dirname( __FILE__ ) );
      with:
      $IP = "/home/groups/p/pr/projectname/htdocs/wiki";
      and by replacing line 1125:
      \$IP = \"{$slconf['IP']}\"
      with:
      \$IP = \"/home/groups/p/pr/projectname/htdocs/wiki\"
    2. Point to the correct languages directory by replacing line 1296:
      global $wgLanguageNames;
      with:
      global $wgLanguageNames, $IP;
      and by replacing line 1306:
      $d = opendir( "../languages" );
      with:
      $d = opendir( "$IP/languages" );
    3. Point to the correct SQL database definition files by replacing all the "dbsource( "../" strings with "dbsource( "$IP/" strings. (Watch for the space after the parantheses.)
  4. Install MediaWiki. Point your browser to http://projectname.sf.net/wiki/config and install MediaWiki through its web interface:
    1. Select Turck MMCache for shared memory caching.
    2. Use your MySQL admin account as the DB username.
    3. On the end of the page there should be an "Installation successful!" message. If it's not there, the installation may have interrupted due to server suckiness which happended to me several times. If that's the case, you should rerun this script. You may also want to drop your wiki database prior rerunning the install script if things don't work out.
    4. Move the generated LocalSettings.php to the wiki root directory:
      $ mv /tmp/persistent/tmpdir/LocalSettings.php /home/groups/p/pr/projectname/htdocs/wiki
    5. Remove old config, since there's no use of it and it also imposes a security risk:
      $ rm -f /tmp/persistent/tmpname/config/index.php
      $ rmdir /tmp/persistent/tmpname/config
      $ rm -f /home/groups/p/pr/projectname/htdocs/wiki/config
    6. Correct the default session save path by including into /home/groups/p/pr/projectname/htdocs/wiki/LocalSettings.php at the end of the PHP section:
      session_save_path("/tmp/persistent/tmpdir");
  5. Fine-tune MediaWiki for the environment. You have a workable MediaWiki installation at this point, but there are still several steps to be made in the current environment:
    1. Restrict editing permissions by including into LocalSettings.php:
      $wgGroupPermissions['*']['edit'] = false;
      $wgGroupPermissions['user']['edit'] = false;
    2. Display SourceForge logo. SourceForge requires every projects to display their logo on every project web page for statistical and PR purposes. There are plenty of docs on this topic.

Thanks

I'd like to thank Diego Torres Milano, developer of the JGlade project for writing the mediawiki-sf installation script which I learned a lot from.