Raspberry Pi as TimeMachine and NAS

This post covers configuring a Raspberry Pi 4 B as a TimeMachine and NAS Server.

Raspberry Pi offers a great guide on how to setup a NAS server (that also supports TimeMachine) using openmediavault.

This post however takes a different approach, where you will configure Samba manually to make your TimeMachine and NAS available on your network.

This is part 3 of 4 in a mini series where we will configure a headless Raspberry Pi 4 B as an efficient home server, capable of hosting Network Attached Storage (NAS), TimeMachine and Plex Media Server.
Through this series we will also look at how we can make automatic backups to keep uor data safe.

Prerequisites

Hardware Requirements

  • Raspberry Pi 4 B
  • microSD
  • External Storage (e.g. SSD in a USB 3.0 enclosure)
  • Second External Storage (e.g. HDD in a USB enclosure) (Optional)

Software Requirements


Setting up the external storage

I use a cheap USB 3.0 enclosure with a 2 TB SSD inside and I want to use one partition for Time Machine and another partition for my NAS.
(I also have a EFI bootloader partition as well as 2 bootable macOS recovery partitions.)

If you need to format and partition your drive, here is a nice guide: How to Partition and Format the Hard Drives on Raspberry Pi?

Note:
If you are looking for a new external storage disk, it is worth noting that the Raspberry Pi 4 is known to be picky about what adapters will work in the USB 3.0 ports
A community built list of adapters that are known to work with the Raspberry Pi 4, as well as those known not to work out of the box can be found here.

If you already own a disk that is causing problems, a solution may be found here.


Mounting the disk

After connecting your external storage in to the Raspberry Pi’s USB port, you can use the lsblk tool to get at list of all the block devices currently attached to your Raspberry Pi, and their mount points using this command:

lsblk -f

[output]

pi@raspberrypi:~ $ lsblk -f
NAME        FSTYPE  FSVER LABEL       UUID                                 FSAVAIL FSUSE% MOUNTPOINT
sda                                                                                       
├─sda1      vfat    FAT32 EFI         D2D7-4855                                           
├─sda2      hfsplus       Monterey    99b629a1-2994-45cf-b8c1-cff6d7450694                
├─sda3      hfsplus       Ventura     3516e24d-84c2-4f9e-9559-71de730a7277                
├─sda4      ext4    1.0   TimeMachine fc924351-26c8-4c01-a25f-e44a6869c5f1  614.6G    25% /media/pi/TimeMachine
└─sda5      ext4    1.0   NAS         665507c3-aee6-41bc-8be8-3594a65468d9    1.3T    45% /media/pi/NAS
mmcblk0                                                                                   
├─mmcblk0p1 vfat    FAT32 boot        444F-BE04                             200.3M    21% /boot
└─mmcblk0p2 ext4    1.0   rootfs      665507c3-aee6-41bc-8be8-3594a65468d9   19.4G    28% /
pi@raspberrypi:~ $ 

sda4 is my TimeMachine partition mounted at /media/pi/TimeMachine.
sda5 is my NAS partition mounted at /media/pi/NAS.

Because you installed Raspberry Pi with Desktop (in part 1), removable media will be auto mounted to /media/pi by the the pcmanfm desktop process.

pcmanfm uses udisksctl on the backend to mount your drive, so you can also mount the sda5 partition manually like this:

udisksctl mount -b /dev/sda5

If you installed Raspberry Pi OS Lite, you can enable the VNC server and create a Virtual Desktop, which loads the default desktop session with the a pcmanfm desktop process, which in turn enables auto mounting.

Otherwise you can use this uamount.sh script to generate udev mounting rules and add their corresponding entries to fstab to make your partitions auto mount at your desired location.

Click to expand: udev mounting rule example

Using the uamount.sh script

Install the uamount.sh script:

wget https://github.com/bswebdk/scripts/blob/master/uamount.sh

To get help run (or just read the top of the script):

./uamount.sh --help

To create a udev mounting rule for /dev/sda on /media/MYDRIVE use:

