How to build a Raspberry Pi NAS

The Raspberry Pi 4 B has Gigabit Ethernet and USB 3.0 Ports, which allows you to construct a basic NAS.

What is a NAS?

A Network Attached Storage (NAS) is a device which allows you to store documents, pictures, and videos on a single system which is accessible to all devices on your home network.
Constructing your own NAS using Linux is cheaper than a commercially available Synology or QNAP NAS, but has the added benefit of being supported for longer and less susceptible to malware, although using a Raspberry Pi would be slower than an x86 system.

Software like Nextcloud turns your NAS into your very own cloud storage device for use on your home network, keeping you in control of your data.
I cover Nextcloud setup on Raspberry Pi on this YouTube video: How to Setup Nextcloud on a Raspberry Pi

What you will need:


Before you boot the OS

Mount the newly imaged MicroSD card on your desktop/laptop and modify the network-config file in the system-boot volume to add your Wi-Fi credentials and set a static IP address.

Set dhcp4 to no, then add the address range for your home network, gateway4 is usually the IP address of the router. I have set the DNS nameserver to OpenDNS (208.67.222.222, 208.67.220.220).

Example settings for the network-config file in system-boot:
version: 2
ethernets:
  eth0:
    addresses: [192.168.1.5/24]
    gateway4: 192.168.1.1
    nameservers:
      addresses: [208.67.222.222,208.67.220.220]
    dhcp4: no
    #optional: true

wifis:
  wlan0:
    addresses: [192.168.1.6/24]
    gateway4: 192.168.6.1
    nameservers:
      addresses: [208.67.222.222,208.67.220.220]
    dhcp4: no
    #optional: true
    access-points:
      "home network":
        password: "123456"

Note: If your network name has a space in it, you need to add quotation marks around it.
Save the file and extract the card from your desktop/laptop. During the first boot, your Raspberry Pi will automatically connect to this network on the assigned IP.


3. Power on the Raspberry Pi

Insert the MicroSD card into the Pi and power it up (plug in your power supply). After a minute or so, Ubuntu on your Raspberry Pi will have fully booted and connected to the network.

Using an SSH Client

On Ubuntu and Mac OS, an SSH client is already installed. Some versions of Windows 10 also include an SSH client too, but if yours does not or you’re unsure, follow these steps to install one.

ssh [email protected]<Raspberry Pi's IP address>

You will be asked to confirm the connection:

Are you sure you want to continue connecting (yes/no/[fingerprint])?

Type “yes” to confirm.

Changing the password

The default password is “ubuntu”
The first thing Ubuntu will do is to ask you to change it to a secure password. Once done, you can reconnect again with the SSH command and the new password.

WARNING: Your password has expired.
You must change your password now and login again!
Changing password for ubuntu.
Current password:
New password:
Retype new password:
passwd: password updated successfully
Connection to <Raspberry Pi's IP address> closed.

Check for Updates

It's worth checking for and installing updates before we get too much further with the setup.

sudo apt update
sudo apt-get dist-upgrade

Hostname

It will be nice to have a different hostname for the system. I have imaginatively gone with “mynas”.

sudo hostnamectl set-hostname mynas
sudo reboot

4. Add Storage

Plug in your USB 3.0 Hub (optional) and then connect all the USB hard drives.

List Partitions

Have a look at the drives mounted on your system to make sure it has recognised the USB drives:

lsblk

The drives starting with loop are folders containing Snap packages.
mmcblk0, mmcblk0p1, mmcblk0p2 are the MicroSD card containing Ubuntu boot firmware and root file system.
The drives starting /dev/sda and /dev/sdb are Storage Device A and Storage Device B respectively. If you have more drives, it will continue up the alphabet.

NAME        MAJ:MIN RM  SIZE RO TYPE MOUNTPOINT
loop0         7:0    0 48.4M  1 loop /snap/core18/1708
loop1         7:1    0 61.3M  1 loop /snap/lxd/14808
loop2         7:2    0 23.5M  1 loop /snap/snapd/7267
sda           8:0    0  3.7T  0 disk
└─sda1        8:1    0  3.7T  0 part
mmcblk0     179:0    0 14.9G  0 disk
├─mmcblk0p1 179:1    0  256M  0 part /boot/firmware
└─mmcblk0p2 179:2    0 14.7G  0 part /

Delete Old Partitions

Next we want to blank the drives and create a new ext4 partition. Starting with the first drive (sda):

sudo fdisk /dev/sda

Press ‘d’ to delete any given partition name from the drive:

Welcome to fdisk (util-linux 2.34).
Changes will remain in memory only, until you decide to write them.

Be careful before using the write command.

Command (m for help): d
Selected partition 1
Partition 1 has been deleted.

Create New Partitions

Now press ‘n’ to create a new primary partition 1 under /dev/sda using the default values fdisk provides.

Command (m for help): n
Partition type
  p   primary (0 primary, 0 extended, 4 free)
  e   extended (container for logical partitions)
Select (default p):

Using default response p.
Partition number (1-4, default 1): 1
First sector (65535-976754644, default 65535):
Last sector, +/-sectors or +/-size{K,M,G,T,P} (65535-976754644, default 976754644):

