Debian / Soekris Reference

Part 1. Introduction

1.0 - Preamble

This guide covers installing Debian GNU/Linux 7.0 (Wheezy) on Soekris net5501 boxes, but should also work for net4xxx and Debian Squeeze, Jessie (but read the appendix first) or derivatives. It should also serve as a convenient reference for using serial consoles, dd, pxe, debian, linux and other belgiums. Most files referenced are available from, for your copy/paste/wget pleasure. The author is not available for contact at takhis dot net, and most certainly not under the alleged alias of reverie.
1.1 - The Hardware

The Soekris 5501 from Cortex Systems packs a 500MHz AMD Geode processor, 512 MiB RAM, 4 100Mib Ethernet ports, 1 external USB-2 port, 1 external serial port used for console, 1 internal CF adapter used for primary storage, and various internal connectors for expansion.

Do be warned, the net5501 is old hardware now, with a custom closed source non-acpi compliant and incredibly buggy BIOS, which requires numerous work-arounds in Linux. The SATA connector is reversed (so you must buy connectors from their homepage), soldering might be required to keep the clock in check (see Issue0004 if drifting), and be prepared to replace the power supply as it is cheap and will die. Futhermore, few combinations of CF cards and HD's will actually work, it is almost a requirement that you stick to a few specific known to work models, namely the SanDisk cards available from their homepage (That's SanDisk Ultra, not Extreme!).

Most models are available from
Additional information is available at
1.2 - The Software

Debian GNU/Linux is the Operating System of choice for embedded devices (on the Linux side), as ports are readily available for most architectures and platforms. Although the hardware covered in this guide uses the normal i386 architecture and PC-BIOS, future use of cheap ARM devices is thus still possible using the same base / expertise / familiarity.

But more importantly, the Debian release cycle is very slow, on the count of years, with many more years of security updates. And this is preferred when putting together boxes designed to last forever, from the dusty closet to the factory floor.

Although this guide was originally written for Debian 4 (Etch, 2007), it has now been updated to only cover version 7 (Wheezy, 2013), with few changes... Which is fairly impressive when you think about it. So, in turn, maybe little will change if you use another Debian/Ubuntu-based system, but no promises.
1.3 - Compact Flash and Gotcha's

Although CF has many advantages (no mechanical failure, industrial tolerance, easy to handle, low power, okay seek), it also has drawbacks; they deteriorate from writes, despite wear-leveling, and so we must shy away from needlessly writing to it.

As a general rule of thumb when dealing with flash, one should always disable swap (honestly, this serves no purpose anymore anyways), mount file-systems with the "noatime" option (which will prevent them from updating the journal with last access times of files, which is only used on ancient news servers) and disable unnecessary logging (enable only what you need, when you need it), but further tweaking is recommended.

As mentioned, the Soekris (net5501 specifically) has numerous problems with varying CF cards, from cheap ones to fast ones, apparently, when combined with a HD, only one of them can support UDMA, mostly due to the crappy BIOS. A generally useful work-around is to force the flash to be the secondary drive in comBIOS and nudging libata, like so:
> set FLASH=Secondary
> set BootDrive=81 80 F0 FF

# For stock kernels
echo "options libata force=short40c,1.1:mwdma2" > /etc/modprobe.d/libata.conf
update-initramfs -u

# For custom kernels

# Second Gotcha, Debian Installer messes up GRUB2/MBR
dpkg-reconfigure grub-pc
So if that's the reason you are reading this, congratulations, you can stop reading now...

Don't worry about the above, it was written for the desperate googler, and will all be repeated in the guide.
1.4 - Reading and Writing System Images

The use of CF has another advantage, they are small and handy, and makes it very easy to copy the entire file-system, partition table, MBR, warts and everything, to a file and back again. The process, once familiarized, is quite easy.

Connect the CF card to your PC somehow, figure out the device name (dmesg|tail usually reveals it to be something like "sdc", notice we want to copy entire disks, warts and all, instead of individual partitions, hence "sdc" instead of "sdc1"). You might want to add "sg" to /etc/modules (modprobe sg now) before inserting a CF, udev tends to load things in the wrong order these days. If it's not picked up right away, force by poking with any kind of stick (fdisk -l /dev/sdc). Also if you've modified it, you need to replug it to update partition tables. I apologize for Linux being more quaint than DOS ): Speaking of partition tables, the simplest way to expand an image (say, if you bought a bigger CF) is to just resize them in gparted.