sudo ./uamount.sh /dev/sda MYDRIVE

To remove the mounting rule again use:

sudo ./uamount.sh /dev/sda

Manually create a udev mounting rule

Edit fstab in nano:

sudo nano /etc/fstab

And add an entry for the desired partition:

UUID=665507c3-aee6-41bc-8be8-3594a65468d9   /media/pi/NAS  ext4    defaults,noauto  0  0

The parameter noauto is important here as it tels the system not to mount during the init process.

Then create a new udev mounting rule:

sudo nano /lib/udev/rules.d/automount-nas.rules

And add the actions for “add” and “remove”

ACTION=="add", ENV{ID_FS_UUID_ENC}=="665507c3-aee6-41bc-8be8-3594a65468d9", RUN+="/bin/mount /dev/%k"
ACTION=="remove", ENV{ID_FS_UUID_ENC}=="665507c3-aee6-41bc-8be8-3594a65468d9", RUN+="/bin/umount /dev/%k"

Note:
Auto mounting removable media directly from fstab without using a udev mounting rule is not recommended.
Since fstab is read during the system init process, removing the drive from the Raspberry Pi will cause the system to hang for a long time on boot or even fail to boot completely.
Using a udev mounting rule defers the mounting procedure in to user space which will prevent boot failure.


Prevent partitions from auto mounting

I don’t want the 2 macOS recovery partitions to be mounted on the Raspberry Pi.

To prevent this, edit fstab in nano:

sudo nano /etc/fstab

And add an entry for each partition:

####################### fstab ########################
proc                    /proc           proc    defaults            0   0
PARTUUID=15ea4d29-01    /boot           vfat    defaults            0   2
PARTUUID=15ea4d29-02    /               ext4    defaults,noatime    0   1

UUID=99b629a1-2994-45cf-b8c1-cff6d7450694   /media/pi/Monterey  hfsplus  noauto  0  0
UUID=3516e24d-84c2-4f9e-9559-71de730a7277   /media/pi/Ventura   hfsplus  noauto  0  0

# a swapfile is not a swap partition, no line here
# use  dphys-swapfile swap[on|off]  for that

Setup TimeMachine and NAS

With your disk properly mounted, it’s time setup the Raspberry Pi to host your TimeMachine and NAS.

Install dependencies

First you need to install the two software packages Samba and Avahi:

sudo apt update
sudo apt install samba avahi-daemon

Samba is a free software re-implementation of the SMB networking protocol, which is officially supported by Apple.
Since macOS Mavericks Apple has preferred SMB over AFP and AFP seems to have been discontinued entirely as of macOS Big Sur.

Avahi is a system which facilitates service discovery on a local network via the mDNS/DNS-SD protocol suite. In Apple language, this is know as Bonjour.


Configuring Samba

In order for Samba to work well with macOS you need to configure vfs_fruit - Enhanced OS X and Netatalk interoperability.

You do this by editing the Samba configuration file/etc/samba/smb.conf in nano:

sudo nano /etc/samba/smb.conf

Near the top of the file you will find something like this:

#======================= Global Settings =======================
# https://www.samba.org/samba/docs/current/man-html/smb.conf.5.html

[global]

The [global] tag marks global section of the file.
Parameters in this section apply to the server as a whole, or are defaults for sections that do not specifically define certain items.

Add the following to the [global] section:

### Basic Samba Options ###
# https://www.samba.org/samba/docs/current/man-html/smb.conf.5.html

   min protocol = SMB2
   ea support = yes
   inherit permissions = yes


### Make Samba like Apples by teaching it about fruit ###
# https://www.samba.org/samba/docs/current/man-html/vfs_fruit.8.html

   vfs objects = catia fruit streams_xattr
   fruit:metadata = stream
   fruit:model = MacSamba
   fruit:posix_rename = yes
   fruit:veto_appledouble = no
   fruit:nfs_aces = no
   fruit:wipe_intentionally_left_blank_rfork = yes 
   fruit:delete_empty_adfiles = yes 
   fruit:zero_file_id = yes

