the website of dither8

Simple Home NAS 2.0 Setup

Published on 2022-07-10

This NAS setup is based on the simple Alpine Linux distro, and works best with two dedicated internal HDD's, and a small SDD for booting the operating system.

Unlike the previous guide, we will not be using btrfs or RAID. Instead we will be opting for two separate EXT4 file systems, with one drive taking the role of backup.

Having an incremental backup system is far more important then mirroring with RAID, since RAID can only provide performance gains, and convenience when a disk fails. Not a bulletproof backup system.

By avoiding RAID, we will loose read performance when reading two different files at once. But we gain much more robust backups, which can let us go back in time, depending on how we configure it.

Perhaps I might investigate in buying 3 HDD's, have two mirrored, and the third as a backup. But for now we will keep it simple, stupid!

During the setup you will be editing system files in a terminal, and therefore will need a way of editing. For a beginner I suggest using the nano text editor. It isn't installed by default, but can be easily added with apk install nano. Many of the system files will require elevating privileges, for this we use a tool called doas, which we will setup.

Most Linux distros will use sudo to elevate privileges. This WON'T work on our system. Keep this in mind if you ever follow another online guide.

Throughout you will need to edit a lot of text files on the file system. If you choose nano, then you edit these files using doas nano /etc/example-file

This guide assumes the following:

We separate the users so we can limit the normal accounts access to the NAS system files.

You will start by logging into the NAS directly (with keyboard and monitor) using the root account, with the password you set during the setup.

Adding administrator accounts

Start by adding any users who will be administrating the NAS:

adduser mea -G wheel
adduser siblinga -G wheel

In my case I will simply add an "a" on the end to differentiate them from the normal accounts. We are also adding them to the wheel group, which will give our admin users greater access to the system, such as privilege escalation with doas.

If the user that you want to add as admin already exists, just simply add them to the wheel group with adduser <user> wheel.

You can also delete users with deluser siblinga

Setting up doas

It is now time to setup doas, and give elevated privileges to our administrator accounts.

First install the doas software and documentation using Alpine's package manager:

apk update
apk add doas doas-doc

Using your preferred text editor edit the file /etc/doas.d/doas.conf and add a new line:

permit persist :wheel

Save and exit the editor. And logout of the root account using the exit command.

Next login into one of the accounts that you added to the wheel group. You should test doas with doas apk update, if the apk update proceeds, then you have access.

We should now disallow login to the root account, otherwise the root account will be an easy target for attackers:

doas passwd -l root

SSH

In order to remotely access the NAS we need to have SSH enabled. Thankfully Alpine Linux setup asks you to install a ssh server (this guide uses the OpenSSH server). If not then you could install with: doas apk add openssh openssh-doc.

On the NAS execute the command: ip a, and in the output find your ethernet interface (usually formatted like enp3s0). Then find the IP address, mine looked like: inet 192.168.1.100/24. Note that the /24 part is not part of the IP address.

From another computer connected to the same local network execute the ssh command, make sure to replace mea with your relevant admin account, and replace the IP address with the IP from the command above.

ssh mea@192.168.1.100

Normal Users

Create a group for our normal users:

addgroup nas

A script for making normal users

To easily add NAS users, I have made a script. It will add system and Samba accounts if they don't exist, then ask you to set passwords for both. Don't worry about Samba right now, we will get that setup later.

For now lets get the script installed.

Create a new file with your preferred text editor:

doas nano /usr/local/bin/nas-user

Once opened, copy and paste the following script:

#!/bin/sh
user=$1

# Fail script if not root
if [ "$(id -u)" != "0" ]; then
    printf "ERROR: Must be run as root \n"
    printf "Try running 'doas nas-user' \n"
    return 2
fi

if [ "$user" == "" ]
then
    printf "ERROR: Username not provided \n"
    printf "Expected: 'nas-user [username]' \n"
    return 1
