Table of Contents

The Result

A small (20x16x9cm) server based on the NanoPI M4 + SATA hat. Check my youtube video below:

The Parts

Amount Part Type Datasheet Links
1  NanoPi M4 (2 or 4 GB RAM)     🛒friendlyarm.com
1  Heat Sink for NanoPi M4     🛒friendlyarm.com
1  16GB eMMC 5.1 Module for NanoPi M4     🛒friendlyarm.com
1  4x SATA HAT for NanoPi M4     🛒friendlyarm.com
1 12V 5A Power Supply      🛒amazon.de
1 80mm Fan     🛒amazon.de

Depending on what you do, the 2GB version is sufficient for you. You will need a micro SD card (>= 8GB) to install your OS. The 16GB eMMC is optional. I chose to use the eMMC because it is faster than (my) micro SD cards, and it frees the micro SD card slot (so I can quickly backup my phone).

The 12V power supply is what I had lying around, and it works. You can use something different here, for example an ATX PSU. Check with the wiki: http://wiki.friendlyarm.com/wiki/index.php/NanoPi_M4_SATA_HAT. Do some calculations as to how much power you will need.

The highest power consumption I could manage with two 2.5” HDDs, Streaming 3 HD Videos via WiFi, and sound via Bluetooth was 20W. You results will vary, especially when starting up 4 HDDs. The idle power consumption with this configuration was 6W (disks spinning).

You can check the wiki for more details about this board: http://wiki.friendlyarm.com/wiki/index.php/NanoPi_M4.

The are other approaches to building a NanoPI M4 NAS. For example https://www.thingiverse.com/thing:3484008. Allthough, this version is a lot sturdier than mine (aluminium profiles!), it requires more parts, and aims for bigger (3.5” disks). As I wanted to keep it smaller (in size, not budget), and learn something, I designed my own.

The 3D Print

Download

💾 Download the V2 .STL (2.5” HDD, tested): /assets/prints/nanopim4-server-v2-stl.zip

💾 Download the V2.1 .STL (3.5” HDD, untested): /assets/prints/nanopim4-server-v2.2-3.5-stl.zip

Important (PLA vs Temperature)

⚠️The entire case can be printed with PLA, if and only if you add the 80mm fan and keep it constantly running. If you run this Pi with high loads the temperature of the core will go beyond 80C and the heat sink will go beyond 65C, without the top part of the case. Running it on max load without active cooling, in the closed case will soften the PLA over time. You can try this if you want, and please let me know what your results are, but I don’t recommend it 😉. Afaik, the CPU will throttle if it runs too hot. If you want your components to last, especially the HDDs, add active cooling ❄️.

While idling the cpu temperature remains at 35C, with active cooling inside the case (at 25C ambient temperature).

Hint: add a fan.

STL files

The following STL files are in the download zips:

If you are planning to use 4 disks from the beginnning, use this file.
If you want to leave some room or decide later to go up to 4 disks use this file.
If you decided to upgrade to 4 disks, print this 4x, lying down.
If you decided to upgrade to 4 disks, print this 1x. (standing up, with rafts and bridge the top parts)
Part 1 of the top. See section below on how to print it.
Part 2 of the top. See section below on how to print it.
Part 3 of the top. See section below on how to print it.

My print settings

The main part prints without supports. Check your printer manages bridging. I printed this with 0.3mm layers max 60mm/s in under 5h.
The front and back parts are printed facing down, with 0 bottom and 0 top layers, using a 15% honeycomb infill. You can experiment here with the infill parameters of your slicer to achieve different patterns as the mesh to let air in and out of the server. I printed the three top parts in 3h+2h+2h=7h.

Make sure the front and back faces point down. The front and back faces are the faces with flat holes (to avoid support).

The Setup

The OS

I installed Armbian Buster from here: https://www.armbian.com/nanopi-m4/. You will find instructions on how to install it on their page.

The SATA hat was supported out of the box.

The FAN

Wiring

The fan (from the parts list) comes with black cables of which the first on has grey/white stripes. This (first) cable is GND. The middle cable is 12V, the third I left unused. As I didn’t have the right connector I had to wirewrap the cables onto the pins:

Wirewrapping to the rescue

Controlling

The socket is connected to a MOSFET which is controlled by GPIO150. This means when you start the server the fan is default OFF.

To enable the fan you need to run the following as root:

echo 150 > /sys/class/gpio/export
# this will create /sys/class/gpio/gpio150
echo out > /sys/class/gpio/gpio150/direction
echo 1 > /sys/class/gpio/gpio150/value

If you want to control the other GPIOs with WiringPi you need to install a patched version of WiringPi, see http://wiki.friendlyarm.com/wiki/index.php/NanoPi_M4#WiringPi_and_Python_Wrapper.

Starting the fan at boot

Login as root and create the file /root/bin/initFan.sh with the content:

#!/bin/bash
echo 150 > /sys/class/gpio/export && echo out > /sys/class/gpio/gpio150/direction && echo 1 > /sys/class/gpio/gpio150/value

Make it executable:

chmod +x /root/bin/initFan.sh

Run crontab -e and add the line

@reboot /root/bin/initFan.sh

Reboot your system and check with cat /sys/class/gpio/gpio150/value if the value 1 is returned.

Adding a Remote Widget

Monitoring via WiFi. This is not specific to this setup, and should work with any system in general. As the hardware is installed in a closet, I wrote a server with javascript (nodejs), that provides a few monitoring values, and an Arduino based client (esp8266), to display these values.

The sources are in this repository: https://github.com/pauls-3d-things/mini-stats

An introduction to the Arduino/esp8266 hardware is in my previous post;

Setting up a mirrored RAID (level 1)