Further down the file, you will find a heading like this:

#======================= Share Definitions =======================

This is where you tell Samba what to share on your network.

At the bottom of this section add the following:

### Adding Shares ###
# https://www.samba.org/samba/docs/current/man-html/smb.conf.5.html#idm51

[TimeMachine]
    comment = TimeMachine
    path = /media/pi/TimeMachine
    valid users = pi
    read only = no
    inherit acls = yes
    fruit:time machine = yes

[NAS]
    comment = NAS    
    path = /media/pi/NAS
    valid users = pi
    read only = no
    inherit acls = yes
;    spotlight backend = elasticsearch

This creates 2 shares “TimeMachine” and “NAS” which can only be accessed by the pi user.

You can now save and close the configuration file.

Even though the pi user already exists, because you created it with raspberry Pi Imager in part 1, you need to explicitly add the user to Samba’s password file with smbpasswd in order to connect with it from macOS:

sudo smbpasswd -a pi

If you want to add other users you can follow this guide: How to add or delete a samba user under Linux

Now you can test if your configuration is free from errors with testparm:

sudo testparm -s

[output]

pi@raspberrypi:~ $ sudo testparm -s
Load smb config files from /etc/samba/smb.conf
Loaded services file OK.
Weak crypto is allowed
Server role: ROLE_STANDALONE

# Global parameters
[global]
	log file = /var/log/samba/log.%m
	logging = file
	map to guest = Bad User
	max log size = 1000
	obey pam restrictions = Yes
	pam password change = Yes
	panic action = /usr/share/samba/panic-action %d
	passwd chat = *Enter\snew\s*\spassword:* %n\n *Retype\snew\s*\spassword:* %n\n *password\supdated\ssuccessfully* .
	passwd program = /usr/bin/passwd %u
	server min protocol = SMB2
	server role = standalone server
	unix password sync = Yes
	usershare allow guests = Yes
	fruit:nfs_aces = no
	fruit:delete_empty_adfiles = yes
	fruit:wipe_intentionally_left_blank_rfork = yes
	fruit:zero_file_id = yes
	fruit:posix_rename = yes
	fruit:veto_appledouble = no
	fruit:model = MacSamba
	fruit:metadata = stream
	idmap config * : backend = tdb
	inherit permissions = Yes
	vfs objects = catia fruit streams_xattr


[TimeMachine]
	comment = TimeMachine
	inherit acls = Yes
	path = /media/pi/TimeMachine
	read only = No
	valid users = pi
	fruit:time machine = yes


[NAS]
	comment = NAS
	inherit acls = Yes
	path = /media/pi/NAS
	read only = No
	valid users = pi
pi@raspberrypi:~ $ 

Your output should look similar to the mine just above. ⬆

Then restart the Samba service to reload the configuration changes:

sudo service smbd reload

You can now connect to your Samba shares from your Mac by pressing Command-K in Finder and enter the IP of your Raspberry Pi like this: smb://192.168.0.200/TimeMachine

Authenticate with your user credentials when prompted.


Configuring Avahi

You can make the process of logging in to your TimeMachine and NAS from your Mac a lot easier by configuring Avahi to advertise the Samba shares on your network.

You have to create a new service in /etc/avahi/services/samba.service:

sudo nano /etc/avahi/services/samba.service

Then add the following configuration that I shamelessly stole from here (where a detailed description is available):

<?xml version="1.0" standalone='no'?><!--*-nxml-*-->
<!DOCTYPE service-group SYSTEM "avahi-service.dtd">
<service-group>
  <name replace-wildcards="yes">%h</name>
  <service>
    <type>_smb._tcp</type>
    <port>445</port>
  </service>
  <service>
    <type>_adisk._tcp</type>
    <port>9</port>
    <txt-record>dk0=adVN=TimeMachine,adVF=0x82</txt-record>
    <txt-record>sys=adVF=0x100</txt-record>
  </service>
  <service>
    <type>_device-info._tcp</type>
    <port>9</port>
    <txt-record>model=MacPro7,1@ECOLOR=226,226,224</txt-record>
  </service>
