Showing posts with label Debian. Show all posts
Showing posts with label Debian. Show all posts

Friday, December 28, 2012

From raw idea to useful source code

A couple months ago I had an Idea.

I even blogged about it: A lookup service for US National Weather Service codes. Those codes are necessary to access their machine-readable products.

In this post, I will show how I developed the idea into some code, how I grew the code into a project, added structure and version control, and finally moved the project onto online hosting.

This is not the only way to create a project.
This is probably not the best way for many projects.
It's just the way I did it, so you can avoid the most common mistakes.

You can see my final product hosted online at Launchpad.



From Idea to Code:

I know barely enough C to be able to ask there the bathroom is, so it's easier for me to use Python.

Code starts out as a single Python script:
- geolocation.py

As we add more features, a single script gets big and unwieldly, and we break it into smaller pieces.

For example, this structure easily allows more interfaces to be added.
- geolocation_service.py
- command_line_interface.py

Let's add a dbus interface, too. Dbus will semd messages to the interface if it knows about it. Let dbus know about it using a service file.
- dbus_interface.py
- dbus_service_file.service

Let's add an http interface, so not everyone in the world needs to download 5-6MB of mostly-unused lookup databases:
- http_interface.py
- specialized_webserver.py

Let's go back and formalize how we create the databases:
- database_creator.py

We have a lot of hard-coded variables in these scripts. Let's break them out into a config file.
- configfile.conf

There are other possible files, that we're not using. For example:
- Upstart config file (if we want the service to run/stop at boot or upon some system signal, lives in /etc/init)
- Udev rule file (if we want the service to run/stop when a device is plugged in, lives in /etc/udev/rules.d)

But that's a lot of files and scripts! 8 files, plus the databases.
 


Adding Version Control:

It's time to get serious about these eight files. We have invested a lot of time creating them, and it's time to start organizing the project so others can contribute, so we can track new bugs and features, and to protect all our invested work.

First, we need to introduce version control. Ideally, we would have done that from the start. But we didn't. So let's fix that.

Version control offers a lot of advantages:
    We can undo mistakes.
    It helps us package the software later.
    It helps us track bugs.
    It helps us apply patches.
    It helps us document changes.

There are plenty of good version control systems available. For this example, I'll use bazaar. The developers have a very good tutorial.

Installing bazaar:

$ sudo apt-get install bzr
$ bzr whoami "My Name "

Since we didn't start with proper version control, we need to create a new directory using version control, move our files into it, and add our files to version control.

