Alpine Linux: Home NAS Setup 3.0
Welcome to my guide on setting up a NAS file server using the lightweight Alpine Linux distro. We will be using the highly reliable ZFS filesystem for data storage and backup. Then we'll setup Samba for network shares and file transfer.
A note on Alpine Linux
This guide assumes you've already installed Alpine Linux with the "sys" method, you've selected dhcp network setup on the installer, and you selected OpenSSH server.
Note these instructions were tested on Alpine Linux version 3.19. Sometimes package name or default software will change between releases, will require manual intervention, and this guide will need updating.
A note on disks
For this setup we are using ZFS's built-in RAID mode "raidz" this works similar to standard RAID5, requires at least 3 disks, and will tolerate 1 disk failure.
We will be using 3 disks of the same size for our main data. And a single backup drive that is double the size of a single data drive. In my case:
- x3 4TB - Data
- x1 8TB - Backup
A note on text editors
Throughout the tutorial, you'll be prompted to edit text files from the terminal. Alpine comes with a text editor called vi
. If you've never used it, you'll want an easier tool called nano
. We'll install it soon.
When prompted to edit files, run something like: doas nano /etc/example-file
.
To exit press Ctrl
+ x
, and press y
to save changes.
Next up, what is doas
?
A note on privilleges
When we need to run something as root from our admin accounts, we'll need to elevate privileges to root. Rather than the common sudo
command, we'll use Alpine Linux's preferred doas
command. Keep this in mind if you ever refer to other guides, you need to change sudo
to doas
.
If you get a permission error after running a command, it probably wasn't run with root when it needed to.
To begin, log into the NAS directly using the root account and the password you set during the setup. Connect a keyboard and monitor to access the system. And follow along.
Essential post-install instructions
1. Add administrator accounts
Start by adding any users who will be administrating the NAS. We will add these users to the wheel
group with the Capital -G
option.
adduser me -G wheel
adduser sibling -G wheel
The wheel group is similar to an "admin" group insofar as it allows it's members privillege esculation.
If you already created the user, add them with: adduser <user> wheel
Verify membership with: groups <user>
You can delete users with: deluser <user>
2. Install base software
Let's get the bare essentials installed. Alpine Linux gives us the apk package manager to install software packages from the server with.
apk update
apk add doas nano
Heres a breakdown on those commands:
- Update our local package list, so
apk
knows what is available. - Install both doas and nano. Packages to install are seperated by a space.
3. Set up doas
Next, using your preferred text editor, open the file /etc/doas.d/doas.conf
:
nano /etc/doas.d/doas.conf
And add the following to the file:
permit persist :wheel
Save the changes and exit the text editor. Then log out of the root account using the exit
command.
Next, log in to one of the accounts that you added to the wheel
group.
If you can login succesfully, test doas
using the following command:
doas apk update
If apk update runs with no permission error, than doas works. If not check you are part of the wheel
group, and the text file, /etc/doas.d/doas.conf
, has been changed according to above.
To enhance security, disallow direct login to the root account:
doas passwd -l root
From now on when we need to run something with elevated privileges, we'll need to prefix each command with doas
.
4. Understanding SSH
To remotely access the NAS, we need SSH. If OpenSSH wasn't installed on the Alpine Linux setup, refer to the reference at the bottom of this document for setup instructions.
SSH let's you get a remote terminal session, which let's us manage the NAS remotely.
To determine the IP address of your NAS on the network, run the following command on the NAS:
ip a
Look for your Ethernet interface in the output (usually formatted like "eth0" or "enp3s0"). Find the IP address associated with it. For example, the output might include a line like this:
inet 192.168.1.100/24 brd 192.168.1.255 scope global eth0
The IP address in my case is 192.168.1.100. Note that the /24
part is not part of the IP address. brd 192.168.1.255
refers to the broadcast address and is not the IP address. Also ignore the loopback interface ("lo").
From another computer connected to the same local network, use the ssh
command to connect to the NAS. Replace me
with your username, and replace the IP address with the IP you obtained in the previous step:
ssh me@192.168.1.100
Type your password, noting that you won't get any feedback while typing your password. You should be able to connect to the NAS.
Once you're able to connect remotely, you no longer need to be directly tethered to the NAS physically. So follow the rest of the guide from another computer. Windows, Mac and Linux OS's provide a built-in ssh
command.
Reserve DHCP
It is highly recommended to reserve an IP address in your network router for the NAS. This will simpify managment, and eleminate issues resulting from change of IP. Not all routers are the same, so you will need to either explore the management interface of your router, otherwise refer to the documentation provided (or search online).
On the NAS use the command ip a
to view network interfaces. As mentioned before the interface will be called something like "eth0" or "enp3s0" Although if you have two network cards installed, this might be different. You will most probably have a "loopback" interface beginning with "lo", don't use that one.
In the output from ip a
, find the MAC address for the network interface it looks something like:
link/ether ee:5b:86:4b:a6:a7 brd ff:ff:ff:ff:ff:ff
The MAC Address is right after link/ether
, ignore brd ff:ff:ff:ff:ff:ff
as this is just the broadcast address, and not what we need.
In your router use the MAC Address you found, and then allocate it an IP address within the same subnet as your router. Most home equipment uses a subnet of 255.255.255.0 (or /24). This means that you only change the forth number when assigning the IP address to the devices.
In this arrangement forth number can be anything between 1 and 254. In my case my router is 192.168.1.1
so I give my NAS 192.168.1.100
. Once set, your NAS will get the same IP address.
In the next step we'll install a subnet calculator called sipcalc
. If you need help, you can use sipcalc
to show the usable IP address range based on the IP address and subnet mask from your router. Otherwise plenty of subnet calculator exist online.
More is said on using sipcalc
further down in the reference section.
Further software install
We'll start by installing packages we'll need throught the guide:
doas apk update
doas apk add mandoc man-pages tmux samba rsync parted lsblk avahi dbus sipcalc ncurses-terminfo
doas apk add doas-doc nano-doc tmux-doc samba-doc rsync-doc parted-doc util-linux-doc avahi-doc dbus-doc sipcalc-doc
First command will update our local package list, and should be run each time you want to install, or upgrade the system. In the second command we install a variety of packages that will be useful.
You'll notice, in the third command, packages ending with -doc
. These will provide documentation for you to read if you ever get stuck. These are called man pages and are useful, if a little dry to read as a newbie.
To get help type man
followed by the command, e.g. man samba
. Press q
to quit.
Add users
Now it is time to add more users to our NAS. We need to create a group to use for access control to the NAS data:
doas addgroup nas
This group is simply called nas
.
Next, you add yourself and any other user's you already created to this group:
doas adduser me nas
doas adduser sibling nas
A script for making normal users
To easily add NAS users, I've made a script. It will add system and Samba accounts if they don't exist, then ask you to set passwords for both. Let's 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:
#!/bin/sh
user=$1
# Fail script if not root
if [ "$(id -u)" != "0" ]; then
printf "ERROR: nas-user must be run as root\n"
return 2
fi
if [ "$user" == "" ]
then
printf "ERROR: Username not provided\nExpected: '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
Then give it execute permissions:
doas chmod +x /usr/local/bin/nas-user
Add more users
Let's add some more users:
doas nas-user mother
doas nas-user father
Re-run this script for any new users that need creation.
ZFS File system
Start by installing the ZFS filesystem for the Linux LTS release:
doas apk install linux-lts zfs-lts zfs-doc
Then enable zfs service scripts to start on boot:
doas rc-update add zfs-import sysinit
doas rc-update add zfs-mount sysinit
Then Reboot.
Once rebooted, list out the physical hard drives. We'll use the lsblk
tool we installed above to list these.
Remember this guide makes use of x3 HDD's of the same size for live data. 3 drives is the minimum to use the RAID level. Backup drive should be at least double the size of a single drive.
List storage devices:
doas lsblk
Sample Output:
# Sample only
sda 8:0 0 3.6T 0 disk
sdb 8:16 0 119.2G 0 disk
├─sdb1 8:17 0 512M 0 part /boot/efi
├─sdb2 8:18 0 4G 0 part [SWAP]
└─sdb3 8:19 0 114.7G 0 part /
sdc 8:32 0 3.6T 0 disk
sdd 8:48 0 3.6T 0 disk
Here we can see 4 devices with 3 partitions belonging to sdb. So for my case, sda, sdc, and sdd are the drives I'm after. Since sdb is only 120GB and is already partitioned, it's very clearly my OS drive, and we should absoulutly avoid formatting it.
We will now create a ZFS zpool called "nas" using the raidz array (raidz is the ZFS version of RAID5). Simply prefix /dev/
before the device name:
# Careful to get the right drives!
doas zpool create nas raidz /dev/sda /dev/sdc /dev/sdd
Next we will create a ZFS dataset simply called "data":
doas zfs create nas/data
The backup drive will be a larger single drive, we will call the zpool backup
, and the dataset borg
, named after the backup program:
doas zpool create backup /dev/sdX
doas zfs create backup/borg
We now have a place to put our data in a way that is high volume (total 8TB), and redundent (RAID5/raidz can handle 1 drive failure).
A few more zfs related command for you to get information about the array:
- View status of pool -
doas zpool status nas
- Broader overview of filesystems -
doas zfs list
- Standard Linux command to view FS mounts -
mount
What you do next depends if this is the first time setup, or if you are transferring data from a previous NAS install.
Path 1 will be for first time set up, whereas path 2 will cover transferring data over from another drive.
Path 1: New file structure
You need to come up with a few top-level folder. I have Documents
, Media
, Photos
, and Projects
. My advice is that you should not add or remove these top-level folders very often.
doas mkdir -p /nas/data/Documents
doas mkdir -p /nas/data/Media
doas mkdir -p /nas/data/Photos
doas mkdir -p /nas/data/Projects
Next let's set correct file permissions on these folders. /nas/data
should be have root as it's owner and group:
doas chown root:root /nas/data
Then, make sure the permissions on /nas/data
give the owner (the root user) full access but gives the group and others read and execute permissions only:
doas chmod 755 /nas/data
Now we will set the nas
group onto all of the sub-folders:
doas chgrp -R nas /nas/data/*
doas chmod -R 770 /nas/data/*
The first command recursivly sets the group on all sub-folders of /nas/data
, that's what the capital -R
options does. And the asterisk *
, is a wildcard which pattern matches. In this case: anything after /nas/data
. Second command changes the scope of those permissions to give owner and group (root
and nas
respectivly) full access but anyone else no permission
To view files permissions change directory to the location is questions and type ls -l
cd /nas/data
ls -l
I will not elaborate on file permissions, instead read the manual pages, or look online:
man chmod
man chown
man chgrp
- Changes permission, changes owner, changes group respectivly.- Linuxcommand.org: Permissions - An explanation of Unix file permissions.
Path 2: Transfer exisiting structure:
Plug the old HDD in either with SATA directly, or a USB caddy. We will create a place to mount the old disk:
doas mkdir /mnt/nas-temp
Next you would use a command like doas df -h
or doas parted -l
to see what the old disk is. With df
you will be able to view disk usage stats, which will help in figuring out what's used in the past. Otherwise work out what is mounted with doas mount
, and by a process of elimination figure out what's not yet mounted.
Make sure to mount the first partiton, or whatever other partition has data on it:
doas mount /dev/sde1 /mnt/nas-temp/ # sde1 is only an example!
Depending on skill level you might want to use a tool like tmux
, so you can detach from your SSH session without interupting the file transfer. Check the reference section further below to see how it's used.
File transfer command will look like:
doas rsync -a --progress /mnt/nas-temp/data /nas/data
Once done, go back to Path 1, and re-run the file permissions commands to make sure you're set!
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
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
Samba
Microsoft's SMB is a well supported protocol for network shares. Samba is an open-source implementation of SMB for Unix-like systems.
We now need to edit the Samba config file, located at /etc/samba/smb.conf
. The file is very large and shows many example settings. We will backup this file and create a new one with just the options we want:
cd /etc/samba
doas mv smb.conf smb.conf.bak
doas nano smb.conf
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 that share.
For the purposes of a simple home NAS, here is the config that I use:
[global]
server string = nas
server role = standalone server
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 = /nas/data/files
valid users = @nas
guest ok = no
read only = no
[Public]
comment = Read-only access to media without an account.
path = /nas/data/Media
read only = yes
guest ok = yes
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's 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
Backup Tool
In the next step we will install an incremental backup tool and set it to run daily.
1. Enable Community repo
This command will enable community repo (-c) and check for the fastest mirror (-f):
doas setup-apkrepos -cf
2. Borg Backup Install
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.
Borg also won't immediately delete files just because they were deleted on the NAS.
We start by installing:
doas apk update
doas apk add borgbackup borgbackup-docs
Borg must be run as root, so we must prepend doas
to all borg commands. 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
We will create a new backup repository on the backup drive:
doas borg init --encryption none /backup/borg
Create the first backup called "First":
doas borg create --list --stats /backup/borg::First /nas/data
I recommend using tmux
so you can detach from SSH without interupting the backup process. Refer to the reference section further below to see how to use it.
3. Cronjobs
We need a backup task to run 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 script
Let's setup automatic backups. First create a script using any text editor you want:
doas nano /etc/periodic/daily/borgbackup.sh
Paste the following script:
#!/bin/sh
export TIME=$(date '+%Y-%m-%d_%H:%M')
export BORG_REPO="/backup/borg"
/usr/bin/borg create ::"Auto_$TIME" /nas/data
/usr/bin/borg prune -v --list --keep-daily=14 --keep-monthly=12
/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/borgbackup.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 /backup/borg
View all the files of a particular backup state:
doas borg list /backup/borg::"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 /backup/borg
View info about particular backup:
doas borg info /backup/borg::"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:
Please note it takes a long time to check the backups.
Restore backup
First list all the archives:
doas borg list /backup/borg
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 /backup/borg::"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 /nas
will be restored, so use the following to fix it:
doas mv nas/* .
This will move all subfolders back to where it was before you can now safely delete the nas
folder. But DON'T delete: /nas
that's the real full path to your NAS hard drive!
Make sure to reread the 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:
Access NAS file share from another computer
Now that we have our SMB share setup, it is time to access it from a different computer.
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
Notes
If you cannot get the nas.local
name working from one or all of your systems, you can use IP instead. E.g. \\192.168.1.100\share
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.
Further Reference and Misc. Tasks
1. Updating system
You should update the packages from time to time. Make sure you always reboot after the updates!
doas apk update
doas apk upgrade
doas reboot
This is enought to upgrade to minor versions, e.g. v3.19.0
to v3.19.1
. But to upgrade, for example, to v3.20
more effort is required.
2. Upgrading to next stable version of Alpine Linux
News about Alpine versions are published on the website.
Edit the /etc/apk/repositories
changing the version number to the latest release, then:
doas apk update
doas apk upgrade --available
doas sync
doas reboot
More detailed instructions on the wiki
3. Install Microcode
To keep the processor's microcode up-to-date, I suggested to install microcode for your CPU:
Intel:
doas add intel-ucode
AMD:
doas add amd-ucode
4. Note about IP Addresses
In this tutorial I have been using IP addresses in the 192.168.1.0 range. When setting IP addresses, make sure to follow the subnet of the router. 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.
Login to your router and view the Network or LAN settings. Take note of the IP address and subnet mask. The math behind subnets can be tricky so use a subnet calculator, plenty online, and Alpine Linux has one called sipcalc
installed with apk
. Simply give it the IP and subnet mask from your routers management page, e.g. sipcalc 192.168.1.1 255.255.255.0
and it will provide information about the subnet.
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.
5. How to use 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 the SSH session.
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"
6. 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.
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 "/nas/data/" "/mnt/external1" --delete
Make sure you are inside tmux if you want to close the remote session on your PC.
Note how /nas/data/
has a leading slash, but /mnt/external1
doesn't. The leading slash means copy anything after /data/
, but not the data
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.
7. Installing OpenSSH
Alpine Linux should ask to install an SSH server, this guide uses OpenSSH. If you didn't install OpenSSH, run the following:
doas apk add openssh openssh-doc
doas rc-update add sshd
doas rc-service sshd start
Changelog
- 2024-02-25: Version 3 started
Notes for future versions of this guide
- Use ZFS snapshots for hot backups instead