</service-group>

In short, you are declaring 3 services.

The first 2 services configures Avahi to follow Apples Advertising Time Machine Availability Through Bonjour documentation by:
1. Advertising that your Raspberry Pi is running a Samba on port 445.
2. Advertising that the share named “TimeMachine” is available for TimeMachine backups.

The 3’rd service configures Avahi to advertise the Raspberry Pi as a Mac Pro (Rack, 2019), which sets a nice icon in macOS Finder.
You can change this icon to any device name listed in /System/Library/CoreServices/CoreTypes.bundle/Contents/Info.plist. Open the file with Xcode and search for “@ECOLOR” to easily highlight your available options.

Avahi should pick up your changes automatically and your Raspberry Pi should now appear in the sidebar of Finder.

If it doesn’t, you can restart the avahi-daemon service:

sudo service avahi-daemon restart

And there you have it! Your very own Raspberry Pi TimeMachine and NAS server.

NAS Backup (Optional)

Now that your Mac is automatically backed up by TimeMachine, and your Raspberry Pi is backed up automatically using the script from part 2. you might be wondering; how do I backup the data on my NAS?

Well, a simple and reliable method of doing just that is using rsync to periodically sync the contents on your NAS with another drive.


Backup script

First make sure your new backup drive is mounted correctly.

Then create a new file for the rsync backup script with touch and set execution permissions with chmod:

touch ./Documents/nas-backup.sh
chmod +x ./Documents/nas-backup.sh

Edit the file in nano:

sudo nano ./Documents/nas-backup.sh

And paste the following (make sure the variables SOURCE_DIRECTORY and BACKUP_DIRECTORY are correct for you):

#!/bin/bash

SOURCE_DIRECTORY="/media/pi/NAS/"
BACKUP_DIRECTORY="/media/pi/BACKUP/NAS"

# Exit script if Backup Directory does not exist
if [ ! -d "${BACKUP_DIRECTORY}" ]; then
  echo "${BACKUP_DIRECTORY} does not exist"
  exit 1
fi

START_DATETIME=`date +"%Y-%m-%dT%H-%M-%S"`
echo "rsync start: ${START_DATETIME}" >> ./Documents/nas-backup.log
echo "rsync start: ${START_DATETIME}"

# rsync entire NAS to BACKUP 
/usr/bin/rsync -aP --exclude="lost+found" "${SOURCE_DIRECTORY}" "${BACKUP_DIRECTORY}" >> ./Documents/nas-backup.log

END_DATETIME=`date +"%Y-%m-%dT%H-%M-%S"`
echo "rsync finished: ${END_DATETIME}" >> ./Documents/nas-backup.log
echo "rsync finished: ${END_DATETIME}"

Open crontab with the commend:

crontab -e

At the end of the document, type the frequency of script execution in the following manner

0 0 * * * /home/pi/Documents/nas-backup.sh

I recommend running this script at least once a day.
The script only copies the delta between each sync, so after the first sync only new changes are added.

Files deleted from your NAS accidentally or intentionally will not be automatically removed from your backup.

You can follow what the script has been and actively is syncing, by looking in ./Documents/nas-backup.log: tail

tail -F -s20 ./Documents/nas-backup.log

Backup cleanup

Since the rsync script never deletes files in the backup directory automatically, you may at some point want to clean your backup directory of old files (deleted files, temporary rsync files, etc.).

To perform a dry-run, and verify that you are deleting the correct files use this command:

/usr/bin/rsync -aPn --del --exclude="lost+found" /media/pi/NAS/ /media/pi/BACKUP/NAS

To delete all files from your backup directory, that are not in your source directory use this command (please verify with dry-run first):

/usr/bin/rsync -aP --del --exclude="lost+found" /media/pi/NAS/ /media/pi/BACKUP/NAS

Sources

Christophe Knage · 2023-02-24