The following instructions are for advanced users only, (i.e. if you are unsure what /dev/sdc is I advise you to get more familiar with your system, fdiskand linux in general). If your system contains no running disks or data a.k.a. “Grüne Wiese”, feel free to try things out. ;).

Prepare Partitions

In my case the devices where /dev/sdc and /dev/sdd. The installation on the eMMC chip is on the device /dev/mmcblk1p1. Both disks are the same, and will be formatted the same:

fdisk /dev/sdc
fdisk /dev/sdd

Create a new primary partition with default parameters (i.e. the entire disk):

Command (m for help): n
Partition type
   p   primary (0 primary, 0 extended, 4 free)
   e   extended (container for logical partitions)
Select (default p): p
Partition number (1-4, default 1):
First sector (2048-500118191, default 2048):
Last sector, +/-sectors or +/-size{K,M,G,T,P} (2048-500118191, default 500118191):

Created a new partition 1 of type 'Linux' and of size 238.5 GiB.

and set the type to fd:

Command (m for help): t
Selected partition 1
Hex code (type L to list all codes): fd
Changed type of partition 'Linux' to 'Linux raid autodetect'.

and write the changes to the disk:

Command (m for help): w
The partition table has been altered.
Calling ioctl() to re-read partition table.
Syncing disks.

Do this with both identical disks.

Assemble RAID

Then assemble the raid (️⚠️make sure to adapt this to the correct disks first (the /dev/sd[c-d]1part)!):

mdadm --create /dev/md0 --level=mirror --raid-devices=2 /dev/sd[c-d]1
mdadm: array /dev/md0 started.

As a result your raid will be available as /dev/md0.

Format it with

mkfs.ext4 /dev/md0

Run blkid to find the RAIDs UUID:

/dev/md0: UUID=”db42bd5c-291d-4c2b-a3b7-34a185918d57” TYPE=”ext4”

And add it to /etc/fstab:

# <file system>                                 <mount point>   <type>  <options>    <dump> <pass>                                           
# [ other lines removed by author]
UUID=db42bd5c-291d-4c2b-a3b7-34a185918d57       /mnt/SSD        ext4    defaults,nofail                                         0       3

Make sure to use a sensible value for <pass> for your system.

Mount your drive either by rebooting or

mount /mnt/SSD

Performance Tests (or Playing around with 2 SSDs and mdadm)

I’m only going to look at bulk write speeds, as everything below that will only be the disk as a bottle neck. If I’m wrong, please let me know :).

I got the following results using two SSD SanDisk SDSSDP256G (2013 era):

Configuration Write Speed up to
raid 1  220 MB/s 
raid 1 (single disk) 300 MB/s
raid 0 400 MB/s

The SATA hat shows promising speeds, especially if you consider the size of the setup. With a Marvell 88SE9215 chip which is connected via PCI-E 2.0 (https://www.marvell.com/storage/system-solutions/assets/Marvell-88SE92xx-002-product-brief.pdf), we get max theoretical speeds of up to 500MB/s (https://en.wikipedia.org/wiki/PCI_Express#PCI_Express_2.0).

For the size and cost of the setup, I am more than happy with these results

mdadm raid level=1 (mirror)

The bulk write speed on the NanoPi M4 to a mirrored raid of SSDs (2x SanDisk SDSSDP256G, mirrored) is

root@nasty:/mnt/SSD# dd if=/dev/zero of=./2GB-of-zero bs=1M count=2048
2048+0 records in
2048+0 records out
2147483648 bytes (2.1 GB, 2.0 GiB) copied, 9.74968 s, 220 MB/s

mdadm raid level=1 (single disk)

If we remove a disk

root@nasty:/mnt# mdadm /dev/md0 --fail /dev/sdd1
mdadm: set /dev/sdd1 faulty in /dev/md0
root@nasty:/mnt# mdadm /dev/md0 --remove /dev/sdd1
mdadm: hot removed /dev/sdd1 from /dev/md0

and write data to an an umirrored SSD we get:

root@nasty:/mnt/SSD# dd if=/dev/zero of=./8GB-of-zero bs=100M count=80
80+0 records in
80+0 records out
8388608000 bytes (8.4 GB, 7.8 GiB) copied, 27.3931 s, 306 MB/s

Let’s check if the measured write speeds get better with larger files (in my theory this represents a better average of writespeed, again only for bulk):

root@nasty:/mnt/SSD# dd if=/dev/zero of=./20GB-of-zero bs=100M count=200
200+0 records in
200+0 records out
20971520000 bytes (21 GB, 20 GiB) copied, 71.0981 s, 295 MB/s

Not a significant difference, but close to the advertised speed of

Lightning read and write performance of up to 490mb/s read speeds and 350mb/s write speeds.

So, the drive seems to be a bit of a limiting factor here.

mdadm raid level=0 (stripe)

Let’s try it with a RAID0 configuration.

First stop the raid:

mdadm --stop /dev/md0

Recreate the disks, see above. Some more details how to destroy your raid config: https://forum.ivorde.com/mdadm-how-can-i-destroy-or-delete-an-array-t85.html

Recreating the disks with fdisk and rebooting already worked for me.

Create a RAID0:

mdadm --create /dev/md0 --level=stripe --raid-devices=2 /dev/sd[c-d]1

And repeat the test of writing 20GB of zeros:

root@nasty:/mnt/SSD# dd if=/dev/zero of=./20GB-of-zero bs=100M count=200
200+0 records in
200+0 records out
20971520000 bytes (21 GB, 20 GiB) copied, 52.7125 s, 398 MB/s

This looks like twice the speed obtained vs the mirrored raid configuration.

Writing via smbd (windows shares)

When writing files via network shares via smbd (nano pi m4) and smb client (linux intel machine) via the 1Gbit/s LAN interface I got write speeds of around 80 MB/s.