The more packages you install on your OpenWRT, the more space you need. If your router has an USB port, here is a simple way to replace the JFFS flash partition with an external USB stick or hard drive.

Install packages

First, install needed modules and a few programs.

~$ opkg install kmod-scsi-core kmod-usb-core kmod-usb2 kmod-usb-storage
~$ opkg cfdisk e2fsprogs swap-utils

Plug your USB key and check kernel messages. It should give you the path to your USB drive.

~$ dmesg
usb.c: USB disconnect on device 01:03.2-2 address 2
hub.c: new USB device 01:03.2-1, assigned address 3
scsi1 : SCSI emulation for USB Mass Storage devices
Vendor: VBTM Model: Store 'n' Go Rev: 1.04
Type: Direct-Access ANSI SCSI revision: 02
Attached scsi removable disk sdb at scsi1, channel 0, id 0, lun 0
SCSI device sdb: 1001472 512-byte hdwr sectors (513 MB)
sdb: Write Protect is off
/dev/scsi/host1/bus0/target0/lun0: p1 p2 p3
WARNING: USB Mass Storage data integrity not assured
USB Mass Storage device found at 3

Prepare USB device

Now partition & format your usb stick as follows.

~$ cfdisk /dev/scsi/host1/bus0/target0/lun0/disc
cfdisk (util-linux-ng

Disk Drive: /dev/scsi/host1/bus0/target0/lun0/disc
Size: 512753664 bytes, 512 MB
Heads: 16 Sectors per Track: 62 Cylinders: 1009

NameFlags Part Type FS Type [Label] Size (MB)
disc1 Primary Linux ext3 [storage] 463.21
disc2 Primary Linux swap / Solaris 49.27

Format the first linux ext3 partition.

~$ mke2fs -j /dev/scsi/host1/bus0/target0/lun0/part1
mke2fs 1.40.11 (17-June-2008)
Filesystem label=
OS type: Linux
Block size=1024 (log=0)
Fragment size=1024 (log=0)
113344 inodes, 452320 blocks
22616 blocks (5.00%) reserved for the super user
First data block=1
Maximum filesystem blocks=67633152
56 block groups
8192 blocks per group, 8192 fragments per group
2024 inodes per group
Superblock backups stored on blocks:
8193, 24577, 40961, 57345, 73729, 204801, 221185, 401409
Writing inode tables: done
Creating journal (8192 blocks): done
Writing superblocks and filesystem accounting information: done

This filesystem will be automatically checked every 20 mounts or
180 days, whichever comes first. Use tune2fs -c or -i to override.

And mount it

~$ mkdir -p /mnt/root
~$ mount /dev/discs/disc0/part1 /mnt/root

We may also need some swap just in case the router runs out of memory

~$ mkswap /dev/discs/disc0/part2
~$ swapon /dev/discs/disc0/part2

Copy all fs into new mounted partition.

~$ tar cvO -C / bin/ etc/ root/ lib/ sbin/ usr/ www/ var/ | tar x -C /mnt/root
~$ mkdir -p /mnt/root/tmp && mkdir -p /mnt/root/dev && mkdir -p /mnt/root/proc && mkdir -p /mnt/root/jffs && mkdir -p /mnt/root/mnt/openwrt && mkdir -p /mnt/root/sys

Use the new partition as root partition

Here comes the interesting part. Create a new script in init.d to mount the usb drive at startup.

~$ cat > /etc/init.d/mountusb << EOF
#!/bin/sh /etc/rc.common


start () {
echo "loading USB and ext3 modules"

for module in usbcore usb-ohci uhci ehci-hcd scsi_mod sd_mod usb-storage jbd ext3; do
insmod $module
sleep 2s

[ "$FAILSAFE" != "true" ] && [ -b $EXTERNAL_PARTITION ] && {
mount $EXTERNAL_PARTITION /mnt/root
[ -x /mnt/root/sbin/init ] && {
mount -o move /proc /mnt/root/proc && \
pivot_root /mnt/root /mnt/root/mnt/openwrt && {
mount -o move /mnt/openwrt/dev /dev
mount -o move /mnt/openwrt/tmp /tmp
~$ chmod +x /etc/init.d/mountusb
~$ cd /etc/rc.d/ && ln -s ../init.d/mountusb S06mountusb

This script uses pivot_root to make /mnt/root the new / and will move the current root folder to /mnt/root/mnt/openwrt. The other mount commands will make sure the /proc, /dev & /tmp are updated.

Now reboot your router "et voilà"! You're ready to fill all this space with new packages & stuff.