Raspberry Pi as a NAS Box

I finally bought myself a Raspberry Pi Rev B from Element 14. I got it from an importer in Bandung, and I decided I’d go for a little shopping myself to the computer store to get me the tidbits. So here’s my kit.

My Raspberry Pi Kit
My Raspberry Pi Kit
  1. Raspberry Pi Revision B (Element 14 UK)
  2. 8GB Class 10 SDHC with NOOBS pre-installed
  3. Local-made acrylic casing
  4. 1.5m USB cable
  5. USB power adapter rated at 2.1A
  6. CAT-5e UTP cable
  7. Ralink RT5730 USB WiFi dongle with rotatable antenna (not shown)
The Pi, made in the U.K.
The Pi, made in the U.K.

The plan is to get it to work with my existing Western Digital MyBook 2TB external hard drive. I found so many tutorials on the interwebs about how to do this, but I guess I’ll just share my experience.

Hardware Assembly

The hardware assembly is pretty straightforward. The acrylic case snaps together without any problems, and voilà, my Pi’s got a casing.

Pi In A Box
Pi In A Box

Operating System

Next, I need to flash the SD card. It’s already got NOOBS on it, but I won’t be using it because I want to use the latest Raspbian Wheezy. I downloaded it from the Raspberry Pi website and flashed my SD card using Win32 Disk Imager. No problems here.

First Boot

OK, so here’s the first problem. I have two 22″ monitors connected to my PC, and nothing else. So I had to hijack the TV in the living room to do the first boot. Luckily I have a wireless mouse/keyboard combo handy, so less cables and it plugs into just one USB port on the Pi.

My Raspberry Pi Rev B, with 8GB SD Card, connected via RCA to my TV, controlled using a wireless keyboard. Yes, that’s a clay cat.
My Raspberry Pi Rev B, with 8GB SD Card, connected via RCA to my TV, controlled using a wireless keyboard. Yes, that’s a clay cat.
I had to do this to install the Pi and enable SSH. Yes, I have three clay cats. Meow.
I had to do this to install the Pi and enable SSH. Yes, I have three clay cats. Meow.

Default username is “pi” and password is “raspberry”. Upon first login, the Pi will automatically enter the raspi-config utility. Here’s my checklist on first boot (and second boot, for that matter):

  1. Expand the filesystem. This needs a reboot. Do this to enter raspi-config:
    sudo raspi-config
  2. Enable SSH. To do this go to Advanced, SSH, then Enable SSH.
  3. Exit raspi-config, and run the following command
    ifconfig

    Take note of the hardware address shown, because it’ll come in handy later on when I reserve an IP address for the Pi.

The Pi is now capable of running headless, so I shut it down.

sudo halt

Then I moved it to a better position, and connected it via UTP to my router. I also plugged in my external hard drive. I’ll be continuing on the setup remotely from the comfort of my PC. Before powering it up again, I decided to go ahead and reserve an IP address for the Pi, using the web-based router management UI. I won’t go into this because every router is different, but the point is to “map” the MAC address of the Pi’s network interface card to an IP address typically assigned by the router’s DHCP server. Alright, now power up!

System Update

The first thing I did after getting the Pi accessible by SSH (I use PuTTY for this) is to do a complete system update.

sudo apt-get update
sudo apt-get dist-upgrade

The upgrade process required that I download 460MB worth of debian packages. After the update completed, I decided to create a backup of the image, using Win32 DiskImager that I also use to write the system image on the SD card. This way, when I want to do a fresh install, I have the Pi updated to a more recent version and ready to run headless.

After saving the updated image, I decided to run raspi-config again to change my hostname. This is probably a good idea because if I buy another Raspberry Pi and run it using the image I just created, the two of them won’t have the same hostname.

Formatting The Hard Drive

I use a 2TB external hard drive connected via USB. I chose to format it using EXT3 for reasons I’ll explain later. I just went along with instructions I found using Google Almighty. First, I go into fdisk:

sudo fdisk /dev/sda

I deleted the one and only partition existing on the hard drive, and created a new primary partition that spans the entire disk. This is probably the scenario if you’re using a new hard drive. If you are going this route, just make sure you don’t have any data worth keeping on the disk. You have been warned.

Command (m for help): p

