HP MicroServer FreeBSD 8.2 NAS build
(Work in progress)
Contents |
Overview
Towards the end of 2010, HP released the ProLiant Microserver, a low-power micro-tower server with four swappable disk bays, priced at around £240 (inc. VAT), plus a £100 cash back promotion. It is a superb low-cost platform upon which to build a FreeBSD-based ZFS NAS solution.
Hardware spec
The first model of MicroServer had the following hardware specification:
- AMD Athlon II Neo N36L CPU, 1.3GHz, dual-core, 64-bit
- AMD RS785E IGP and SB820M southbridge chipset
- 1GB DDR3-1333 ECC RAM
- Broadcom BCM5784 gigabit ethernet controller, jumbo frames not supported
- Six port SATA controller, configured as follows:
- Ports 0-3 in native AHCI mode, wired to swappable disk bays
- Port 4 in IDE compatibility mode, wired to SATA header on motherboard, intended for internal DVD/CD-ROM
- Port 5 in IDE compatibility mode, wired to eSATA port on rear
- Three USB 2.0 controllers, presented as follows:
- Controller 0, wired to four ports on front panel
- Controller 1, wired to internal port on motherboard, intended for internal tape drive
- Controller 2, wired to two ports on rear panel
- PCI Express slots
- One x16 low-profile slot
- One x1 low-profile slot
- One x4 slot, located at the inboard end of the 1x slot, only usable by optional IPMI card
In August 2011, an updated model was released with a faster AMD Turion II Neo N40L 1.5GHz CPU and 2GB of RAM as standard, but otherwise unchanged.
Hardware additions
- Extra 1GB DDR3-1333 ECC RAM, for a total of 2GB and enabling dual-channel operation
- Intel PRO/1000 CT PCIe 1x network adapter to provide jumbo frames support
- SanDisk Cruzer Blade 2GB USB flash drive, connected to internal USB port
- Four Samsung HD204UI disks, 2TB (1.86TiB), 4KiB sectors, 5400rpm
Root-on-ZFS considerations
In order to boot a FreeBSD system with a ZFS root filesystem, it is usually necessary to partition the disks to reserve some space for bootstrap code outside of the zpool. This is often done using GPT partitioning, placing a small freebsd-boot partition at the beginning of the disk to contain the gptzfsboot code and a freebsd-zfs partition spanning the rest of the disk. The zpool is then built on top of the freebsd-zfs partitions on each disk.
The inclusion of an internal USB port inside the MicroServer provides another possibility: boot and load the kernel from a permanently connected USB stick, then mount the root filesystem from a zpool comprised of whole, unpartitioned disks. This allows a simpler configuration than building the zpool from partitions and makes it easier to replace disks in the event of a failure or when upgrading to larger ones. There would no longer be any need to replicate partition layouts on new disks - just insert the new one and invoke a 'zpool replace'.
This may also possibly prevent performance problems with new Advanced Format disks - those with 4KB sectors. If ZFS is given the whole disk to use, there are no partition alignment concerns.
Build process
FreeBSD 8.2-RELEASE was used for the initial build. A Root-on-ZFS setup requires manual installation using the Fixit environment on the installation media, in this case a USB stick containing the FreeBSD-8.2-RELEASE-amd64-memstick image.
The process was as follows:
Boot from memstick media and enter Fixit mode
- Plug in USB stick and boot system, selecting USB storage device from BIOS boot menu if necessary
- At the loader menu screen, press 6 to escape to a loader prompt
- Load AHCI and ZFS modules, then continue booting, as follows:
Type '?' for a list of commands, 'help' for more detailed help. OK load ahci /boot/kernel/ahci.ko size 0xfd88 at 0x126b000 OK load zfs /boot/kernel/zfs.ko size 0x19eb18 at 0x127b000 loading required module 'opensolaris' /boot/kernel/opensolaris.ko size 0x3868 at 0x141a000 OK boot
- Once system has booted and sysinstall is running, choose appropriate country and keymap, then select Fixit from the main menu. This will start a Fixit shell.
Set up zpool and initial datasets
The ZFS dataset layout is set up to mimic that of Solaris, avoiding the use of the root dataset of the pool.
Set up a GNOP provider on top of one of the physical disks, reporting 4KB sectors, so that ZFS optimises the new pool for 4KB sector size:
# gnop create -S 4096 ada0
Create /boot/zfs directory to contain zpool.cache file, and create zpool:
# mkdir /boot/zfs # zpool create -O mountpoint=none pool0 raidz ada0.nop ada1 ada2 ada3
Create datasets and mount root dataset at /mnt:
# zfs create -p pool0/ROOT/freebsd # zfs set mountpoint=/ pool0/ROOT/freebsd # zfs set canmount=noauto pool0/ROOT/freebsd # mount -t zfs pool0/ROOT/freebsd /mnt
Install minimal FreeBSD into new root filesystem
# export DESTDIR=/mnt # cd /dist/8.2-RELEASE/base # ./install.sh You are about to extract the base distribution into /mnt - are you SURE you want to do this over your installed system (y/n)? y # cd ../kernels # ./install.sh GENERIC You are about to extract the GENERIC kernel distribution into /mnt/boot - are you SURE you want to do this over your installed system (y/n)? y #
Update boot configuration files
Create /boot/loader.conf file with boot time directives: modules to load, root filesystem location:
# vi /mnt/boot/loader.conf
ahci_load="YES" zfs_load="YES" vfs.root.mountfrom="zfs:pool0/ROOT/freebsd"
Create empty /etc/fstab file to prevent error on boot:
# touch /mnt/etc/fstab
Copy zpool.cache into /boot/zfs and set bootfs property on zpool:
# zpool set bootfs=pool0/ROOT/freebsd pool0 # cp /boot/zfs/zpool.cache /mnt/boot/zfs/
Prepare bootable USB stick
Connect a second empty USB stick. It will most likely be detected as /dev/da1, with /dev/da0 being the stick we booted from, containing the installation media.
GPT partition and install bootcode to USB stick:
# gpart create -s GPT da1 # gpart add -t freebsd-boot -b 64k -s 64k da1 # gpart add -t freebsd-ufs da1 # gpart bootcode -b /mnt/boot/pmbr -p /mnt/boot/gptboot -i 1 da1
Create and mount UFS filesystem:
# newfs -L usbboot /dev/da1p2 # mkdir /mnt/usbboot # mount /dev/ufs/usbboot /mnt/usbboot
Copy /boot directory from ZFS to USB stick (note the directory must be copies, not just its contents. loader looks for /boot/kernel/kernel):
# cp -Rpv /mnt/boot /mnt/usbboot