The tool used to perform these operations is called "dd", all it does is copy bits from one place to another. It is for this reason said to be the number one tool for System Administrators and Programmers alike, as it not only moves the problems from one place to another, but causes them to grow! The syntax is as follows: "dd if=inputfile of=outputfile [options]". If no input or output is specified, STDIN/STDOUT is presumed, so to redirect or pipe the data we simply leave one of them out.

Now, to make a copy of a CF, we do like this:
dd if=/dev/sdc|gzip>myImage.img.gz
Notice we compress the data on-the-fly with gzip, as gigabyte files can be quite unwieldy. When we want to restore our box, we can simply write that image out again, or we can configure a completely new box, like so:
zcat myImage.gz|dd of=/dev/sdc
This process takes roughly a minute or two per gigabyte. This is quite the steal, compared to repeating the steps in this guide, each taking as much as an hour.

You can find a dd for Windows at
1.5 - Serial Terminal, MiniCom & comBIOS Settings

Instead of the traditional VGA and PS/2 connectors, the Soekris box uses the serial port for terminal access. This is actually the traditional Unix way of using computers (back when they were all called mainframes), but will require some getting used to.

In order to connect to the Soekris box, we need a terminal program, this would be PuTTY in Windows, in Linux we have, and use "minicom" (apt-get install minicom lrzsz). First we must configure minicom to use the correct serial port and the following baud-rate/options: 19200-8n1, as these are the defaults for the Soekris box. To configure we type:
sudo minicom -s
Replicate the following settings:

Serial port setup: A=/dev/ttyS0, E=19200 8N1, No to F and G.

Hit escape once to return to the configuration menu and select "Save setup as dfl" then "Exit from Minicom". From now on we can just type:
sudo minicom
This will bring you to the main screen. To exit hit "ctrl+a" followed by "q". Try doing this now, then connect a Soekris box and power it on. You should now see a bunch of text flickering across the screen, if you don't, try changing the serial port, mess around in your bios, load random modules and pray. Hint: /dev/ttyS0 is synonym for COM1, for USB try /dev/ttyUSB0 or /dev/ttyACM0. You can usually find out the name of the tty device using dmesg, e.g. "dmesg|grep serial".

Presuming everything went okay, we will now familiarize ourselves with the BIOS. When power is connected you will have a few seconds to enter the BIOS, press "ctrl+p" to do so. If successful a prompt (>) will await us patiently, if not, cut the power and try again.

The very first line transmitted should read something like: "comBIOS ver. 1.32i..." (you may have to scroll up a bit), if the BIOS is older than that, a firmware upgrade is recommended (see Appendix D). Next, to see the current BIOS settings simply type "show" at the prompt.

The following default options need to be set if they do not match the output of show, otherwise our images and installation procedures will not work:
> set ConSpeed=19200
> set PCIROMS=Enabled
> set PXEBoot=Enabled
> set FLASH=Secondary
> set BootDelay=3
> set BootDrive=81 80 F0 FF
Verify the settings with "show" before rebooting. Re-verify after reboot (ctrl+p), as the BootDrive setting sometimes doesn't stick. Normally you would just pop in a prepared CF and connect over Ethernet. However, this reference is divided into stages, the first one being the initial installation. So, how do we install a new Debian system onto an empty CF when there is no CD/FD/USB boot support?

Part 2. Installation

2.0 - PXE Network Booting

Preboot Execution Environment simply means that we load the boot loader over Ethernet. To be specific, a special DHCP request is made and the IP-address of a TFTP boot server is returned along with the file-name of the boot-loader, which is then retrieved using TFTP (a simpler, trivial version of FTP).
2.1 - Preparing the Soekris for PXE Network Booting

To do this, enter the Soekris BIOS (ctrl + p) and type:
boot f0
F0(zero) is the BIOS code for eth0 (the first Ethernet port), like 0x80 for primary IDE, 0x81 for secondary, etc.. Make sure a cable is connected first. You will now see something like:
CLIENT MAC ADDR: 00 00 24 C8 B2 10
Those numbers are important and you should write them down, it is the MAC address of the Ethernet device, which we will use to configure the DHCP server to hand out the necessary information to begin the installation.
2.2 - Preparing the PXE Network Boot Server

As root on any old Debian box, we first install the necessary software:
apt-get install isc-dhcp-server tftpd-hpa
nano /etc/dhcp/dhcpd.conf
Here is an example dhcpd.conf, modify to fit your needs:
ddns-update-style interim;
option domain-name-servers;
default-lease-time 600;
max-lease-time 7200;
log-facility local7;