else
    # Try to add a Unix user with no password and part of nas group
    # Then set password with passwd command.
    adduser $user -D -G nas 1&> /dev/null || true && \
    passwd $user && \

    # Do the same with Samba
    smbpasswd -a $user && \
    return 0
fi

Now give it execute permissions:

doas chmod +x /usr/local/bin/nas-user

The script won't work right now, as we don't have Samba installed. We will worry about this later.

Enable Community repo

Open /etc/apk/repositories with text editor. You then need to uncomment line containing a URL ending with /community

You can do this by removing the hash (#) symbol at the beginning of the relevant line. Here is an example of what mine looks like:

#/media/sdb/apks
http://mirror.lagoon.nc/alpine/v3.16/main
http://mirror.lagoon.nc/alpine/v3.16/community
#http://mirror.lagoon.nc/alpine/edge/main
#http://mirror.lagoon.nc/alpine/edge/community
#http://mirror.lagoon.nc/alpine/edge/testing

Ignore the repositories with /alpine/edge/. These are the very latest packages, and don't play well with the stable versions of Alpine Linux.

Now execute

apk update
apk upgrade

Manual Pages

In case you get stuck we will be installing the documentation alongside the required software. In order to view these docs we need a program called man installed:

doas apk add mandoc man-pages

Now to get help for any program you run (e.g. doas) type: man doas.

Partition the hard drives

This guide will get the NAS hard drives up and running. If you already have the drives setup from a previous NAS, you should skip the partitioning step.

Install parted

Since fdisk cannot partition anything larger then 2TB you should install and use GNU Parted instead:

doas apk add parted parted-doc

Make sure to only partition the drives you intend to store the data on. I tend to have a 120GB SSD purely for the operating system, while having multiple 3TB HDD's for data storage. Take into account your hard-drive setup while going through these steps.

List the available hard drives using parted:

doas parted -l

Determine one of the disks that will be used for storage. Make note of the disk names (usually formatted as /dev/sd* for SATA disks.), We now need to partition them, please note this will DESTROY any data on the drive(s):

doas parted /dev/sd*

Replace /dev/sd* with the relevant disk drive you intend to format.

Set the label to "gpt":

mklabel gpt

Make a primary partition that takes all of the drive.

For example from 0% (the start) to 100% (the end):

mkpart primary 0% 100%

Then use the print command to check the disk. And quit once you are finished.

Repeat the partition process on all drives that you intend to use for data. Note that executing doas parted -l again might show old information until the new file system is created.

File system

When you execute the doas parted -l command, note the disk: e.g. /dev/sd* and the partition number, since we only created one partition on these drives, there will only be one. this will then come together to make the full drive as Linux understands it: /dev/sd*1

doas mkfs.ext4 -L NAS_2022 /dev/sd*1
doas mkfs.ext4 -L BACKUP_2022 /dev/sd*1

reboot

doas mkdir /mnt/nas
doas mkdir /mnt/backup

Make sure the /dev/sd*1 matches from the file system creation phase.

View UUID, Labels, and Block device:

doas blkid

Using the information from this command, we will edit the fstab file, so these partitions are automatically mounted on boot.

Edit /etc/fstab with your text editor of choice. We will need to create two new lines.

Column by column press the Tab key to jump to the next column

LABEL=NAS_2022       /mnt/nas     ext4    defaults        0 0
LABEL=BACKUP_2022       /mnt/backup     ext4    defaults        0 0

The second column specifies the mount point, for my system I mount at /mnt but you could choose a different location:

Third column specifies the file system:

Forth column are for options, we use the defaults:

The last column are options which we leave default at 0 0

Now you should verify that it works:

doas mount -a

File structure

Now that our btrfs device is mounted, we should create some folders for our users to create files underneath:

doas mkdir -p /mnt/nas/files/Documents
doas mkdir -p /mnt/nas/files/Media
doas mkdir -p /mnt/nas/files/Photos
doas mkdir -p /mnt/nas/files/Projects

File permissions

An important step for making sure your users can read/write in certain directories.

Right now root has ownership of all example folders, meaning that our users won't have access. Before we correct that we should ensure all folder have correct permissions.

Setting permissions can be dangerous, so make sure to copy exactly!

Make sure the containing folder files is owned by root:

doas chown root:root /mnt/nas/files/

Then, make sure that the permissions on /mnt/nas/files give the owner (the root user) full access but gives the group and others read and execute permissions only:

doas chmod 755 /mnt/nas/files

Now we will set the nas group onto all of the sub-folders:

doas chgrp -R nas /mnt/nas/files/*

Notice the -R option, this means that it will recursively apply this setting onto all of the sub-folders. Be careful with this option!

Let's lock down the permissions by giving root and our group r(ead) w(rite) x(execute) permissions, and giving anyone else no permission:

doas chmod -R 770 /mnt/nas/files/*

This will make sure all sub-folders belong to the nas group, and then gives those in the group full access to the files.

If at any point you want to check the file permissions simply use cd to move directories and ls -l to list the files/directories and show owner/group and the permissions.

The permissions are represented as drwxrwxrwx. The d stands for directory, and only appears when the item is a folder. The r stands for read, the w stands for write, and the x stands for execute. These are duplicated 3 times to show the permissions for different users and groups. The first set is for our owner, the second is for the group, and the third is for others (Which is anyone, who doesn't fall into either owner or group).

The set of three numbers in the chmod command represent the permissions for all three groups. The first number is for the owner, the second for the group, and third for anyone else. 7 means full access, 0 means no permission. You can work out what other numbers mean by adding up any of these three numbers:

read = 4
write = 2
execute = 1

So to give someone read and execute permission the number would be 5.

Besides that you should see root nas next to all of the sub-folders. The first is the owner which is root and the group is set to nas, both root and nas have full permission.

File permissions: Sources

Set the hostname

To make it easier to access your NAS, we will set a hostname and a domain: nas.local. The first part is the hostname, second part the domain. You can change the hostname, but you should keep the domain as "local" since that is convention for local network devices.

To change the hostname edit the /etc/hostname file with a text editor using doas. Clear whatever name in that file and replace it with the new hostname.domainname scheme.

Use the command hostname to print the current hostname of your NAS.

Hostname: Zeroconf with avahi

In order for other computers to discover your NAS through Zeroconf you should setup avahi

Start by installing avahi and dbus:

doas apk add avahi avahi-doc dbus dbus-doc

Open /etc/init.d/avahi-daemon in a text editor and ensure that under depend(), hostname is listed next to `need'. E.g:

depend() {
        before netmount nfsmount
        use net
        need dbus hostname
}

If hostname isn't listed as a needed dependency, then upon boot, the system will advertise the hostname none instead of the desired name.

Add avahi-daemon to boot:

doas rc-update add avahi-daemon boot

Reserve DHCP

Next you will have to reserve an address in your router. The default router management IP address should be in the documentation provided with your router. Otherwise use a search engine to find information about your router.

Type this IP address into a web browser.

On the NAS use the command ip a to view network interfaces. More then likely your interface will be called "eth0" (or similar) although if you use WiFi or have two network cards installed, this might be different. Most OS's will have a "loopback" interface beginning with "lo", don't use that one.

In your router use the MAC Address found from the ip a command, and then allocate it an IP address within the same subnet as your router. In my case my router is 192.168.1.1 so I give my NAS 192.168.1.100.

Subnets will be explained later on, but most home equipment uses a subnet of 255.255.255.0 (or /24). This means that you only change the forth number when assigning IP addresses to devices. Keep in mind that 254 is the highest you can go for a particular number.

Once set, your NAS will get the same IP address each time it comes on the network.

Samba

Microsoft's SMB is a well supported protocol for network shares. Samba is an open-source implementation of SMB for Unix-like systems.

Install Samba:

doas apk add samba samba-doc

We can now use the user setup script we installed at the beginning of this document. Create any user you will need:

doas nas-user me
doas nas-user sibling
doas nas-user mother
doas nas-user father

This will create both a Unix and Samba account with the same name. You will need to enter your password 4 times. It will also sometimes look like no input was detected, but it is working, just invisibly.

We now need to edit the Samba config file, located at /etc/samba/smb.conf. You should make a backup of it with doas cp /etc/samba/smb.conf ~. Open this file with a text editor and lets get underway...

The text file is quite huge and shows many example configuration settings, most are commented out (meaning they are inactive by putting a symbol at the beginning of the line). You should completely delete what is in the file for simplicity sake.

Defining a share is simple, just put the name you want (anything except for "global") between two square brackets. Underneath it is where you add configuration options.

For the purposes of a simple home NAS, here is the config that I use:

[global]
        server string = nas
        server role = standalone server
        hosts allow = 192.168.1.0/24
        hosts deny = 0.0.0.0/0
        force group = nas
        inherit permissions = yes
        force create mode = 0750
        force directory mode = 0770
        client min protocol = SMB3
        map to guest = Bad User

[Share]
        comment = Files shared will all users.
        path = /mnt/nas/files
        valid users = @nas
        guest ok = no
        read only = no

[Public]
        comment = Read-only access to media without an account.
        path = /mnt/nas/files/Media
        read only = yes
        guest ok = yes

hosts allow and deny is an important one, as it will limit the IP address range that can access your home network. Make sure to change the network address for "hosts allow" so that it matches the subnet used by your router. From what is set above, the NAS will allow anyone connecting from 192.168.1.1 to 192.168.1.254, and deny anything else.

Keep in mind that there are a number of private address ranges, and your router could be using any of the following in these ranges:

10.0.0.0 - 10.255.255.255
172.16.0.0 - 172.31.255.255
192.168.0.0 - 192.168.255.255

Most home networks should have the subnets at /24 (can also be represented as 255.255.255.0), so working out the network address is a simple as replacing the last character with a 0.

If in doubt, use a subnet calculator! Alpine Linux has one called sipcalc, installed with apk. Simply give it the IP and subnet mask from inside your routers management site: sipcalc 192.168.1.1 255.255.255.0 and it will provide information about the subnet. The network address and CIDR notation is what you put in hosts allow.

Now is a good time to try and simplify your home network (if need be) to prevent confusion. You really only need one device functioning as a router. Most new gear gives you a setting to put the device in "Bridge mode" (whereby the router functions are disabled and the device acts like a dumb access point). I would suggest enabling bridge mode on any other router or managed switch that isn't your main.

Back to the smb.conf:

The various "force" options will enforce permissions on any new file uploaded. Refer to the "File Permissions" section for more details.

The minimum protocol will prevent clients from using an older version of SMB. You might want to change this to SMB2 if you still have Windows 7 PCs.

I have added "@nas" to the valid users, the @ symbol tells Samba to allow any user from that group. This is why it is essential to have the same SMB and UNIX usernames.

I have also made a read-only group for guests that will allow access to anything in the "Media" folder. This is useful for setting up things like Kodi, without having to store a password.

For detailed information on any samba option, refer to the man page man smb.conf, or the web.

Finally, set the samba service to start on boot and then start for current session:

doas rc-update add samba
doas rc-service samba start

Cronjobs

We want to run certain maintenance tasks consistently and automatically. Cron is perfect for this. We specify a time for a script to be run, and cron will run it at the specified time.

First make sure crond is running, and set has been set to startup on boot:

doas rc-update add crond
doas rc-service crond start

By default scripts in the folder /etc/periodic/daily will run everyday at 2am. If you are not planning on having the NAS on 24/7, you can change this to a better time by running doas crontab -e. By default Alpine Linux gives you hourly, daily, weekly etc. folders, all the scripts in these folders will be run at the set time each hour/day/week. In our entry for the daily period, you can see that it is set to run at the 2nd hour (2am in the morning):

# min   hour    day     month   weekday command
0       2       *       *       *       run-parts /etc/periodic/daily

Using 24hour time we can change this to be (for example) 6:30PM in the evening:

# min   hour    day     month   weekday command
30      18      *       *       *       run-parts /etc/periodic/daily

Save and quit once you are happy.

Backup

For our backups we will be using the incredible Borg Backup. We can use this to take daily snapshots of the NAS. Borg is deduplicating, so it won't store two copies of files from different days, which will save on hard disk space.

Borg also won't immediately delete files just because they were deleted on the NAS.

We start by installing:

doas apk add borgbackup borgbackup-docs

Borg must be run as root, so we must prepend doas to each borg command. Each function of borg is broken down into different sub-commands. To initialise a repo we type doas borg init, to create a new backup state doas borg create, and so on. Then after call the sub-command, you give any options, and then the location of the backup repo.

Borg has very good documentation, which I suggest you read here

Setting up the backup

We will create a new backup repository on the backup drive:

doas borg init --encryption none /mnt/backup/borgbackup-nas

Create the first backup called "First":

doas borg create --list --stats /mnt/backup/borgbackup-nas::First /mnt/nas/files/

Automatic backups

Let's setup automatic backups. First create a script using any text editor you want:

doas vi /etc/periodic/daily/borgbackup.sh

Paste the following script:

#!/bin/sh
export TIME=$(date '+%Y-%m-%d %H:%M')
export BORG_REPO="/mnt/backup/borgbackup-nas"

echo "Starting Backup"
/usr/bin/borg create ::"Auto $TIME" /mnt/nas/files/

echo "Pruning Backup"
/usr/bin/borg prune -v --list --keep-daily=14 --keep-monthly=12

echo "Compacting Backup"
/usr/bin/borg compact

In the pruning stage, I have set it to keep the last 14 days of backups, and the last 12 months. In other words you'll be able to get back to a state from any day within two weeks, or the last backup for each month of the last year.

Set permissions to allow execute using chmod, and check that the script will run:

doas chmod a+x /etc/periodic/daily/package-update.sh
doas run-parts --test /etc/periodic/daily

View info about backups

It is a very good idea to frequently check that backups are successfully being ran.

Get a list of all current backup states in the repository:

doas borg list /mnt/backup/borgbackup-nas/

View all the files of a particular backup state:

doas borg list /mnt/backup/borgbackup-nas::"Auto 2022-05-07 18:30"

Make sure to replace "Auto 2022-05-07 18:30" with the relevant backup name.

View info about the backup repository:

doas borg info /mnt/backup/borgbackup-nas/

View info about particular backup:

doas borg info /mnt/backup/borgbackup-nas::"Auto 2022-05-07 18:30"

More info can simply be viewed by running borg. you can also get help in regards to a single command (e.g. create) by running borg help create. The Borg backup website is also very helpful.

Checking backups

Please reference the documentation on borgbackup website:

Restore backup

First list all the archives:

doas borg list /mnt/backup/borgbackup-nas

You'll likely want to restore from the latest backup.

To extract to a new drive. You'll want to use a command like this:

doas borg extract /mnt/backup/borgbackup-nas::"Auto 2022-07-08 18:30"

BE WARNED: borg extract will always extract to your current directory. Make sure you mount the new drive and then use the cd command to change to the new drive.

Watch out for permissions. Use doas su to change to a root shell, if you are getting permissions issues when navigating the extracted backup.

The full path including mnt/nas will be restored, so use the following to fix it:

doas mv mnt/nas/files .

This will move the files folder back to where it was before you can now safely delete mnt/nas. But DON'T delete: /mnt/nas that's the real full path to your NAS's hard drive!

Make sure to reread this guide checking permissions, and file paths in Samba etc.

There are some other things you can do, like only doing a partial restore. Please read the documentation for more info:

Keep system up-to-date

The first script we'll write is one to automatically update all Alpine Linux packages:

doas vi /etc/periodic/daily/package-update.sh
#!/bin/sh

/sbin/apk update && /sbin/apk upgrade

Set permissions to allow execute using chmod, and check that the script will run:

doas chmod a+x /etc/periodic/daily/package-update.sh
doas run-parts --test /etc/periodic/daily

Other Tools

These are some other tools I use every now and again that I suggest get installed.

doas apk add tmux tmux-doc ncurses-terminfo rsync rsync-doc sipcalc

Microcode

To keep the processor up-to-date, it is suggested to install microcode for your CPU:

Intel:

doas add intel-ucode

AMD:

doas add amd-ucode

Upgrading Alpine Linux

News about Alpine versions are published on the website.

edit /etc/apk/repositories

doas apk update
doas apk upgrade --available
doas sync
doas reboot

More detailed instructions on the wiki


Backup to an external NTFS drive

In cases where Windows users might need access to data in-case of emergency. It's a good idea to store a backup on external hard-drives with the Microsoft NTFS file system.

We won't discuss formatting the drive on the NAS. That should be done in Windows, since it's best at doing that. Instead we will plug the drive directly into the NAS, mount it, and do a backup on the NAS.

Optional: Tmux

When you run commands over SSH, you must keep the terminal open on the PC you ran them from. Using tmux allows us to execute a long running command on the remote NAS, and then disconnect our PC. You'll need to install tmux and terminfo as mentioned in "Other Tools" section. You may also need to install a *-extra-terminfo package if tmux doesn't like your terminal program.

Start new tmux session called backup:

tmux new -s "backup"

To detach from the tmux session press Ctrl+B to put it into command mode, then press: D. You can then close your SSH session, with the backup still running on the NAS.

To attach again type:

tmux attach -t "backup"

Mount drive

First get a list of attached hard drives:

doas parted -l

Find your external drive making note of it's location (e.g. /dev/sd*), and partition number in the list.

Next create a mount point in /mnt:

doas mkdir /mnt/external1

Install NTFS driver:

doas apk add ntfs-3g

Mount the drive, in this example we mount the 1st partition of whatever /dev/ device is your external drive:

doas mount.ntfs-3g /dev/sd*1 /mnt/external1/

Confirm by viewing all mounts:

df -h

Run the following rsync command:

doas rsync -a --progress "/mnt/nas/files/" "/mnt/external1" --delete

Make sure you are inside tmux if you want to close the remote session on your PC.

Note how /mnt/nas/files/ has a leading slash, but /mnt/external1 doesn't. The leading slash means copy anything under files, but not the files folder itself. Slashes in rsync are significant, so make sure to follow above.

The --delete option will delete any files in the backup that were deleted on the NAS. --progress will show us progress.


Client-side SMB

Now that we have our SMB share setup, it is time to access it from our computers.

On Windows, head to file explorer and add a Network location from "My PC". The address will look like:

\\nas.local\share

On Linux, most file managers will allow access through an address bar, or an option titled "other locations" or "connect to server" or "network". Once connected, there should be a way to bookmark to the sidebar. The address to connect will look like:

smb://nas.local/share

Note: Some Linux distros won't pre-install gvfs-smb, which is required to connect. KDE users should make sure kio-extras is installed.

Type username and password, set the workgroup to "WORKGROUP" if needed. You can also choose to save the credentials for faster login.

On Linux thumbnails might not display for photos. Check your file manager settings for thumbnails options, most will only display them on local files by default.

There are some drawbacks to using the share through the file manager on Linux. Some other options include adding details to /etc/fstab so that it will mount on boot, or using doas mount.cifs to mount it. KDE users can also take a look at SMB4k.


Changelog