Disk /dev/sda: 2000.4 GB, 2000365289472 bytes
58 heads, 60 sectors/track, 1122690 cylinders, total 3906963456 sectors
Units = sectors of 1 * 512 = 512 bytes
Sector size (logical/physical): 512 bytes / 512 bytes
I/O size (minimum/optimal): 512 bytes / 512 bytes
Disk identifier: 0x00064002

   Device Boot      Start         End      Blocks   Id  System
/dev/sda1            2048  3906963455  1953480704   83  Linux

Command (m for help): d
Selected partition 1

Command (m for help): p

Disk /dev/sda: 2000.4 GB, 2000365289472 bytes
58 heads, 60 sectors/track, 1122690 cylinders, total 3906963456 sectors
Units = sectors of 1 * 512 = 512 bytes
Sector size (logical/physical): 512 bytes / 512 bytes
I/O size (minimum/optimal): 512 bytes / 512 bytes
Disk identifier: 0x00064002

   Device Boot      Start         End      Blocks   Id  System

Command (m for help): n
Partition type:
   p   primary (0 primary, 0 extended, 4 free)
   e   extended
Select (default p): p
Partition number (1-4, default 1): 1
First sector (2048-3906963455, default 2048):
Using default value 2048
Last sector, +sectors or +size{K,M,G} (2048-3906963455, default 3906963455):
Using default value 3906963455

Command (m for help): w
The partition table has been altered!

Calling ioctl() to re-read partition table.
Syncing disks.

Explanation of commands in the order they are issued:

  • p: list partitions
  • d: delete partition
  • p: list partitions, to check that the partition is indeed marked for delete
  • n: new partition, and then just accept default values for a single primary partition
  • w: write the changes to disk

I then check that the partition is indeed available.

sudo fdisk -l

That command spits out the following result:

Disk /dev/mmcblk0: 15.7 GB, 15720251392 bytes
4 heads, 16 sectors/track, 479744 cylinders, total 30703616 sectors
Units = sectors of 1 * 512 = 512 bytes
Sector size (logical/physical): 512 bytes / 512 bytes
I/O size (minimum/optimal): 512 bytes / 512 bytes
Disk identifier: 0x000b5098

        Device Boot      Start         End      Blocks   Id  System
/dev/mmcblk0p1            8192      122879       57344    c  W95 FAT32 (LBA)
/dev/mmcblk0p2          122880    30703615    15290368   83  Linux

Disk /dev/sda: 2000.4 GB, 2000365289472 bytes
38 heads, 36 sectors/track, 2855967 cylinders, total 3906963456 sectors
Units = sectors of 1 * 512 = 512 bytes
Sector size (logical/physical): 512 bytes / 512 bytes
I/O size (minimum/optimal): 512 bytes / 512 bytes
Disk identifier: 0x00064002

   Device Boot      Start         End      Blocks   Id  System
/dev/sda1            2048  3906963455  1953480704   83  Linux

Alright, now that I have the disk recognized as /dev/sda1, I need to make the filesystem.

sudo mkfs /dev/sda1

It takes a while to make the filesystem, so grabbing a cup of joe at this point might be a good idea.

Mounting and Sharing

After mkfs, the drive is ready to use but not yet mounted. So I prepared a directory for the share mount point:

sudo mkdir /media/USBHDD1

I decided to just add an entry into fstab and reboot the Pi so that I know for sure it works.

sudo pico /etc/fstab

In the editor, I added the following entry:

/dev/sda1       /media/USBHDD1  ext3    noatime           0       0

Next, I reboot the machine.

sudo reboot

After logging in, I tried running df to see if the hard drive is properly mounted.

df

The following output thus emerge:

Filesystem      1K-blocks    Used  Available Use% Mounted on
rootfs           14988412 2785492   11548708  20% /
/dev/root        14988412 2785492   11548708  20% /
devtmpfs           219764       0     219764   0% /dev
tmpfs               44788     220      44568   1% /run
tmpfs                5120       0       5120   0% /run/lock
tmpfs               89560       0      89560   0% /run/shm
/dev/mmcblk0p1      57288    9864      47424  18% /boot
/dev/sda1      1922698040   69088 1824954920   1% /media/USBHDD1

Now that I’m sure I have the drive mounted properly on boot, it’s time to install samba. I found some instructions for how to do it, but it uses NTFS-formatted hard drives and is different than my setup. The samba part is, however, pretty much the same.