Created a new partition 1 of type 'Linux' and of size 3.7 TiB.

Write changes to Disk

If you’re happy with the changes and recognise that it will delete all data on the drive press ‘w’ to complete and write the changes to the disk.
Or press ‘q’ if you want to discard the changes and start over.

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

Repeat for all sdb, sdc, etc drives that you have added.

Format New Partitions

Format new partitions with ext4:

sudo mkfs.ext4 /dev/sda1
sudo mkfs.ext4 /dev/sdb1
sudo mkfs.ext4 /dev/sdc1

5. Mount Drives

Create folders under /mnt:

sudo mkdir /mnt/disk1
sudo mkdir /mnt/disk2
sudo mkdir /mnt/disk3

Getting the blkid

We need to add the drives to the fstab (file system table) file in order to make the drives mount at bootup. It‘s better to utilise the unique Block ID of each drive to ensure that each disk is mounted in the correct folder.

sudo blkid
/dev/mmcblk0p1: LABEL_FATBOOT="system-boot" LABEL="system-boot" UUID="0468-A52F" TYPE="vfat" PARTUUID="87c6153d-01"
/dev/mmcblk0p2: LABEL="writable" UUID="5fcce78f-2de3-4805-8ffa-d0f11247d5bb" TYPE="ext4" PARTUUID="87c6153d-02"
/dev/loop0: TYPE="squashfs"
/dev/loop1: TYPE="squashfs"
/dev/loop2: TYPE="squashfs"
/dev/sda1: UUID="3763c386-a3ab-43f0-b1fe-1d34ad0ed85c" TYPE="ext4"

Make a note of blkid of each sda1, sdb1, sdc1 partition, e.g. UUID="3763c386-a3ab-43f0-b1fe-1d34ad0ed85c".

Adding the drives to fstab

There is a specific formatting required with fstab, so I have prepared this echo | tee command to ensure it‘s correctly entered. Substitute the UUID number and /mnt/disk folders with your system requirements.

echo -e "UUID=3763c386-a3ab-43f0-b1fe-1d34ad0ed85c\t/mnt/disk1\text4\tuser,auto\t0\t2" | sudo tee -a /etc/fstab

Check how it looks:

cat /etc/fstab
LABEL=writable  /        ext4   defaults        0       0
LABEL=system-boot       /boot/firmware  vfat    defaults        0       1
UUID=3763c386-a3ab-43f0-b1fe-1d34ad0ed85c       /mnt/disk1      ext4    user,auto       0       2

Mount the drives:

sudo mount -a

If all is well you won‘t receive any feedback from the mount command.
However, if there are any problems go back and edit fstab with sudo nano /etc/fstab, ensure that UUID numbers are correct and that the folder names exist.

Take ownership of the drives

chown changes ownership of a folder. $(whoami) provides the current user.

sudo chown $(whoami):$(whoami) -hR /mnt/disk1
sudo chown $(whoami):$(whoami) -hR /mnt/disk2
sudo chown $(whoami):$(whoami) -hR /mnt/disk3

6. Share The Drives

What would the use of a NAS be without the drives shared to other computers...
We have a couple of options of making the drives accessible to other computers: NFS and Samba.

NFS (Network File System) is used with Unix operating systems such as Linux and Apple macOS. Skip this step if you only want to share with Microsoft Windows-based computers.

Samba (or SMB/CIFS) is used with Microsoft Windows, but can also be understood by Linux and Android phones.


7. NFS

Install dependencies:

sudo apt install nfs-kernel-server

Export the drive folders

NFS will only export specified folders to a certain network range when they‘re added to /etc/exports:

sudo nano /etc/exports

Add the following to the end of the exports file:
Note: Use tab instead of space between the folder and IP address

/mnt/disk1	192.168.1.0/24(rw,sync,root_squash,subtree_check)
/mnt/disk2	192.168.1.0/24(rw,sync,root_squash,subtree_check)
/mnt/disk3	192.168.1.0/24(rw,sync,root_squash,subtree_check)

Restart NFS

sudo service nfs-server restart

Please see this NFS Setup Tutorial for further information on NFS setup and what you need to add to the /etc/fstab file on your other client systems.


8. Samba

Install dependencies:

sudo apt install samba samba-common-bin

Setup Network Shares

Edit the Samba config:

sudo nano /etc/samba/smb.conf

Add the following to the end of the smb.conf file:

[mynas]
	comment = Samba on My NAS
	path = /mnt/
	read only = no
	browsable = yes

This creates a share called “mynas” allowing access to all the drives mounted under the /mnt folder.
Read-only is set to no, which permits modifying and writing data to the share.
Browsable allows the share to be seen by a Linux file manager or Windows Explorer.

Add user account to access the Samba share

Since Samba doesn’t use the system account password, we need to set up a Samba password for our user account:
You can also specify a different username, although it must exist on the system.

sudo smbpasswd -a $(whoami)
sudo smbpasswd -a anotheruser

Restart Samba

sudo service smbd restart

Connect to the Share

You can now connect to the share using \\Raspberry Pi's IP address from Windows Explorer.

Or smb://Raspberry Pi's IP address from a Linux file manager.