$ bzr init-repo My_NEW_project_directory
$ bzr init My_NEW_project_directory
$ mv My_OLD_project_directory/* My_NEW_project_directory/
$ cd My_NEW_project_directory
$ bzr add *

Finally, we need to clean up the old directory, and commit the changes.

$ rm ../My_OLD_project_directory
$ bzr commit -m "Initial setup"


Organizing the code

My project directory is starting to get disorganized, with eight scripts and files, plus six database files, plus version control, plus more to come. I'm going to restructure my project folder like this:

My_project_directory
  +-- data   (all the database files)
  +-- src    (all the python scripts and other non-data files)
  +-- .bzr   (bzr's version control tracking)


Once version control is active, we cannot just move things around. We need to use the version control tools so it can keep tracking the right files.

$ bzr mkdir data src
$ bzr mv *.gz data/
$ bzr mv *.py src/
$ bzr mv dbus_service_file.service src/
$ bzr mv configfile.conf src/

See how bazaar adds the directories and performs the moves?

Now My_project_directory should be empty of files. Once reorganization is complete, remember to commit the change:

$ bzr commit -m "Reorganize the files to a better project structure"




Integrating into the system:

We have a problem with our eight files. They run beautifully, but only if they are in our home directory.

That won't work in the long run. A server should not be run as a user with shell access - that's a security hole. Nor should it be run out of a user's /home. Nor should it be run as root. Also, other applications that are looking for our server won't find it - all the files are in the wrong places.

So we need to put our files into the right places. And often that means fixing the scripts to replace hard-coded temporary paths (like '~/server/foo') with the proper locations ('/usr/lib/foo-server/foo').

Where are the right places?

The Linux Filesystem Hierarchy Standard (FHS) is used by Debian to define the right places.

Two files are directly user-launched in regular use:
- specialized_webserver.py: /usr/bin
- command_line_interface.py: /usr/bin

The database files are read-only and available to any application:
- database files: /usr/shared

Three files are launched or imported by other applications or scripts:
- geolocation_service.py: /usr/lib
- dbus_interface.py: /usr/lib
- http_interface.py: /usr/lib

One file is very rarely user-launched under unusual circumstances:
- database_creator.py

The  dbus service file will be looked for by dbus in a specific location:
- geolocation_dbus.service: /usr/share/dbus-1/services

Config files belong in /etc
- geolocation.conf: /etc

Makefiles make organization easier:

Now that we know where the right places are, let's create a Makefile that will install and uninstall the files to the right place. Our originals stay where they are - the makefile copies them during the install, and deletes the copies during uninstall.

Makefiles are really config files for the make application (included in the build-essential metapackage). Makefiles tell make which files depend upon which, which files to compile (we won't be compiling), and where the installed application files should be located, and how to remove the application.

Here is a sample makefile for my project (wbs-server):
DATADIR = $(DESTDIR)/usr/share/weather-location
LIBDIR  = $(DESTDIR)/usr/lib/wbs-server
BINDIR  = $(DESTDIR)/usr/bin
DBUSDIR = $(DESTDIR)/usr/share/dbus-1/services
CONFDIR = $(DESTDIR)/etc
CACHDIR = $(DESTDIR)/var/cache/wbs-webserver

install: 
 # Indents use TABS, not SPACES! Space indents will cause make to fail
 mkdir -p $(DATADIR)
 cp data/*.gz $(DATADIR)/

 mkdir -p $(LIBDIR)
 cp src/geolocation.py $(LIBDIR)/
 cp src/wbs_dbus_api.py $(LIBDIR)/
 cp src/wbs_http_api.py $(LIBDIR)/
 cp src/wbs_database_creator.py $(LIBDIR)/

 cp src/wbs_cli_api.py $(BINDIR)/
 cp src/wbs_webserver.py $(BINDIR)/
 cp src/wbs-server.service $(DBUSDIR)/
 cp src/confile.conf $(CONFDIR)/wbs-server.conf
 mkdir -p $(CACHDIR)

uninstall:
 rm -rf $(DATADIR)
 rm -rf $(LIBDIR)

 rm -f $(BINDIR)/wbs_cli_api.py
 rm -f $(BINDIR)/wbs_webserver.py
 rm -f $(DBUSDIR)/wbs-server.service
 rm -f $(CONFDIR)/wbs-server.conf
 rm -rf $(CACHDIR)

Let's save the makefile as Makefile, and run it using sudo make install and sudo make uninstall.

We run a test:

$ sudo make install
$ /usr/bin/wbs_cli_api.py zipcode 43210
bash: /usr/lib/wbs-server/wbs_cli_api.py: Permission denied

Uh-oh. Let's investigate:

$ ls -l /usr/lib/wbs-server/wbs_cli_api.py 
-rw-r--r-- 1 root root 3287 Dec 23 20:46 /usr/lib/wbs-server/wbs_cli_api.py

Aha. Permissions are correct, but the executable flag is not set. Let's uninstall the application so we can fix the makefile.

$ sudo make uninstall

In the makefile, we can make a few changes if we wish. We can set the executable flag. We can also create links or symlinks, or rename the copy.

For example, wbs_cli_api.py is a rather obtuse name for a command-line executable. Instead of copying it to /usr/bin, let's copy it to /usr/lib with its fellow scripts, make it executable, and create a symlink to /usr/bin with a better name like 'weather-lookup'

install:
        ...
 cp src/wbs_cli_api.py $(LIBDIR)/
 chmod +x $(LIBDIR)/wbs_cli_api.py
 ln -s $(LIBDIR)/wbs_cli_api.py $(BINDIR)/weather-lookup
        ...

uninstall:
        ...
 rm -f $(BINDIR)/weather-lookup
        ...


Another example: It's a bad idea to run a webserver as root. So let's add a couple lines to the makefile to create (and delete) a separate system user to run the webserver.

USERNAM = wbserver
        ...
install:
        ...
 adduser --system --group --no-create-home --shell /bin/false $(USERNAM)
 cp chgrp $(USERNAM) $(LIBDIR)/*
 cp chgrp $(USERNAM) $(CACHDIR)
 # Launch the webserver using the command 'sudo -u wbserver wbs-server'
        ...

uninstall:
        ...
 deluser --system --quiet $(USERNAM)
        ...




Sharing the code

Now we have a complete application, ready to distribute.

Thanks to the Makefile, we include a way to install and uninstall.

It's not a package yet. It's not even a source package yet. It's just source code and an install/uninstall script.

We can add a README file, a brief description of how to install and use the application.

We can also add an INSTALL file, detailed instructions on how to unpack (if necessary) and install the application.

It would be very very wise to add a copyright and/or license file, so other people know how they can distribute the code.

After all that, remember to add those files to version control! And to finally commit the changes:

bzr commit -m "Initial code upload. Add README, INSTALL, copyright, and license files."

Finally, we need a place to host the code online. Since I already have a Launchpad account and use bzr, I can easily create a new project on bzr.

And then uploading the version-controlled files is as simple as:

bzr launchpad-login my-launchpad-name
bzr push lp:~my-launchpad-name/my-project/trunk 

You can see my online code hosted at Launchpad.


Next time, we'll get into how to package this source code.

Saturday, June 9, 2012

How to recompile the linux kernel for specific hardware in Debian 6

I have Debian 6 installed on my mini-ITX system.

I want to try recompiling the kernel to speed up boot and reduce the footprint on the slow, old system. Eventually, I want to use the lessons learned to recompile Ubuntu 12.04 to work on the system. Currently, 12.04 will not boot, since the old VIA 32-bit processor does not fully support x686 nor pae.

If the kernel and modules are small enough, and customized for the equipment, we can even get rid of the initrd at boot. That will also speed up the boot a lot!

Step 1: Collect CPU and module information 

We can compile the CPU for the specific processor and modules we actually use. On such a resource-constrained system, getting rid of a lot of unused bloat is welcome.

The following command shows that we have a VIA Samuel 2 processor, 533MHz, 32-bit system.

$ cat /proc/cpuinfo 
processor : 0
vendor_id : CentaurHauls
cpu family : 6
model  : 7
model name : VIA Samuel 2
stepping : 3
cpu MHz  : 533.370
cache size : 64 KB
fdiv_bug : no
hlt_bug  : no
f00f_bug : no
coma_bug : no
fpu  : yes
fpu_exception : yes
cpuid level : 1
wp  : yes
flags  : fpu de tsc msr cx8 mtrr pge mmx 3dnow
bogomips : 1066.74
clflush size : 32
cache_alignment : 32
address sizes : 32 bits physical, 32 bits virtual
power management:

The following command lists most of the modules used (modules used during boot then unloaded do not show up here).

$ lsmod
Module                  Size  Used by
fuse                   43213  1 
snd_via82xx            15020  0 
gameport                6105  1 snd_via82xx
snd_ac97_codec         79248  1 snd_via82xx
ac97_bus                 710  1 snd_ac97_codec
snd_mpu401_uart         4155  1 snd_via82xx
snd_rawmidi            12737  1 snd_mpu401_uart
snd_pcm                46098  2 snd_via82xx,snd_ac97_codec
snd_seq_device          3661  1 snd_rawmidi
snd_timer              12304  1 snd_pcm
via_ircc               13188  0 
snd                    34142  7 snd_via82xx,snd_ac97_codec,snd_mpu401_uart,snd_rawmidi,snd_pcm,snd_seq_device,snd_timer
vt8231                  8678  0 
irda                   71690  1 via_ircc
snd_page_alloc          5021  2 snd_via82xx,snd_pcm
i2c_viapro              4387  0 
shpchp                 21168  0 
parport_pc             15747  0 
evdev                   5520  4 
parport                22170  1 parport_pc
button                  3578  0 
processor              23003  1 
pcspkr                  1235  0 
serio_raw               2912  0 
i2c_core               12739  1 i2c_viapro
soundcore               3294  1 snd
crc_ccitt               1039  1 irda
pci_hotplug            18493  1 shpchp
ext3                   92928  3 
jbd                    28166  1 ext3
mbcache                 3482  1 ext3
sd_mod                 25961  5 
crc_t10dif              1012  1 sd_mod
ata_generic             2239  0 
fan                     2590  0 
pata_via                5721  4 
uhci_hcd               16021  0 
libata                117427  2 ata_generic,pata_via
via_rhine              14427  0 
thermal                 9210  0 
ehci_hcd               28859  0 
thermal_sys             9346  3 processor,fan,thermal
scsi_mod              105921  2 sd_mod,libata
mii                     2654  1 via_rhine
usbcore                99061  3 uhci_hcd,ehci_hcd
nls_base                4445  1 usbcore

The following command tells us that the current version of the kernel in use is 2.6.32-5-486:

$ uname -a
Linux mini-deb6 2.6.32-5-486 #1 Sun May 6 03:29:22 UTC 2012 i686 GNU/Linux


Step 2: Install the kernel source

The kernel source code is needed. "Recompiling" a kernel actually just means compiling a new version of the kernel from source. The process is covered very well in this forum post. We will install all the needed packages for the recompile, install the linux source code too /usr/src, and copy the existing old kernel config so we have a nice baseline if we mess it up.

# apt-get install ncurses-dev kernel-package cpio initramfs-tools linux-base module-init-tools udev linux-source-2.6.32-5-486
# cd /usr/src
# tar -xjf linux-source-*.tar.bz2
# ln -s linux-source-* linux
# cd linux
# cp .config .config-original-2.6.32

One tiny extra step - we'll be manually rebooting at the end of the process, so I reset my grub timeout to 15 seconds so I have time to select the kernel I want without rushing. Grub will grab this new value when it automatically updates in Step 4.

# nano /etc/default/grub
(change the line GRUB TIMEOUT= )


Step 3: Edit the config file, then compile

Now we're ready to modify the .config file.

# make menuconfig 

Menuconfig takes about an hour, perhaps more. To build a really minimal kernel, go through and switch all of the options off. Next, go back and look at the list of modules. Search for each module (search is the forward-slash key '/'), and turn each back on. Make sure each is compiled into the kernel, not added as a module. Some options require you to search for prerequisites and turn those on first. Like I said, it took me over an hour to work through all the modules on the list.

When finished, save the config. Then we're ready to compile:

# make-kpkg clean
# make-kpkg --append-to-version=-custom1 kernel_image kernel_headers

Iterate the version number (-custom1 to -custom2) or you'll lose track of progress very quickly! If you want an initrd, add --initrd to the line.

Compiling on my slow machine takes about 2.5 hours. I run make-kpkg inside a screen session. I can ssh in, start compiling, detach the screen, and return in a few hours to see the result.


Step 4: Install the new kernel

The make-kpkg command creates a lovely new package for us in /usr/src. Install it.

# ls -l /usr/src
total 97892
lrwxrwxrwx  1 root root       19 Jun  2 19:20 linux -> linux-source-2.6.32
-rw-r--r--  1 root root  6060196 Jun  2 13:56 linux-headers-2.6.32-custom1_2.6.32-custom1-10.00.Custom_i386.deb
-rw-r--r--  1 root root  4170548 Jun  2 13:47 linux-image-2.6.32-custom1_2.6.32-custom1-10.00.Custom_i386.deb
drwxr-xr-x 25 root root     4096 Jun  9 14:02 linux-source-2.6.32
-rw-r--r--  1 root root 65220157 May  5 18:19 linux-source-2.6.32.tar.bz2
drwx------  2 root root    16384 May 27 17:36 lost+found

# dpkg -i  /usr/src/linux-image-2.6.32-custom1_2.6.32-custom1-10.00.Custom_i386.deb

The install will also create an updated initrd (if you asked for one) and add the appropriate grub entries. If you changed the Grub Timeout value in Step 2, the update will reflect that, too.

Change one setting in the new /etc/grub/grub.cfg. Normally, grub tells the kernel to load the boot drive read-only, then initrd unmounts it and remounts it read-write. Since we don't have an initrd, we must change that grub behavior. For the first few iterations of kernel testing, this doesn't matter - it wont affect anything until you reach busybox prompts because the root filesystem cannot be loaded:

# nano /etc/grub/grub.cfg

Look for the root=/dev/sda1 ro stanza in the last line of the appropriate menuentry, and change ro (read only) to rw (read/write). Here's an example of an unchanged menuentry:

menuentry 'Debian GNU/Linux, with Linux 2.6.32-custom8' --class debian --class gnu-linux --class gnu --class os {
        insmod part_gpt
        insmod ext2
        set root='(hd0,gpt1)'
        search --no-floppy --fs-uuid --set 89b0fb32-b7e3-46e8-878b-5da4cd69fbdd
        echo    'Loading Linux 2.6.32-custom8 ...'
        linux   /boot/vmlinuz-2.6.32-custom8 root=/dev/sda1 ro console=tty1 console=ttyS0,115200n8
}


Reboot into the new kernel.

# shutdown -r now


Step 5: Lather, Rinse, Repeat

Keep the hardware handy - you need to see the console boot messages, and you need access to the power switch.

The first few times you try this, the kernel is likely to fail. Either you forgot to add a module, or you set something wrong. Record the error off the screen, and jump into a search engine to see what it means.

Kernel failures fall into several broad categories. Each is usually due to the same cause - a misconfigured kernel .config file. Happily, these are sequential. As you move down the list, you're getting closer to final success.
- The easiest to diagnose is the simple refusal to start. The kernel fails a basic start test, and tells you in plain language that it won't start because it doesn't support this processor or the processor doesn't support this service, etc.
- Once the kernel passes those start tests, the next set of failures are kernel panics. This means that the kernel has loaded, but some piece of hardware or initrd instruuction or filesystem has mystified it, so it barfs a bunch of diagnostic information and freezes.
- Once the kernel is over its panic attacks, the next set of failures are dropping to the busybox prompt when the root filesystem fails to be recognized or loaded. This usually means either a misconfigured root= or UUID= in grub, or a missing or incorrect filesystem module.
- Finally, the system boots and works...mostly. Some application or piece of hardware doesn't work, though.

Reboot into the original working kernel (hard reboot, using the power switch).

Remove the non-working kernel. This will also remove the appropriate initrd (if any), and appropriate grub entries.

# apt-get remove linux-image-2.6.32-custom1

Return to Step 3, change the config file to fix the problem, and compile again.


Step 6: The new kernel works!

Once the new kernel works, clean up. Backup the working config file, remove the source code package, and delete the 'linux' symlink so a future recompile doesn't accidentally overwrite this working version.

# cp .config .config-2.6.32-custom5   # or whatever custom iteration number you want
# apt-get remove linux-source-2.6.32
# cd /usr/src
# rm linux

Now you can brag to your friends about how easy it was...

Let's take a quick look at the old and new kernels side-by-side:

$ ls -l /boot
total 17052
-rw-r--r-- 1 root root  110922 May  6 07:49 config-2.6.32-5-486
-rw-r--r-- 1 root root   55311 Jun 10 08:54 config-2.6.32-custom8
drwxr-xr-x 3 root root    4096 Jun 10 11:48 grub
-rw-r--r-- 1 root root 8722934 May 27 15:54 initrd.img-2.6.32-5-486
-rw-r--r-- 1 root root 1249814 May  6 07:49 System.map-2.6.32-5-486
-rw-r--r-- 1 root root 1333763 Jun 10 11:00 System.map-2.6.32-custom8
-rw-r--r-- 1 root root 2192352 May  6 07:48 vmlinuz-2.6.32-5-486
-rw-r--r-- 1 root root 3734224 Jun 10 11:00 vmlinuz-2.6.32-custom8

The actual kernel, vmlinuz, is 1.5MB (70%) larger, but no longer has an initrd (saves 8.7 MB) or /lib/modules directory (saves 67 kB). Boot time savings seems negligible so far

Here is the final working config file.




Saturday, June 2, 2012

How to use a null-modem serial cable

This will be useful when I need access to a headless server (or any other headless machine) with my laptop.

For example, my little mini-ITX headless server needs occasional terminal input, and leaving my big screen and keyboard nearby is taking up valuable space that I prefer to devote to more important issues...like laundry or loose change or perhaps a book or two.


Desktop clutter comparison: extra monitor & keyboard vs serial cable & laptop

Headless Mini-ITX board booted
to Debian 6 (LXDE)
using native keyboard and monitor.
Headless Mini-ITX board booted
to GRUB, seen through serial port.
Laptop acting as terminal



Hardware

The server has a good, old-fashioned RS-232, 9-pin serial port for the console connection. One client also has an RS-232 port. A different client (laptop) has only USB ports.






  • $3.49 for a 6-foot serial null-modem cable, female RS-232 to female RS-232.







  • $3.19 for a 3-foor USB-to-male RS-232 adapter cable. This is for later when I try from my laptop.




  • Connectivity Test of the null-modem cable between two machines with serial ports. This test proves that the cable is really a null-modem cable (not a data cable) and working, that the serial ports are working, and that both systems are configured correctly,  If possible, avoid using the USB-to-serial adapter for this test - it adds another variable unnecessarily.

    Plug the cable into a serial port on each machine. Designate one machine Server and the other machine Client. It really does not matter which.

    On the Server , open the serial port, and leave it open.
    # getty -L ttyS0 115200 vt100

    On the Client with a serial port, install the screen application, then use it at a terminal emulator to connect over the serial port.
    # apt-get install screen
    # screen /dev/ttyS0 115200
      (Hit return once or twice)

    When finished with screen, quit using the command (CTRL+A , then backslash \)

    You should be able to login to the Server from the Client. If you have problems:
    • Make sure you didn't start multiple screen sessions (they interfere)
    • Make sure neither machine is running both getty and screen on the same port (they interfere). One machine should run getty, the other should run screen.
    • Make sure both sides are using the same speed (115200). This modem setup does not auto-negotiate speeds!
    • Try varying which service starts first. After each attempt, kill both the screen and getty services (but only the getty running on that port!)



    Configuring the Server

    If the console is available during a reboot, then you don't need that external monitor or keyboard anymore! A nearby laptop or desktop can serve (this saves me a lot of valuable space). In order to be useful at reboot time, the bootloader and startup need to be configured to use the serial port.

    I'm assuming the first serial port (serial 0 = COM1 = /dev/ttyS0)

    1) Add the serial port to the bootloader.
       If using grub, see the well-written instructions on the Ubuntu Wiki.
       If the bootloader is Syslinux, add the following line to /boot/syslinux.cfg. It must be the first line.
    serial 0 115200

    2) This server runs Debian 6, which uses sysvinit (for newer, upstart-based systems, see these instructions). Edit the /etc/inittab file. Add the following line near Line 55, with the other getty respawn lines:
    T0:2345:respawn:/sbin/getty -L 115200 ttyS0 vt100

    Reload the inittab using the command init q

    3) Edit the /etc/securetty file. In Debian 6, this isn't necessary, the proper ttyS0 entry to create a serial port already exists.

    Instructions
    Even better instructions
    Thorough instructions, including bootloaders
    Syslinux instructions



    Configuring the Client. Not much to do here, since screen is already installed. It works just like the test. If the client does not have a serial port, use a serial-to-USB adapter as shown below.
    # screen /dev/ttyS0 115200      # Null-modem serial-to-serial
    # screen /dev/ttyUSB0 115200    # Using a serial-to-USB adapter

    I found greater success if the server getty is started first, then the client screen. Including when trying to catch the grub boot screen - push the power-on button on the server, then hit [return] on the client to launch screen, then slowly press a few arrow keys and space bar until the menu appears. Sometimes the connection just doesn't work, and after a pause (grub waiting), you hear disk activity (kernel loading). Then just poweroff the server and try again.


    Switching client and server. Console setup is one-way only, because screen and getty cannot control the same port at the same time. If inittab on the server causes getty to respawn, then edit (comment out) and reload inittab to kill that getty.


    Running screen as user instead of root. Screen might refuse to start for a user if the serial port is owned by root. Running as a user is preferable if you'll be using the serial port a lot.

    Create a new group, add the group to the port, change permissions on the port to match the group, and add the user to the group.

    # ls -l /dev/ttyS0
    crw------- 1 root root 4, 64 Jun 1 04:25 /dev/ttyS0
    # groupadd serialport
    # chgrp serialport
    # chmod 0060 /dev/ttys0
    # ls -l /dev/ttyS0
    c---rw---- 1 root serialport 4, 64 Jun 1 04:27 /dev/ttyS0
    # usermod <my-name> --append --groups serialport

    Log out, log back in, now user can access screen.

    $ screen /dev/ttyS0 115200


    Capturing console output to a text file. This is handy for debugging and keeping notes. Screen doesn't really seem to have this capability. But hooray for the shell environment - you can use the 'tee' command. The following will save a textfile that gets overwritten each session, so feel free to change the name each time.

    $ screen /dev/ttyS0 115200 | tee /path/to/console-recording-textfile


    Sunday, May 27, 2012

    Installing Debian 6 onto a VIA Epia 5000-L and IDE HDD

    First boot with GUI
    LXDE + Debian 6.0.5 on 10-year-old Epia 5000-L motherboard
    I have a 10-year-old mini-ITX motherboard that I'm cobbling with a few parts into a useful system.

    In this post, I discussed testing the old motherboard, and getting it to boot.

    Since it arrived without any storage attached, in this post I discussed the hurdles getting it to boot Debian 6 from a USB drive. That wasn't easy, since the motherboard predated most forms of USB-boot, and the BIOS didn't support USB-HDD, the current standard for bootable USB.

    Next, in this post, I discussed the adventure of using that USB boot to bootstrap a Debian install into an IDE-connected SD card. This didn't work out - one bootable IDE connector was defective, and a second worked...but wasn't bootable. I may return to this, since 3.5-inch HDDs are enormous - almost as big as the motherboard!

    So I finally broke down and spent a few dollars on a 40GB HDD. This has the big advantage that the HDD can be partitioned for experimentation. Installing to the HDD is essentially the same process as installing to the SD card.




    Lessons Learned

    Hooked up:
    Left: PS/2 Mouse, PS/2 Keyboard, VGA Monitor,
               USB Wireless-g dongle
    Bottom: Power button
    Right: Power to HDD, Power from wall, IDE to HDD
    1) The -i486 architecture is important. This motherboard is too old to support cmov, cx8, and pae. All three of those are in the latest Ubuntu kernels. cmov and cx8 are part of the i686 instruction set, so specifying a i486 kernel gets rid of them. pae is a new default since Debian 6.0. So a Debian 6.0 kernel compiled for x486 will be useful on the motherboard...until I get better at compiling my own kernels.

    2) Debootstrap does not include the wireless-tools package, so a bootstrapped system won't have wireless access. Adding wireless-tools is trivial if you remember to do it: During the chroot session when installing the kernel and grub and configuring the accounts and fstab and hostname, install wireless-tools and configure /etc/network/interfaces too.




    For the first HDD experiment, I installed Debian 6 + LXDE onto a partition of the HDD.

    Startup test: 45 Seconds from power-on to text-login prompt, 95 seconds to power-on to GDM login prompt.

    Next tests: I want to try Debian Live for running the whole system in RAM. And I want to try modding the latest Ubuntu kernel to remove those three features and try Unity on it.

    Tuesday, May 1, 2012

    How to build a Simutrans .deb package manually

    Simutrans, as I've written before, is a fun game.

    Currently it's in active development, with new features and bug fixes arriving several times each year.  But Ubuntu's repository system is based on six-month snapshots; it cannot keep up with the pace of Simutrans releases.

    That causes a big problem for multiplayer games: The server requires clients to be on a similar pakset and release, and the server operators usually keep up with the releases. So Ubuntu users are locked out of multiplayer games - the versions in the Ubuntu repos are simply too old.

    So I want roll my own .deb of the latest version of Simutrans. This is the first step - eventually a PPA of the backported latest release would be cool.



    1) Create a VM for the build environment. For this, I used a VM of my current install, Ubuntu 11.10. But you can use anything back to Debian 6, of course.

    The VM serves several purposes. It provides the appropriate build environment for each version of Ubuntu. It also provides a safe place to test the final package installation. And, of course, it protects my main system.

    Beyond the basic setup, you should probably clean up the desktop shortcut bar; you don't need Software Center or LibreOffice, but you do need Terminal on there. You should also set Software Sources to automatically download-and-apply security updates, you can safely ignore all non-security updates.

    Also, install the following packages needed for a useful Simutrans build environment:
    $ sudo apt-get install build-essential devscripts debhelper libsdl1.2-dev 
    libsdl-mixer1.2-dev zlib1g-dev imagemagick libpng-dev libbz2-dev libssl-dev subversion

    Do NOT install the simutrans package from the Ubuntu repositories. If you do install it, for example to confirm that it works, remove it.


    2) Prepare the working directory for Simutrans and download the sources

    First, let's set up the Simutrans working directory

    ~$ mkdir Simutrans_Development
    ~$ cd Simutrans_Development
    ~/Simutrans_Development$ wget http://ftp.us.debian.org/debian/pool/main/s/simutrans/simutrans_111.2.2-1.debian.tar.xz 
    ~/Simutrans_Development$ tar -xvf simutrans_111.2.2-1.debian.tar.xz 

    Increment the version number by editing the changelog in each Debian directory.

    ~/Pak64_Development$ cd ~/Simutrans_Development
    ~/Simutrans_Development$ dch -v 111.2.2-0ppa1
    
    simutrans (111.2.1-0ppa1) oneiric; urgency=low
    
      * New upstream release
    
     -- me <me@example.com>  Wed, 25 Apr 2012 07:23:32 -0500

    Edit the Debian rules file to reflect the most recent upstream release, then download a new source code tarball, uncompress the tarball, and copy the debian folder into the new folder.

    ~/Pak64_Development$ cd ~/Simutrans_Development
    ~/Simutrans_Developmen$ nano debian/rules
    
    SVNREV  = 5583
    VERSION = 111.2.2
    
    
    ~/Simutrans_Development$ make -f debian/rules get-orig-source
    tar -xvf simutrans_111.2.2.orig.tar.zx
    cp -r debian/ simutrans-111.2.2/
    

    Finally, a progress check: The directory should look something like this:

    ~$ ls Simutrans_Development/
    debian             simutrans_111.2.2-1.debian.tar.xz
    simutrans-111.2.2  simutrans_111.2.2-1.orig.tar.xz


    3) Prepare the working directory for Pak64 and download the sources

    ~$ mkdir Pak64_Development
    ~/Simutrans_Development$ cd ~/Pak64_Development
    ~/Pak64_Development$ wget http://ftp.us.debian.org/debian/pool/main/s/simutrans-pak64/simutrans-pak64_111.2-1.debian.tar.xz
    ~/Pak64_Development$ tar -xvf simutrans_111.2-1.debian.tar.xz

    Increment the version number by editing the changelog in each Debian directory.

    ~/Simutrans_Development$ cd ~/Pak64_Development
    ~/Pak64_Development$ dch -v 111.2-0ppa1
    
    simutrans-pak64 (111.2-0ppa1) oneiric; urgency=low
    
      * New upstream release
    
     -- me <me@example.com>  Wed, 25 Apr 2012 07:23:32 -0500

    Edit the Debian rules file to reflect the most recent upstream release, then download a new source code tarball, uncompress the tarball, and copy the debian folder into the new folder.

    ~/Simutrans_Development$ cd ~/Pak64_Development
    ~/Pak64_Development$ nano debian/rules
    
    SVNREV  = 811
    VERSION = 111.2
    UPSTREAM_SVNREV = 810M # see README.source
    
    ~/Pak64_Development$ make -f debian/rules get-orig-source
    tar -xvf simutrans-pak64_111.2.orig.tar.xz
    cp -r debian/ simutrans-pak64-111.2/

    Finally, a progress check: The directory should look something like this:

    ~$ ls Pak64_Development/
    debian                                 simutrans-pak64-111.2
    simutrans-pak64_111.2-1.debian.tar.xz  simutrans-pak64_111.2.orig.tar.xz


    4) Build Simutrans

    We're ready to try building the package. This is where the troubleshooting really starts.

    ~$ cd Simutrans_Development/simutrans-111.2.2
    ~/Simutrans_Development/simutrans-111.2.2$ debuild -us -uc

    First  Problem: debhelper 9.
     
    dpkg-checkbuilddeps: Unmet build dependencies: debhelper (>= 9)
    dpkg-buildpackage: warning: Build dependencies/conflicts unsatisfied; aborting.
    dpkg-buildpackage: warning: (Use -d flag to override.)
    debuild: fatal error at line 1348:
    dpkg-buildpackage -rfakeroot -D -us -uc failed
    

    The debhelper package was originally version 7.x. According to the git log, it incremented up to 9 in March 2012, long after the build environment (that's why we review the log!). We can try the -h flag to avoid this...or unapply the patch that incremented debhelper.
     
    ~/Simutrans_Development/simutrans-111.2.1$ debuild -us -uc -d

    Second Problem: Lintian errors.
     
    Now running lintian...
    W: simutrans source: newer-standards-version 3.9.3 (current is 3.9.2)
    W: simutrans: binary-without-manpage usr/games/simutrans-nettool
    Finished running lintian.

    Lintian errors are a good sign - it means everything else worked! Both warnings in this case can be safely ignored...though a good citizen would also file bugs with patches to fix those warnings.

    Take a look at the Simutrans_Development directory now. See all those ready-to-install deb packages?
     
    ian@VM-11-10:~/Simutrans_Development$ ls
    debian                                simutrans_111.2.2-0ppa1_i386.deb
    simutrans-111.2.2                     simutrans_111.2.2.debian.tar.gz
    simutrans_111.2.2-1.debian.tar.xz     simutrans_111.2.2.orig.tar.xz
    simutrans_111.2.2-1.dsc               simutrans-data_111.2.2-0ppa1_all.deb
    simutrans_111.2.2-0ppa1_i386.build    simutrans-makeobj_111.2.2-0ppa1_i386.deb
    simutrans_111.2.2-0ppa1_i386.changes

    Do not install the simutrans_111.2.1-1_i386.deb or simutrans-data_111.2.1-1_all.deb packages yet. If you try, they will install a pak64 package from the repositories instead of the one you are about to build.

    5) Install makeobj

    makeobj is a package (simutrans-makeobj_111.2.1-1_i386.deb) that is built with the Simutrans game, and used in turn to create the paks. Install the deb that was just created before building pak64.

    ~/Simutrans_Development$ sudo dpkg -i simutrans-makeobj_111.2.2-0ppa1_i386.deb 
    

    6) Build Pak64


    We're ready to try building the pak package.

    ~$ cd Pak64_Development/simupak-64
    ~/Pak64_Development/simupak64$ debuild -us -uc

    Problem: Makefile patches failed

    The file debian/patches/buildsystem has several patches that get applied to the makefile. As the makefile changes over time, the patch program may not find the right place to apply some patches. Those changes to the patch must be applied manually.

    patching file Makefile
    Hunk #2 FAILED at 46.
    Hunk #3 succeeded at 65 (offset 2 lines).
    Hunk #4 FAILED at 84.
    2 out of 4 hunks FAILED -- saving rejects to file Makefile.rej
    

    Hunk #2 was a straightforward change to one line (adding the word "zip").
    Hunk #4 had the old version number instead of the new.

    Upon the second try, the pak64 build was successful. You can see the deb package in the directory listing:

    ~$ ls Pak64_Development/
    debian                                     simutrans-pak64_111.2.1-1.dsc
    simutrans-pak64_111.2-0ppa1.debian.tar.xz  simutrans-pak64_111.2.1-1_i386.build
    simutrans-pak64-111.2                      simutrans-pak64_111.2.1-1_i386.changes
    simutrans-pak64_111.2-0ppa1_all.deb        simutrans-pak64_111.2-1.orig.tar.xz
    simutrans-pak64_111.2-1.debian.tar.xz      simutrans-pak64_111.2-1.orig.tar.xz

    7) Test Install

    When installing package-by-package, make sure to install in the right order!

    sudo dpkg -i Pak64_Development/simutrans-pak64_111.2-0ppa1_all.deb
    sudo dpkg -i Simutrans_Development/simutrans-data_111.2.2-0ppa1_all.deb 
    sudo dpkg -i Simutrans_Development/simutrans_111.2.2-0ppa1_i386.deb


    I fire up Simutrans...and it works!

    8) Removing Simutrans

    When the test is complete, and I want to remove simutrans:
    sudo dpkg -r simutrans
    sudo dpkg -r simutrans-data
    sudo dpkg -r simutrans-pak64

    Tuesday, January 24, 2012

    Installing a TP-Link TL-WN722N (Atheros AR9721 802.11n) wireless dongle into Debian 6

    My stock command-line Debian 6 (squeeze) install needs a few additional packages to handle a wireless dongle.

    According to the Debian wiki, this chipset requires the firmware-atheros package, which is non-free.

    Also the kernel needs to be 2.6.39 or higher...so stock squeeze (2.6.32) won't work, but the version in squeeze-backports (2.6.39) will work. Alternately, I could upgrade to Wheezy (the future Debian 7.0) or roll-my-own kernel.

    Edit /etc/apt/sources.list to add the non-free archive and backports.
    deb http://ftp.us.debian.org/debian/ squeeze main non-free
    deb http://security.debian.org/ squeeze/updates main non-free
    deb http://ftp.us.debian.org/debian/ squeeze-updates main non-free
    deb http://backports.debian.org/debian-backports squeeze-backports main non-free

    Begin using non-free and backports by updating the package cache:
    # apt-get update

    Install the packages needed to get wireless working in general, and this dongle in particular:
    # apt-get install wireless-tools usbutils firmware-atheros

    For backported packages, must specify. Use the Debian package search tool to locate the correct package name in the backport archive. For my 486-compatible system, it's:
    # apt-get -t squeeze-backports install linux-image-2.6.39-bpo.2-486

    Finally, create a wireless interface entry in /etc/network/interfaces
    # The wireless interface
    auto wlan0
    iface wlan0 inet dhcp
        wireless-essid YourNetwork
        wireless-mode Managed

    Since I use the syslinux bootloader (instead of grub) to get around the limitations of my 10-year-old motherboard, the new /boot/initrd.img generated by the new kernel must be manually copied over to my /boot partition. The following commands are specific to my setup only! IGNORE THIS SECTION IF YOU USE GRUB!

    Remove unused grub stuff:
    rm -r /boot/grub
    rm /boot/System.map-2.6.39-bpo.2-486
    rm /boot/config-2.6.39-bpo.2-486
    Backup the old bootables:
    # mv /boot/vmlinuz /boot/vmlinuz.old
    # mv /boot/initrd.img /boot/initrd.old
    
    Change the name of the new bootlables to 8-and-3 compatible so syslinux can use them:
    mv /boot/initrd.img-2.6.39-bpo.2-486 /boot/initrd.img
    mv /boot/vmlinuz-2.6.39-bpo.2-486 /boot/vmlinuz

    Reboot, and suddenly the wireless works...until a bug or two intercede.

    The dongle keeps crashing due to a possible kernel bug (or perhaps several). Interestingly, I also seemed to have two dhclient processes running. So lots of narrowing down to do...

    1) Two dhclient processes upon boot (killed one manually)
    2) Kernel bug that kills the dongle with dmesg: phy0: wlan0: No probe response from AP
    3) Kernel or crda bug that thinks I'm in China (CN) instead of the US (US). The preferred fix is to install the crda package (not available for Debian 6.0). Alternate fix is to add a file /etc/modprobe.d/regdom.conf, containing the line options cfg80211 ieee80211_regdom=US (source)

    Let's reboot.

    Aha. After a reboot, ps -e | grep dh shows two dhclient processes. I killed the higher-numbered (later-started) one...which killed both of them and respawned a fresh dhclient process. So there's a bug: dhclient is getting spawned twice upon boot. But it's not related to the crash - that's a separate bug....

    Tuesday, January 10, 2012

    Local file cache to speed up debootstrap

    For my server project, I'm using debootstrap. Here's how to speed up debootstrap by using the existing local cache instead of re-downloading hundreds of MB of packages. Using debootstrap requires a little preparation, and installation of the 'apt-move' package.

    Apt-move is a nifty little tool that moves (or copies) existing packages out of your cache and into a debian archive format. Apt-move creates all three elements of the archive: The various directories full of packages, the Release file, and the Packages file.

    This is only a useful technique if your package cache is complete. If you have cleaned it out since your last major upgrade, then this technique may fail. It's easy to regenerate the cache, though the large download is probably what you were trying to avoid!

    1) Prepare the local mirror. For this example, let's use 6.0 (squeeze):
    Create a place to host the mirror
    # mkdir /var/local/mirrors
    
         Install the apt-move package. 
    # apt-get install apt-move
    
         Edit the configuration file:
    # nano /etc/apt-move.conf
    LOCALDIR=/var/local/mirrors
    DIST=squeeze
    COPYONLY=yes
    
         Create the mirror
    # apt-move update
    You can see the mirror in /var/local/mirrors

    2) Use the new mirror to debootstrap a new chroot environment
    Create the new environment
    # mkdir /var/new-env
    
         Debootstrap from the local mirror
    # debootstrap squeeze /var/new-env file:///var/local/mirrors
    
    Environment complete, ready to chroot into.

    3) If debootstrap fails, it's probably due to a file missing from the cache. There are two ways to regenerate.

    The hard way is to work error by error:
    1) Run debootstrap, and identifying the missing file from the error message.
    2) Use dpkg -S filename to identify the package name.
    3) Use apt-get --reinstall install packagename to add it to the package cache.
    4) Use apt-move update to move the package to the mirror.
    5) Run debootstrap again.

    The easy way is to use debootstrap to recreate all the missing files, and copy them into the cache:
    # mkdir /tmp/cache
    # debootstrap --arch=i386 --download-only squeeze /tmp/cache
    # mv /tmp/cache/var/cache/apt/archives/* /var/cache/apt/
    # rm -rf /tmp/cache
    # apt-move update

    Sunday, January 8, 2012

    Creating a bootable USB drive when the BIOS supports only USB-ZIP

    Mini-ITX Epia 5000-L motherboard, ready to boot.
    The red USB stick is the boot medium,
    1GB USB stick with a complete Debian 6 install
    masquerading as a 250MB USB-ZIP drive.

    My used mini-ITX motherboard has a BIOS limitation that prevents it from booting from ordinary hybrid-iso images. The BIOS doesn't recognize USB-HDD (the popular type used today), but only older USB-FDD (USB floppy drive, limited to 1.4MB) or USB-ZIP (USB Zip Drive, limited to 250MB).

    Who today has useful systems that fit in 250MB?

    This is a demonstration of how to use a chainloader to get around the 250MB restriction. Here is how to build a working full install of Debian 6 on a bootable USB Stick. It's a full install (not a live-install that uses a ramdisk), so all the slow read/writes to the USB stick will make the system very slow and wear out the USB stick prematurely. Again, this is just a demo of how to use a chainloader to get around that 250MB restriction.

    1) Create the Linux system

    This is the long and complicated part. Use debootstrap to create a complete system somewhere else. I explained how I did it in this post for an SD card, and it's almost exactly the same.

    Creating the complete system in, say, /var/usb-env should include creating /boot/initrd.img.version# and vmlinuz.version# , but not grub. We will use initrd.img and vmlinuz in Step #3, and this demo uses the simpler syslinux instead of grub.

    2) Prepare the USB Stick

    To be understood by the old BIOS, the USB stick needs an MBR up front, followed by a FAT boot partition of less than 250MB and labeled as the 4th partition (though it's really the first partition). After that, we can do whatever we like.

    The best tool for creating a USB-ZIP bootable partition is 'mkdiskimage', part of the syslinux package. Everything below should be done as root to the unmounted USB-stick:
    MAKE SURE you are using the right /dev/DEVICE
        /dev/sdb was mine, but probably won't be yours!
    
    # mkdiskimage -Mz4 -i usb-zip /dev/sdb 15 64 32
        -M and 15: Create a 15 MB partition (I only needed 12 MB)
        -z4: Create a zip-disk geometry on partition 4 (normal for zip disks)
        -i usb-zip: Name of the partition. Use any name you wish
        Of course, your /dev/DEVICENODE may vary. BE SURE you are using the right node!
        15 64 32: 15 MB (see -M), 64 heads, 32 sectors (62 and 32 are required for zip)

    After the USB-ZIP partition is made, you can do the rest of the partitions in your favorite editor. I used Gparted to create a 700MB Linux partition and the remaining space on the device as a swap partition.

    3) Install files onto the boot partition

    The install files consist of the bootloader, and the Linux /boot/initrd.img.version# and vmlinuz.version# files. The bootloader simply tells the system to load the linux kernel (vmlinuz), then to load the temporary system startup files (initrd.img) that the kernel can understand. One of the appended command options tells initrd where to find the final system root mountpoint on the other partition.

    There are many bootloaders that can be used here, including grub. For simplicity, I'm using syslinux instead of grub. I don't need all of grub's configuration options - I just want the bootloader to immediately start loading the kernel and initrd.

    For syslinux, we only need four files on the boot partition: The syslinux binary, syslinux.cfg, vmlinuz, and initrd.img. We also need to know the UUID of the other partitions for the syslinux.cfg file.
    Once again, MAKE SURE you are using the right /dev/DEVICE
        /dev/sdb was mine, but probably won't be yours!
    
        Check the USB stick partitions before mounting
    # fsck -f /dev/sdb1  # Blank linux, -f forces a check
    # fsck -f /dev/sdb4  # Blank boot
    
        Get the UUIDs of the various partitions
    # blikd   # Get the UUIDs of the newly created partitions
    
        Install Syslinux 
    # syslinux --install /dev/sdb4
    
        Mount the boot partition
    # mount -t vfat /dev/sdb4 /mnt
    
        Copy vmlinuz and initrd.img from the prepared system.
        Rename the files to comply with MSDOS 8.3 format
    # cp /var/usb-env/vmlinuz.version /mnt/vmlinuz
    # cp /var/usb-env/initrd.img.version /mnt/initrd.img
    
        Create the syslinux.cfg file
    # nano /mnt/syslinux.cfg    # Use any editor you wish
    
    ##### Begin File
    Default USB-Stick
    
    display syslinux.msg
    F1      syslinux.f1
    
    prompt 40
    timeout 30
    
    Label USB-Stick
      kernel vmlinuz
      append initrd=initrd.img root=UUID=>UUID of the root partition<
    ##### End file
    
        Unount the boot partition
    # umount /mnt

    4) Copy the linux system onto the USB Stick

    Once again, MAKE SURE you are using the right /dev/DEVICE
        /dev/sdb was mine, but probably won't be yours!
    
        Mount the Linux partition
    # mount /dev/sdb1 /mnt
    
        Copy the system files
    # cp -r /var/usb-env/{bin,etc,home,lib,media,mnt,opt,root,sbin,selinux,srv,tmp,usr,var} /mnt/
    
        Create the system mountpoints
    # mkdir /mnt/{boot,dev,proc,sys}
    
        Edit /etc/fstab to add the correct UUIDs for the root, boot, and swap partitions
        and remove the cruft from the creating-system disks.
    If you need to discover a UUID, use the 'blkid' command.
    # nano /mnt/etc/fstab     # Use any editor you wish, of course
    
    #####Begin File
    # <file system> <mount point> <type> <options> <dump>  <pass>
    UUID=<UUID of the main system> / ext3 defaults,errors=remount-ro,noatime 0 1
    UUID=<UUID of the boot partition> /boot vfat defaults,errors=remount-ro,noatime 0 2 
    UUID=<UUID of the swap partition> none  swap sw 0 0 
    #####End File
    
        Unmount the linux partition, check the USB stick for damage once more
    # umount /mnt
    # fsck -f /dev/sdb4
    # fsck -f /dev/sdb1
    

    Successful boot to Debian 6 login prompt!
    5) You're Done

    Unplug the USB stick, walk over to the system you want to boot, plug in the USB stick, and....well, boot.

    Friday, January 6, 2012

    Installing Debian 6 onto an SD card, installing into an old VIA EPIA-5000L motherboard

    In this post I discussed my new-to-me fanless motherboard, and how I got it to turn on/off, and test the boot.

    Next step is to install a hard drive and install Debian 6.

    Hardware

    This hardware will eventually become a router or light-duty server, so the OS doesn't need huge storage. I used:
    • SD-to-IDE adapter (ebay, $8.88)
    • The adapter reqires a FDD (floppy disk) power connector. Since my power supply doesn't have that connector, I picked up a molex (IDE HDD power) to FDD adapter (amazon, $3.92)
    • 8GB SD card (left over from a now-dead camera). An SD card can also be plugged in to my Ubuntu 11.10 laptop. This turned out to be critically useful for me

    Install Failures

    Using the same method as this post to make bootable USB drives, I tried the latest Debian 6 businesscard and netinstall disks. Both failed at various points. Sometimes the iso was corrupted during download. Sometimes there was a failure writing the new partition table. Sometimes the table was successfully written, but the new partition couldn't be mounted for install. Sometimes the install was successful, but grub failed to install.

    One by one, I winnowed through the issues. MD5 for the iso downloads. Pull the card and reformat it in my laptop to fix the partition table. Finally, I got consistent failures: The businesscard iso failed during the install debootstrap, and the netinstall iso failed to create an initramfs and grub.

    The businesscard iso could successfully drop to a working shell, so I used these instructions to manually install debootstrap and see if I could bypass the installer failures. This worked well, though slowly (writing to the SD card is much slower than to a real hard drive), and my many mistakes after this point were a learning experience in filesystem corruption, chroot, initramfs, and grub.

    fsck, chroot, initramfs, and grub

    Booting to a live environment, dropping to a shell, debootstrapping to an installed system, and then rebooting to test it...only to discover it's unbootable...take a long time for each cycle, mostly due to the SD card slow write speed, and the SD card's seeming love of getting it's filesystem corrupted somewhere in the process each time.

    I sped up the process and injected filesystem checks by moving most of it onto a Debian VM on my laptop. The SD card mounts as a USB drive, so the VM must be USB-capable. Lesson Learned: Before mounting/unmounting the card, fsck it! Every time! This is how I got rid of the filesystem corruption, which seemed to be happening from something unclean during shutdown (almost true - I'll tell you the real story later). On some occasions the filesystem was so messed up that I simply wiped it and copied a new system over from the VM.

    Now, I could reliably build a system that would boot...but grub would complain or initramfs would drop to a shell. On two occasions it successfully booted, then froze (and corrupted the filesystem). Testing with variations in /boot/grub/grub.cfg fixed grub to boot reliably...only to later learn that grub 'error' wasn't an error at all, but a different configuration problem I had caused somewhere else.

    That left a frustrating initramfs refusal to mount the card. I could mount it manually, but that resulted in kernel panic. After a lot of digging through initramfs scripts, I discovered a packaging bug - initramfs relies on klibc-tools...but the dependency is not listed in Debian 6! (It is correct in Ubuntu 10.10). One apt-get later and the system booted reliably every time...but the filesystem was frequently corrupting.

    Apt activities that triggered man-db began returning "fopen: Permission denied" errors. Fixed with chown -R man:root /var/cache/man


    And the result...

    I finally determined that the frequent filesystem corruptions were due to a defective SD-to-IDE adapter. I tested the card reader on my laptop - no problems, so it wasn't the laptop, the card, or my handling. The proof was when the SD card was freshly installed, fsck'd before removal from the laptop, fsck'd again upon insertion to the Epia system, and run for an hour. Missing and corrupted file errors began to proliferate. Still need to check the RAM.


    Lessons Learned
    1) fsck the SD card before every mount and after every unmount
    2) Manually check for the existence of /boot/grub/grub.cfg, /boot/grub/normal.mod, and /sbin/init
    3) Use blkid to get the UUID of the root partition. Check that against /boot/grub/grub.cfg

    Steps to succesfully creating the SD card
    Without wandering down my many blind paths, here is the final process to install a bootable Debian 6 onto an SD card.

    1) Use a VM (I used Virtualbox) with USB access on a fast machine (my laptop).
    2) Within the VM, create a chroot environment and use debootstrap to create the new linux system that will be copied onto the card.
    3) Prepare the SD card, copy the environment, and install grub.
    4) Ensure a good system after the first boot from the card.

    Creating a VM is beyond the scope of this discussion.

    Creating the new linux system happens entirely on the VM. Create the base debian install
    # mkdir /var/card-env
    # debootstrap --arch=i386 squeeze /var/card-env
    Depending on your network connection, debootstrap may take a long time.


    Mount the system-required stuff
    # mkdir /var/card-env/proc
    # mount --bind /proc /var/card-env/proc
    # mkdir /var/card-env/dev
    # mount --bind /dev /var/card-env/dev
    # mount --bind /dev/pts /var/card-env/dev-pts
    # mkdir /var/card-env/sys
    # mount --bind /sys /var/card-env/sys
    Copy useful stuff before chrooting


    These files must be edited later in the process
    # cp /etc/fstab /var/card-env/etc/
    # cp /etc/network/interfaces /var/card-env/etc/network/
    # cp /etc/hosts /var/card-env/etc/
    Chroot into the card-env
    # chroot /var/card-env
    Set up the package manager. Do these in the chroot environment.
    # echo "deb-src http://ftp.us.debian.org/debian squeeze main" >> /etc/apt/sources.list
    # echo "deb http://security.debian.org/ squeeze/updates main" >> /etc/apt/sources.list
    # echo "deb-src http://security.debian.org/ squeeze/updates main" >> /etc/apt/sources.list
    # apt-get update
    If any apt-get errors pop up, take time and fix them now. Do these in the chroot environment.

    If any command-not-found errors occur:
    Use 'which commandname' to find the full path
    for example, 'which date' returns '/bin/date'
    Use dpkg -S full-path to find the package name
    for example, 'dpkg -S /bin/date' returns 'coreutils'
    Reinstall that package
    for example, 'apt-get remove coreutils && apt-get install coreutils'

    Edit hostname, hosts, and interfaces. Do these in the chroot environment
    # echo MyNewHostName > /etc/hostname
    # nano /etc/hosts                # Change the hostname
    # nano /etc/network/interfaces   # Reduce interfaces to just to loopback device
                                   # udev will add the rest anyway upon boot

    Add your root and user accounts. Do these in the chroot environment
    # passwd root
    # adduser MyName

    Add essential elements to the new filesystem. Do these in the chroot environment
    # apt-get install locales
    # dpkg-reconfigure locales     # Choose a UTF-8 in your preferred language
    # apt-cache search linux-image # Choose a kernel that matches your architecture
    # apt-get install klibc-tools initramfs-tools linux-image-VERSION-i486 grub-pc

    Take a few minutes and troubleshoot any kernel-install or initramfs issues. Do this in the chroot environment. Grub will have a lot of incorrect information, and we'll fix that after we plug in the SD card.

    Add desired optional packages. Do this in the chroot environment
    # apt-get install openssh-server     # For example

    Exit the chroot environment, then unmount the system-essentials
    # exit
    # umount /var/card-env/proc
    # umount /var/card-env/dev-pts
    # umount /var/card-env/dev
    # umount /var/card-env/sys

    You now have a complete Debian environment (except for grub and fstab), ready to copy from the VM onto the SD card.

    Plug in the SD card to the VM machine, and add the SD card (as a USB) to the VM. Leave it unmounted. udev assigned my card as /dev/sdb.

    Partition the card as desired. I created /dev/sdb1 (bootable ext3), and /dev/sdb5 (swap). Do these steps as root. Card must be plugged in but unmounted for these steps:
    # mke2fs -j /dev/sdb1   # Assuming you haven't formatted it yet
    # mkswap /sev/sdb5   # Assuming you haven't formatted it yet

    Mount the card
    # fsck /dev/sdb1
    # mount /dev/sdb1 /mnt

    Change grub's device map to the SD Card
    # ls /dev/disk/by_id    # Note the SD Card's ID string
    # nano /var/card-env/boot/grub/device.map  # Change HD0 to the SD card

    Change grub's config file and fstab to the SD Card partition
    # blkid        # Note the linux partition's UUID string
    # nano /var/card-env/boot/grub/grub.cfg    # Change all the UUID strings to the SD Card Partition
    # nano /var/card-env/etc/fstab             # Change the UUID strings on the root and swap lines

    Copy the environment over to the card
    # cp /var/card-env/* /mnt/
    # grub-install --root-directory /mnt /dev/sdb

    Final checks
    # blkid   # Note the UUID of the card boot partition
    # nano /mnt/boot/grub/grub.cfg   # Check for the same UUID
    # ls -l /mnt/sbin/init    # Check for existence
    # ls /mnt/boot            # Check for an initrd.img file and a vmlinuz file

    Unmount and fsck the SD card
    # umount /mnt
    # fsck /dev/sdb1
    You now have a complete bootable Debian 6 installed on the SD card, ready to try booting from.

    During the first boot from the SD card, do the following:
    # update-initramfs -u  # Get rid of "Can't find disk" errors
    # tune2fs -c 1 /dev/sda # Set the flag to run fsck every boot until further notice
    # ifconfig -a   # Note the MAC address and interface of the ethernet port

    Keep the current system interfaces, delete leftovers from the laptop environment
    # nano /etc/udev/rules.d/70-persistent-net-rules

    Bring up the network and prepare apt-get
    # ifconfig up eth1  # Your eth may differ
    # dhclient eth1
    # apt-get update
    # apt-get upgrade

    Add essential system components
    # apt-get install rsyslog

    Thursday, December 22, 2011

    Missing a file during compile

    During a compile, I kept getting 'missing file' errors.

    Solution: Use packages.debian.org to fing the package that includes the missing file, so I can install it.

    Tuesday, November 29, 2011

    Booting an old VIA EPIA-5000L motherboard

    I purchased an old VIA fanless mini-ITX motherboard on eBay, including CPU and RAM and shipping, for a reasonable price ($43). I want to play with it and see what I can get it to do. Maybe build a cool case for it...

    MB attached to ordinary ATX power supply, VGA monitor, and PS/2 Mouse.
    Tiny black rectangle on the right is the on/off jumper.
    Step 1: Hook it up

    Happily, I have an old PS/2 keyboard, VGA monitor, and ATX power supply handy.
    Hook them all up...and nothing.

    Of course, the power switch.
    Get the manual, read the manual, find the jumper, and use a spare jumper to connect them for a moment.

    Hooray! Fans on the power supply start to spin! Beep! Splash appears on the monitor!

    I made the following BIOS changes:
    • Always restart upon power loss (since I don't have a power switch!)
    • Enable fast startup (skip memtest, faster boot)
    • Skip splash (annoying)
    • Skip BIOS summary (annoying)
    • Change the boot device to USB-ZIP (not USB-FDD, essential for USB-boot later)


    Step 2: Create a Debian Boot USB drive.

    This is a pretty old motherboard, so the standard USB-HDD booting option is missing. That means Live-USB (hybrid USB/CD) .iso files won't work without some tweaking. The available USB options are USB-ZIP and USB-FDD. A quick web search turns up this page of instructions, but it doesn't work. Further digging reveals this page, a version of which does work.

    1. Select a USB Drive (small). Everything on it will be erased, so backup if needed.
    2. On a different (working) Debian or Ubuntu system, as root (use 'sudo su' to get a root prompt on Ubuntu). Not all commands will work with sudo alone.
    3. Plugin the USB drive. If your system automatically mounts it, then unmount (not eject) it.
    4. Use dmesg to find the USB drive's /dev/sd* node. For example, mine was sdz and sdz3.
    5. Format the USB drive to a bootable configuration. This will limit the accessible size to 250MB (the old ZIP-format maximum), so CD-sized live .isos won't work. See this page for mkdiskimage commands for other-size drives.
      mkdiskimage -4 /dev/sdz 0 64 32   # 1GB and below USB drives only
    6. Install the MBR:
      cat /usr/lib/syslinux/mbr.bin > /dev/sdz
    7. Get and install the boot image:
      wget -O /tmp/boot.img.gz http://ftp.debian.org/debian/dists/squeeze/main/installer-i386/current/images/hd-media/boot.img.gz
      zcat /tmp/boot.img.gz > /dev/sdz1
    8. Download the Live Session image. In this case, I used a Debian businesscard installer simply because it was a very small download:
      wget -O /tmp/debian-6.0.3-i386-businesscard.iso http://cdimage.debian.org/debian-cd/6.0.3/i386/iso-cd/debian-6.0.3-i386-businesscard.iso
      md5sums /tmp/debian-6.0.3-i386-businesscard.iso
      Compare the md5sum result to http://cdimage.debian.org/debian-cd/6.0.3/i386/iso-cd/MD5SUMS
    9. Mount the USB drive, and install the Live Session image:
      mkdir /tmp/usbmountpoint
      mount /dev/sdz3 /tmp/usbmountpoint
      cp /tmp/debian-6.0.3-i386-businesscard.iso /tmp/usbmountpoint/
      umount /tmp/usbmountpoint
    10. Check the resulting filesystem, and correct any errors (there may be a couple!)
      fsck.msdos -r /dev/sdz3
      My resulting filesystem is about 214MB, below the 250MB limit.
    11. Clean-up is optional, since all working files are in /tmp and will be deleted upon reboot anyway.
    12. Unplug the USB drive (it should already be unmounted)


    Step 3: Boot Debian

    The BIOS should be set to a startup device of USB-ZIP (step 1), and you should have a Debian USB drive (step 2). Put them together - try to boot the new motherboard from it. In my case, success!

    I don't have a hard drive installed yet, so I'm not ready to actually install. But this was a successful power-on and boot.


    UPDATE #1: For Xmas, one of the kids got a toy butterly-in-a-jar. It has a "Try Me" feature for in the store, a button that detached after opening the package. The button's connector looked just right to fit the power jumper, and indeed now I have a real power button for the motherboard. This turns out to be handy, because a stable system needs better power control than flipping the switch on the power supply...and my new silent power supply has no switch!

    UPDATE #2: A chainloader can be used to bypass the USB-ZIP 250MB boot limit. I did a successful USB-ZIP boot to a complete Debian 6 system.

    Friday, October 28, 2011

    The better, easier way to install wanpipe

    In this post from march 2011, I described my successful installation of Sangoma software for my Sangoma S518 PCI DSL Modem.

    Well, for unknown reasons a couple weeks ago the software failed completely upon a reboot.

    So it's time to reinstall. And this time, to do it the right way. (Instructions)

    In this case, PPPoE, two interfaces are created, dsl0 and ppp0. Wanrouter creates the physical dsl0 interface, and the pon/poff creates the virtual ppp0 interface that actually shows up in the routing table and enables real network activity.

    To install wanrouter, do the following as root:
    #Create the build environment
    apt-get install gcc g++ automake autoconf libtool make libncurses5-dev flex bison patch libtool linux-headers-$(uname -r)
    
    # Get the latest driver tarball
    cd /usr/src
    wget ftp://ftp.sangoma.com/linux/current_wanpipe/wanpipe-3.5.23.tgz
    tar xvfz wanpipe-<version>.tgz
    
    # Create a deb package from the tarball
    cd wanpipe-<version>
    ./Setup builddeb    # no make, no prepare. Setup does it all for you.
    dpkg -i wanpipe_<version> 
    
    And that's all for the install.

    It seems last time I made a few mistakes. Live and learn:
    1) I missed a couple build dependencies like automake and autoconf
    2) I used obsolete information to prepare for the installation
    3) I completely missed the builddeb option!

    Next, configure the dsl0 interface. The DSL line does not need to be connected:
    wanrouter hwprobe  # Test if the card is detected
    wancfg             # Ncurses tool to configure the wanpipe and interface
                       # Name the interface (foe example dsl0)
                       # Enable the startup and shutdown scripts
                       # Note the name of the configuration file (wanpipe1)
    

    Let's test to make sure wanrouter works:
    wanrouter start wanpipe1   # Test - should bring up interface
    ifconfig                   # The interface should be on the list
    ifconfig dsl0 down         # Test - should bring down interface
    ifconfig                   # The interface should *not* be on the list
    ifconfig dsl0 up           # Test - should bring up interface
    ifconfig                   # The interface should be on the list
    wanrouter stop wanpipe1    # Test - should being down interface
    ifconfig                   # The interface should *not* be on the list
    

    Next, create and configure the ppp0 connection. The DSL line must be connected for this step to work.
    wanrouter start   # Activate wanrouter so pppoeconf can detect it
    ppoeconf          # Configure ppp0
                      # The pppoeconf program will ask two important questions:
                      # 1) Do you want to start PPPoE at each startup? 
                      #  NO, because it will fail - dsl0 will not be ready yet.
                      # 2) Do you want to start PPPoE now? 
                      #  You can, but if there are any problems, the process will be 
                      #  orphaned. Kill it with the command 'poff -a'
                      # You can see the PPPoE configuration (link to the dsl0 interface) 
                      # in /etc/ppp/peers/dsl-provider. You can see your dsl username 
                      # and password in /etc/ppp/pap-secrets.
    

    Configuration is complete. DSL connectivity should work now.

    Let's test it:

    To manually open/close the dsl connection:

    wanrouter start     # To bring up the dsl0 interface. Wanrouter does this at boot already.
    pon dsl-provider    # To bring up the ppp0 interface, which is the real PPPoE connection 
                        # (with an IP address).
    plog                # A handy debugging tool. Take a quick look at the log
    ifconfig            # The dsl0 interface does not have an IP. 
                        # The ppp0 interface does have an IP
    route               # The upstream DSL server should be showing as a gateway,
                        # and a 'default' route should exist
    ping <example>      # Test network connectivity
    poff -a             # To close the PPPoE connection, and bring down the ppp0 interface
    wanrouter stop      # To bring down the dsl0 interface. Wanrouter does this at shutdown already,
    


    To automatically open/close the dsl connection: Insert a start script and a stop script as follows. Automatically starting takes about 45 seconds:

    echo "pon dsl-provider" >> etc/wanpipe/scripts/wanpipe1-dsl0-start
    echo "poff -a" >> etc/wanpipe/scripts/wanpipe1-dsl0-stop
    # If these don't work, then you may need to use 'wancfg' to enable the start/stop scripts.
    



    For my own reference, here's the Setup output:
    me@mysystem:/usr/src/wanpipe-3.5.23# ./Setup builddeb
    Enabling the FR Protocol
    Enabling the CHDLC Protocol
    Enabling the PPP Protocol
    Enabling the X25 API Protocol
    Enabling the ADSL Protocol
    Enabling the Multi Protocol Driver
    Enabling the AFT TE1 Support
    Enabling the AFT TE3 Support
    
    WARNING: Module installation dir mismatch!
             Linux source name  = 2.6.
             Current image name = 2.6.32-5-686
    
      If you are building wanpipe modules for the
      currently running image, use the 2.6.32-5-686
      directory (i.e. select 'y') 
    
    Install modules for current image: 2.6.32-5-686 ? (y/n) y
    
    Installing modules for kernel: 2.6.32-5-686 !
    
    
     ----------------------------------------------------------
               WANPIPE v3.5.23 Installation Script
         Copyright (c) 1995-2011, Sangoma Technologies Inc.
     ----------------------------------------------------------
    
    
      
     WANPIPE DEB BUILD
    
    Wanpipe DEB will be build based on the 
    following Environment variables.
     
     1. Linux Source Dir  : /lib/modules/2.6.32-5-686/build
    
     2. Linux Source Name : 2.6.32-5-686
    
     3. Current Image Name: 2.6.32-5-686
     
     4. CPU Type          : i686
     
     5. Wan Protocols     : FR-CHDLC-PPP-MFR-MPROT-X25-AFT_TE1-AFT_TE3-ADSL-ATM
     
     6. Build Directory   : /usr/src/wanpipe-3.5.23/debbuild 
    
    
    
    Would you like to build WANPIPE DEB ? (y/n) y
    Enabling the FR Protocol
    Enabling the CHDLC Protocol
    Enabling the PPP Protocol
    Enabling the X25 API Protocol
    Enabling the ADSL Protocol
    Enabling the Multi Protocol Driver
    Enabling the AFT TE1 Support
    Enabling the AFT TE3 Support
    
     ----------------------------------------------------------
               WANPIPE v3.5.23 Installation Script
         Copyright (c) 1995-2011, Sangoma Technologies Inc.
     ----------------------------------------------------------
    
    WANPIPE INSTALLATION
    
    You are about to install WANPIPE Multi-Protocol
    TDM Voice & WAN Router into your system.
    
    This script will examine your system, then install, create
    and/or modify necessary files and directories.
    
    You must have Linux Kernel Headers along with
    full development tools (i.e. GNU C compiler and utilities)
    installed in order to be able to install this product.
    
    This script will automatically compile all WANPIPE kernel
    drivers and install them in their appropriate directory.
    
    If you are installing Wanpipe for ASTERISK/ZAPTEL this
    script will will prompt you for zaptel source location.
    
    If you have previoulsy installed WANPIPE, this release
    will overrite/upgrade full release without the need to
    uninstall first!
    
    IMPORTANT:
    It is always recommended to say YES to all options
    prompted during the install!
    
    Please visit: http://wiki.sangoma.com for more info.
    
    
     ----------------------------------------------------------
               WANPIPE v3.5.23 Installation Script
         Copyright (c) 1995-2011, Sangoma Technologies Inc.
     ----------------------------------------------------------
    
    Fixing file permissions...
    
    Verifying files and fixing permissions ...Done
    Checking for C developement tools ...(gcc) OK
    Checking for C++ developement tools ...OK
    Checking for Make utility ...OK
    Checking for ncurses library ... OK
    Checking for Perl developement tools ...OK
    Checking for AWK ...OK
    Checking for FLEX ...OK
    Checking for Patch ...OK
    Checking for libtermcap-devel...OK
    Checking for bison...OK
    Checking for libtool...OK
    
    
     ----------------------------------------------------------
               WANPIPE v3.5.23 Installation Script
         Copyright (c) 1995-2011, Sangoma Technologies Inc.
     ----------------------------------------------------------
    
    
    Installing WANPIPE Device Drivers: Linux KERNEL
    
    To integrate WANPIPE Multi-Protocol Voice & WAN Router 
    modules into the Linux kernel, the kernel has to be 
    updated with latest wanpipe sources.  Install will only
    modify existing wanpipe source that is already in the
    Kernel. 
    
    IMPORTANT:
    It is always recommended to say YES to all options 
    prompted during the install!
    
    
     ----------------------------------------------------------
               WANPIPE v3.5.23 Installation Script
         Copyright (c) 1995-2011, Sangoma Technologies Inc.
     ----------------------------------------------------------
    
    Setting linux directory to /lib/modules/2.6.32-5-686/build
    
    
    
    Upgrading WANPIPE kernel documentation ...Done.
    
    
    Installing WANPIPE include headers ...Done.
    
    WANPIPE device drivers upgraded successfully!
    
    
     ----------------------------------------------------------
               WANPIPE v3.5.23 Installation Script
         Copyright (c) 1995-2011, Sangoma Technologies Inc.
     ----------------------------------------------------------
    
    WANPIPE KERNEL DRIVER COMPILATION
     
    The next step in WANPIPE installation involves compiling 
    WANPIPE kernel modules.  
    
    This script will compile and install WANPIPE modules
    into the currently running linux kernel.
    
    For greater customization you will be prompted to
    select which Protocol/Drivers you would like to
    build into the WANPIPE kernel modules.
    
    Wanpipe for Asterisk/Dahdi/Zaptel
     Default for Asterisk/Dahdi/Zaptel
    Wanpipe for Wan Routing/API 
     Default for Wan/IP Routing and Data API
    Wanpipe for Asterisk SMG/SS7
     Default for Asterisk SS7
    Wanpipe for TDM API
     Default for FreeSwitch and Voice API  
    
    Custom Compilation:
    ------------------
      Customise WANPIPE driver compilation to add only the
      protocols that you need.  This way one can reduce
      the size of the WANPIPE kernel drivers.
    
    Refer to http://wiki.sangoma.com for more info
    
    
     ----------------------------------------------------------
               WANPIPE v3.5.23 Installation Script
         Copyright (c) 1995-2011, Sangoma Technologies Inc.
     ----------------------------------------------------------
    
    
    Checking for SMP support ...Enabled.
    
    Checking current processor type ...i686
    
    Wan Update Flags:  -DWANPIPE_MOD_266_FORCE_UPDATE
    
    
    --------------------------------------------------
    CFLAGS: gcc -Wp,-MD,.wanpipe.o.d -nostdinc -iwithprefix include -D__LINUX__ -Dlinux -D__KERNEL__ -I/usr/src/wanpipe-3.5.23/debbuild/usr/include/wanpipe -I/lib/modules/2.6.32-5-686/build/include  -DMODULE   -DWANPIPE_MOD_266_FORCE_UPDATE  make: Entering directory `/usr/src/linux-headers-2.6.32-5-686'
    make: Leaving directory `/usr/src/linux-headers-2.6.32-5-686'
    --------------------------------------------------
    
    Checking for REGPARM kernel option ...
    Warning: Failed to determine regparm from Makefile defaulting to YES!
    
    Enabled.
    
    Compiling General WANPIPE Driver for 2.6.X Kernel .....Done.
    
    
    WAN HWEC module enabled and compiled!
    
    FR compiled for GCC Ver=3 Arch=i686 File:wanpipe_fr.gcc3.i686.regparm.o
    
    PPP/CHDLC compiled for GCC Ver=3 Arch=i686 File:wanpipe_sppp.gcc3.i686.regparm.o
    
    ATM compiled for GCC Ver=3 Arch=i686 File:wanpipe_lip_atm.gcc3.i686.regparm.o
    
    ADSL binary compiled for GCC Ver=3 Arch=i686 File:wanpipe_adsl.gcc3.i686.regparm.o
    
    ATM binary compiled for GCC Ver=3 Arch=i686 File:wanpipe_atm.gcc3.i686.regparm.o
    
    Linking Wanpipe Driver and protocols ...Done.
    
    Updating Kernel Modules ...Done.
    
    Compilation Successful.
    
     ----------------------------------------------------------
               WANPIPE v3.5.23 Installation Script
         Copyright (c) 1995-2011, Sangoma Technologies Inc.
     ----------------------------------------------------------
    
    WANPIPE META CONFIGURATION
    
    There are two configuration files associated with WANPIPE.  
    
    1) /usr/src/wanpipe-3.5.23/wanrouter.rc: 
     - defines locations of important files such as lock
       and configuration files as well as start/stop 
       order of multiple WANPIPE devices.
    2) /usr/src/wanpipe-3.5.23/wanpipe1.conf:
     - main configuration file for each WANPIPE device.
     - defines interfaces, hardware and protocol information.
     - this file can be created using the 'wancfg' GUI
       utility or manually based on sample files located
       in /etc/wanpipe/samples.
       
    Please read the WanpipeInstallation.(pdf/txt) manual for further
    information.
    
    
     ----------------------------------------------------------
               WANPIPE v3.5.23 Installation Script
         Copyright (c) 1995-2011, Sangoma Technologies Inc.
     ----------------------------------------------------------
    
    WANPIPE UTILITIES SETUP
    
    WANPIPE utilities are used to:
     1) create configuration files: for Zaptel and Asterisk
      /usr/sbin/wancfg_zaptel #Zaptel and Asterisk
      /usr/sbin/wancfg_dahdi #Dahdi and Asterisk
      /usr/sbin/wancfg_smg #BRI/SS7, Zaptel and Asterisk
      /usr/sbin/wancfg_tdmapi #TDM API
     2) create WANPIPE WAN/IP configuration files.
      (/usr/sbin/wancfg)
     3) start,stop,restart individual/all devices and interfaces.
      (/usr/sbin/wanrouter)
     4) debug line, protocol and driver problems.
      (/usr/sbin/wanpipemon)
     5) aid in WANPIPE API development
      (/etc/wanpipe/api)
    
    Refer to the WanpipeInstallation.(pdf/txt) for more information.
    
    Compiling WANPIPE LibSangoma API library ...Done.
    
    
    
    Compiling WANPIPE Utilities ...Done.
    
    
    Compiling WANPIPE WanCfg Utility ...Done.
    
    
    Compiling WANPIPE API Development Utilities ...Skipped, no makefile
    
    Compiling WANPIPE HWEC Utilities ...Done.
    
    
     WANPIPE Environment Setup Complete !!!
    
    Installing WANPIPE Files ... !
    Installing  WANPIPE Utilities in /usr/src/wanpipe-3.5.23/debbuild/usr/sbin
    Installing wanrouter.rc in /usr/src/wanpipe-3.5.23/debbuild/etc/wanpipe
    Installing wanpipe libraries in /usr/src/wanpipe-3.5.23/debbuild/etc/wanpipe
    Installing firmware in /usr/src/wanpipe-3.5.23/debbuild/etc/wanpipe/firmware
    Installing documentation in /usr/src/wanpipe-3.5.23/debbuild/usr/share/doc/wanpipe
    Installing sample api code in /usr/src/wanpipe-3.5.23/debbuild/etc/wanpipe/api
    Installing AFT Firmware update utility in /usr/src/wanpipe-3.5.23/debbuild/etc/wanpipe/util
    Installing driver headers in /usr/src/wanpipe-3.5.23/debbuild/etc/wanpipe/api/include/linux
    Installing Hardware Echo Cancel Utilites
    
     ----------------------------------------------------------
               WANPIPE v3.5.23 Installation Script
         Copyright (c) 1995-2011, Sangoma Technologies Inc.
     ----------------------------------------------------------
    
    WANPIPE INSTALLATON: COMPLETE
     
    WANPIPE installation is now complete. WANPIPE kernel drivers 
    and configuration/debug utilities have been compiled and installed.
    
     1) Proceed to configure the WANPIPE drivers:
      Asterisk/Zaptel  : /usr/sbin/wancfg_zaptel
      Asterisk/Dahdi   : /usr/sbin/wancfg_dahdi
      TDM API          : /usr/sbin/wancfg_tdmapi
      SMG SS7/BRI/PRI  : /usr/sbin/wancfg_smg
      WAN Routing/API  : /usr/sbin/wancfg
     2) Use the /usr/sbin/wanrouter startup script to start and stop
        the router. (eg: wanrouter start)
     3) To uninstall WANPIPE package run ./Setup remove
      
    Please read http://wiki.sangoma.com for further instructions.
    
    
    WANPIPE DEB BUILD SUCCESSFUL
    
    The new rpm is located in /usr/src/wanpipe-3.5.23:  wanpipe_3523-k266_i686.deb
    
    To install run:
     dpkg -i 
    

    Wednesday, September 7, 2011

    More useful sshd on the gateway

    I need access to my gateway machine (which runs irssi) while out in the world on the internet.


    Currently, SSH access from the internet is blocked by firewall. There are a couple ways to enable it. I need to select one, add a secure connection method, and block brute-force methods to crack that connection.


    The easiest way is to:

    1. Open port 22 on the firewall
      iptables -A INPUT -p tcp --dport 22 -j ACCEPT
    2. Add a method of blocking brute force attacks
      # Allow incoming ssh attempts for the internet, and add them track them
      #iptables -A INPUT -i ppp0 -p tcp -m tcp --dport 22 -m state --state NEW -m recent --set --name DEFAULT --rsource
      # After three inbound ssh attempts in three minutes, drop any subsequent attempts until the three minutes expires
      #iptables -A INPUT -i ppp0 -p tcp -m tcp --dport 22 -m state --state NEW -m recent --update --seconds 180 --hitcount 4 --name DEFAULT --rsource -j DROP
    3. Check the settings of /etc/ssh/sshd_config
      # What ports, IPs and protocols we listen for
      Port 22
    4. Check the settings of etc/hosts.allow
      sshd:              ALL
    5. Restart the firewall so the new rules take effect. Restart sshd if any changes to sshd_config or hosts.allow were made.


    Alternately, we can tell ssh to listen on a second (unadvertised) port. This may (or may not) be more secure than using firewall rules to block brute force attacks.

    1. Open port 33 on the firewall
      iptables -A INPUT -p tcp --dport 33 -j ACCEPT
    2. Change the settings of /etc/ssh/sshd_config
      # What ports, IPs and protocols we listen for
      Port 22
      Port 33
    3. Check the settings of etc/hosts.allow
      sshd:              ALL
    4. Restart the firewall so the new rules take effect. Restart sshd.
      bash /etc/network/if-up.d/00-firewall
      service restart ssh
      


    Since the ddclient package is installed, I can now connect to my server from the internet using:
    ssh [--port 33] accountname@myusername.dyndns.org

    Saturday, March 5, 2011

    Installing a Sangoma S518 DSL Modem card in a Dell Optiplex GX60 running Debian 6

    This post is obsolete and has been superseded

    Ebay provided a new-to-me used DSL PCI modem card to replace my 10-year-old DSL modem. The old modem still works; this is purely for fun.

    The card is recognized, but no kernel module is associated with it.

    lspci -vv
    01:07.0 Network controller: Globespan Semiconductor Inc. Pulsar [PCI ADSL Card] (rev 01)
     Subsystem: Globespan Semiconductor Inc. Device d018
     Control: I/O- Mem+ BusMaster+ SpecCycle- MemWINV- VGASnoop- ParErr- Stepping+ SERR+ FastB2B- DisINTx-
     Status: Cap+ 66MHz- UDF- FastB2B+ ParErr- DEVSEL=slow >TAbort- <TAbort- <MAbort- >SERR- <PERR- INTx-
     Latency: 64 (750ns min, 50000ns max)
     Interrupt: pin A routed to IRQ 16
     Region 0: Memory at ff8f0000 (32-bit, non-prefetchable) [size=64K]
     Capabilities: [40] Power Management version 2
      Flags: PMEClk- DSI- D1- D2- AuxCurrent=0mA PME(D0+,D1+,D2+,D3hot+,D3cold+)
      Status: D0 NoSoftRst- PME-Enable- DSel=0 DScale=0 PME-
    

    Sangoma has a Linux driver, but it needs to be compiled, so it needs linux source code to refer to during compilation. The linux kernel itself does not need to be recompiled. It's annoying and time consuming, but it does work. Sangoma's information and downloads are at their wiki. Details of how to prepare the kernel source and headers is here.

    Compatibility with networking and commands:

    • Do not make any changes to the /etc/network/interfaces file. The wanrouter program defines and brings up/down the dsl interface without using the file.
    • Ifup/ifdown does not work, because they rely on the interfaces file.
    • Ifconfig *does* work but only after a wanpipe is already active. Ifconfig up/down do work without restarting the wanpipe.

    The nomenclature and order of events can be confusing:

    wanrouter is the command that starts everything. It's just a bash script at usr/sbin/wanrouter. Don't be fooled by the name - it's not really a router. The wanrouter command turns on/off a wanpipe. A wanpipe is the low-level connection to the PCI card, and they create/destroy the dsl0 high-level network interface. Wanpipes are configured by the wancfg command.

    pon/poff create a pppoe connection from the dsl0 interface to the upstream network provider. The pppoe connection, including dsl login/password, are configured by the pppoeconf command. pon/poff are actually just part of pppd, the ppp daemon, which creates another high-level interface, ppp0 to represent the actual live dsl link.

    The upshot of all this is that wanrouter must create the dsl0 interface before pon can create the ppp0 connection (interface), and poff must terminate the ppp0 interface before wanrouter can destroy the dsl0 interface. Happily, wanpipes include a place to insert these commands so wanrouter appears to handle it all.


    How to install the Sangoma wanpipe drivers, configure the card, configure the interface, and configure pppoe. The dsl line does not need to be plugged in until the final steps of configuring pppoe.

    # Install the tools needed
    apt-get install build-essential linux-source-2.6.32 linux-headers-2.6.32-5-686 libncurses5-dev bison libtool pppoe
    
    # Get the Sangoma Wanpipe package. Unpack the linux-source and wanpipe packages 
    cd /usr/src
    wget ftp://ftp.sangoma.com/linux/current_wanpipe/wanpipe-3.5.18.tgz
    tar zxvf wanpipe-3.5.18.tgz
    tar xjf /usr/src/linux-source-2.6.32.tar.bz2
    
    # Prepare the linux source for the wanpipe install script 
    cd linux-source-2.6.32
    cp /usr/src/linux-headers-2.6.32-5-686/Module.symvers ./
    make oldconfig && make prepare && make modules_prepare
    
    # Run the wanpipe install script
    cd /usr/src/wanpipe-3.5.18
    ./Setup install
    
    The script will ask for the linux source directory: /usr/src/linux-source-2.6.32. It will throw a lot of questions about using 2.6.32-5-686 instead, just answer yes and let the installer continue.
    # When install is successfully completed
    cd /home/USERNAME
    wanrouter hwprobe  # Test if the card is detected
    wancfg             # Ncurses tool to configure the wanpipe and interface
    
    See the Sangoma Wiki for details, really all you need to choose is the interface name (for example, 'dsl0')
    wanrouter start wanpipe1   # Test - should bring up interface
    ifconfig                   # The interface should be on the list
    ifconfig dsl0 down         # Test - should bring down interface
    ifconfig                   # The interface should *not* be on the list
    ifconfig dsl0 up           # Test - should bring up interface
    ifconfig                   # The interface should be on the list
    wanrouter stop wanpipe1    # Test - should being down interface
    ifconfig                   # The interface should *not* be on the list
    
    Plug in the dsl connection in order to configure pppoe. Then run the PPPoE configuration program (pppoeconf). You need your dsl login and password at this point.
    ppoeconf
    
    The pppoeconf program will ask two important questions:
    • Do you want to start PPPoE at each startup? NO, because it will fail - dsl0 will not be ready yet
    • Do you want to start PPPoE now? You can, but if there are any problems, the process will be orphaned. Kill it with the command 'poff -a'

    You can see the PPPoE configuration (linking it to the dsl0 interface) in /etc/ppp/peers/dsl-provider. You can see your dsl username and password in /etc/ppp/pap-secrets.

    To manually open/close the dsl connection:

    wanrouter start     # To bring up the dsl0 interface. Doing this at boot is part of the Wanrouter install
    pon dsl-provider    # To bring up the ppp0 interface, which is the real PPPoE connection 
                        # (with an IP address). We'll automate this in the next section
    plog                # A handy debugging tool. Take a quick look at the log
    ifconfig            # The dsl0 interface does not have an IP, and the new ppp0 interface does have an IP
    poff                # To close the PPPoE connection, and bring down the ppp0 interface
    wanrouter stop      # To bring down the dsl0 interface. Doing this at shutdown is part of the Wanrouter install
    

    To automatically open/close the dsl connection: Go back into wancfg. Edit the wanpipe1 file --> Interface Setup --> Interface Configuration --> Advanced options. Insert a start script and a stop script as follows:

    pon dsl-provider    # Append this to the bottom of the START script
    
    poff -a             # Append this to the bottom of the STOP script
    
    Save the wanpipe1 config file, and let's test automatic dsl connection/disconnection:
    wanrouter stop      # In case it was on.
    ifconfig            # Neither dsl0 nor ppp0 interfaces should be live.
    wanrouter start     # Bring up dsl0. The script should then bring up ppp0
    ifconfig            # ppp0 should be up, and have an IP address. If not, try again - ppp0 is often missing the first time I try.
    wanrouter stop      # Bring down the intefaces
    ifconfig            # Should be back to the normal down state. ppp0 and dsl0 should not be showing.
    
    Finally, test with a reboot and a shutdown to see in the interfaces change properly. Success! Time to clean up using the following commands:
    apt-get remove build-essential linux-source-2.6.32 linux-headers-2.6.32-5-686 libncurses5-dev bison libtool
    apt-get autoremove
    rm -r /usr/src/wanpipe-3.5.18
    rm -r /usr/src/linux-source-2.6.32
    


    BUG: missing LSB tags and overrides. When I tried to install something else later, I got the following warnings:

    insserv: warning: script 'K01wanrouter' missing LSB tags and overrides
    insserv: warning: script 'wanrouter' missing LSB tags and overrides
    
    A quick search on the warnings gave an answer. LSB tags are used by init, and the tags are easily added to the beginning of the /etc/init.d/wanrouter script. Here is a sample script that eliminated the warning:
    #! /bin/sh        # Just to show where we are in the file
    
    ### BEGIN INIT INFO
    # Provides:             wanpipe
    # Required-Start:       $syslog
    # Required-Stop:        $syslog
    # Default-Start:        2 3 4 5
    # Default-Stop:         
    # Short-Description:    kernal support to DSL modem
    ### END INIT INFO
    



    Final notes:
    • Three elements of the Sangoma package failed to compile: LibSangoma API library, LibStelephony API library, and API Development Utilities. I have seen no effect from those failures.
    • To uninstall WANPIPE package run ./Setup remove
    • There is additional documentation at /usr/share/doc/wanpipe
    • A firmware update utility is included in /etc/wanpipe/util
    • 'wanpipemon' is an included diagnostic tool. The easiest way to use it is 'wanpipemon -g' for the ncurses gui.
    • Changing the default route to send packets across the dsl connection is beyond the scope of what I wanted to do. I just wanted to see if it worked.