sudo apt-get install samba samba-common-bin

Next, it’s always a good idea to store a backup of any config file before editing it.

sudo cp /etc/samba/smb.conf /etc/samba/smb.conf.old

On to the config!

sudo pico /etc/samba/smb.conf

First order of business: activate user-based security. So I find the following line:

####### Authentication #######

# "security = user" is always a good idea. This will require a Unix account
# in this server for every user accessing the server. See
# /usr/share/doc/samba-doc/htmldocs/Samba3-HOWTO/ServerType.html
# in the samba-doc package for details.
#   security = user

I uncommented the last line to activate user-based security by removing the hashtag:

# "security = user" is always a good idea. This will require a Unix account
# in this server for every user accessing the server. See
# /usr/share/doc/samba-doc/htmldocs/Samba3-HOWTO/ServerType.html
# in the samba-doc package for details.
   security = user

To add shared folders, I add the following section to the very end of the configuration file:

[Public$]
comment = Public Shared Folder
path = /media/USBHDD1/Public
valid users = @sambausers
read only = no

[Apps$]
comment = Applications Repository
path = /media/USBHDD1/Apps
valid users = @sambausers
read only = yes
write list = mysambauser

[MediaCenter$]
comment = Media Center Repository
path = /media/USBHDD1/MediaCenter
valid users = @sambausers
read only = yes
write list = mysambauser

[private$]
comment = mysambauser's private folder
path = /media/USBHDD1/Users/mysambauser
valid users = mysambauser
read only = no

I repeated the private folder for every user I plan to have in the network to provide them with personal space. This would probably not be necessary if I had a huge SD card because I could just activate their home folders with read-and-write access. Unfortunately, that is not the case.

Now, I could just go ahead and create users who will have access to the samba shares, but I like to put them in a group together so I can easily assign privileges as a group. Thus the new user group sambausers:

sudo addgroup sambausers

Next, the users that will be in the group:

sudo adduser mysambauser -m -G sambausers

The -m flag creates a home directory for the user (in case we need it later), and the -G flag adds the new user to the sambausers group. I do this for every samba user I have. After that’s done, I set UNIX passwords and samba passwords for them (also repeat for all intended users):

sudo passwd mysambauser
sudo smbpasswd -a mysambauser

Now, I need to change ownership of the mount point, set its permissions, and create the correct directory structure inside it to match the samba configuration file.

sudo chown mysambauser.sambausers /media/USBHDD1
sudo chmod -R 775 /media/USBHDD1

I won’t go into the details of creating the directories, but I will point out that this will need to be done as the mysambauser user. All done! Now I can log out as mysambauser (and return to pi user) and start the samba service.

sudo /etc/init.d/samba start

Now I can browse to \\HOSTNAME from any Windows machine and map a network drive to the shares I just set up.

NOTE: If you use a firewall of some sort, please make sure your firewall allows access to ports 137, 138, 139, and 445 using TCP, and also port 137 using UDP. These ports are in use either by Samba itself or Windows hostname resolution (NetBIOS).

Performance and Conclusion

This article actually documents the second build. That’s why you may have noticed that the SD card in use is 16GB instead of 8GB. Also, I chose to use a wired connection to my router, I’m saving the Ralink for a second unit later on.

Performance is a lot better on this build. Here are the figures:

Test Wireless Connection Wired Connection
FAT32 EXT3 FAT32 EXT3
Copy 3GB file from desktop to Pi 400 ~ 600 kB/s 600 kB/s ~ 1 MB/s 600 kB/s ~ 1.5 MB/s 700 kB/s ~ 3 MB/s
Copy several files (2 ~ 10 MB each) from desktop to Pi 450 ~ 800 kB/s 700 kB/s ~ 1.2 MB/s 700 kB/s ~ 1.8 MB/s 700 kB/s ~ 4 MB/s

The figures are approximations only and should be taken with a grain of salt. I am by no means an experienced tester, and these are just some real-world results that I’ve got from my week-long use of the Pi unit. Further testing should include simultaneous read/write operations serving anywhere from 2-10 clients concurrently, but I’ll leave that to Anand or Linus or whoever else wants to do the testing.

Any comments or suggestions are welcome. Until next time. Cheers!