My Profile Photo


Using liberty-minded opensource tools, and using them well

A NAS for my Media

Despite my purported discipline about avoiding visual media, I still keep a number of movies and tv shows along with a whole host of music and other archived information. Along with keeping backups, I also require access online access to them. Previously, I used a Raspberry Pi and an external HDD. Now it's time to get serious.

This post is a WIP - please let me know if I’ve got something wrong here, as I’m most likely still working on it.


I got a Zyxel NAS 540 for cheap on eBay, and then ran across $50 used WD SATA II RAID drives, and bought four of those. There’s a bit of prep to do here though.

Testing the Drives

Apparently this is what you do when SpinRite craps out:

dd if=/dev/zero of=/dev/<your drive> bs=1M status=progress

This will write zeros to all sectors on that disk forcing the bad sector to reallocate. After you do this, run the following to perform a full read check of the entire disk to make sure there are no other bad sectors.

smartctl -t long /dev/<your drive>

Installing Debian onto the Zyxel

First, since the process involves me exploiting a telnet backdoor in the NAS, I have to get it registered with the DHCP server which only happened once I did a long factory reset. Once I did that, it popped up as NAS540. All good and well.


Getting root wasn’t bad. Following the backdoor instructions for firmware version 4.70, I was able to own the box with root privileges via the user NsaRescueAngel over telnet. The webpage to visit never fully loads, it just stays open while the telnet connection is made. However, it can be closed once the login is complete.

Building bareboxenv from source

I downloaded the latest version of the barebox source. I needed to specify the architecture and the cross-compilation prefix for the compilation and then run the compiler.

# yaourt arm-linux-gnueabihf-gcc
# pacman -S lzop
# wget -O barebox-YYYY.MM.0/arch/arm/configs/freescale-1024a_defconfig
# ARCH=arm make freescale-1024a_defconfig
# ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- make

SD Filesystem

Since I’m running Arch right now, it’s going to be somewhat roundabout getting the bootstrapped system onto the SD card. However, wiping it and partitioning it is easy enough.

# dd if=/dev/zero of=/dev/mmcblk0 bs=1M status=progress
# parted --script --align optimal /dev/mmcblk0 mklabel gpt mkpart primary ext4 0% 100%
# mkfs.ext4 /dev/mmcblk0p1

Luckily enough, Arch does have debootstrap available for install, however, I need a bit more than that.

# pacman -S debootstrap qemu-arch-extra
# yaourt binfmt-qemu-static
# yaourt qemu-user-static
# yaourt binfmt-support

I’m not sure that all of these packages are required, but they are the ones that I installed to get this working.

There were a couple steps to install this as opposed to the clean way that was in the post.

# mount /dev/mmcblk0p1 /mnt
# debootstrap --no-check-gpg --arch=armhf --foreign testing /mnt ""

This got the first half of the install working - it downloaded the files in the armhf architecture. Next, I had to enable arm emulation, place the emulation binary into the chroot filesystem, and chroot in to finish the debootstrap.

# update-binfmts --enable qemu-arm
# cp /usr/bin/qemu-arm-static /mnt/usr/bin

If the files are put into /mnt/bin, no further commands will work, but putting it in /mnt/usr/bin allows everything to work just fine. This might be able to be fixed with a debootstrap argument --merged-usr.

# DEBIAN_FRONTEND=noninteractive DEBCONF_NONINTERACTIVE_SEEN=true LC_ALL=C LANGUAGE=C LANG=C chroot /mnt /debootstrap/debootstrap --second-stage
# DEBIAN_FRONTEND=noninteractive DEBCONF_NONINTERACTIVE_SEEN=true LC_ALL=C LANGUAGE=C LANG=C chroot /mnt dpkg --configure -a

Upon repeating this after the initial test setup, I had to chroot into the build itself with chroot /mnt /bin/bash -l in order to run it, as I was getting a command not found for cat. It’s certainly there. God knows what happened.

After that, the base system is installed, and the rest of the setup tasks can be performed in a proper chroot.

# chroot /mnt /bin/bash -l
# mount -t proc proc /proc
# mount -t sysfs sysfs /sys
# cat > /etc/apt/sources.list << EOF
deb testing main contrib non-free
deb-src testing main contrib non-free
# apt update && apt upgrade && apt install openssh-server mtd-utils vim ranger tmux xz-utils

And now for a little housekeeping.

# echo <my-hostname> > /etc/hostname
# passwd
# cat > /etc/network/interfaces.d/eth0 << EOF
auto eth0
iface eth0 inet dhcp

I got a lot of locale errors, so I’ll probably have to fix that. Next up, I need to find the partition UUID to identify the root partition. This is done outside of the chroot, and then it is put into the /etc/fstab file inside of the chroot.

(host) # ls -l /dev/disk/by-partuuid
(chroot) # cat > /etc/fstab << EOF
PARTUUID = <part-uuid> / ext4 defaults 0 1

The prebuilt binaries provided at allow for the box to boot.

# cd /
# wget
# wget
# tar xf modules.tar.xz

The bareboxenv binary is no longer located at, but is installed already under /firmware on the box.

After that, I followed the configuration to create a barebox config and a set a couple other parameters. The instructions at uses $PARTUUID to denote the places that the actual PARTUUID needs to go. Also, the scripts and the bareboxenv executable need to be executable in order to run. After that, the SD card is ready to be placed into the NAS and setup.

Now for the tricky bit

After logging back in via telnet, I ran a cat /proc/mtd and saw that there were two additional entries. Those were ubi_rootfs2 and ubi_config. I hope that’s not bad. To find out which /dev/sdX to mount, I had to run blkid and match the PARTUUID to what I had used earlier.

When I went to use flash_eraseall, I found that there was no such command, however, there was a flash_erase. From my further research, they seem to do similar things. Simply specifying 0 for the block count (as show with flash_erase --help) erased the entirety of the device as was intended.

# flash_erase <mtd-device> 0 0

Then I installed the bb.env and the uImage kernel

# flashcp bb.env /dev/mtd2
# flashcp /mnt/uImage /dev/mtd6

The uImage kernel gave an error after it flashed, but I zeroed out the device with dd, and it was fine. The flashcp command also only gave an invalid argument only after flashing the entirety of the kernel onto the device and returning an ‘OK’. Unfortunately, the device fell into a boot loop after rebooting, and I’ll have to utilize a serial connection to debug it.

Serial Connection

This is the first time I’m using a serial connection, so apologies if I ramble on here. I initially figured I had to use a TTL to a RS232 connection, but that seems to not be the case. There’s an Adafruit USB-to-TTL converter, and I should just be able to plug it into the usb port and play. Of course, it’s not quite that simple, but following that everything is a file, I can use a terminal emulator program. It has to deal with bauds and stuff. Anyways, it should create a virtual terminal at /dev/ttyUSBX that I can connect to with that program, provided my user is in the group uucp. At least, that’s what the arch wiki says.

After plugging in the USB end of the cable into my machine, I was able to see that it registered itself when it was plugged in.

# dmesg | grep tty
usb 2-1: cp210x converter now attached to ttyUSB0

Unfortunately, there is no output, and I am forced to put this project aside for awhile.