subnet netmask {
 option domain-name "home";
 option subnet-mask;
 option broadcast-address;
 option domain-name-servers;
 option routers;
 default-lease-time 259200;
 max-lease-time 518400;

host soekris {
 filename "pxelinux.0";
 server-name "";
 hardware ethernet 00:00:24:c8:b2:10;

host mybox {
 hardware ethernet 00:00:00:00:00:42;
Replace the MAC address (hardware ethernet) with the one we got from the previous step. Be sure to use the correct syntax (lower case, colons instead of spaces). Server-name refers to the TFTP server, usually the same box. The filename referenced is pxelinux.0, which is the default name for Debian net-installers. So let's set that up now. We'll start by fetching a Debian netboot image and configure it for serial console @19200n8.
tar zxvf netboot.tar.gz -C /srv/tftp
rm netboot.tar.gz /srv/tftp/pxelinux.cfg
mkdir /srv/tftp/pxelinux.cfg
cat >> /srv/tftp/pxelinux.cfg/default << EOF DEFAULT soekris LABEL soekris kernel debian-installer/i386/linux append vga=normal initrd=debian-installer/i386/initrd.gz -- quiet console=ttyS0,19200n8 PROMPT 0 TIMEOUT 0 EOF
Remember to restart the dhcp server:
/etc/init.d/isc-dhcp-server restart
We are now ready to start the installation, returning to the Soekris box enter the BIOS (ctrl + p) and type "boot f0".
2.3 - Debian Installation

After a while, you will be greeted with the usual, and hopefully familiar, Debian-installer. The process, as outlined below, is largely the same for any box. The following options should be used (replace regional settings);
1.	Language, Country and Locale: English, Denmark, en_US.UTF8
2.	Network: eth0, dhcp, soekris, home, no proxy
3.	Partitioning: Manual, the following scheme was used:
	sdb1 (CF) as max size Primary (Beginning) ext3 for / with noatime option.
	Continue despite lack of swap (choose no when asked)
4.	Password: Root password is set to "changeme" (hint hint, nudge nudge)
5.	Users: Forced on us, so we make a "randomdent" and delete it when done.
6.	Software selection: Standard, ssh. We want a mostly clean system.
7.	Grub: Yes and yes, unfortunately, installer is bugged and installs to wrong MBR, so:
8.	Do not hit <continue>, instead, <Go Back> and select "Execute a shell":

# installer mounts root on /target, and a dev/ on top of it
mount --bind /proc /target/proc
mount --bind /sys /target/sys
chroot /target /bin/bash --login
If you accidently rebooted (and the CF is a dud), don't worry, just follow the next chapter to get back into a working chroot, and then come back here.

Now for the hard part. The Soekris net5501 has a buggy BIOS, and can only support 1 drive in UDMA mode, that means if your CF is anything but an old slow crappy CF like the SanDisk Ultra from their homepage, the Linux kernel will throw a bunch of errors and limit transfer rates of both drives to nothing, this sucks, so we need to apply the following work-around, if, if and only if, you have both a CF and a HD installed
# If an invalid libata.force option is used, the kernel will just panic!
# So this option must only be used on a net5501 featuring both a CF and HD.
echo "options libata force=short40c,1.1:mwdma2" > /etc/modprobe.d/libata.conf

# Try not to mess with the .force, the documentation is wrong, the syntax broken, kernel, panic.
Next we optimize the initrd, the Soekris has trouble working with large initrd's (and initrd's won't work in anything but GRUB2 either, at least as of Wheezy), revert to using device names instead of UUID's, update the initrd, and re-install GRUB to, heck, to ALL MBR's, it's the only way to be safe against random GRUB freezes.
sed -i 's/MODULES=most/MODULES=dep/' /etc/initramfs-tools/initramfs.conf
#sed -i 's/#GRUB_DISABLE_LINUX_UUID=true/GRUB_DISABLE_LINUX_UUID=true/' /etc/default/grub

# Update the INITRD
update-initramfs -u

# The Debian Installer will probably mess up the
# Verify the order, the CF should be hd1, manually correct if wrong
grub-install --recheck /dev/sdb
nano /boot/grub/

# Be Safe, check off all MBR's, otherwise GRUB2 can confuse itself and freeze!
# It should automatically run "update-grub" for you as well.
dpkg-reconfigure grub-pc

Finish and Reboot.

It should now successfully reboot into your new Debian system, the first thing we do is see how well our hardware performs (are you feeling lucky?)
dmesg|grep ata|grep configured
If it says something like MWDMA2 for 1.1 and UDMA/100 for 1.0, then you're golden. If however 1.0 has been set to an abysmal PIO4, then you're effed. That means you have a CF card that the Soekris box simply cannot work with, and although your box is usable, your HD will be very slow. I highly recommend simply buying a new CF at this stage and starting over. You are of course welcome to play with libata force settings (remember to rebuild the initrd), your best bet is probably libata dma=1 instead of force, however, last I tried, I tried all combinations, and no luck, sorry.

Moving on, we remove the temporary user and fix one critical bug. For some odd reason Debian has defaulted to generate udev rules to make the Ethernet devices static by remembering their MAC, so right now the first Ethernet device may be called eth0, but dd the image to another box, the MAC is different, and so the first Ethernet port would become eth4 and so on, very annoying, at least for our purposes:
userdel -r randomdent
rm /etc/udev/rules.d/70-persistent-net.rules
rm /lib/udev/rules.d/75-persistent-net-generator.rules
If you've successfully rebooted and things seems to be working, well, that makes what we have right now a pristine system, and that is a really good place to take a break, "halt" the system, and image it:
dd if=/dev/sdc|gzip>soekris-pristine.img.gz
You don't have to, of course, but you might thank yourself later, as the above steps can be very tedious to reproduce.
2.4 - Using the Debian Installer for System Rescue

We pause our guide momentarily to re-use what we just learned for future maintenance. Usually if the boot-loader stops working for you, you can repeat the installation-process above, but when reaching step 9 (partitioning) simply select "Go back", then further down select "Execute a shell". From here, you can "chroot" into the disk, this process is slightly tricky but the general gist of it is as follows:
mkdir /target
mount /dev/sdb1 /target
mount --bind /dev /target/dev
mount --bind /proc /target/proc
mount --bind /sys /target/sys
chroot /target /bin/bash --login

# grub2
nano /etc/default/grub
nano /boot/grub/
# || grub-install /dev/sdb
# || dpkg-reconfigure grub-pc

# grub1
nano /boot/grub/menu.lst
grub-install /dev/sdb

# lilo
nano /etc/lilo.conf

# extlinux
nano /boot/extlinux.conf
cat /usr/lib/extlinux/mbr.bin > /dev/sdb

# fsck
fsck.ext3 /dev/sdb

If the boot-loader actually works, you are generally better off just using single-user mode for repairs (that would be the "recovery mode" entry in grub2, for others, or in general, just append "1" to the boot options). If the filesystem checks out, you can remount it read-write like so:
mount -o remount,noatime,rw /

Part 3. Optimization and Cleanup

3.0 - Disks and Filesystems

Set a few sane defaults for ensuring automatic booting and less wear:
sed -i 's/#FSCKFIX=no/FSCKFIX=yes/' /etc/default/rcS
sed -i 's/#RAMLOCK=yes/RAMLOCK=no/' /etc/default/tmpfs
sed -i 's/#RAMSHM=yes/RAMSHM=no/' /etc/default/tmpfs
sed -i 's/#RAMTMP=no/RAMTMP=yes/' /etc/default/tmpfs
tune2fs -c 0 -i 0 /dev/sdb1
tune2fs -c 0 -i 0 /dev/sda1
With root on flash, it is possible to keep the hd powered down most of the time:
apt-get install hdparm
cat >> /etc/hdparm.conf << EOF

/dev/sda {
 spindown_time = 60
I should probably mention that I used to just put a hdparm line in rc.local, but since wheezy, I couldn't get that to work at all, the hdparm package will do all sorts of stuff behind your back which overwrites whatever you do, so now, use the hdparm.conf. So if you had this problem, now you know why. Another thing to note is that I also failed to reliably power down the hd if I used ext4 (it would keep waking up, regardless of mkfs and fstab options), and this is why we stick to ext3. And on the thought of disks, most combinations outside of keeping the hd as master and the flash as slave, despite being root, resulted in problematic performance, which is why we stick to reversed sda and sdb.

Speaking of disks, you might want them mounted by now. Sample fstab:
# /etc/fstab (man 5 fstab)
/dev/sdb1	/		ext3	noatime,errors=remount-ro	0 1
/dev/sda1	/mnt		ext3	noatime				0 2
#/dev/sdc1	/mnt/usb	vfat	rw,user,noauto,uid=1000,gid=100,fmask=133,dmask=022 0 0
And a few personal tweaks;
# make life a little more quiet
sed -i 's/session    optional    optional' /etc/pam.d/login
sed -i 's/session    optional    optional' /etc/pam.d/sshd

# if you want to create users at this point and want groups to mean a damn
sed -i 's/# GROUP=100/GROUP=100/' /etc/default/useradd
sed -i 's/USERGROUPS=yes/USERGROUPS=no/' /etc/adduser.conf
3.1 - Aptitude and Services

We have now worked long enough on this box for us to become frustrated with the lack of useful tools (mc), so it's time to install the basics, we optimize and start apt'ing:
sed -i 's/deb-src/#deb-src/' /etc/apt/sources.list
echo 'Acquire::Languages "none";' > /etc/apt/apt.conf.d/99translations

apt-get update
apt-get upgrade

# must haves
apt-get install fuse mc screen sudo fortunes fortunes-bofh-excuses
sed -i 's/#user_allow_other/user_allow_other/' /etc/fuse.conf
sed -i 's/#startup_message off/startup_message off/' /etc/screenrc
sed -i 's/vbell on/vbell off/' /etc/screenrc

# network tools
apt-get install arping bind9utils ncftp rsync
apt-get --no-install-recommends install nmap

# network services
apt-get install bind9 esmtp-run isc-dhcp-server ntp nullidentd openbsd-inetd tftpd-hpa

# we use esmtp instead of broken exim4, settings to follow...
apt-get purge exim4 exim4-base exim4-config exim4-daemon-light

# remove fluff that got installed (optional; nfs, apt, grub dualboot probe)
apt-get purge rpcbind nfs-common at libevent-2.0-5 libnfsidmap2 libtirpc1
apt-get purge installation-report tasksel tasksel-data aptitude aptitude-common
apt-get purge os-prober

# stuff I use, just ignore this
#apt-get install cfv p7zip-full par2 parchive rtorrent unrar-free unzip
#apt-get install mediatomb-daemon samba

# clean up after our selves
apt-get clean

# clean up after debian
sed -i 's/do_symlinks = yes/do_symlinks = no/' /etc/kernel-img.conf
rmdir /media /opt
rm /initrd.img /vmlinuz
Debian still depends on a mail server, how quaint, we will oblige, just not with exim, let's use something simple which actually fits into the way e-mail works now (using gmail as sample provider). A forwarder:
# /etc/esmtprc (man 5 esmtprc)
mda "/usr/bin/procmail -d %T"
And call me old fashioned, but let's use inetd for the rare things (in case you don't know, it's a legacy daemon which in turn only spawns processes once a connection is made on the relevant port)
# append this to /etc/inetd.conf (man 5 inetd.conf)
ident   stream  tcp     nowait  nobody  /usr/sbin/nullidentd    nullidentd
tftp    dgram   udp     wait    root    /usr/sbin/in.tftpd /usr/sbin/in.tftpd -s /srv/tftp
Want to have your own time server?
# /etc/ntp.conf (man 5 ntp.conf)
server iburst
server iburst
server iburst
server iburst

fudge stratum 8 refid NIST

restrict default kod notrap nomodify nopeer noquery
restrict mask nomodify
restrict mask nomodify

And a sample /etc/rc.local file:
#!/bin/sh -e

if [ -x /etc/iptables ]; then

mkdir -pm 777 /run/rtorrent
#su - myuser -c "screen -dmS torrent rtorrent"

#fun with leds; for reference, net5501 module not included in debian  
#echo heartbeat > /sys/class/leds/net5501\:1/trigger
#echo none > /sys/class/leds/net5501\:1/trigger
#echo 1 > /sys/class/leds/net5501\:1/brightness
#echo 0 > /sys/class/leds/net5501\:1/brightness

exit 0
Useful aliases and fancy shell:
# append some of this to /etc/profile

alias ll='ls -al --color'
alias pa='ps aux'
alias ka='killall'
alias k='kill -9'
#alias mc='mc -b'

if [[ "$PS1" && "$BASH" && "`id -u`" -gt 1000 ]]; then
 /bin/echo -e "\nWelcome to $HOSTNAME\n.... and your fortune O'day is:\n"
 /bin/echo -e
Disable IPv6 if unused:
echo net.ipv6.conf.all.disable_ipv6=1 > /etc/sysctl.d/disableipv6.conf 
echo "AddressFamily inet" >> /etc/ssh/sshd_config
Recommended SSH options:
echo 'UseDNS no' >> /etc/ssh/sshd_config
sed -i 's/#PermitRootLogin yes/PermitRootLogin no/' /etc/ssh/sshd_config
sed -i 's/    HashKnownHosts yes/    HashKnownHosts no/' /etc/ssh/ssh_config
/etc/init.d/ssh restart
Service defaults (yes, this is how you disable a service in debian, proper) :
#remove these only if you don't want them enabled on this box @ boot;
# update-rc.d -f bind9 remove
# update-rc.d -f isc-dhcp-server remove

#we use inetd for tftp now...
update-rc.d -f tftpd-hpa remove
To re-enable a service, you do this:
update-rc.d bind9 defaults
If this is hard to remember, apt-get install rcconf.

To manually start and stop services, ls /etc/init.d
/etc/init.d name start|stop|restart
3.2 - Routing and Firewalls

The Soekris box might also be used for routing/firewalling, so we make the necessary preparations, but leave that particular functionality disabled for now, to enable routing later on, simply modify /etc/iptables to fit your needs, make it executable (chmod +x /etc/iptables) so that it will be run by /etc/rc.local above, and then reboot or "/etc/iptables". Some knowledge of IPv4 is required, but if one only touches the top exports and the Port Forwarding's at the bottom, there is a small chance of survival regardless of experience. For convenience we provide a better /etc/network/interfaces as well which obviously need to be modified later to fit the environment.
# /etc/iptables (man iptables && cry)
export WAN=eth0
export LAN=eth1

# Flush Rules
iptables -F
iptables -t nat -F

# Setup default policies to handle unmatched traffic
iptables -P INPUT ACCEPT
iptables -P FORWARD DROP

# Lock our services so they only work from the LAN
iptables -I INPUT 1 -i ${LAN} -j ACCEPT
iptables -I INPUT 1 -i lo -j ACCEPT
iptables -A INPUT -p UDP --dport bootps ! -i ${LAN} -j REJECT
iptables -A INPUT -p UDP --dport domain ! -i ${LAN} -j REJECT

# Allow access to our local services on WAN
iptables -A INPUT -p TCP --dport ssh  -i ${WAN} -j ACCEPT
iptables -A INPUT -p TCP --dport ftp  -i ${WAN} -j ACCEPT
iptables -A INPUT -p TCP --dport http -i ${WAN} -j ACCEPT
iptables -A INPUT -p TCP --dport auth -i ${WAN} -j ACCEPT

# Drop TCP / UDP packets to privileged ports
iptables -A INPUT -p TCP ! -i ${LAN} -d 0/0 --dport 0:1023 -j DROP
iptables -A INPUT -p UDP ! -i ${LAN} -d 0/0 --dport 0:1023 -j DROP

# Finally we add the rules for NAT
iptables -I FORWARD -i ${LAN} -d -j DROP
iptables -A FORWARD -i ${LAN} -s -j ACCEPT
iptables -A FORWARD -i ${WAN} -d -j ACCEPT
iptables -t nat -A POSTROUTING -o ${WAN} -j MASQUERADE

# Tell the kernel that ip forwarding is OK
echo 1 > /proc/sys/net/ipv4/ip_forward
for f in /proc/sys/net/ipv4/conf/*/rp_filter ; do echo 1 > $f ; done

# Port Forwarding
# First Example is a redirection from port 1337 to port 1873 to local ip .69
iptables -t nat -A PREROUTING -p tcp --dport 1337  -i ${WAN} -j DNAT --to
# Second Example is a tcp range from 6881 to 6999 to local ip on .42
iptables -t nat -A PREROUTING -p tcp --dport 6881:6999 -i ${WAN} -j DNAT --to

exit 0
# /etc/network/interfaces (man 5 interfaces)
auto lo
iface lo inet loopback

auto eth0
iface eth0 inet dhcp

# Examples; eth0 for wan, eth1 for lan,
# matches the /etc/iptables example.

#iface eth0 inet static
# address
# netmask
# broadcast
# gateway

#auto eth1
#iface eth1 inet static
# address
# netmask
# broadcast
Next we want to prepare the box for standard network services like dhcpd, bind, tftp(with netboot image) etc., but leave them disabled. Having these services handy might prove to be very useful in case we need to perform rescue operations on-site with PXE, or we need to re-configure an existing Soekris box to take over the routers role in case that box dies or whatever, plenty of unknown scenarious on the horizon, and best to have the tools readily available, it only costs us a megabyte. It also turns our network of Soekris boxes into a self-sustaining ecology, nifty.

Repeat the steps in 2.2 - Preparing the PXE Network Boot Server, specifically the part about modifying /etc/dhcp/dhcpd.conf, wget and preparing the netboot image.
3.3 - Post-Installation

That's pretty much it for now, remember to configure the basics
# configure the network
nano /etc/network/interfaces
nano /etc/resolv.conf
/etc/init.d/networking restart
nano /etc/hostname
nano /etc/hosts
hostname myhostname

# configure network services
nano /etc/bind/named.conf.local
nano /etc/dhcp/dhcpd.conf

# configure services
ls /etc/init.d
#update-rc.d -f name remove
#update-rc.d name defaults
#|| rc-conf

# configure logging
nano /etc/rsyslog.conf

# configure routing/fw
#nano /etc/sysctl.conf
#nano /etc/iptables
#chmod +x /etc/iptables


# pop cf in workstation
dd if=/dev/sdc|gzip>soekris-prepped.img.gz


A - Packages

A package is just a tarball with a few extra meta-files, the Debian packager is called "dpkg", using this tool we can install (dpkg -i), remove (dpkg -r) or list (dpkg -l) installed packages. This, however, is not very apt. Which is where "apt" comes in, apt-get is used to handle repositories and apt-cache is used to query the local repository files.
apt-get update		refreshes package database
apt-get upgrade		upgrades all packages to latest version
apt-get install $pkg	download/installs $pkg plus dependencies
apt-get remove $pkg	removes a package again
apt-get clean		removes temporary downloaded files
apt-cache show $pkg	display information about a package
apt-cache search $1	search for packages with name/description $1
dpkg --search $1	which packages owns file $1
dpkg -L $pkg		show the contents of package $pkg
dpkg -l			simplest way to show what's installed, combine with |grep
There are many frontends for these basic programs (feta, aptitude, tasksel, dselect, synaptic), but they are usually not very good and tend to corrupt (aptitude).

A good source of information is:
B - Packaging

Making packages is a different matter, the system is very, very old and very, very cryptic, and to learn it, you have to read around a thousand pages of very, very bad documentation at

A few pointers to the basic process follows (insofar as you have an existing source package). First set up a source repository by uncommenting the two deb-src lines in /etc/apt/sources.list and run apt-get update and apt-get install dpkg-dev.

Now you can just type apt-get source $packagename, this will retrieve the necessary files (the original source, diffs and a meta/dsc file), unpack it and apply patches. You can manually wget the files of course and extract them using "dpkg-source -x *.dsc".

Inside we have the actual source code and a "debian" sub-directory, inside which the magic happens. If it is a simple package you should only see around 10 files (if not, you'll be dazzled by megabytes of scripts). The ones you should concentrate on are: 'changelog' (to bump version), 'control' (to modify meta-info like desc/deps/etc) and 'rules' (the actual build file, interpreted by make no less, and which calls debian supplied helper scripts (dh_*) written in the m4 macro-processor language).

So, to modify the package, we edit 'rules' and add, say, a few new configure options, setting DEB_CONFIGURE_EXTRA_FLAGS += --with-my-optimizations, and create a new entry in 'changelog', with a -1 version increase, tagged for the 'stable' branch and with a proper timestamp. It is important to keep the exact syntax of existing entries! Now we can build the package and update our repository:
dpkg-buildpackage -rfakeroot
dpkg-scanpackages . /dev/null|gzip>~/packages/Packages.gz
dpkg-scansources . /dev/null|gzip>~/packages/Sources.gz
Following these steps you should be able to customize existing packages. You can often find what you need (new packages or newer versions) in the unstable or experimental branch and then backport them using this approach. Use to locate the package, when found you'll notice 3 source links (.dsc, .orig.tar.gz, .diff.gz) top-right, wget those and extract as mentioned above.
C - Kernel

It is no longer a necessity to compile a custom kernel for the soekris in order to get acceptable performance, but if this is your preference, a quick guide follows along with a few token options. We start by retrieving the basics (gcc, kernel, etc):
apt-get -y install build-essential libncurses5-dev
cd /mnt/somewhere_not_on_flash!
tar jxf linux-3.6.tar.bz2
mv config linux-3.6/.config
cd linux-3.6
Above we've also retrieved a custom configuration file, this particular one is optimized for the soekris net5501, with some of the following build in options (including the pata driver, so we don't even need an initrd):
CONFIG_MGEODE_LX=y		Processor / Family / Geode GX/LX
CONFIG_SCx200=y			Bus / NatSemi SCx200 support
CONFIG_NET5501=y		Bus / Soekris Engineering net5501
CONFIG_CS5535_MFGPT=y		Drivers / Misc / CS5536 Geode MFGPT
CONFIG_PATA_CS5536=y		Drivers / SATA / SFF / BMDMA / CS5536
CONFIG_BLK_DEV_SD=y		Drivers / SCSI / SCSI disk
CONFIG_VIA_RHINE=y		Drivers / Network / Ethernet / Via Rhine
CONFIG_SERIAL_8250=y		Drivers / Char / Serial / 8250 + Console
CONFIG_HW_RANDOM_GEODE=y	Drivers / Char / H Random Number G / Geode
CONFIG_SCx200_ACB=y		Drivers / I2C / Bus / Geode Access
CONFIG_GPIO_CS5535=y		Drivers / GPIO / CS5536 GPIO
CONFIG_MFD_CS5535=y		Drivers / Multifunction / CS5536
CONFIG_LEDS_GPIO=y		Drivers / LED / Class + GPIO + Triggers
CONFIG_EXT3_FS=y		File systems / EXT3
CONFIG_CRYPTO_DEV_GEODE=y	Cryptographic / Hardware / Geode
You might also be wanting to apply a few patches to your kernel, the procedure is quite simple:
bzcat ../patch-3.6.11.bz2|patch -p1
You want to start tweaking it, adding whatever you need yourself, removing what little there is that you don't like, etc.
make nconfig
When done, you'll be wanting to make a backup of the file .config for future reference, or to use on another box. You can also retrieve the config used on any running box with a simple "zcat /proc/config.gz>.config". Nifty. Next up, building and installing our custom kernel:
#make modules_install		# if you enabled modules
#make firmware_install		# you really shouldn't be needing this
cp arch/x86/boot/bzImage /boot	# or scp to soekris
Make an entry in GRUB2: nano /etc/grub.d/40_custom
exec tail -n +3 $0

menuentry "My Kernel" {
 linux /boot/bzImage root=/dev/sdb1 ro console=ttyS0,19200n8 libata.force=short40c,1.1:mwdma2
But be careful, GRUB2 bugs out if the linux line is too long, case in point, append "quiet" to the line above and it won't boot, no, really. Finally, run "update-grub" to... update grub.

There is an optimized config available at
D - Firmware

IMHO, all available firmwares are equally broken, but if you want to try them out, this is how:

# must be root, because of a lock file, no really
sudo minicom -s
sudo minicom

# enter firmware (ctrl+p)
download -

# ctrl+a, then s, xmodem, tag with space and enter

E - Jessie (Debian 8.0)

While this guide was written for Wheezy, only minor tweaks are required for Jessie. First, use the latest netboot and make some tweaks to pxelinux.cfg (vga emu now borked, must doubly force use of serial):
tar zxvf netboot.tar.gz -C /srv/tftp
rm netboot.tar.gz /srv/tftp/pxelinux.cfg
mkdir /srv/tftp/pxelinux.cfg

cat >> /srv/tftp/pxelinux.cfg/default << EOF
DEFAULT soekris
LABEL soekris
 kernel debian-installer/i386/linux
 append initrd=debian-installer/i386/initrd.gz console=ttyS0,19200n8 -- console=ttyS0,19200n8
Second, GRUB2 is now unborked and will correctly prompt you for the desired MBR during installation, choose sdb, and reboot when prompted, remember to still perform the following steps after your first reboot:
sed -i 's/MODULES=most/MODULES=dep/' /etc/initramfs-tools/initramfs.conf
echo "options libata force=short40c,1.1:mwdma2" > /etc/modprobe.d/libata.conf
update-initramfs -u
userdel -r randomdent
And skip to Part 3. Optimization and Cleanup. Most things in that chapter still applies, although if you wish to use systemd's journal (instead of rsyslog), timers (instead of cron), and time (instead of ntp), say;
install -d -g systemd-journal /var/log/journal
setfacl -R -nm g:adm:rx,d:g:adm:rx /var/log/journal
apt install systemd-cron
apt purge rsyslog logrotate cron
timedatectl set-ntp 1
Some minor changes to services as well, mediatomb is no longer available (manually dpkg -i the mediatomb mediatomb-common & i386/mediatomb-daemon from sid) and samba no longer supports the "share" security setting, if you relied on that, simply change it to "user" and add "map to guest = Bad Password" to smb.conf, yes really, because that is more intuitive!

Also note that apt-get, apt-cache, etc, has been combined into a single simple "apt" command, missing only "apt-get clean" from it's featureset, and a last tip for it's ultimate lazy use:
echo 'APT::Get::Assume-Yes "true";' > /etc/apt/apt.conf.d/99local
echo 'APT::Get::Purge "true";' > /etc/apt/apt.conf.d/99local
F - Sources

You can use the site to download the source code for any and all binaries distributed from, except for the kernels which can be downloaded from
G - License

Public Domain To the extent possible under law, Per Jensen has waived all
copyright and related or neighboring rights to this work.