Test Area Index

Zyxel NSA221

Customisation

This page contains technical support notes on customising particularly the Zyxel NSA221 NAS unit, although details given here will doubtless apply more generally to similar models from the same manufacturer.

Note that the original firmware's functionality can be extended more easily by installing FFP-Stick on a USB stick, follow the link for instructions.  However, as the FFP-Stick enables telnet, which is inherently insecure, and is configured not to require a password, the aim here is to customise the NSA221's behaviour in such a way that the stick, although necessary to obtain initial or later emergency access, can be locked away in a drawer for normal use of the NAS.

As with customising most embedded devices running Linux, the process can be broken down into stages:

  1. Gaining Administrator (root) Access To Linux

    For this particular device, this is most easily done by booting from the FFP-Stick linked above, which will enable you to telnet into it.  First ensure that your firewall will allow a telnet connection.  Next follow the instructions given in the link to create the USB image, then plug it into the NSA221 and boot from it.  The first boot from the stick takes a while because it connects over the internet and downloads a minimal Linux image.  Once all the lights are steady showing that it has finished installation, go into a console/DOS prompt and type …
    telnet <Name or IP>
    … where <Name or IP> is either the network name you gave to the device as per section 9.2.1 p107 of the <a href="ftp://ftp.zyxel.co.uk/NSA221/user_guide/NSA221_v4_ed1.pdf" title = "ftp.zyxel.co.uk" target="_blank"> NSA221 User's Guide</a> (link now dead), or the device's IP address  the latter will either be acquired dynamically (the default), and will therefore have to be discovered via your router's web browser configuration pages, usually under a heading such as DHCP Clients, or else fixed as per section 9.3.1 p109 of the manual.  All being well, you shouldn't need to log in.  When desired, you can close the telnet session by typing:
    exit

  2. Customisation Of The Device's Linux Boot Process

    With this device, this is complicated rather than difficult.  The crucial point is that Zyxel packages installable from the web browser management interface are installed to the hard disk, and these must somehow be initialised at boot time, a combination which implies that it must be possible to intercept and adapt the process.  In fact, initialisation is accomplished by the script …
    /etc/init.d/zypkg_controller.sh
    … examination of which suggests that executable scripts placed in …
    /usr/local/zy-pkgs/etc/init.d
    … itself a remapping of a folder on the first hard disk …
    /i-data/<8 hex digits>/.zyxel/zy-pkgs/etc/init.d
    … will be run regardless of whether or not they were installed there as part of a Zyxel package.  We will use this to restore the user accounts overwritten with default values during boot up, and to run Optware. 

        # Fix Zyxel firmware overwriting the user accounts and environment
        # (!!! Sigh! Why do they do this to us? !!!)
        #
        # Saves account and environment data during shutdown and restores it after it
        # ... has been wiped by Zyxel's tyrannical boot process.
        #
        # To be certain of saving changed passwords, etc, run ...
        #    $0 save
        # ... after making changes, before rebooting.
        
        ETCPATH=/etc
        SAMBAPATH=${ETCPATH}/samba
        PAMPATH=${ETCPATH}/pam.d
        SAVEPATH=/opt/.save
        BTMP=/var/log/btmp
        MD0="$(cat /proc/mounts | grep -E 'md0[[:space:]]+/i-data/[^/]+$' | sort -u | awk '{print $2}')"
        MD1="$(cat /proc/mounts | grep -E 'md1[[:space:]]+/i-data/[^/]+$' | sort -u | awk '{print $2}')"
        
        # ===========================================
        # function makedir()
        # Checks if $1 exists, and if not create it
        # $1 Required directory
        # ===========================================
        makedir()
            {
            if [ ! -d "$1" ]
                then
                    mkdir -p "$1"
                    if [ -d "$1" ]
                        then
                            chown "$2" "$1"
                            chmod "$3" "$1"
                        else
                            echo "Failed to create $1, perhaps RO file system."
                    fi
            fi
            }
        
        # ==============================================
        # function remdir()
        # Checks if $1 exists, and if tries to remove it
        # $1 Required directory
        # ==============================================
        remdir()
            {
            if [ -d "$1" ]
                then
                    rmdir "$1"
            fi
            }
        
        # ===========================================
        # function copyfile()
        # Restore a file, backing up any existing one
        # $1 file, $2 src dir, $3 dest dir
        # ===========================================
        copyfile()
            {
            if [ -f "$2/$1" ]
                then
                    if [ -f "$3/$1" ]
                        then
                            mv "$3/$1" "$3/$1.bak"
                    fi
                    cp -a "$2/$1" "$3/$1"
            fi
            }
        
        start_acc()
            {
            # Needed for ssh login
            if [ "$(cat /proc/mounts | grep ^devpts)" = "" ]
                then
                    mount devpts /dev/pts -t devpts -o defaults
            fi
            touch "${BTMP}"
            chown root:root "${BTMP}"
            chmod 600 "${BTMP}"
            
            # Restore account data and environment lost by Zyxel's boot process ...
            # See /etc/init.d/rcS2, line 259
            if [ -d ${SAVEPATH} ]
                then
                    # Restore account data and environment lost by Zyxel's
                    # boot script: /etc/init.d/rcS2, line 259
                    copyfile group ${SAVEPATH} ${ETCPATH}
                    copyfile passwd ${SAVEPATH} ${ETCPATH}
                    copyfile shadow ${SAVEPATH} ${ETCPATH}
                    copyfile smb.conf ${SAVEPATH} ${SAMBAPATH}
                    copyfile smbpasswd ${SAVEPATH} ${SAMBAPATH}
                    copyfile secrets.tdb ${SAVEPATH} ${SAMBAPATH}
                    copyfile weblogin ${SAVEPATH} ${PAMPATH}
                    /etc/init.d/samba.sh restart
                    # Zyxel's version of /etc/profile has already been ...
                    # ... 'source'd before we get here, so it can be ...
                    # overwritten safely.  See /etc/init.d/rcS2, line 4
                    copyfile profile ${SAVEPATH} ${ETCPATH}
                    # Fix unwanted share directories rammed down our throats by Zyxel
                    for D in music photo public video
                        do
                            if [ "${MD0}" != "" ]
                                then
                                    remdir ${MD0}/${D}
                            fi
                            if [ "${MD1}" != "" ]
                                then
                                    remdir ${MD1}/${D}
                            fi
                        done
            fi
            
            # Give root proper environment when logging in
            if [ -d ${MD0}/admin ]
                then
                    if [ ! -d /root ]
                        then
                            makedir "/root" "root:root" "700"
                    fi
                    mount ${MD0}/admin /root -o bind
            fi
            
            # Ensure users can have home directory when logging in
            makedir "/home" "root:root" "700"
            exit 0
            }
        
        save_acc()
            {
            if [ ! -d ${SAVEPATH} ]
                then
                    makedir ${SAVEPATH} root:root 700
            fi
            copyfile group ${ETCPATH} ${SAVEPATH}
            copyfile passwd ${ETCPATH} ${SAVEPATH}
            copyfile shadow ${ETCPATH} ${SAVEPATH}
            copyfile smb.conf ${SAMBAPATH} ${SAVEPATH}
            copyfile smbpasswd ${SAMBAPATH} ${SAVEPATH}
            copyfile secrets.tdb ${SAMBAPATH} ${SAVEPATH}
            copyfile weblogin ${PAMPATH} ${SAVEPATH}
            # Save our version of /etc/profile
            copyfile profile ${ETCPATH} ${SAVEPATH}
            exit 0
            }
        
        echo "Running $0 $* ..."
        case "$1" in
        
            start)
                start_acc;
                ;;
            
            startup)
                start_acc;
                ;;
            
            stop)
                # Doesn't work, seemingly not called at shutdown
                # save_acc;
                ;;
            
            save)
                save_acc;
                ;;
            
            *)
                echo "Usage: $0 {save|start|startup|stop}"
                exit 1
                ;;
            
        esac
  3. Add Custom Software

    Normally, this can either be done using a Linux distro package manager or a userland package manager such as (link now dead) <a href="http://www.nslu2-linux.org/wiki/Optware/HomePage" title="nslu2-linux.org">Optware</a>, or by onboard compilation or cross-compilation elsewhere, and subsequent manual installation.  Embedded devices usually do not have the resources to run a full distro package manager, and quite possibly not onboard compilation either, and anyway the latter or cross-compiling on another machine is a level of effort and expertise beyond that expected here.  Hence as an example of what can be achieved, the rest of this page demonstrates how to get Optware running on the NSA221.

    1. Make a suitable directory on the hard disk for Optware:
      mkdir /i-data/<8 hex digits>/opt
      chown root:root /i-data/<8 hex digits>/opt
      chmod 755 /i-data/<8 hex digits>/opt

    2. If there is no existing /opt directory, create one …
      mkdir /opt
      chown root:root /opt
      chmod 755 /opt
      … otherwise, if the existing /opt directory is non-empty , copy its contents to the new directory:
      cp -a /opt/* /i-data/<8 hex digits>/opt

    3. Bind the two directories:
      mount /i-data/<8 hex digits>/opt /opt -o bind

    4. Create a directory for Optware's package manager ipkg:
      mkdir /opt/ipkg
      chown root:root /opt/ipkg
      chmod 755 /opt/ipkg

    5. Download ipkg into this directory:
      cd /opt/ipkg
      wget http://ipkg.nslu2-linux.org/feeds/optware/cs08q1armel/cross/stable/ipkg-opt_0.99.163-10_arm.ipk

    6. Install ipkg:
      tar -xzf ipkg-opt_0.99.163-10_arm.ipk
      cp -a data.tar.gz /
      cd /
      tar -xzf data.tar.gz
      rm data.tar.gz

    7. Configure ipkg:
      echo"src cs08q1armel http://ipkg.nslu2-linux.org/feeds/optware/cs08q1armel/cross/stable">> /opt/etc/ipkg.conf
      /opt/bin/ipkg update

FAQs And Notes On Possible Problems