<?xml version="1.0"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en">
	<id>https://wiki.alpinelinux.org/w/api.php?action=feedcontributions&amp;feedformat=atom&amp;user=Maestro-jiggiE</id>
	<title>Alpine Linux - User contributions [en]</title>
	<link rel="self" type="application/atom+xml" href="https://wiki.alpinelinux.org/w/api.php?action=feedcontributions&amp;feedformat=atom&amp;user=Maestro-jiggiE"/>
	<link rel="alternate" type="text/html" href="https://wiki.alpinelinux.org/wiki/Special:Contributions/Maestro-jiggiE"/>
	<updated>2026-04-25T22:45:52Z</updated>
	<subtitle>User contributions</subtitle>
	<generator>MediaWiki 1.40.0</generator>
	<entry>
		<id>https://wiki.alpinelinux.org/w/index.php?title=Classic_install_or_sys_mode_on_Raspberry_Pi&amp;diff=26654</id>
		<title>Classic install or sys mode on Raspberry Pi</title>
		<link rel="alternate" type="text/html" href="https://wiki.alpinelinux.org/w/index.php?title=Classic_install_or_sys_mode_on_Raspberry_Pi&amp;diff=26654"/>
		<updated>2024-04-18T18:45:58Z</updated>

		<summary type="html">&lt;p&gt;Maestro-jiggiE: can&amp;#039;t mv /boot documents if the directory doesn&amp;#039;t exist. created instructions on how to create it then move them.&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{TOC right}}&lt;br /&gt;
&lt;br /&gt;
A how-to for classic (&amp;quot;sys mode&amp;quot;) installation.&lt;br /&gt;
&lt;br /&gt;
This method works with a desktop PC under Ubuntu and other Linuxes.&lt;br /&gt;
&lt;br /&gt;
= Preparation =&lt;br /&gt;
&lt;br /&gt;
[https://alpinelinux.org/downloads/ Download] the Alpine for Raspberry Pi tarball. Use the [[Raspberry_Pi#Compability_list|compatibility list]] when choosing image/file to download.&lt;br /&gt;
&#039;&#039;&#039;Sha256&#039;&#039;&#039; and &#039;&#039;&#039;GPG&#039;&#039;&#039; links appear next to the link to check the download.&lt;br /&gt;
&lt;br /&gt;
Create an MBR partition table with two partitions on an 8 GB (or larger) class 10 sd-card:&lt;br /&gt;
* First one, a &#039;&#039;&#039;fat16&#039;&#039;&#039; type, of 256MB. You may have to set &amp;lt;code&amp;gt;boot&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;lba&amp;lt;/code&amp;gt; flags&lt;br /&gt;
* The second one, an &#039;&#039;&#039;ext4&#039;&#039;&#039; type, occupying the remaining space on the media&lt;br /&gt;
&lt;br /&gt;
Eject and re-insert your SD card to ensure recognition of all the partitions.&lt;br /&gt;
&lt;br /&gt;
Go into the first partition (&#039;&#039;&#039;fat16&#039;&#039;&#039;).&lt;br /&gt;
&lt;br /&gt;
Untar the archive with {{pkg|tar|arch=}}:&lt;br /&gt;
 tar zxvf ~/Download/alpine-rpi-{{AlpineLatest}}-armhf.tar.gz&lt;br /&gt;
&lt;br /&gt;
If using the UART is required, add a file named &amp;lt;code&amp;gt;usercfg.txt&amp;lt;/code&amp;gt; into the partition containing the following single line:&lt;br /&gt;
&lt;br /&gt;
 enable_uart=1&lt;br /&gt;
&lt;br /&gt;
For headless use, you can add the following parameters to maximize available memory (32 megs is required for the rpi bootloader):&lt;br /&gt;
&lt;br /&gt;
 gpu_mem=32&lt;br /&gt;
&lt;br /&gt;
to enable audio support:&lt;br /&gt;
&lt;br /&gt;
 dtparam=audio=on&lt;br /&gt;
&lt;br /&gt;
Eject the SD card properly. Insert it into the Raspberry Pi. Plug in a usb keyboard as well as the HDMI and network cables. Power on.&lt;br /&gt;
&lt;br /&gt;
When the command prompt displays, log in as root. (no password)&lt;br /&gt;
&lt;br /&gt;
== OSX Preparation: creating a FAT16 partition on microSD ==&lt;br /&gt;
&lt;br /&gt;
To create a FAT16 partition with OSX, use the diskutil program and a USB microSD card reader (I used an older version of this: https://www.bestbuy.com/site/insignia-usb-3-0-memory-card-reader/5787406.p?skuId=5787406).&lt;br /&gt;
&lt;br /&gt;
Put the microSD card in the reader. Connect the reader to a USB port and type &amp;lt;code&amp;gt;ls -1 /Volumes&amp;lt;/code&amp;gt; in a terminal.  Note the name of the microSD volume; for example, VOL1 in the output below:&lt;br /&gt;
  $ ls -1 /Volumes&lt;br /&gt;
  Macintosh HD&lt;br /&gt;
  Preboot&lt;br /&gt;
  VOL1&lt;br /&gt;
  $&lt;br /&gt;
&lt;br /&gt;
Unmount the reader. Disconnect it and re-run &amp;lt;code&amp;gt;ls -1 /Volumes&amp;lt;/code&amp;gt;.  Verify the microSD volume name is no longer listed, then re-insert the USB reader.&lt;br /&gt;
&lt;br /&gt;
Find the mount point of your microSD volume. For example, disk3 in the output below:&lt;br /&gt;
  $ diskutil list VOL1&lt;br /&gt;
  /dev/disk3 (external, physical):&lt;br /&gt;
     #:                       TYPE NAME                    SIZE       IDENTIFIER&lt;br /&gt;
     0:     FDisk_partition_scheme                        *31.4 GB    disk3&lt;br /&gt;
     1:                 DOS_FAT_16 VOL1                    256.0 MB   disk3s1&lt;br /&gt;
     2:                      Linux                         30.0 GB    disk3s2&lt;br /&gt;
     3:                 Linux_Swap                         1.2 GB     disk3s3&lt;br /&gt;
  $&lt;br /&gt;
&lt;br /&gt;
(For help with the diskutil command, type &amp;lt;code&amp;gt;diskutil&amp;lt;/code&amp;gt; to list all command verbs.  For help on a specific verb, add the verb. For example, &amp;lt;code&amp;gt;diskutil partitionDisk&amp;lt;/code&amp;gt;)&lt;br /&gt;
&lt;br /&gt;
Destroy all the existing partitions on the microSD card and create two new ones: &lt;br /&gt;
# a 256MB, FAT16, DOS-compatible partition and &lt;br /&gt;
# a free space gap for the rest of the card&lt;br /&gt;
&lt;br /&gt;
  $ diskutil partitionDisk disk3 MBR   &amp;quot;MS-DOS FAT16&amp;quot; VOL1 256MB    &amp;quot;Free Space&amp;quot; VOL2 R&lt;br /&gt;
  Started partitioning on disk3&lt;br /&gt;
  Unmounting disk&lt;br /&gt;
  Creating the partition map&lt;br /&gt;
  Waiting for partitions to activate&lt;br /&gt;
  Formatting disk3s1 as MS-DOS (FAT16) with name VOL1&lt;br /&gt;
  512 bytes per physical sector&lt;br /&gt;
  /dev/rdisk3s1: 499472 sectors in 62434 FAT16 clusters (4096 bytes/cluster)&lt;br /&gt;
  bps=512 spc=8 res=1 nft=2 rde=512 mid=0xf8 spf=244 spt=32 hds=32 hid=2 drv=0x80 bsec=500000&lt;br /&gt;
  Mounting disk&lt;br /&gt;
  Finished partitioning on disk3&lt;br /&gt;
  /dev/disk3 (external, physical):&lt;br /&gt;
    #:                       TYPE NAME                    SIZE       IDENTIFIER&lt;br /&gt;
    0:     FDisk_partition_scheme                        *31.4 GB    disk3&lt;br /&gt;
    1:                 DOS_FAT_16 VOL1                    256.0 MB   disk3s1&lt;br /&gt;
  $ &lt;br /&gt;
&lt;br /&gt;
Change your current working directory to the new FAT16 partition then continue with the untar instruction in the parent prep section.&lt;br /&gt;
&lt;br /&gt;
  $ cd /Volumes/VOL1/&lt;br /&gt;
&lt;br /&gt;
= Installation =&lt;br /&gt;
&lt;br /&gt;
Execute the following commands. Make sure there is an internet connection available otherwise setting up the apk mirrors will fail.&lt;br /&gt;
&lt;br /&gt;
 setup-alpine &lt;br /&gt;
&lt;br /&gt;
Set the keyboard map, the timezone, how to connect to the network (&#039;&#039;&#039;dhcp&#039;&#039;&#039; is the best method), say &#039;&#039;&#039;none&#039;&#039;&#039; at &amp;lt;code&amp;gt;save config&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;save cache&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
 apk update&lt;br /&gt;
&lt;br /&gt;
If the extra space in the sd card was left empty, a partition must be created now:&lt;br /&gt;
&lt;br /&gt;
 apk add {{pkg|cfdisk|arch=*}} {{pkg|e2fsprogs|arch=*}}  # or the tool of your choice&lt;br /&gt;
 cfdisk /dev/mmcblk0       # create the new partition with the free space&lt;br /&gt;
 mkfs.ext4 /dev/mmcblk0p2  # create the ext4 filesystem in the new partition&lt;br /&gt;
&lt;br /&gt;
Raspberry Pi has no hardware clock, so synchronize with an ntp server:&lt;br /&gt;
&lt;br /&gt;
 apk add {{pkg|chrony|arch=a*}}&lt;br /&gt;
 service chronyd restart&lt;br /&gt;
&lt;br /&gt;
{{warning | 22 June 2021 - There is a bug in Alpine 3.12.x and older that causes setup-disk to fail on ext4 mounts on Raspberry Pi. The work around is marked in the instructions below. &amp;lt;br /&amp;gt;{{Issue|12353}} }}&lt;br /&gt;
&lt;br /&gt;
 mount /dev/mmcblk0p2 /mnt             # The second partition, in ext4 format, where Alpine Linux is installing in sys mode&lt;br /&gt;
 export FORCE_BOOTFS=1                 # work around for issue 12353&lt;br /&gt;
 setup-disk -m sys /mnt&lt;br /&gt;
 mount -o remount,rw /media/mmcblk0p1  # An update in the first partition is required for the next reboot.&lt;br /&gt;
&lt;br /&gt;
You may get some warning about syslinux when you run setup-disk.  You can safely ignore this.&lt;br /&gt;
&lt;br /&gt;
== Update boot partition (keep alpine-rpi* image layout) ==&lt;br /&gt;
Clean up the boot folder in the first partition to drop unused files:&lt;br /&gt;
&lt;br /&gt;
 rm -f /media/mmcblk0p1/boot/*  &lt;br /&gt;
 cd /mnt       # We are in the second partition &lt;br /&gt;
 rm boot/boot  # Drop the unused symbolic link&lt;br /&gt;
&lt;br /&gt;
Move the image and initramfs for Alpine Linux into the right place:&lt;br /&gt;
&lt;br /&gt;
 mv boot/* /media/mmcblk0p1/boot/  &lt;br /&gt;
 rm -Rf boot&lt;br /&gt;
 mkdir media/mmcblk0p1   # It&#039;s the mount point for the first partition on the next reboot&lt;br /&gt;
&lt;br /&gt;
Don&#039;t worry about the error when you execute the following:&lt;br /&gt;
&lt;br /&gt;
 ln -s media/mmcblk0p1/boot boot&lt;br /&gt;
&lt;br /&gt;
== Update boot partition (keep system partition/setup-alpine layout) ==&lt;br /&gt;
It turns out that the system partition created by setup-alpine has a working boot layout. To keep this, perform the following steps &#039;&#039;&#039;instead&#039;&#039;&#039; of the steps in the previous chapter.&lt;br /&gt;
&lt;br /&gt;
Clean up the boot / first partition to drop unused files:&lt;br /&gt;
&lt;br /&gt;
 rm -f /media/mmcblk0p1/*&lt;br /&gt;
 cd /mnt       # We are in the second partition &lt;br /&gt;
 rm boot/boot  # Drop the unused symbolink link&lt;br /&gt;
&lt;br /&gt;
Move the boot folder created by setup-alpine into the right place:&lt;br /&gt;
&lt;br /&gt;
cd /media/mmcblk0p1&lt;br /&gt;
mkdir boot&lt;br /&gt;
cd ..&lt;br /&gt;
cd boot &lt;br /&gt;
mv boot/* /media/mmcblk0p1/  &lt;br /&gt;
cd ..&lt;br /&gt;
rm -Rf boot&lt;br /&gt;
mkdir media/mmcblk0p1   **# It&#039;s the mount point for the first partition on the next reboot**&lt;br /&gt;
&lt;br /&gt;
Don&#039;t worry about the error when you execute the following:&lt;br /&gt;
&lt;br /&gt;
 ln -s media/mmcblk0p1 boot&lt;br /&gt;
&lt;br /&gt;
== End of update boot partition - continue here in both cases ==&lt;br /&gt;
&lt;br /&gt;
Update &amp;lt;code&amp;gt;/etc/fstab&amp;lt;/code&amp;gt;:&lt;br /&gt;
&lt;br /&gt;
 echo &amp;quot;/dev/mmcblk0p1 /media/mmcblk0p1 vfat defaults 0 0&amp;quot; &amp;gt;&amp;gt; etc/fstab&lt;br /&gt;
 sed -i &#039;/cdrom/d&#039; etc/fstab   # Of course, you don&#039;t have any cdrom or floppy on the Raspberry Pi&lt;br /&gt;
 sed -i &#039;/floppy/d&#039; etc/fstab&lt;br /&gt;
 cd /media/mmcblk0p1&lt;br /&gt;
&lt;br /&gt;
If you want to activate the edge repository:&lt;br /&gt;
 sed -i &#039;/edge/s/^#//&#039; etc/apk/repositories   # But enable the repository for community if you want vim, mc, php, apache, nginx, etc.&lt;br /&gt;
&lt;br /&gt;
For the next boot, indicate that the root filesystem is on the second partition.  If the cmdline.txt file&lt;br /&gt;
contains a line that starts with &amp;lt;code&amp;gt;/root&amp;lt;/code&amp;gt;, then use sed:&lt;br /&gt;
&lt;br /&gt;
 sed -i &#039;s/$/ root=\/dev\/mmcblk0p2 /&#039; /media/mmcblk0p1/cmdline.txt  &lt;br /&gt;
 reboot&lt;br /&gt;
&lt;br /&gt;
That works on &#039;&#039;&#039;Raspberry Pi 3B&#039;&#039;&#039; and &#039;&#039;&#039;1B&#039;&#039;&#039;, but if you have the &#039;&#039;&#039;1B&#039;&#039;&#039; version, you&#039;ll need to be very, very patient (several tens of minutes).&lt;br /&gt;
&lt;br /&gt;
If a hard disk is connected via &#039;&#039;&#039;usb&#039;&#039;&#039;, you can replace the &amp;lt;code&amp;gt;/dev/mmcblk0p2&amp;lt;/code&amp;gt; above with &amp;lt;code&amp;gt;/dev/sda1&amp;lt;/code&amp;gt;, for example.&lt;br /&gt;
&lt;br /&gt;
If you don&#039;t want to use &#039;&#039;&#039;sed&#039;&#039;&#039;, you can use the nano editor instead, after executing the following command:&lt;br /&gt;
&lt;br /&gt;
 apk add {{pkg|nano|arch=a*}}&lt;br /&gt;
&lt;br /&gt;
= Post-installation =&lt;br /&gt;
&lt;br /&gt;
See the [[Raspberry_Pi#Post_Installation]] for common post-installation steps.&lt;br /&gt;
&lt;br /&gt;
Additionally, the following may be of value on a sys mode installation:&lt;br /&gt;
&lt;br /&gt;
If you want a cool editor ({{Pkg|vim}}), a file manager ({{Pkg|mc}}), and to determine which tasks are running and which services are starting on boot ({{Pkg|htop}}), install the packages with this command:&lt;br /&gt;
&lt;br /&gt;
 apk add {{pkg|vim|arch=a*}} {{pkg|mc|arch=a*}} {{pkg|htop|arch=a*}}&lt;br /&gt;
&lt;br /&gt;
The &#039;&#039;&#039;RPI 3B&#039;&#039;&#039; has wifi on board. To start the service for the encrypted key using wpa2 protocol:&lt;br /&gt;
&lt;br /&gt;
 apk add {{pkg|wpa_supplicant|arch=a*}}&lt;br /&gt;
 rc-update add wpa_supplicant boot&lt;br /&gt;
 service wpa_supplicant start&lt;br /&gt;
 setup-interfaces &lt;br /&gt;
Replace the IP address by dhcp for all the interfaces if necessary;  select the SSID network for wifi, add the password.&lt;br /&gt;
 ip addr    # to find the IP address for all interfaces&lt;br /&gt;
&lt;br /&gt;
If you want to connect to your RPI via &amp;lt;code&amp;gt;ssh&amp;lt;/code&amp;gt;, an additional user (&#039;&#039;foo&#039;&#039;) and the {{Pkg|sudo|arch=*}} package are required because it&#039;s forbidden to connect as root:&lt;br /&gt;
&lt;br /&gt;
 apk add sudo&lt;br /&gt;
 adduser foo&lt;br /&gt;
 adduser foo wheel&lt;br /&gt;
 visudo &lt;br /&gt;
&lt;br /&gt;
Uncomment line #82 with &amp;lt;code&amp;gt;wheel ALL=(ALL) ALL&amp;lt;/code&amp;gt;. If {{Pkg|vim}} is installed, save the changes by typing &#039;&#039;&#039;Esc :x&#039;&#039;&#039;&lt;br /&gt;
&lt;br /&gt;
= Troubleshooting =&lt;br /&gt;
&lt;br /&gt;
Following the preparation instructions for setting up the boot partition as outlined, using the armv7 image (3.10.3), my rpi2 would not even boot, and I was trapped at the dreaded rainbow screen, with the green led blinking a few times in a row, repeatedly.&lt;br /&gt;
&lt;br /&gt;
The rpi2 I had appears to require &#039;&#039;&#039;fat32&#039;&#039;&#039; for the boot partition, NOT &#039;&#039;&#039;fat16&#039;&#039;&#039; as suggested in the instructions.  Use linux fdisk to set the boot partition type as &amp;quot;c&amp;quot; (for fat32/lba) amd set the &#039;&#039;&#039;lba&#039;&#039;&#039; and &#039;&#039;&#039;boot&#039;&#039;&#039; flags for the partition as suggested.  Create the boot partition filesystem as fat32 with:&lt;br /&gt;
&lt;br /&gt;
 mkdosfs -F 32 /dev/sdX1 &lt;br /&gt;
&lt;br /&gt;
Mount and unpacke the tarball to that, and everything should work as documented after the prep instructions.&lt;br /&gt;
&lt;br /&gt;
After booting, you may find less system memory available than you expect.  Currently the Pi requires a minimum of 32 megs of memory for the gpu, to boot unless you have the cut down boot loader installed, in which case you can use 16.  However, you may find more gpu memory is still being used, even if you configure it for less, if you enable audio or camera support.  To find out how your system is actually split:&lt;br /&gt;
&lt;br /&gt;
{{Note|Directions below are for Alpine versions older than 3.18... Help wanted: Is there something equivalent in current versions?}} &lt;br /&gt;
 apk add {{pkg|raspberrypi|arch=*|branch=v3.17}}&lt;br /&gt;
 /opt/vc/bin/vcgencmd get_mem gpu&lt;br /&gt;
 /opt/vc/bin/vcgencmd get_mem arm&lt;br /&gt;
&lt;br /&gt;
= See also =&lt;br /&gt;
&lt;br /&gt;
* [[Raspberry Pi]]&lt;br /&gt;
* [[Raspberry Pi 3 - Setting Up Bluetooth]]&lt;br /&gt;
* [[Raspberry Pi 3 - Configuring it as wireless access point -AP Mode]]&lt;br /&gt;
* [[Linux Router with VPN on a Raspberry Pi]]&lt;br /&gt;
&lt;br /&gt;
[[Category:Installation]]&lt;br /&gt;
[[category: Raspberry]]&lt;/div&gt;</summary>
		<author><name>Maestro-jiggiE</name></author>
	</entry>
	<entry>
		<id>https://wiki.alpinelinux.org/w/index.php?title=Raspberry_Pi_4_-_Persistent_system_acting_as_a_NAS_and_Time_Machine&amp;diff=26653</id>
		<title>Raspberry Pi 4 - Persistent system acting as a NAS and Time Machine</title>
		<link rel="alternate" type="text/html" href="https://wiki.alpinelinux.org/w/index.php?title=Raspberry_Pi_4_-_Persistent_system_acting_as_a_NAS_and_Time_Machine&amp;diff=26653"/>
		<updated>2024-04-18T03:14:31Z</updated>

		<summary type="html">&lt;p&gt;Maestro-jiggiE: just one &amp;quot;cd ..&amp;quot; is needed in order to run &amp;quot;diskutil eject /dev/disk2&amp;quot;&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Tinker, Tailor, Raspberry Pi ==&lt;br /&gt;
&lt;br /&gt;
I went ahead and got myself a Raspberry Pi 4B with 4GB RAM, which I intend to use as a job scheduling server, only to find out that the suggested OS, Raspberry Pi OS, is 32-bit. Fortunately, the Linux distro Alpine, which I’ve grown very fond of lately, is available for Raspberry Pi as aarch64, meaning it’s both 64-bit kernel and userland. Unfortunately the distro is currently, as of version 3.12, not set up for persistent storage and is more of a live playground. Gathering bits and pieces from various guides online, this can however be remedied with some tinkering. On this page you will find how to set up a persistent 64-bit OS on the Raspberry Pi, share a USB attached disk, while also adding some interesting software.&lt;br /&gt;
&lt;br /&gt;
If you go ahead and buy the Pi 4, note that it has micro-HDMI ports. I thought they were mini, for which I already had cabling, but alas, another adapter had to be purchased. Also, when attaching a USB disk it is better if it is externally powered. The Pi can however power newer external SSD drives that have low power consumption. I tried with a magnetic disk based one powered over USB first, but it behaved somewhat strangely. With that said, let’s go ahead and look at how to get yourself a shiny tiny new server.&lt;br /&gt;
&lt;br /&gt;
=== Tinkering for Persistence ===&lt;br /&gt;
&lt;br /&gt;
After downloading the v3.12 tarball from Alpine on my macOS, it’s time to set up the SDHC card for the Pi. I actually borrowed my old hand-me-down MacBook Air that I gave to my daughter a few years ago, since it has a built-in card reader, as opposed to my newer Air. The Pi boots off a FAT32 partition, but we want the system to reside in an ext4 partition later, so we will start by reserving a small portion of the card for the boot partition. This is done using Terminal in macOS with the following commands.&lt;br /&gt;
&lt;br /&gt;
 diskutil list&lt;br /&gt;
 diskutil partitionDisk /dev/disk2 MBR &amp;quot;FAT32&amp;quot; ALP 256MB &amp;quot;Free Space&amp;quot; SYS R&lt;br /&gt;
 sudo fdisk -e /dev/disk2&lt;br /&gt;
 &amp;gt; f 1&lt;br /&gt;
 &amp;gt; w&lt;br /&gt;
 &amp;gt; exit&lt;br /&gt;
&lt;br /&gt;
The tarball should have decompressed once it hit your download folder. If not, use the option “xvzf” for tar.&lt;br /&gt;
&lt;br /&gt;
 cd /Volumes/ALP&lt;br /&gt;
 tar xvf ~/Downloads/alpine-rpi-3.12.0-aarch64.tar&lt;br /&gt;
 nano usercfg.txt&lt;br /&gt;
&lt;br /&gt;
The newly created file usercfg.txt should contain the following:&lt;br /&gt;
&lt;br /&gt;
 enable_uart=1&lt;br /&gt;
 gpu_mem=32&lt;br /&gt;
 disable_overscan=1&lt;br /&gt;
&lt;br /&gt;
The least amount of memory for headless is 32MB. The UART thing is beyond me, but seems to be a recommended setting. Removing overscan gives you more screen estate. If you intend to use this as a desktop computer rather than a headless server you probably want to allot more memory to the GPU and enable sound. Full specification for options can be found on the official Raspberry Pi homepage.&lt;br /&gt;
&lt;br /&gt;
After that we just need to make sure the card is not busy, so we change to a safe directory and thereafter eject the card (making sure that any pending writes are finalized).&lt;br /&gt;
&lt;br /&gt;
 cd ..&lt;br /&gt;
 diskutil eject /dev/disk2&lt;br /&gt;
&lt;br /&gt;
Put the SDHC card in the Pi and boot. Login with “root” as username and no password. This presumes that you have connected everything else, such as a keyboard and monitor.&lt;br /&gt;
&lt;br /&gt;
 setup-alpine&lt;br /&gt;
&lt;br /&gt;
During setup, select your keymap, hostname, etc, as desired. However, when asked where to store configs, type “none”, and the same for the apk cache directory. If you want to follow this guide to the point, you should also select “chrony” as the NTP client. The most important part here though is to get your network up and running. A full description of the setup programs can be found on the Alpine homepage.&lt;br /&gt;
&lt;br /&gt;
 apk update&lt;br /&gt;
 apk upgrade&lt;br /&gt;
 apk add cfdisk&lt;br /&gt;
 cfdisk /dev/mmcblk0&lt;br /&gt;
&lt;br /&gt;
In cfdisk, select “Free space” and the option “New”. It will suggest using the entire available space, so just press enter, then select the option “primary”, followed by “Write”. Type “yes” to write the partition table to disk, then select “Quit”.&lt;br /&gt;
&lt;br /&gt;
 apk add e2fsprogs&lt;br /&gt;
 mkfs.ext4 /dev/mmcblk0p2&lt;br /&gt;
 mount /dev/mmcblk0p2 /mnt&lt;br /&gt;
 setup-disk -m sys /mnt&lt;br /&gt;
 mount -o remount,rw /media/mmcblk0p1&lt;br /&gt;
&lt;br /&gt;
Ignore the warnings about extlinux. This and the following trick was found in the Alpine Wiki, but in some confusing order. &lt;br /&gt;
&lt;br /&gt;
 rm -f /media/mmcblk0p1/boot/*&lt;br /&gt;
 cd /mnt&lt;br /&gt;
 rm boot/boot&lt;br /&gt;
 mv boot/* /media/mmcblk0p1/boot/&lt;br /&gt;
 rm -Rf boot&lt;br /&gt;
 mkdir media/mmcblk0p1&lt;br /&gt;
 ln -s media/mmcblk0p1/boot boot&lt;br /&gt;
&lt;br /&gt;
Now the mountpoints need fixing, so run:&lt;br /&gt;
&lt;br /&gt;
 apk add nano&lt;br /&gt;
 nano etc/fstab&lt;br /&gt;
&lt;br /&gt;
If you prefer some other editor (since people tend to become religious about these things) then feel free to use whatever makes you feel better than nano. Add the following line:&lt;br /&gt;
&lt;br /&gt;
 /dev/mmcblk0p1   /media/mmcblk0p1   vfat   defaults   0 0&lt;br /&gt;
&lt;br /&gt;
Now the kernel needs to know where the root filesystem is.&lt;br /&gt;
&lt;br /&gt;
 nano /media/mmcblk0p1/cmdline.txt&lt;br /&gt;
&lt;br /&gt;
Append the following at the end of the one and only line in the file:&lt;br /&gt;
&lt;br /&gt;
 root=/dev/mmcblk0p2&lt;br /&gt;
&lt;br /&gt;
After exiting nano, it’s safe to reboot, so:&lt;br /&gt;
&lt;br /&gt;
 reboot&lt;br /&gt;
&lt;br /&gt;
After rebooting, login using “root” as username, and the password you selected during setup-alpine earlier. Now you have a persistent system and everything that is done will stick, as opposed to how the original distro was configured.&lt;br /&gt;
&lt;br /&gt;
=== Tailoring for Remote Access ===&lt;br /&gt;
&lt;br /&gt;
OpenSSH should already be installed, but it will not allow remote root login. We will initially relax this constraint. Last in this article is a section on hardening where we again disallow root login. If you intend to have this box accessible from the Internet I strongly advice on hardening the Pi.&lt;br /&gt;
&lt;br /&gt;
 nano /etc/ssh/sshd_config&lt;br /&gt;
&lt;br /&gt;
Uncomment and change the line (about 30 lines down) with PermitRootLogin to:&lt;br /&gt;
&lt;br /&gt;
 PermitRootLogin yes&lt;br /&gt;
&lt;br /&gt;
Then restart the service:&lt;br /&gt;
&lt;br /&gt;
 rc-service sshd restart&lt;br /&gt;
&lt;br /&gt;
Now you should be able to ssh to your Pi. The following steps are easier when you can cut and paste things into a terminal window. Feeling lucky? Then now is a good time to disconnect your keyboard and monitor.&lt;br /&gt;
&lt;br /&gt;
=== Keeping the Time ===&lt;br /&gt;
&lt;br /&gt;
If you selected chrony as your NTP client it may take a long time for it to actually correct the clock. Since the Pi does not have a hardware clock, it’s necessary to have time corrected at boot time, so we will change the configuration such that the clock is set if it is more than 60 seconds off during the first 10 lookups. &lt;br /&gt;
&lt;br /&gt;
 nano /etc/chrony/chrony.conf&lt;br /&gt;
&lt;br /&gt;
Add the following line at the bottom of the file.&lt;br /&gt;
&lt;br /&gt;
 makestep 60 10&lt;br /&gt;
&lt;br /&gt;
Check the date, restart the service, and check the (now hopefully corrected) date again.&lt;br /&gt;
&lt;br /&gt;
 date&lt;br /&gt;
 rc-service chronyd restart&lt;br /&gt;
 date&lt;br /&gt;
&lt;br /&gt;
Having the correct time is a good thing, particularly when building a job scheduling server.&lt;br /&gt;
&lt;br /&gt;
=== Silencing the Fan ===&lt;br /&gt;
&lt;br /&gt;
Together with the Pi I also bought a fan, the Pimoroni Fan Shim. According to reviews it is one of the better ways to cool your Pi, but it’s still too soon for me to have an opinion. Unless controller software is installed, it will always run at full speed. It’s not noisy, but still noticeable sitting a metric meter from the Pi. Again, some tinkering will be needed since the controller software needs some prerequisites installed. We lost nano between reboots, so we will go ahead and add it again.&lt;br /&gt;
&lt;br /&gt;
 apk update&lt;br /&gt;
 apk upgrade&lt;br /&gt;
 apk add nano&lt;br /&gt;
&lt;br /&gt;
Other software we need is in the “community” repositories of Alpine. In order to active that repository we need to edit a file:&lt;br /&gt;
&lt;br /&gt;
 nano /etc/apk/repositories&lt;br /&gt;
&lt;br /&gt;
Uncomment the second line (ending in v3.12/community), exit, then install the necessary packages.&lt;br /&gt;
&lt;br /&gt;
 apk update&lt;br /&gt;
 apk add git bash python3 python3-dev py3-pip py3-wheel build-base&lt;br /&gt;
&lt;br /&gt;
After those prerequisites are in place, install the fan shim software using:&lt;br /&gt;
&lt;br /&gt;
 git clone https://github.com/pimoroni/fanshim-python&lt;br /&gt;
 cd fanshim-python&lt;br /&gt;
 ./install.sh&lt;br /&gt;
 apk add py3-psutil&lt;br /&gt;
 cd examples&lt;br /&gt;
 ./install-service.sh&lt;br /&gt;
&lt;br /&gt;
The last script will fail with “systemctl: command not found”, since Alpine uses OpenRC as its init system, and not systemd which this script presumes. We will instead write our own startup script:&lt;br /&gt;
&lt;br /&gt;
 nano /etc/init.d/fanshim&lt;br /&gt;
&lt;br /&gt;
This new file should have the following contents:&lt;br /&gt;
&lt;br /&gt;
 #!/sbin/openrc-run&lt;br /&gt;
 name=&amp;quot;fanshim&amp;quot;&lt;br /&gt;
 command=&amp;quot;/usr/bin/python3 /root/fanshim-python/examples/automatic.py&amp;quot;&lt;br /&gt;
 command_args=&amp;quot;--on-threshold 65 --off-threshold 55 --delay 2&amp;quot;&lt;br /&gt;
 pidfile=&amp;quot;/var/run/$SVCNAME.pid&amp;quot;&lt;br /&gt;
 command_background=&amp;quot;yes&amp;quot;&lt;br /&gt;
&lt;br /&gt;
There are a lot of interesting options for fanshim that you can explore, like tuning it’s RGB led. Now we want this to run at boot time, so add it the the default runlevel, then start it.&lt;br /&gt;
&lt;br /&gt;
 rc-update add fanshim default&lt;br /&gt;
 rc-service fanshim start&lt;br /&gt;
&lt;br /&gt;
Enjoy the silence!&lt;br /&gt;
&lt;br /&gt;
=== Adding and Sharing a Disk ===&lt;br /&gt;
&lt;br /&gt;
Some of files we will be transferring are going to be quite large. It would also be neat to be able to access files easily from the Finder in macOS, so I am adding a USB3 connected hard disk with 4TB storage. What follows will be very similar to setting up a NAS, and in fact, the way I fell in love with Alpine was by building my own NAS from scratch (with the minor differences being more disks and using zfs). &lt;br /&gt;
&lt;br /&gt;
First we need to change the filesystem. The disk comes formatted as FAT32, which is very poorly suited for a networked disk. Samba, which is what we will be using for sharing, more or less requires a filesystem that supports extended attributes. After plugging in the drive, we will therefore repartition the drive and format it to ext4. &lt;br /&gt;
&lt;br /&gt;
 cfdisk /dev/sda&lt;br /&gt;
&lt;br /&gt;
Using cfdisk, delete any existing partitions and create one new partition. It should become “Linux filesystem” by default. Don’t forget to “Write” before “Quit”. Then format it:&lt;br /&gt;
&lt;br /&gt;
 mkfs.ext4 /dev/sda1&lt;br /&gt;
&lt;br /&gt;
Now we need to add autofs to get automatic mounting. This package is in edge/testing though, so we need to enable that branch and repository, but still have main and community take preference. This can be done by labelling a repository.&lt;br /&gt;
&lt;br /&gt;
 nano /etc/apk/repositories&lt;br /&gt;
&lt;br /&gt;
Change the line with the testing repository (last line in my file) to the following. Note that yours will have some server.from.setup/path depending on what you selected in setup-alpine. You only uncomment and add the @testing label in other words.&lt;br /&gt;
&lt;br /&gt;
 @testing http://&amp;lt;server.from.setup/path&amp;gt;/edge/testing&lt;br /&gt;
&lt;br /&gt;
Now autofs can be installed from the labelled repo.&lt;br /&gt;
&lt;br /&gt;
 apk add autofs@testing&lt;br /&gt;
&lt;br /&gt;
Note that dependencies are still pulled from main/community to the extent it is possible. In order to configure autofs, first:&lt;br /&gt;
&lt;br /&gt;
 nano /etc/autofs/auto.master&lt;br /&gt;
&lt;br /&gt;
Add the following line after the uncommented line starting with /misc. It will also disconnect the hard disk after 5 minutes to save energy:&lt;br /&gt;
&lt;br /&gt;
 /-   /etc/autofs/auto.hdd   --timeout=300&lt;br /&gt;
&lt;br /&gt;
Then create this new config file:&lt;br /&gt;
&lt;br /&gt;
 nano /etc/autofs/auto.hdd&lt;br /&gt;
&lt;br /&gt;
Add the the following line to the empty file.&lt;br /&gt;
&lt;br /&gt;
 /hdd   -fstype=ext4   :/dev/sda1&lt;br /&gt;
&lt;br /&gt;
Now, the user pi needs to be created.&lt;br /&gt;
&lt;br /&gt;
 adduser pi&lt;br /&gt;
 smbpasswd -a pi&lt;br /&gt;
&lt;br /&gt;
Select desirable passwords for the pi user. The latter one will later be stored in the macOS keychain and therefore easy to forget, so make note of it somewhere. &lt;br /&gt;
&lt;br /&gt;
Add autofs to startup and start it now. Change the ownership of /hdd to pi.&lt;br /&gt;
&lt;br /&gt;
 rc-update add autofs default&lt;br /&gt;
 rc-service autofs start&lt;br /&gt;
 chown -R pi.pi /hdd&lt;br /&gt;
&lt;br /&gt;
With that in place (disk can be accessed through /hdd) it is time to set up the sharing. For this we will use samba and avahi for network discovery.&lt;br /&gt;
&lt;br /&gt;
 apk add samba avahi dbus&lt;br /&gt;
 nano /etc/samba/smb.cfg&lt;br /&gt;
&lt;br /&gt;
Now, this is what my entire smb.cfg file looks like, with all the tweaks to get stuff running well from macOS.&lt;br /&gt;
&lt;br /&gt;
 [global]&lt;br /&gt;
  create mask = 0664&lt;br /&gt;
  directory mask = 0775&lt;br /&gt;
  veto files = /.DS_Store/lost+found/&lt;br /&gt;
  delete veto files = true&lt;br /&gt;
  nt acl support = no&lt;br /&gt;
  inherit acls = yes&lt;br /&gt;
  ea support = yes&lt;br /&gt;
  security = user&lt;br /&gt;
  passdb backend = tdbsam&lt;br /&gt;
  map to guest = Bad User&lt;br /&gt;
  vfs objects = catia fruit streams_xattr recycle&lt;br /&gt;
  acl_xattr:ignore system acls = yes&lt;br /&gt;
  recycle:repository = .recycle&lt;br /&gt;
  recycle:keeptree = yes&lt;br /&gt;
  recycle:versions = yes&lt;br /&gt;
  fruit:aapl = yes&lt;br /&gt;
  fruit:metadata = stream&lt;br /&gt;
  fruit:model = MacSamba&lt;br /&gt;
  fruit:veto_appledouble = yes&lt;br /&gt;
  fruit:posix_rename = yes &lt;br /&gt;
  fruit:zero_file_id = yes&lt;br /&gt;
  fruit:wipe_intentionally_left_blank_rfork = yes &lt;br /&gt;
  fruit:delete_empty_adfiles = yes &lt;br /&gt;
  server max protocol = SMB3&lt;br /&gt;
  server min protocol = SMB2&lt;br /&gt;
  workgroup = WORKGROUP    &lt;br /&gt;
  server string = NAS      &lt;br /&gt;
  server role = standalone server&lt;br /&gt;
  dns proxy = no&lt;br /&gt;
 [Harddisk]&lt;br /&gt;
  comment = Raspberry Pi Removable Harddisk                     &lt;br /&gt;
  path = /hdd    &lt;br /&gt;
  browseable = yes          &lt;br /&gt;
  writable = yes            &lt;br /&gt;
  spotlight = yes           &lt;br /&gt;
  valid users = pi       &lt;br /&gt;
  fruit:resource = xattr &lt;br /&gt;
  fruit:time machine = yes&lt;br /&gt;
  fruit:advertise_fullsync = true&lt;br /&gt;
&lt;br /&gt;
Those last two lines can be removed if you are not interested in using the disk as a Time Machine backup for your Apple devices. I will likely not use it, but since this is how I configured my NAS and it was a hassle to figure out how to get it working I thought I’d leave it here for reference. Doesn’t hurt to keep it there in any way.&lt;br /&gt;
&lt;br /&gt;
Let us also configure the avahi-daemon, by creating a config file for the samba service. Avahi will announce the server using Bonjour, making them easily recognizable from macOS (where they automagically show up in the Finder). &lt;br /&gt;
&lt;br /&gt;
 nano /etc/avahi/services/samba.service&lt;br /&gt;
&lt;br /&gt;
This new file should have the following contents:&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;?xml version=&amp;quot;1.0&amp;quot; standalone=&#039;no&#039;?&amp;gt;&lt;br /&gt;
 &amp;lt;!DOCTYPE service-group SYSTEM &amp;quot;avahi-service.dtd&amp;quot;&amp;gt;&lt;br /&gt;
 &amp;lt;service-group&amp;gt;&lt;br /&gt;
 &amp;lt;name replace-wildcards=&amp;quot;yes&amp;quot;&amp;gt;%h&amp;lt;/name&amp;gt;&lt;br /&gt;
 &amp;lt;service&amp;gt;&lt;br /&gt;
 &amp;lt;type&amp;gt;_smb._tcp&amp;lt;/type&amp;gt;&lt;br /&gt;
 &amp;lt;port&amp;gt;445&amp;lt;/port&amp;gt;&lt;br /&gt;
 &amp;lt;/service&amp;gt;&lt;br /&gt;
 &amp;lt;service&amp;gt;&lt;br /&gt;
 &amp;lt;type&amp;gt;_device-info._tcp&amp;lt;/type&amp;gt;&lt;br /&gt;
 &amp;lt;port&amp;gt;0&amp;lt;/port&amp;gt;&lt;br /&gt;
 &amp;lt;txt-record&amp;gt;model=RackMac&amp;lt;/txt-record&amp;gt;&lt;br /&gt;
 &amp;lt;/service&amp;gt;&lt;br /&gt;
 &amp;lt;service&amp;gt;&lt;br /&gt;
 &amp;lt;type&amp;gt;_adisk._tcp&amp;lt;/type&amp;gt;&lt;br /&gt;
 &amp;lt;txt-record&amp;gt;sys=waMa=0,adVF=0x100&amp;lt;/txt-record&amp;gt;&lt;br /&gt;
 &amp;lt;txt-record&amp;gt;dk0=adVN=HDD,adVF=0x82&amp;lt;/txt-record&amp;gt;&lt;br /&gt;
 &amp;lt;/service&amp;gt;&lt;br /&gt;
 &amp;lt;/service-group&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Not that the txt-record containing adVN=HDD can be removed if you are not interested in using the disk as a Time Machine backup. Still, leaving it won’t hurt.&lt;br /&gt;
&lt;br /&gt;
Finally, it’s time to add samba and avahi to the startup and start the services.&lt;br /&gt;
&lt;br /&gt;
 rc-update add samba default&lt;br /&gt;
 rc-update add avahi-daemon default&lt;br /&gt;
 rc-service samba start&lt;br /&gt;
 rc-service avahi-daemon start&lt;br /&gt;
&lt;br /&gt;
The disk should now be visible from macOS. Remember to click “Connect as…” and enter “pi” as the username and your selected smbpasswd from earlier. Check the box “Remember this password in my keychain” for quicker access next time. Sometimes, due to a bug in Catalina, you may get “The original item cannot be found” when accessing the remote disk. If that happens, force quit Finder, and you should be good to go again. If anyone knows of any other fix to this issue, let me know!&lt;br /&gt;
&lt;br /&gt;
=== Automation ===&lt;br /&gt;
&lt;br /&gt;
Now, this server will be used as a job server. Some of the jobs running will need the psql command from PostgreSQL and some others will be R jobs. Let’s install both, or whatever you need to satisfy your desires. You can skip this step for now if you are undecided about what to run or just need basic services like the built-in shell scripting.&lt;br /&gt;
&lt;br /&gt;
 apk add R postgresql&lt;br /&gt;
&lt;br /&gt;
In order to automate these jobs, we will be using Cronicle. It depends on node.js so we need to install the prerequisites. It’s run script is fetched using curl, so it will also need to be installed.&lt;br /&gt;
&lt;br /&gt;
 apk add nodejs npm curl&lt;br /&gt;
&lt;br /&gt;
The installation is done as follows (it is a oneliner even if it looks broken here).&lt;br /&gt;
&lt;br /&gt;
 curl -s https://raw.githubusercontent.com/jhuckaby/Cronicle/master/bin/install.js | node&lt;br /&gt;
&lt;br /&gt;
I want to use standard ports, so I need to change the config slightly.&lt;br /&gt;
&lt;br /&gt;
 nano /opt/cronicle/conf/config.json&lt;br /&gt;
&lt;br /&gt;
Change base_app_url from port 3012 to 80. Much further down, change http_port from 3012 to 80, and https_port from 3013 to 443. If you want mails to be sent, change smtp_hostname in the beginning of the file to the mail relay you are using. After that an initialization script needs to be run.&lt;br /&gt;
&lt;br /&gt;
 /opt/cronicle/bin/control.sh setup&lt;br /&gt;
&lt;br /&gt;
Now we just need to get it running at boot time. This is, however, a service that we do not want to “kill” using a PID, so we are going to enable local scripts that start and stop the service in a controlled manner instead.&lt;br /&gt;
&lt;br /&gt;
 rc-update add local default&lt;br /&gt;
 nano /etc/local.d/cronicle.start&lt;br /&gt;
&lt;br /&gt;
This new file should have the following line in it:&lt;br /&gt;
&lt;br /&gt;
 /opt/cronicle/bin/control.sh start&lt;br /&gt;
&lt;br /&gt;
Now we need to create a stop file as well:&lt;br /&gt;
&lt;br /&gt;
 nano /etc/local.d/cronicle.stop&lt;br /&gt;
&lt;br /&gt;
This file should have the contents:&lt;br /&gt;
&lt;br /&gt;
 /opt/cronicle/bin/control.sh stop&lt;br /&gt;
&lt;br /&gt;
In order for the local script daemon to run these, they need to be executable.&lt;br /&gt;
&lt;br /&gt;
 chmod +x /etc/local.d/cronicle.*&lt;br /&gt;
&lt;br /&gt;
With that, let’s secure things.&lt;br /&gt;
&lt;br /&gt;
=== Hardening ===&lt;br /&gt;
&lt;br /&gt;
Now that most configuring is done, it’s time to harden the Pi. First we will install a firewall with some basic login protection using the builtin ‘limit’ in iptables. Assuming you are in the 192.168.1.0/24 range, which was set during setup-alpine, the following should be run. Only clients on the local network are allowed access to shared folders.&lt;br /&gt;
&lt;br /&gt;
 apk add ufw@testing&lt;br /&gt;
 rc-update add ufw default&lt;br /&gt;
 ufw allow 22&lt;br /&gt;
 ufw limit 22/tcp&lt;br /&gt;
 ufw allow 80&lt;br /&gt;
 ufw allow 443&lt;br /&gt;
 ufw allow from 192.168.1.0/24 to any app CIFS&lt;br /&gt;
 ufw allow Bonjour&lt;br /&gt;
&lt;br /&gt;
With the rules in place, it’s time to disallow root login over ssh, and make sure that only fresh protocols are used.&lt;br /&gt;
&lt;br /&gt;
 nano /etc/ssh/sshd_config&lt;br /&gt;
&lt;br /&gt;
Change the line that previously said yes to no, and add the other lines at the bottom of the file (borrowed from this security site):&lt;br /&gt;
&lt;br /&gt;
 PermitRootLogin no&lt;br /&gt;
 PrintMotd no&lt;br /&gt;
 Protocol 2&lt;br /&gt;
 HostKey /etc/ssh/ssh_host_ed25519_key&lt;br /&gt;
 HostKey /etc/ssh/ssh_host_rsa_key&lt;br /&gt;
 KexAlgorithms curve25519-sha256@libssh.org,diffie-hellman-group-exchange-sha256&lt;br /&gt;
 Ciphers chacha20-poly1305@openssh.com,aes256-gcm@openssh.com,aes128-gcm@openssh.com,aes256-ctr,aes192-ctr,aes128-ctr&lt;br /&gt;
 MACs hmac-sha2-512-etm@openssh.com,hmac-sha2-256-etm@openssh.com,umac-128-etm@openssh.com,hmac-sha2-512,hmac-sha2-256,umac-128@openssh.com&lt;br /&gt;
&lt;br /&gt;
After that, enable ufw and restart sshd. Note that if something goes wrong here you will need to plug in a monitor and keyboard again to login locally and fix things.&lt;br /&gt;
&lt;br /&gt;
 ufw enable&lt;br /&gt;
 rc-service sshd restart&lt;br /&gt;
&lt;br /&gt;
Now is a good time to reboot and reconnect to check that everything is working.&lt;br /&gt;
&lt;br /&gt;
 reboot&lt;br /&gt;
&lt;br /&gt;
With root not being able to login, you will instead login as “pi”. It is possible for this user to (temporarily, until exit) elevate privileges by the following command:&lt;br /&gt;
&lt;br /&gt;
 su&lt;br /&gt;
&lt;br /&gt;
Another option is to use sudo, but I will leave it like this for now, and go ahead with setting up some jobs. That’s a story for another article though.&lt;br /&gt;
&lt;br /&gt;
I hope this guide has been of help. It should be of use for anyone tinkering with Alpine on their Raspberries, and likely some parts for those running other Linux flavors on different hardware as well.&lt;/div&gt;</summary>
		<author><name>Maestro-jiggiE</name></author>
	</entry>
	<entry>
		<id>https://wiki.alpinelinux.org/w/index.php?title=Raspberry_Pi_4_-_Persistent_system_acting_as_a_NAS_and_Time_Machine&amp;diff=26639</id>
		<title>Raspberry Pi 4 - Persistent system acting as a NAS and Time Machine</title>
		<link rel="alternate" type="text/html" href="https://wiki.alpinelinux.org/w/index.php?title=Raspberry_Pi_4_-_Persistent_system_acting_as_a_NAS_and_Time_Machine&amp;diff=26639"/>
		<updated>2024-04-17T04:38:20Z</updated>

		<summary type="html">&lt;p&gt;Maestro-jiggiE: add &amp;quot;..&amp;quot; to cd command and another one to get to home directory&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Tinker, Tailor, Raspberry Pi ==&lt;br /&gt;
&lt;br /&gt;
I went ahead and got myself a Raspberry Pi 4B with 4GB RAM, which I intend to use as a job scheduling server, only to find out that the suggested OS, Raspberry Pi OS, is 32-bit. Fortunately, the Linux distro Alpine, which I’ve grown very fond of lately, is available for Raspberry Pi as aarch64, meaning it’s both 64-bit kernel and userland. Unfortunately the distro is currently, as of version 3.12, not set up for persistent storage and is more of a live playground. Gathering bits and pieces from various guides online, this can however be remedied with some tinkering. On this page you will find how to set up a persistent 64-bit OS on the Raspberry Pi, share a USB attached disk, while also adding some interesting software.&lt;br /&gt;
&lt;br /&gt;
If you go ahead and buy the Pi 4, note that it has micro-HDMI ports. I thought they were mini, for which I already had cabling, but alas, another adapter had to be purchased. Also, when attaching a USB disk it is better if it is externally powered. The Pi can however power newer external SSD drives that have low power consumption. I tried with a magnetic disk based one powered over USB first, but it behaved somewhat strangely. With that said, let’s go ahead and look at how to get yourself a shiny tiny new server.&lt;br /&gt;
&lt;br /&gt;
=== Tinkering for Persistence ===&lt;br /&gt;
&lt;br /&gt;
After downloading the v3.12 tarball from Alpine on my macOS, it’s time to set up the SDHC card for the Pi. I actually borrowed my old hand-me-down MacBook Air that I gave to my daughter a few years ago, since it has a built-in card reader, as opposed to my newer Air. The Pi boots off a FAT32 partition, but we want the system to reside in an ext4 partition later, so we will start by reserving a small portion of the card for the boot partition. This is done using Terminal in macOS with the following commands.&lt;br /&gt;
&lt;br /&gt;
 diskutil list&lt;br /&gt;
 diskutil partitionDisk /dev/disk2 MBR &amp;quot;FAT32&amp;quot; ALP 256MB &amp;quot;Free Space&amp;quot; SYS R&lt;br /&gt;
 sudo fdisk -e /dev/disk2&lt;br /&gt;
 &amp;gt; f 1&lt;br /&gt;
 &amp;gt; w&lt;br /&gt;
 &amp;gt; exit&lt;br /&gt;
&lt;br /&gt;
The tarball should have decompressed once it hit your download folder. If not, use the option “xvzf” for tar.&lt;br /&gt;
&lt;br /&gt;
 cd /Volumes/ALP&lt;br /&gt;
 tar xvf ~/Downloads/alpine-rpi-3.12.0-aarch64.tar&lt;br /&gt;
 nano usercfg.txt&lt;br /&gt;
&lt;br /&gt;
The newly created file usercfg.txt should contain the following:&lt;br /&gt;
&lt;br /&gt;
 enable_uart=1&lt;br /&gt;
 gpu_mem=32&lt;br /&gt;
 disable_overscan=1&lt;br /&gt;
&lt;br /&gt;
The least amount of memory for headless is 32MB. The UART thing is beyond me, but seems to be a recommended setting. Removing overscan gives you more screen estate. If you intend to use this as a desktop computer rather than a headless server you probably want to allot more memory to the GPU and enable sound. Full specification for options can be found on the official Raspberry Pi homepage.&lt;br /&gt;
&lt;br /&gt;
After that we just need to make sure the card is not busy, so we change to a safe directory and thereafter eject the card (making sure that any pending writes are finalized).&lt;br /&gt;
&lt;br /&gt;
 cd ..&lt;br /&gt;
 cd ..&lt;br /&gt;
 diskutil eject /dev/disk2&lt;br /&gt;
&lt;br /&gt;
Put the SDHC card in the Pi and boot. Login with “root” as username and no password. This presumes that you have connected everything else, such as a keyboard and monitor.&lt;br /&gt;
&lt;br /&gt;
 setup-alpine&lt;br /&gt;
&lt;br /&gt;
During setup, select your keymap, hostname, etc, as desired. However, when asked where to store configs, type “none”, and the same for the apk cache directory. If you want to follow this guide to the point, you should also select “chrony” as the NTP client. The most important part here though is to get your network up and running. A full description of the setup programs can be found on the Alpine homepage.&lt;br /&gt;
&lt;br /&gt;
 apk update&lt;br /&gt;
 apk upgrade&lt;br /&gt;
 apk add cfdisk&lt;br /&gt;
 cfdisk /dev/mmcblk0&lt;br /&gt;
&lt;br /&gt;
In cfdisk, select “Free space” and the option “New”. It will suggest using the entire available space, so just press enter, then select the option “primary”, followed by “Write”. Type “yes” to write the partition table to disk, then select “Quit”.&lt;br /&gt;
&lt;br /&gt;
 apk add e2fsprogs&lt;br /&gt;
 mkfs.ext4 /dev/mmcblk0p2&lt;br /&gt;
 mount /dev/mmcblk0p2 /mnt&lt;br /&gt;
 setup-disk -m sys /mnt&lt;br /&gt;
 mount -o remount,rw /media/mmcblk0p1&lt;br /&gt;
&lt;br /&gt;
Ignore the warnings about extlinux. This and the following trick was found in the Alpine Wiki, but in some confusing order. &lt;br /&gt;
&lt;br /&gt;
 rm -f /media/mmcblk0p1/boot/*&lt;br /&gt;
 cd /mnt&lt;br /&gt;
 rm boot/boot&lt;br /&gt;
 mv boot/* /media/mmcblk0p1/boot/&lt;br /&gt;
 rm -Rf boot&lt;br /&gt;
 mkdir media/mmcblk0p1&lt;br /&gt;
 ln -s media/mmcblk0p1/boot boot&lt;br /&gt;
&lt;br /&gt;
Now the mountpoints need fixing, so run:&lt;br /&gt;
&lt;br /&gt;
 apk add nano&lt;br /&gt;
 nano etc/fstab&lt;br /&gt;
&lt;br /&gt;
If you prefer some other editor (since people tend to become religious about these things) then feel free to use whatever makes you feel better than nano. Add the following line:&lt;br /&gt;
&lt;br /&gt;
 /dev/mmcblk0p1   /media/mmcblk0p1   vfat   defaults   0 0&lt;br /&gt;
&lt;br /&gt;
Now the kernel needs to know where the root filesystem is.&lt;br /&gt;
&lt;br /&gt;
 nano /media/mmcblk0p1/cmdline.txt&lt;br /&gt;
&lt;br /&gt;
Append the following at the end of the one and only line in the file:&lt;br /&gt;
&lt;br /&gt;
 root=/dev/mmcblk0p2&lt;br /&gt;
&lt;br /&gt;
After exiting nano, it’s safe to reboot, so:&lt;br /&gt;
&lt;br /&gt;
 reboot&lt;br /&gt;
&lt;br /&gt;
After rebooting, login using “root” as username, and the password you selected during setup-alpine earlier. Now you have a persistent system and everything that is done will stick, as opposed to how the original distro was configured.&lt;br /&gt;
&lt;br /&gt;
=== Tailoring for Remote Access ===&lt;br /&gt;
&lt;br /&gt;
OpenSSH should already be installed, but it will not allow remote root login. We will initially relax this constraint. Last in this article is a section on hardening where we again disallow root login. If you intend to have this box accessible from the Internet I strongly advice on hardening the Pi.&lt;br /&gt;
&lt;br /&gt;
 nano /etc/ssh/sshd_config&lt;br /&gt;
&lt;br /&gt;
Uncomment and change the line (about 30 lines down) with PermitRootLogin to:&lt;br /&gt;
&lt;br /&gt;
 PermitRootLogin yes&lt;br /&gt;
&lt;br /&gt;
Then restart the service:&lt;br /&gt;
&lt;br /&gt;
 rc-service sshd restart&lt;br /&gt;
&lt;br /&gt;
Now you should be able to ssh to your Pi. The following steps are easier when you can cut and paste things into a terminal window. Feeling lucky? Then now is a good time to disconnect your keyboard and monitor.&lt;br /&gt;
&lt;br /&gt;
=== Keeping the Time ===&lt;br /&gt;
&lt;br /&gt;
If you selected chrony as your NTP client it may take a long time for it to actually correct the clock. Since the Pi does not have a hardware clock, it’s necessary to have time corrected at boot time, so we will change the configuration such that the clock is set if it is more than 60 seconds off during the first 10 lookups. &lt;br /&gt;
&lt;br /&gt;
 nano /etc/chrony/chrony.conf&lt;br /&gt;
&lt;br /&gt;
Add the following line at the bottom of the file.&lt;br /&gt;
&lt;br /&gt;
 makestep 60 10&lt;br /&gt;
&lt;br /&gt;
Check the date, restart the service, and check the (now hopefully corrected) date again.&lt;br /&gt;
&lt;br /&gt;
 date&lt;br /&gt;
 rc-service chronyd restart&lt;br /&gt;
 date&lt;br /&gt;
&lt;br /&gt;
Having the correct time is a good thing, particularly when building a job scheduling server.&lt;br /&gt;
&lt;br /&gt;
=== Silencing the Fan ===&lt;br /&gt;
&lt;br /&gt;
Together with the Pi I also bought a fan, the Pimoroni Fan Shim. According to reviews it is one of the better ways to cool your Pi, but it’s still too soon for me to have an opinion. Unless controller software is installed, it will always run at full speed. It’s not noisy, but still noticeable sitting a metric meter from the Pi. Again, some tinkering will be needed since the controller software needs some prerequisites installed. We lost nano between reboots, so we will go ahead and add it again.&lt;br /&gt;
&lt;br /&gt;
 apk update&lt;br /&gt;
 apk upgrade&lt;br /&gt;
 apk add nano&lt;br /&gt;
&lt;br /&gt;
Other software we need is in the “community” repositories of Alpine. In order to active that repository we need to edit a file:&lt;br /&gt;
&lt;br /&gt;
 nano /etc/apk/repositories&lt;br /&gt;
&lt;br /&gt;
Uncomment the second line (ending in v3.12/community), exit, then install the necessary packages.&lt;br /&gt;
&lt;br /&gt;
 apk update&lt;br /&gt;
 apk add git bash python3 python3-dev py3-pip py3-wheel build-base&lt;br /&gt;
&lt;br /&gt;
After those prerequisites are in place, install the fan shim software using:&lt;br /&gt;
&lt;br /&gt;
 git clone https://github.com/pimoroni/fanshim-python&lt;br /&gt;
 cd fanshim-python&lt;br /&gt;
 ./install.sh&lt;br /&gt;
 apk add py3-psutil&lt;br /&gt;
 cd examples&lt;br /&gt;
 ./install-service.sh&lt;br /&gt;
&lt;br /&gt;
The last script will fail with “systemctl: command not found”, since Alpine uses OpenRC as its init system, and not systemd which this script presumes. We will instead write our own startup script:&lt;br /&gt;
&lt;br /&gt;
 nano /etc/init.d/fanshim&lt;br /&gt;
&lt;br /&gt;
This new file should have the following contents:&lt;br /&gt;
&lt;br /&gt;
 #!/sbin/openrc-run&lt;br /&gt;
 name=&amp;quot;fanshim&amp;quot;&lt;br /&gt;
 command=&amp;quot;/usr/bin/python3 /root/fanshim-python/examples/automatic.py&amp;quot;&lt;br /&gt;
 command_args=&amp;quot;--on-threshold 65 --off-threshold 55 --delay 2&amp;quot;&lt;br /&gt;
 pidfile=&amp;quot;/var/run/$SVCNAME.pid&amp;quot;&lt;br /&gt;
 command_background=&amp;quot;yes&amp;quot;&lt;br /&gt;
&lt;br /&gt;
There are a lot of interesting options for fanshim that you can explore, like tuning it’s RGB led. Now we want this to run at boot time, so add it the the default runlevel, then start it.&lt;br /&gt;
&lt;br /&gt;
 rc-update add fanshim default&lt;br /&gt;
 rc-service fanshim start&lt;br /&gt;
&lt;br /&gt;
Enjoy the silence!&lt;br /&gt;
&lt;br /&gt;
=== Adding and Sharing a Disk ===&lt;br /&gt;
&lt;br /&gt;
Some of files we will be transferring are going to be quite large. It would also be neat to be able to access files easily from the Finder in macOS, so I am adding a USB3 connected hard disk with 4TB storage. What follows will be very similar to setting up a NAS, and in fact, the way I fell in love with Alpine was by building my own NAS from scratch (with the minor differences being more disks and using zfs). &lt;br /&gt;
&lt;br /&gt;
First we need to change the filesystem. The disk comes formatted as FAT32, which is very poorly suited for a networked disk. Samba, which is what we will be using for sharing, more or less requires a filesystem that supports extended attributes. After plugging in the drive, we will therefore repartition the drive and format it to ext4. &lt;br /&gt;
&lt;br /&gt;
 cfdisk /dev/sda&lt;br /&gt;
&lt;br /&gt;
Using cfdisk, delete any existing partitions and create one new partition. It should become “Linux filesystem” by default. Don’t forget to “Write” before “Quit”. Then format it:&lt;br /&gt;
&lt;br /&gt;
 mkfs.ext4 /dev/sda1&lt;br /&gt;
&lt;br /&gt;
Now we need to add autofs to get automatic mounting. This package is in edge/testing though, so we need to enable that branch and repository, but still have main and community take preference. This can be done by labelling a repository.&lt;br /&gt;
&lt;br /&gt;
 nano /etc/apk/repositories&lt;br /&gt;
&lt;br /&gt;
Change the line with the testing repository (last line in my file) to the following. Note that yours will have some server.from.setup/path depending on what you selected in setup-alpine. You only uncomment and add the @testing label in other words.&lt;br /&gt;
&lt;br /&gt;
 @testing http://&amp;lt;server.from.setup/path&amp;gt;/edge/testing&lt;br /&gt;
&lt;br /&gt;
Now autofs can be installed from the labelled repo.&lt;br /&gt;
&lt;br /&gt;
 apk add autofs@testing&lt;br /&gt;
&lt;br /&gt;
Note that dependencies are still pulled from main/community to the extent it is possible. In order to configure autofs, first:&lt;br /&gt;
&lt;br /&gt;
 nano /etc/autofs/auto.master&lt;br /&gt;
&lt;br /&gt;
Add the following line after the uncommented line starting with /misc. It will also disconnect the hard disk after 5 minutes to save energy:&lt;br /&gt;
&lt;br /&gt;
 /-   /etc/autofs/auto.hdd   --timeout=300&lt;br /&gt;
&lt;br /&gt;
Then create this new config file:&lt;br /&gt;
&lt;br /&gt;
 nano /etc/autofs/auto.hdd&lt;br /&gt;
&lt;br /&gt;
Add the the following line to the empty file.&lt;br /&gt;
&lt;br /&gt;
 /hdd   -fstype=ext4   :/dev/sda1&lt;br /&gt;
&lt;br /&gt;
Now, the user pi needs to be created.&lt;br /&gt;
&lt;br /&gt;
 adduser pi&lt;br /&gt;
 smbpasswd -a pi&lt;br /&gt;
&lt;br /&gt;
Select desirable passwords for the pi user. The latter one will later be stored in the macOS keychain and therefore easy to forget, so make note of it somewhere. &lt;br /&gt;
&lt;br /&gt;
Add autofs to startup and start it now. Change the ownership of /hdd to pi.&lt;br /&gt;
&lt;br /&gt;
 rc-update add autofs default&lt;br /&gt;
 rc-service autofs start&lt;br /&gt;
 chown -R pi.pi /hdd&lt;br /&gt;
&lt;br /&gt;
With that in place (disk can be accessed through /hdd) it is time to set up the sharing. For this we will use samba and avahi for network discovery.&lt;br /&gt;
&lt;br /&gt;
 apk add samba avahi dbus&lt;br /&gt;
 nano /etc/samba/smb.cfg&lt;br /&gt;
&lt;br /&gt;
Now, this is what my entire smb.cfg file looks like, with all the tweaks to get stuff running well from macOS.&lt;br /&gt;
&lt;br /&gt;
 [global]&lt;br /&gt;
  create mask = 0664&lt;br /&gt;
  directory mask = 0775&lt;br /&gt;
  veto files = /.DS_Store/lost+found/&lt;br /&gt;
  delete veto files = true&lt;br /&gt;
  nt acl support = no&lt;br /&gt;
  inherit acls = yes&lt;br /&gt;
  ea support = yes&lt;br /&gt;
  security = user&lt;br /&gt;
  passdb backend = tdbsam&lt;br /&gt;
  map to guest = Bad User&lt;br /&gt;
  vfs objects = catia fruit streams_xattr recycle&lt;br /&gt;
  acl_xattr:ignore system acls = yes&lt;br /&gt;
  recycle:repository = .recycle&lt;br /&gt;
  recycle:keeptree = yes&lt;br /&gt;
  recycle:versions = yes&lt;br /&gt;
  fruit:aapl = yes&lt;br /&gt;
  fruit:metadata = stream&lt;br /&gt;
  fruit:model = MacSamba&lt;br /&gt;
  fruit:veto_appledouble = yes&lt;br /&gt;
  fruit:posix_rename = yes &lt;br /&gt;
  fruit:zero_file_id = yes&lt;br /&gt;
  fruit:wipe_intentionally_left_blank_rfork = yes &lt;br /&gt;
  fruit:delete_empty_adfiles = yes &lt;br /&gt;
  server max protocol = SMB3&lt;br /&gt;
  server min protocol = SMB2&lt;br /&gt;
  workgroup = WORKGROUP    &lt;br /&gt;
  server string = NAS      &lt;br /&gt;
  server role = standalone server&lt;br /&gt;
  dns proxy = no&lt;br /&gt;
 [Harddisk]&lt;br /&gt;
  comment = Raspberry Pi Removable Harddisk                     &lt;br /&gt;
  path = /hdd    &lt;br /&gt;
  browseable = yes          &lt;br /&gt;
  writable = yes            &lt;br /&gt;
  spotlight = yes           &lt;br /&gt;
  valid users = pi       &lt;br /&gt;
  fruit:resource = xattr &lt;br /&gt;
  fruit:time machine = yes&lt;br /&gt;
  fruit:advertise_fullsync = true&lt;br /&gt;
&lt;br /&gt;
Those last two lines can be removed if you are not interested in using the disk as a Time Machine backup for your Apple devices. I will likely not use it, but since this is how I configured my NAS and it was a hassle to figure out how to get it working I thought I’d leave it here for reference. Doesn’t hurt to keep it there in any way.&lt;br /&gt;
&lt;br /&gt;
Let us also configure the avahi-daemon, by creating a config file for the samba service. Avahi will announce the server using Bonjour, making them easily recognizable from macOS (where they automagically show up in the Finder). &lt;br /&gt;
&lt;br /&gt;
 nano /etc/avahi/services/samba.service&lt;br /&gt;
&lt;br /&gt;
This new file should have the following contents:&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;?xml version=&amp;quot;1.0&amp;quot; standalone=&#039;no&#039;?&amp;gt;&lt;br /&gt;
 &amp;lt;!DOCTYPE service-group SYSTEM &amp;quot;avahi-service.dtd&amp;quot;&amp;gt;&lt;br /&gt;
 &amp;lt;service-group&amp;gt;&lt;br /&gt;
 &amp;lt;name replace-wildcards=&amp;quot;yes&amp;quot;&amp;gt;%h&amp;lt;/name&amp;gt;&lt;br /&gt;
 &amp;lt;service&amp;gt;&lt;br /&gt;
 &amp;lt;type&amp;gt;_smb._tcp&amp;lt;/type&amp;gt;&lt;br /&gt;
 &amp;lt;port&amp;gt;445&amp;lt;/port&amp;gt;&lt;br /&gt;
 &amp;lt;/service&amp;gt;&lt;br /&gt;
 &amp;lt;service&amp;gt;&lt;br /&gt;
 &amp;lt;type&amp;gt;_device-info._tcp&amp;lt;/type&amp;gt;&lt;br /&gt;
 &amp;lt;port&amp;gt;0&amp;lt;/port&amp;gt;&lt;br /&gt;
 &amp;lt;txt-record&amp;gt;model=RackMac&amp;lt;/txt-record&amp;gt;&lt;br /&gt;
 &amp;lt;/service&amp;gt;&lt;br /&gt;
 &amp;lt;service&amp;gt;&lt;br /&gt;
 &amp;lt;type&amp;gt;_adisk._tcp&amp;lt;/type&amp;gt;&lt;br /&gt;
 &amp;lt;txt-record&amp;gt;sys=waMa=0,adVF=0x100&amp;lt;/txt-record&amp;gt;&lt;br /&gt;
 &amp;lt;txt-record&amp;gt;dk0=adVN=HDD,adVF=0x82&amp;lt;/txt-record&amp;gt;&lt;br /&gt;
 &amp;lt;/service&amp;gt;&lt;br /&gt;
 &amp;lt;/service-group&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Not that the txt-record containing adVN=HDD can be removed if you are not interested in using the disk as a Time Machine backup. Still, leaving it won’t hurt.&lt;br /&gt;
&lt;br /&gt;
Finally, it’s time to add samba and avahi to the startup and start the services.&lt;br /&gt;
&lt;br /&gt;
 rc-update add samba default&lt;br /&gt;
 rc-update add avahi-daemon default&lt;br /&gt;
 rc-service samba start&lt;br /&gt;
 rc-service avahi-daemon start&lt;br /&gt;
&lt;br /&gt;
The disk should now be visible from macOS. Remember to click “Connect as…” and enter “pi” as the username and your selected smbpasswd from earlier. Check the box “Remember this password in my keychain” for quicker access next time. Sometimes, due to a bug in Catalina, you may get “The original item cannot be found” when accessing the remote disk. If that happens, force quit Finder, and you should be good to go again. If anyone knows of any other fix to this issue, let me know!&lt;br /&gt;
&lt;br /&gt;
=== Automation ===&lt;br /&gt;
&lt;br /&gt;
Now, this server will be used as a job server. Some of the jobs running will need the psql command from PostgreSQL and some others will be R jobs. Let’s install both, or whatever you need to satisfy your desires. You can skip this step for now if you are undecided about what to run or just need basic services like the built-in shell scripting.&lt;br /&gt;
&lt;br /&gt;
 apk add R postgresql&lt;br /&gt;
&lt;br /&gt;
In order to automate these jobs, we will be using Cronicle. It depends on node.js so we need to install the prerequisites. It’s run script is fetched using curl, so it will also need to be installed.&lt;br /&gt;
&lt;br /&gt;
 apk add nodejs npm curl&lt;br /&gt;
&lt;br /&gt;
The installation is done as follows (it is a oneliner even if it looks broken here).&lt;br /&gt;
&lt;br /&gt;
 curl -s https://raw.githubusercontent.com/jhuckaby/Cronicle/master/bin/install.js | node&lt;br /&gt;
&lt;br /&gt;
I want to use standard ports, so I need to change the config slightly.&lt;br /&gt;
&lt;br /&gt;
 nano /opt/cronicle/conf/config.json&lt;br /&gt;
&lt;br /&gt;
Change base_app_url from port 3012 to 80. Much further down, change http_port from 3012 to 80, and https_port from 3013 to 443. If you want mails to be sent, change smtp_hostname in the beginning of the file to the mail relay you are using. After that an initialization script needs to be run.&lt;br /&gt;
&lt;br /&gt;
 /opt/cronicle/bin/control.sh setup&lt;br /&gt;
&lt;br /&gt;
Now we just need to get it running at boot time. This is, however, a service that we do not want to “kill” using a PID, so we are going to enable local scripts that start and stop the service in a controlled manner instead.&lt;br /&gt;
&lt;br /&gt;
 rc-update add local default&lt;br /&gt;
 nano /etc/local.d/cronicle.start&lt;br /&gt;
&lt;br /&gt;
This new file should have the following line in it:&lt;br /&gt;
&lt;br /&gt;
 /opt/cronicle/bin/control.sh start&lt;br /&gt;
&lt;br /&gt;
Now we need to create a stop file as well:&lt;br /&gt;
&lt;br /&gt;
 nano /etc/local.d/cronicle.stop&lt;br /&gt;
&lt;br /&gt;
This file should have the contents:&lt;br /&gt;
&lt;br /&gt;
 /opt/cronicle/bin/control.sh stop&lt;br /&gt;
&lt;br /&gt;
In order for the local script daemon to run these, they need to be executable.&lt;br /&gt;
&lt;br /&gt;
 chmod +x /etc/local.d/cronicle.*&lt;br /&gt;
&lt;br /&gt;
With that, let’s secure things.&lt;br /&gt;
&lt;br /&gt;
=== Hardening ===&lt;br /&gt;
&lt;br /&gt;
Now that most configuring is done, it’s time to harden the Pi. First we will install a firewall with some basic login protection using the builtin ‘limit’ in iptables. Assuming you are in the 192.168.1.0/24 range, which was set during setup-alpine, the following should be run. Only clients on the local network are allowed access to shared folders.&lt;br /&gt;
&lt;br /&gt;
 apk add ufw@testing&lt;br /&gt;
 rc-update add ufw default&lt;br /&gt;
 ufw allow 22&lt;br /&gt;
 ufw limit 22/tcp&lt;br /&gt;
 ufw allow 80&lt;br /&gt;
 ufw allow 443&lt;br /&gt;
 ufw allow from 192.168.1.0/24 to any app CIFS&lt;br /&gt;
 ufw allow Bonjour&lt;br /&gt;
&lt;br /&gt;
With the rules in place, it’s time to disallow root login over ssh, and make sure that only fresh protocols are used.&lt;br /&gt;
&lt;br /&gt;
 nano /etc/ssh/sshd_config&lt;br /&gt;
&lt;br /&gt;
Change the line that previously said yes to no, and add the other lines at the bottom of the file (borrowed from this security site):&lt;br /&gt;
&lt;br /&gt;
 PermitRootLogin no&lt;br /&gt;
 PrintMotd no&lt;br /&gt;
 Protocol 2&lt;br /&gt;
 HostKey /etc/ssh/ssh_host_ed25519_key&lt;br /&gt;
 HostKey /etc/ssh/ssh_host_rsa_key&lt;br /&gt;
 KexAlgorithms curve25519-sha256@libssh.org,diffie-hellman-group-exchange-sha256&lt;br /&gt;
 Ciphers chacha20-poly1305@openssh.com,aes256-gcm@openssh.com,aes128-gcm@openssh.com,aes256-ctr,aes192-ctr,aes128-ctr&lt;br /&gt;
 MACs hmac-sha2-512-etm@openssh.com,hmac-sha2-256-etm@openssh.com,umac-128-etm@openssh.com,hmac-sha2-512,hmac-sha2-256,umac-128@openssh.com&lt;br /&gt;
&lt;br /&gt;
After that, enable ufw and restart sshd. Note that if something goes wrong here you will need to plug in a monitor and keyboard again to login locally and fix things.&lt;br /&gt;
&lt;br /&gt;
 ufw enable&lt;br /&gt;
 rc-service sshd restart&lt;br /&gt;
&lt;br /&gt;
Now is a good time to reboot and reconnect to check that everything is working.&lt;br /&gt;
&lt;br /&gt;
 reboot&lt;br /&gt;
&lt;br /&gt;
With root not being able to login, you will instead login as “pi”. It is possible for this user to (temporarily, until exit) elevate privileges by the following command:&lt;br /&gt;
&lt;br /&gt;
 su&lt;br /&gt;
&lt;br /&gt;
Another option is to use sudo, but I will leave it like this for now, and go ahead with setting up some jobs. That’s a story for another article though.&lt;br /&gt;
&lt;br /&gt;
I hope this guide has been of help. It should be of use for anyone tinkering with Alpine on their Raspberries, and likely some parts for those running other Linux flavors on different hardware as well.&lt;/div&gt;</summary>
		<author><name>Maestro-jiggiE</name></author>
	</entry>
	<entry>
		<id>https://wiki.alpinelinux.org/w/index.php?title=Raspberry_Pi_4_-_Persistent_system_acting_as_a_NAS_and_Time_Machine&amp;diff=26638</id>
		<title>Raspberry Pi 4 - Persistent system acting as a NAS and Time Machine</title>
		<link rel="alternate" type="text/html" href="https://wiki.alpinelinux.org/w/index.php?title=Raspberry_Pi_4_-_Persistent_system_acting_as_a_NAS_and_Time_Machine&amp;diff=26638"/>
		<updated>2024-04-17T04:30:43Z</updated>

		<summary type="html">&lt;p&gt;Maestro-jiggiE: usercfg.txt file is non-existence when using latest tar file for alpine-rpi-3.19.1-aarch64. Need to manually create it then edit it.&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Tinker, Tailor, Raspberry Pi ==&lt;br /&gt;
&lt;br /&gt;
I went ahead and got myself a Raspberry Pi 4B with 4GB RAM, which I intend to use as a job scheduling server, only to find out that the suggested OS, Raspberry Pi OS, is 32-bit. Fortunately, the Linux distro Alpine, which I’ve grown very fond of lately, is available for Raspberry Pi as aarch64, meaning it’s both 64-bit kernel and userland. Unfortunately the distro is currently, as of version 3.12, not set up for persistent storage and is more of a live playground. Gathering bits and pieces from various guides online, that can be remedied with some tinkering. On this page you will find how to set up a persistent 64-bit OS on the Raspberry Pi, share a USB attached disk, as well as some interesting software.&lt;br /&gt;
&lt;br /&gt;
Note: the Pi 4 has micro-HDMI ports. I thought they were mini, for which I already had cabling, but alas, another adapter had to be purchased. Also, when attaching a USB disk it is better if it is externally powered. The Pi can however power newer external SSD drives that have low power consumption. I tried with a USB powered magnetic disk drive, but it behaved somewhat strangely. With that said, let’s look at how to get yourself a shiny, tiny, new server.&lt;br /&gt;
&lt;br /&gt;
=== Tinkering for Persistence ===&lt;br /&gt;
&lt;br /&gt;
After downloading the Alpine v3.12 tarball, the next step is to set up the SDHC card for the Pi. I borrowed a MacBook Air, since it has a built-in card reader. The Pi boots off a FAT32 partition, but ultimately, we want the system to reside in an ext4 partition. We&#039;ll start by reserving a small portion of the card for the boot partition. This is done using Terminal in macOS with the following commands.&lt;br /&gt;
&lt;br /&gt;
 diskutil list&lt;br /&gt;
 sudo diskutil partitionDisk disk2 MBR FREE SYS R FAT32 ALP 256MB&lt;br /&gt;
 sudo fdisk -e /dev/disk2&lt;br /&gt;
 &amp;gt; f 1&lt;br /&gt;
 &amp;gt; w&lt;br /&gt;
 &amp;gt; exit&lt;br /&gt;
&lt;br /&gt;
The tarball should have decompressed once it hit your download folder. If not, use the option “xvzf” for tar.&lt;br /&gt;
&lt;br /&gt;
 cd /Volumes/ALP&lt;br /&gt;
 tar xvf ~/Downloads/alpine-rpi-3.12.0-aarch64.tar&lt;br /&gt;
 touch usercfg.txt&lt;br /&gt;
 nano usercfg.txt&lt;br /&gt;
&lt;br /&gt;
The newly created file usercfg.txt should contain the following:&lt;br /&gt;
&lt;br /&gt;
 enable_uart=1&lt;br /&gt;
 gpu_mem=32&lt;br /&gt;
 disable_overscan=1&lt;br /&gt;
&lt;br /&gt;
The smallest amount of memory for a headless install is 32MB. Removing overscan gives you more usable screen area. If you intend to use this as a desktop computer rather than a headless server, you probably want to allocate more memory to the GPU and enable sound. Full specifications for options can be found on the official Raspberry Pi homepage.&lt;br /&gt;
&lt;br /&gt;
After that, you need to make sure the card is not busy. Change to a safe directory then eject the card (making sure that any pending writes are finalized).&lt;br /&gt;
&lt;br /&gt;
 cd&lt;br /&gt;
 diskutil eject /dev/disk2&lt;br /&gt;
&lt;br /&gt;
Put the SDHC card in the Pi and boot. Login with “root” as username and no password. This presumes that you have connected everything else, e.g. a keyboard and monitor.&lt;br /&gt;
&lt;br /&gt;
 setup-alpine&lt;br /&gt;
&lt;br /&gt;
During setup, select your keymap, hostname, etc, as desired. However, when asked where to store configs, type “none”, and the same for the apk cache directory. If you want to follow this guide to the point, you should also select “chrony” as the NTP client. The most important part here though is to get your network up and running. A full description of the setup programs can be found on the Alpine homepage.&lt;br /&gt;
&lt;br /&gt;
 apk update&lt;br /&gt;
 apk upgrade&lt;br /&gt;
 apk add cfdisk&lt;br /&gt;
 cfdisk /dev/mmcblk0&lt;br /&gt;
&lt;br /&gt;
In cfdisk, select “Free space” and the &amp;quot;New&amp;quot; option. It will suggest using the entire available space, so just press enter, then select the option &amp;quot;primary&amp;quot; followed by &amp;quot;Write&amp;quot;. Type &amp;quot;yes&amp;quot; to write the partition table to disk, then select &amp;quot;Quit&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
 apk add e2fsprogs&lt;br /&gt;
 mkfs.ext4 /dev/mmcblk0p2&lt;br /&gt;
 mount /dev/mmcblk0p2 /mnt&lt;br /&gt;
 export FORCE_BOOTFS=1                 # work around for issue 12353&lt;br /&gt;
 setup-disk -m sys /mnt&lt;br /&gt;
 mount -o remount,rw /media/mmcblk0p1&lt;br /&gt;
&lt;br /&gt;
Ignore the warnings about extlinux. This and the following trick was found in the Alpine Wiki, but in a confusing order. &lt;br /&gt;
&lt;br /&gt;
 rm -f /media/mmcblk0p1/boot/*&lt;br /&gt;
 cd /mnt&lt;br /&gt;
 rm boot/boot&lt;br /&gt;
 mv boot/* /media/mmcblk0p1/boot/&lt;br /&gt;
 rm -Rf boot&lt;br /&gt;
 mkdir media/mmcblk0p1&lt;br /&gt;
 ln -s media/mmcblk0p1/boot boot&lt;br /&gt;
&lt;br /&gt;
Now the mountpoints need fixing, so run:&lt;br /&gt;
&lt;br /&gt;
 apk add nano&lt;br /&gt;
 nano etc/fstab&lt;br /&gt;
&lt;br /&gt;
If you prefer some other editor (since people tend to become religious about these things) feel free to use whatever you want. Add the following line:&lt;br /&gt;
&lt;br /&gt;
 /dev/mmcblk0p1   /media/mmcblk0p1   vfat   defaults   0 0&lt;br /&gt;
&lt;br /&gt;
Now the kernel needs to know where the root filesystem is.&lt;br /&gt;
&lt;br /&gt;
 nano /media/mmcblk0p1/cmdline.txt&lt;br /&gt;
&lt;br /&gt;
Append the following at the end of the one and only line in the file:&lt;br /&gt;
&lt;br /&gt;
 root=/dev/mmcblk0p2&lt;br /&gt;
&lt;br /&gt;
After exiting nano, reboot:&lt;br /&gt;
&lt;br /&gt;
 reboot&lt;br /&gt;
&lt;br /&gt;
After rebooting, login using &amp;quot;root&amp;quot; as username, and the password you selected during setup-alpine earlier. Now you have a persistent system, as opposed to the way the original distro was configured.&lt;br /&gt;
&lt;br /&gt;
=== Tailoring for Remote Access ===&lt;br /&gt;
&lt;br /&gt;
OpenSSH should already be installed, but it will not allow remote root login. Initially, we&#039;ll relax this restriction. Last in this article is a section on hardening where we again disallow root login. If you intend to have this box accessible from the Internet, I strongly advise hardening the Pi.&lt;br /&gt;
&lt;br /&gt;
 nano /etc/ssh/sshd_config&lt;br /&gt;
&lt;br /&gt;
Uncomment and change the line (about 30 lines down) with PermitRootLogin to:&lt;br /&gt;
&lt;br /&gt;
 PermitRootLogin yes&lt;br /&gt;
&lt;br /&gt;
Then restart the service:&lt;br /&gt;
&lt;br /&gt;
 rc-service sshd restart&lt;br /&gt;
&lt;br /&gt;
Now you should be able to ssh to your Pi. The following steps are easier when you can cut and paste things into a terminal window.&lt;br /&gt;
&lt;br /&gt;
=== Keeping the Time ===&lt;br /&gt;
&lt;br /&gt;
If you selected chrony as your NTP client, it may take a long time for it to correct the clock. Since the Pi does not have a hardware clock, it’s necessary to have the correct time at bootup. We&#039;ll change the configuration such that the clock gets set if it is more than 60 seconds off during the first 10 lookups. &lt;br /&gt;
&lt;br /&gt;
 nano /etc/chrony/chrony.conf&lt;br /&gt;
&lt;br /&gt;
Add the following line at the bottom of the file.&lt;br /&gt;
&lt;br /&gt;
 makestep 60 10&lt;br /&gt;
&lt;br /&gt;
Check the date, restart the service, and check the (now hopefully corrected) date again.&lt;br /&gt;
&lt;br /&gt;
 date&lt;br /&gt;
 rc-service chronyd restart&lt;br /&gt;
 date&lt;br /&gt;
&lt;br /&gt;
Having the correct time is a good thing, particularly when building a job scheduling server.&lt;br /&gt;
&lt;br /&gt;
=== Silencing the Fan ===&lt;br /&gt;
&lt;br /&gt;
Together with the Pi, I also bought a fan, the Pimoroni Fan Shim. According to reviews it is one of the better ways to cool your Pi. Unless control software is installed, it runs at full speed. It’s not noisy, but still noticeable a meter from the Pi. Again, some tinkering will be needed since the control software needs some prerequisites installed. We lost nano between reboots, so we&#039;ll reinstall it.&lt;br /&gt;
&lt;br /&gt;
 apk update&lt;br /&gt;
 apk upgrade&lt;br /&gt;
 apk add nano&lt;br /&gt;
&lt;br /&gt;
Other software we need is in the “community” repositories of Alpine. In order to activate that repository, we need to edit a file:&lt;br /&gt;
&lt;br /&gt;
 nano /etc/apk/repositories&lt;br /&gt;
&lt;br /&gt;
Uncomment the second line (ending in v3.12/community), exit, then install the necessary packages.&lt;br /&gt;
&lt;br /&gt;
 apk update&lt;br /&gt;
 apk add git bash python3 python3-dev py3-pip py3-wheel build-base&lt;br /&gt;
&lt;br /&gt;
After those prerequisites are in place, install the fan shim software using:&lt;br /&gt;
&lt;br /&gt;
 git clone https://github.com/pimoroni/fanshim-python&lt;br /&gt;
 cd fanshim-python&lt;br /&gt;
 ./install.sh&lt;br /&gt;
 apk add py3-psutil&lt;br /&gt;
 cd examples&lt;br /&gt;
 ./install-service.sh&lt;br /&gt;
&lt;br /&gt;
The last script will fail with “systemctl: command not found”, since Alpine uses OpenRC as its init system, and not systemd which this script presumes.&lt;br /&gt;
We&#039;ll write our own startup script:&lt;br /&gt;
&lt;br /&gt;
 nano /etc/init.d/fanshim&lt;br /&gt;
&lt;br /&gt;
The new file should have the following contents:&lt;br /&gt;
&lt;br /&gt;
 #!/sbin/openrc-run&lt;br /&gt;
 name=&amp;quot;fanshim&amp;quot;&lt;br /&gt;
 command=&amp;quot;/usr/bin/python3 /root/fanshim-python/examples/automatic.py&amp;quot;&lt;br /&gt;
 command_args=&amp;quot;--on-threshold 65 --off-threshold 55 --delay 2&amp;quot;&lt;br /&gt;
 pidfile=&amp;quot;/var/run/$SVCNAME.pid&amp;quot;&lt;br /&gt;
 command_background=&amp;quot;yes&amp;quot;&lt;br /&gt;
&lt;br /&gt;
There are a lot of interesting options for fanshim you can explore, like tuning it’s RGB led. We want this to run at boot time, so add it the the default runlevel, then start it.&lt;br /&gt;
&lt;br /&gt;
 rc-update add fanshim default&lt;br /&gt;
 rc-service fanshim start&lt;br /&gt;
&lt;br /&gt;
Enjoy the silence!&lt;br /&gt;
&lt;br /&gt;
=== Adding and Sharing a Disk ===&lt;br /&gt;
&lt;br /&gt;
Some of files we&#039;ll be transferring are quite large. It would also be neat to be able to access files easily from the Finder in macOS, so I am adding a USB3 connected hard disk with 4TB storage. What follows will be very similar to setting up a NAS, and in fact, the way I fell in love with Alpine was by building my own NAS from scratch (with the minor differences being more disks and using zfs). &lt;br /&gt;
&lt;br /&gt;
First we need to change the filesystem. The disk comes formatted as FAT32, which is very poorly suited for a network disk. Samba, which is what we will be using for sharing, more or less requires a filesystem that supports extended attributes. After plugging in the drive, we will repartition the drive and format it to ext4. &lt;br /&gt;
&lt;br /&gt;
 cfdisk /dev/sda&lt;br /&gt;
&lt;br /&gt;
Using cfdisk, delete any existing partitions and create one new partition. It should become &amp;quot;Linux filesystem&amp;quot; by default. Don’t forget to &amp;quot;Write&amp;quot; before &amp;quot;Quit&amp;quot;ing. Next, format it:&lt;br /&gt;
&lt;br /&gt;
 mkfs.ext4 /dev/sda1&lt;br /&gt;
&lt;br /&gt;
Now we need to add autofs to get automatic mounting. This package is in edge/testing though, so we need to enable that branch and repository, but still have main and community take preference. This can be done by labelling a repository.&lt;br /&gt;
&lt;br /&gt;
 nano /etc/apk/repositories&lt;br /&gt;
&lt;br /&gt;
Change the line with the testing repository to the following. Note that yours will have some server.from.setup/path depending on what you selected in setup-alpine. You only uncomment and add the @testing label in other words.&lt;br /&gt;
&lt;br /&gt;
 @testing http://&amp;lt;server.from.setup/path&amp;gt;/edge/testing&lt;br /&gt;
&lt;br /&gt;
Now autofs can be installed from the labelled repo.&lt;br /&gt;
&lt;br /&gt;
 apk add autofs@testing&lt;br /&gt;
&lt;br /&gt;
Note that dependencies are still pulled from main/community to the extent it is possible. In order to configure autofs, first:&lt;br /&gt;
&lt;br /&gt;
 nano /etc/autofs/auto.master&lt;br /&gt;
&lt;br /&gt;
Add the following line after the uncommented line starting with /misc. It will also disconnect the hard disk after 5 minutes to save energy:&lt;br /&gt;
&lt;br /&gt;
 /-   /etc/autofs/auto.hdd   --timeout=300&lt;br /&gt;
&lt;br /&gt;
Then create this new config file:&lt;br /&gt;
&lt;br /&gt;
 nano /etc/autofs/auto.hdd&lt;br /&gt;
&lt;br /&gt;
Add the the following line to the empty file.&lt;br /&gt;
&lt;br /&gt;
 /hdd   -fstype=ext4   :/dev/sda1&lt;br /&gt;
&lt;br /&gt;
Now, the user pi needs to be created.&lt;br /&gt;
&lt;br /&gt;
 adduser pi&lt;br /&gt;
 smbpasswd -a pi&lt;br /&gt;
&lt;br /&gt;
Select passwords for the pi user. The latter one will later be stored in the macOS keychain and therefore easy to forget, so make note of it somewhere. &lt;br /&gt;
&lt;br /&gt;
Add autofs to startup and start it now. Change the ownership of /hdd to pi.&lt;br /&gt;
&lt;br /&gt;
 rc-update add autofs default&lt;br /&gt;
 rc-service autofs start&lt;br /&gt;
 chown -R pi.pi /hdd&lt;br /&gt;
&lt;br /&gt;
With that in place (disk can be accessed through /hdd) it is time to set up the sharing. For this we will use samba and avahi for network discovery.&lt;br /&gt;
&lt;br /&gt;
 apk add samba avahi dbus&lt;br /&gt;
 nano /etc/samba/smb.cfg&lt;br /&gt;
&lt;br /&gt;
Now, this is what my entire smb.cfg file looks like, with all the tweaks to get stuff running well from macOS.&lt;br /&gt;
&lt;br /&gt;
 [global]&lt;br /&gt;
  create mask = 0664&lt;br /&gt;
  directory mask = 0775&lt;br /&gt;
  veto files = /.DS_Store/lost+found/&lt;br /&gt;
  delete veto files = true&lt;br /&gt;
  nt acl support = no&lt;br /&gt;
  inherit acls = yes&lt;br /&gt;
  ea support = yes&lt;br /&gt;
  security = user&lt;br /&gt;
  passdb backend = tdbsam&lt;br /&gt;
  map to guest = Bad User&lt;br /&gt;
  vfs objects = catia fruit streams_xattr recycle&lt;br /&gt;
  acl_xattr:ignore system acls = yes&lt;br /&gt;
  recycle:repository = .recycle&lt;br /&gt;
  recycle:keeptree = yes&lt;br /&gt;
  recycle:versions = yes&lt;br /&gt;
  fruit:aapl = yes&lt;br /&gt;
  fruit:metadata = stream&lt;br /&gt;
  fruit:model = MacSamba&lt;br /&gt;
  fruit:veto_appledouble = yes&lt;br /&gt;
  fruit:posix_rename = yes &lt;br /&gt;
  fruit:zero_file_id = yes&lt;br /&gt;
  fruit:wipe_intentionally_left_blank_rfork = yes &lt;br /&gt;
  fruit:delete_empty_adfiles = yes &lt;br /&gt;
  server max protocol = SMB3&lt;br /&gt;
  server min protocol = SMB2&lt;br /&gt;
  workgroup = WORKGROUP    &lt;br /&gt;
  server string = NAS      &lt;br /&gt;
  server role = standalone server&lt;br /&gt;
  dns proxy = no&lt;br /&gt;
 [Harddisk]&lt;br /&gt;
  comment = Raspberry Pi Removable Harddisk                     &lt;br /&gt;
  path = /hdd    &lt;br /&gt;
  browseable = yes          &lt;br /&gt;
  writable = yes            &lt;br /&gt;
  spotlight = yes           &lt;br /&gt;
  valid users = pi       &lt;br /&gt;
  fruit:resource = xattr &lt;br /&gt;
  fruit:time machine = yes&lt;br /&gt;
  fruit:advertise_fullsync = true&lt;br /&gt;
&lt;br /&gt;
Those last two lines can be removed if you are not interested in using the disk as a Time Machine backup for your Apple devices. I will likely not use it, but since this is how I configured my NAS and it was a hassle to figure out how to get it working I thought I’d leave it here for reference. Doesn’t hurt to keep it there.&lt;br /&gt;
&lt;br /&gt;
Let us also configure the avahi-daemon, by creating a config file for the samba service. Avahi will announce the server using Bonjour, making them easily recognizable from macOS (where they automagically show up in the Finder). &lt;br /&gt;
&lt;br /&gt;
 nano /etc/avahi/services/samba.service&lt;br /&gt;
&lt;br /&gt;
This new file should have the following contents:&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;?xml version=&amp;quot;1.0&amp;quot; standalone=&#039;no&#039;?&amp;gt;&lt;br /&gt;
 &amp;lt;!DOCTYPE service-group SYSTEM &amp;quot;avahi-service.dtd&amp;quot;&amp;gt;&lt;br /&gt;
 &amp;lt;service-group&amp;gt;&lt;br /&gt;
 &amp;lt;name replace-wildcards=&amp;quot;yes&amp;quot;&amp;gt;%h&amp;lt;/name&amp;gt;&lt;br /&gt;
 &amp;lt;service&amp;gt;&lt;br /&gt;
 &amp;lt;type&amp;gt;_smb._tcp&amp;lt;/type&amp;gt;&lt;br /&gt;
 &amp;lt;port&amp;gt;445&amp;lt;/port&amp;gt;&lt;br /&gt;
 &amp;lt;/service&amp;gt;&lt;br /&gt;
 &amp;lt;service&amp;gt;&lt;br /&gt;
 &amp;lt;type&amp;gt;_device-info._tcp&amp;lt;/type&amp;gt;&lt;br /&gt;
 &amp;lt;port&amp;gt;0&amp;lt;/port&amp;gt;&lt;br /&gt;
 &amp;lt;txt-record&amp;gt;model=RackMac&amp;lt;/txt-record&amp;gt;&lt;br /&gt;
 &amp;lt;/service&amp;gt;&lt;br /&gt;
 &amp;lt;service&amp;gt;&lt;br /&gt;
 &amp;lt;type&amp;gt;_adisk._tcp&amp;lt;/type&amp;gt;&lt;br /&gt;
 &amp;lt;txt-record&amp;gt;sys=waMa=0,adVF=0x100&amp;lt;/txt-record&amp;gt;&lt;br /&gt;
 &amp;lt;txt-record&amp;gt;dk0=adVN=HDD,adVF=0x82&amp;lt;/txt-record&amp;gt;&lt;br /&gt;
 &amp;lt;/service&amp;gt;&lt;br /&gt;
 &amp;lt;/service-group&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Not that the txt-record containing adVN=HDD can be removed if you are not interested in using the disk as a Time Machine backup. Still, leaving it won’t hurt.&lt;br /&gt;
&lt;br /&gt;
Finally, it’s time to add samba and avahi to the startup, and start the services.&lt;br /&gt;
&lt;br /&gt;
 rc-update add samba default&lt;br /&gt;
 rc-update add avahi-daemon default&lt;br /&gt;
 rc-service samba start&lt;br /&gt;
 rc-service avahi-daemon start&lt;br /&gt;
&lt;br /&gt;
The disk should now be visible from macOS. Remember to click “Connect as…” and enter “pi” as the username and your selected smbpasswd from earlier. Check the box “Remember this password in my keychain” for quicker access next time. Sometimes, due to a bug in Catalina, you may get “The original item cannot be found” when accessing the remote disk. If that happens, force quit Finder, and you should be good to go again. If anyone knows of any other fix to this issue, let me know!&lt;br /&gt;
&lt;br /&gt;
=== Automation ===&lt;br /&gt;
&lt;br /&gt;
This server will be used as a job server. Some of the jobs running will need the psql command from PostgreSQL and some others will be R jobs. Let’s install both, or whatever you need to satisfy your desire. You can skip this step for now if you are undecided about what to run or just need basic services like the built-in shell scripting.&lt;br /&gt;
&lt;br /&gt;
 apk add R postgresql&lt;br /&gt;
&lt;br /&gt;
In order to automate these jobs, we will be using Cronicle. It depends on node.js so we need to install the prerequisites. It’s run script is fetched using curl, so that will also need to be installed.&lt;br /&gt;
&lt;br /&gt;
 apk add nodejs npm curl&lt;br /&gt;
&lt;br /&gt;
The installation is done as follows (it is a oneliner even if it looks broken here).&lt;br /&gt;
&lt;br /&gt;
 curl -s https://raw.githubusercontent.com/jhuckaby/Cronicle/master/bin/install.js | node&lt;br /&gt;
&lt;br /&gt;
I want to use standard ports, so I had to change the config slightly.&lt;br /&gt;
&lt;br /&gt;
 nano /opt/cronicle/conf/config.json&lt;br /&gt;
&lt;br /&gt;
Change base_app_url from port 3012 to 80. Much further down, change http_port from 3012 to 80, and https_port from 3013 to 443. If you want mail to be sent, change smtp_hostname at the beginning of the file to the mail relay you are using. After that, an initialization script needs to be run.&lt;br /&gt;
&lt;br /&gt;
 /opt/cronicle/bin/control.sh setup&lt;br /&gt;
&lt;br /&gt;
We need to get it running at boot time. This is, however, a service that we do not want to “kill” using a PID, so we are going to enable local scripts that start and stop the service in a controlled manner instead.&lt;br /&gt;
&lt;br /&gt;
 rc-update add local default&lt;br /&gt;
 nano /etc/local.d/cronicle.start&lt;br /&gt;
&lt;br /&gt;
This new file should have the following line in it:&lt;br /&gt;
&lt;br /&gt;
 /opt/cronicle/bin/control.sh start&lt;br /&gt;
&lt;br /&gt;
Now we need to create a stop file as well:&lt;br /&gt;
&lt;br /&gt;
 nano /etc/local.d/cronicle.stop&lt;br /&gt;
&lt;br /&gt;
This file should have the contents:&lt;br /&gt;
&lt;br /&gt;
 /opt/cronicle/bin/control.sh stop&lt;br /&gt;
&lt;br /&gt;
In order for the local script daemon to run these, they need to be executable.&lt;br /&gt;
&lt;br /&gt;
 chmod +x /etc/local.d/cronicle.*&lt;br /&gt;
&lt;br /&gt;
With that, let’s secure things.&lt;br /&gt;
&lt;br /&gt;
=== Hardening ===&lt;br /&gt;
&lt;br /&gt;
Now that most configuring is done, it’s time to harden the Pi. First we will install a firewall with some basic login protection using the builtin &#039;limit&#039; in iptables. Assuming you are in the 192.168.1.0/24 range, which was set during setup-alpine, the following should be run. Only clients on the local network are allowed access to shared folders.&lt;br /&gt;
&lt;br /&gt;
 apk add ufw@testing&lt;br /&gt;
 rc-update add ufw default&lt;br /&gt;
 ufw allow 22&lt;br /&gt;
 ufw limit 22/tcp&lt;br /&gt;
 ufw allow 80&lt;br /&gt;
 ufw allow 443&lt;br /&gt;
 ufw allow from 192.168.1.0/24 to any app CIFS&lt;br /&gt;
 ufw allow Bonjour&lt;br /&gt;
&lt;br /&gt;
With the rules in place, it’s time to disallow root login via ssh, and make sure only fresh protocols are used.&lt;br /&gt;
&lt;br /&gt;
 nano /etc/ssh/sshd_config&lt;br /&gt;
&lt;br /&gt;
Change the line that previously said yes to no, and add the other lines at the bottom of the file (borrowed from this security site):&lt;br /&gt;
&lt;br /&gt;
 PermitRootLogin no&lt;br /&gt;
 PrintMotd no&lt;br /&gt;
 Protocol 2&lt;br /&gt;
 HostKey /etc/ssh/ssh_host_ed25519_key&lt;br /&gt;
 HostKey /etc/ssh/ssh_host_rsa_key&lt;br /&gt;
 KexAlgorithms curve25519-sha256@libssh.org,diffie-hellman-group-exchange-sha256&lt;br /&gt;
 Ciphers chacha20-poly1305@openssh.com,aes256-gcm@openssh.com,aes128-gcm@openssh.com,aes256-ctr,aes192-ctr,aes128-ctr&lt;br /&gt;
 MACs hmac-sha2-512-etm@openssh.com,hmac-sha2-256-etm@openssh.com,umac-128-etm@openssh.com,hmac-sha2-512,hmac-sha2-256,umac-128@openssh.com&lt;br /&gt;
&lt;br /&gt;
After that, enable ufw and restart sshd. Note: if something goes wrong here, you will need to plug in a monitor and keyboard again to login locally and fix things.&lt;br /&gt;
&lt;br /&gt;
 ufw enable&lt;br /&gt;
 rc-service sshd restart&lt;br /&gt;
&lt;br /&gt;
Now is a good time to reboot and reconnect to check that everything is working.&lt;br /&gt;
&lt;br /&gt;
 reboot&lt;br /&gt;
&lt;br /&gt;
With root not being able to login, you will instead login as &amp;quot;pi&amp;quot;. It is possible for this user to (temporarily, until exit) elevate privileges with the following command:&lt;br /&gt;
&lt;br /&gt;
 su&lt;br /&gt;
&lt;br /&gt;
Another option is to use sudo, but I will leave it like this for now, and go ahead with setting up some jobs. That’s a story for another article though.&lt;br /&gt;
&lt;br /&gt;
I hope this guide has been of help. It should be of use for anyone tinkering with Alpine on their Raspberries, and likely some parts for those running other Linux flavors on different hardware as well.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Category:Raspberry]]&lt;/div&gt;</summary>
		<author><name>Maestro-jiggiE</name></author>
	</entry>
	<entry>
		<id>https://wiki.alpinelinux.org/w/index.php?title=Raspberry_Pi_4_-_Persistent_system_acting_as_a_NAS_and_Time_Machine&amp;diff=26637</id>
		<title>Raspberry Pi 4 - Persistent system acting as a NAS and Time Machine</title>
		<link rel="alternate" type="text/html" href="https://wiki.alpinelinux.org/w/index.php?title=Raspberry_Pi_4_-_Persistent_system_acting_as_a_NAS_and_Time_Machine&amp;diff=26637"/>
		<updated>2024-04-17T04:15:29Z</updated>

		<summary type="html">&lt;p&gt;Maestro-jiggiE: the diskutil command needs to be run as sudo and the configuration provided did not work for me. However, after reformatting as edited above, my microsd card was formatted correctly.&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Tinker, Tailor, Raspberry Pi ==&lt;br /&gt;
&lt;br /&gt;
I went ahead and got myself a Raspberry Pi 4B with 4GB RAM, which I intend to use as a job scheduling server, only to find out that the suggested OS, Raspberry Pi OS, is 32-bit. Fortunately, the Linux distro Alpine, which I’ve grown very fond of lately, is available for Raspberry Pi as aarch64, meaning it’s both 64-bit kernel and userland. Unfortunately the distro is currently, as of version 3.12, not set up for persistent storage and is more of a live playground. Gathering bits and pieces from various guides online, that can be remedied with some tinkering. On this page you will find how to set up a persistent 64-bit OS on the Raspberry Pi, share a USB attached disk, as well as some interesting software.&lt;br /&gt;
&lt;br /&gt;
Note: the Pi 4 has micro-HDMI ports. I thought they were mini, for which I already had cabling, but alas, another adapter had to be purchased. Also, when attaching a USB disk it is better if it is externally powered. The Pi can however power newer external SSD drives that have low power consumption. I tried with a USB powered magnetic disk drive, but it behaved somewhat strangely. With that said, let’s look at how to get yourself a shiny, tiny, new server.&lt;br /&gt;
&lt;br /&gt;
=== Tinkering for Persistence ===&lt;br /&gt;
&lt;br /&gt;
After downloading the Alpine v3.12 tarball, the next step is to set up the SDHC card for the Pi. I borrowed a MacBook Air, since it has a built-in card reader. The Pi boots off a FAT32 partition, but ultimately, we want the system to reside in an ext4 partition. We&#039;ll start by reserving a small portion of the card for the boot partition. This is done using Terminal in macOS with the following commands.&lt;br /&gt;
&lt;br /&gt;
 diskutil list&lt;br /&gt;
 sudo diskutil partitionDisk disk2 MBR FREE SYS R FAT32 ALP 256MB&lt;br /&gt;
 sudo fdisk -e /dev/disk2&lt;br /&gt;
 &amp;gt; f 1&lt;br /&gt;
 &amp;gt; w&lt;br /&gt;
 &amp;gt; exit&lt;br /&gt;
&lt;br /&gt;
The tarball should have decompressed once it hit your download folder. If not, use the option “xvzf” for tar.&lt;br /&gt;
&lt;br /&gt;
 cd /Volumes/ALP&lt;br /&gt;
 tar xvf ~/Downloads/alpine-rpi-3.12.0-aarch64.tar&lt;br /&gt;
 nano usercfg.txt&lt;br /&gt;
&lt;br /&gt;
The newly created file usercfg.txt should contain the following:&lt;br /&gt;
&lt;br /&gt;
 enable_uart=1&lt;br /&gt;
 gpu_mem=32&lt;br /&gt;
 disable_overscan=1&lt;br /&gt;
&lt;br /&gt;
The smallest amount of memory for a headless install is 32MB. Removing overscan gives you more usable screen area. If you intend to use this as a desktop computer rather than a headless server, you probably want to allocate more memory to the GPU and enable sound. Full specifications for options can be found on the official Raspberry Pi homepage.&lt;br /&gt;
&lt;br /&gt;
After that, you need to make sure the card is not busy. Change to a safe directory then eject the card (making sure that any pending writes are finalized).&lt;br /&gt;
&lt;br /&gt;
 cd&lt;br /&gt;
 diskutil eject /dev/disk2&lt;br /&gt;
&lt;br /&gt;
Put the SDHC card in the Pi and boot. Login with “root” as username and no password. This presumes that you have connected everything else, e.g. a keyboard and monitor.&lt;br /&gt;
&lt;br /&gt;
 setup-alpine&lt;br /&gt;
&lt;br /&gt;
During setup, select your keymap, hostname, etc, as desired. However, when asked where to store configs, type “none”, and the same for the apk cache directory. If you want to follow this guide to the point, you should also select “chrony” as the NTP client. The most important part here though is to get your network up and running. A full description of the setup programs can be found on the Alpine homepage.&lt;br /&gt;
&lt;br /&gt;
 apk update&lt;br /&gt;
 apk upgrade&lt;br /&gt;
 apk add cfdisk&lt;br /&gt;
 cfdisk /dev/mmcblk0&lt;br /&gt;
&lt;br /&gt;
In cfdisk, select “Free space” and the &amp;quot;New&amp;quot; option. It will suggest using the entire available space, so just press enter, then select the option &amp;quot;primary&amp;quot; followed by &amp;quot;Write&amp;quot;. Type &amp;quot;yes&amp;quot; to write the partition table to disk, then select &amp;quot;Quit&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
 apk add e2fsprogs&lt;br /&gt;
 mkfs.ext4 /dev/mmcblk0p2&lt;br /&gt;
 mount /dev/mmcblk0p2 /mnt&lt;br /&gt;
 export FORCE_BOOTFS=1                 # work around for issue 12353&lt;br /&gt;
 setup-disk -m sys /mnt&lt;br /&gt;
 mount -o remount,rw /media/mmcblk0p1&lt;br /&gt;
&lt;br /&gt;
Ignore the warnings about extlinux. This and the following trick was found in the Alpine Wiki, but in a confusing order. &lt;br /&gt;
&lt;br /&gt;
 rm -f /media/mmcblk0p1/boot/*&lt;br /&gt;
 cd /mnt&lt;br /&gt;
 rm boot/boot&lt;br /&gt;
 mv boot/* /media/mmcblk0p1/boot/&lt;br /&gt;
 rm -Rf boot&lt;br /&gt;
 mkdir media/mmcblk0p1&lt;br /&gt;
 ln -s media/mmcblk0p1/boot boot&lt;br /&gt;
&lt;br /&gt;
Now the mountpoints need fixing, so run:&lt;br /&gt;
&lt;br /&gt;
 apk add nano&lt;br /&gt;
 nano etc/fstab&lt;br /&gt;
&lt;br /&gt;
If you prefer some other editor (since people tend to become religious about these things) feel free to use whatever you want. Add the following line:&lt;br /&gt;
&lt;br /&gt;
 /dev/mmcblk0p1   /media/mmcblk0p1   vfat   defaults   0 0&lt;br /&gt;
&lt;br /&gt;
Now the kernel needs to know where the root filesystem is.&lt;br /&gt;
&lt;br /&gt;
 nano /media/mmcblk0p1/cmdline.txt&lt;br /&gt;
&lt;br /&gt;
Append the following at the end of the one and only line in the file:&lt;br /&gt;
&lt;br /&gt;
 root=/dev/mmcblk0p2&lt;br /&gt;
&lt;br /&gt;
After exiting nano, reboot:&lt;br /&gt;
&lt;br /&gt;
 reboot&lt;br /&gt;
&lt;br /&gt;
After rebooting, login using &amp;quot;root&amp;quot; as username, and the password you selected during setup-alpine earlier. Now you have a persistent system, as opposed to the way the original distro was configured.&lt;br /&gt;
&lt;br /&gt;
=== Tailoring for Remote Access ===&lt;br /&gt;
&lt;br /&gt;
OpenSSH should already be installed, but it will not allow remote root login. Initially, we&#039;ll relax this restriction. Last in this article is a section on hardening where we again disallow root login. If you intend to have this box accessible from the Internet, I strongly advise hardening the Pi.&lt;br /&gt;
&lt;br /&gt;
 nano /etc/ssh/sshd_config&lt;br /&gt;
&lt;br /&gt;
Uncomment and change the line (about 30 lines down) with PermitRootLogin to:&lt;br /&gt;
&lt;br /&gt;
 PermitRootLogin yes&lt;br /&gt;
&lt;br /&gt;
Then restart the service:&lt;br /&gt;
&lt;br /&gt;
 rc-service sshd restart&lt;br /&gt;
&lt;br /&gt;
Now you should be able to ssh to your Pi. The following steps are easier when you can cut and paste things into a terminal window.&lt;br /&gt;
&lt;br /&gt;
=== Keeping the Time ===&lt;br /&gt;
&lt;br /&gt;
If you selected chrony as your NTP client, it may take a long time for it to correct the clock. Since the Pi does not have a hardware clock, it’s necessary to have the correct time at bootup. We&#039;ll change the configuration such that the clock gets set if it is more than 60 seconds off during the first 10 lookups. &lt;br /&gt;
&lt;br /&gt;
 nano /etc/chrony/chrony.conf&lt;br /&gt;
&lt;br /&gt;
Add the following line at the bottom of the file.&lt;br /&gt;
&lt;br /&gt;
 makestep 60 10&lt;br /&gt;
&lt;br /&gt;
Check the date, restart the service, and check the (now hopefully corrected) date again.&lt;br /&gt;
&lt;br /&gt;
 date&lt;br /&gt;
 rc-service chronyd restart&lt;br /&gt;
 date&lt;br /&gt;
&lt;br /&gt;
Having the correct time is a good thing, particularly when building a job scheduling server.&lt;br /&gt;
&lt;br /&gt;
=== Silencing the Fan ===&lt;br /&gt;
&lt;br /&gt;
Together with the Pi, I also bought a fan, the Pimoroni Fan Shim. According to reviews it is one of the better ways to cool your Pi. Unless control software is installed, it runs at full speed. It’s not noisy, but still noticeable a meter from the Pi. Again, some tinkering will be needed since the control software needs some prerequisites installed. We lost nano between reboots, so we&#039;ll reinstall it.&lt;br /&gt;
&lt;br /&gt;
 apk update&lt;br /&gt;
 apk upgrade&lt;br /&gt;
 apk add nano&lt;br /&gt;
&lt;br /&gt;
Other software we need is in the “community” repositories of Alpine. In order to activate that repository, we need to edit a file:&lt;br /&gt;
&lt;br /&gt;
 nano /etc/apk/repositories&lt;br /&gt;
&lt;br /&gt;
Uncomment the second line (ending in v3.12/community), exit, then install the necessary packages.&lt;br /&gt;
&lt;br /&gt;
 apk update&lt;br /&gt;
 apk add git bash python3 python3-dev py3-pip py3-wheel build-base&lt;br /&gt;
&lt;br /&gt;
After those prerequisites are in place, install the fan shim software using:&lt;br /&gt;
&lt;br /&gt;
 git clone https://github.com/pimoroni/fanshim-python&lt;br /&gt;
 cd fanshim-python&lt;br /&gt;
 ./install.sh&lt;br /&gt;
 apk add py3-psutil&lt;br /&gt;
 cd examples&lt;br /&gt;
 ./install-service.sh&lt;br /&gt;
&lt;br /&gt;
The last script will fail with “systemctl: command not found”, since Alpine uses OpenRC as its init system, and not systemd which this script presumes.&lt;br /&gt;
We&#039;ll write our own startup script:&lt;br /&gt;
&lt;br /&gt;
 nano /etc/init.d/fanshim&lt;br /&gt;
&lt;br /&gt;
The new file should have the following contents:&lt;br /&gt;
&lt;br /&gt;
 #!/sbin/openrc-run&lt;br /&gt;
 name=&amp;quot;fanshim&amp;quot;&lt;br /&gt;
 command=&amp;quot;/usr/bin/python3 /root/fanshim-python/examples/automatic.py&amp;quot;&lt;br /&gt;
 command_args=&amp;quot;--on-threshold 65 --off-threshold 55 --delay 2&amp;quot;&lt;br /&gt;
 pidfile=&amp;quot;/var/run/$SVCNAME.pid&amp;quot;&lt;br /&gt;
 command_background=&amp;quot;yes&amp;quot;&lt;br /&gt;
&lt;br /&gt;
There are a lot of interesting options for fanshim you can explore, like tuning it’s RGB led. We want this to run at boot time, so add it the the default runlevel, then start it.&lt;br /&gt;
&lt;br /&gt;
 rc-update add fanshim default&lt;br /&gt;
 rc-service fanshim start&lt;br /&gt;
&lt;br /&gt;
Enjoy the silence!&lt;br /&gt;
&lt;br /&gt;
=== Adding and Sharing a Disk ===&lt;br /&gt;
&lt;br /&gt;
Some of files we&#039;ll be transferring are quite large. It would also be neat to be able to access files easily from the Finder in macOS, so I am adding a USB3 connected hard disk with 4TB storage. What follows will be very similar to setting up a NAS, and in fact, the way I fell in love with Alpine was by building my own NAS from scratch (with the minor differences being more disks and using zfs). &lt;br /&gt;
&lt;br /&gt;
First we need to change the filesystem. The disk comes formatted as FAT32, which is very poorly suited for a network disk. Samba, which is what we will be using for sharing, more or less requires a filesystem that supports extended attributes. After plugging in the drive, we will repartition the drive and format it to ext4. &lt;br /&gt;
&lt;br /&gt;
 cfdisk /dev/sda&lt;br /&gt;
&lt;br /&gt;
Using cfdisk, delete any existing partitions and create one new partition. It should become &amp;quot;Linux filesystem&amp;quot; by default. Don’t forget to &amp;quot;Write&amp;quot; before &amp;quot;Quit&amp;quot;ing. Next, format it:&lt;br /&gt;
&lt;br /&gt;
 mkfs.ext4 /dev/sda1&lt;br /&gt;
&lt;br /&gt;
Now we need to add autofs to get automatic mounting. This package is in edge/testing though, so we need to enable that branch and repository, but still have main and community take preference. This can be done by labelling a repository.&lt;br /&gt;
&lt;br /&gt;
 nano /etc/apk/repositories&lt;br /&gt;
&lt;br /&gt;
Change the line with the testing repository to the following. Note that yours will have some server.from.setup/path depending on what you selected in setup-alpine. You only uncomment and add the @testing label in other words.&lt;br /&gt;
&lt;br /&gt;
 @testing http://&amp;lt;server.from.setup/path&amp;gt;/edge/testing&lt;br /&gt;
&lt;br /&gt;
Now autofs can be installed from the labelled repo.&lt;br /&gt;
&lt;br /&gt;
 apk add autofs@testing&lt;br /&gt;
&lt;br /&gt;
Note that dependencies are still pulled from main/community to the extent it is possible. In order to configure autofs, first:&lt;br /&gt;
&lt;br /&gt;
 nano /etc/autofs/auto.master&lt;br /&gt;
&lt;br /&gt;
Add the following line after the uncommented line starting with /misc. It will also disconnect the hard disk after 5 minutes to save energy:&lt;br /&gt;
&lt;br /&gt;
 /-   /etc/autofs/auto.hdd   --timeout=300&lt;br /&gt;
&lt;br /&gt;
Then create this new config file:&lt;br /&gt;
&lt;br /&gt;
 nano /etc/autofs/auto.hdd&lt;br /&gt;
&lt;br /&gt;
Add the the following line to the empty file.&lt;br /&gt;
&lt;br /&gt;
 /hdd   -fstype=ext4   :/dev/sda1&lt;br /&gt;
&lt;br /&gt;
Now, the user pi needs to be created.&lt;br /&gt;
&lt;br /&gt;
 adduser pi&lt;br /&gt;
 smbpasswd -a pi&lt;br /&gt;
&lt;br /&gt;
Select passwords for the pi user. The latter one will later be stored in the macOS keychain and therefore easy to forget, so make note of it somewhere. &lt;br /&gt;
&lt;br /&gt;
Add autofs to startup and start it now. Change the ownership of /hdd to pi.&lt;br /&gt;
&lt;br /&gt;
 rc-update add autofs default&lt;br /&gt;
 rc-service autofs start&lt;br /&gt;
 chown -R pi.pi /hdd&lt;br /&gt;
&lt;br /&gt;
With that in place (disk can be accessed through /hdd) it is time to set up the sharing. For this we will use samba and avahi for network discovery.&lt;br /&gt;
&lt;br /&gt;
 apk add samba avahi dbus&lt;br /&gt;
 nano /etc/samba/smb.cfg&lt;br /&gt;
&lt;br /&gt;
Now, this is what my entire smb.cfg file looks like, with all the tweaks to get stuff running well from macOS.&lt;br /&gt;
&lt;br /&gt;
 [global]&lt;br /&gt;
  create mask = 0664&lt;br /&gt;
  directory mask = 0775&lt;br /&gt;
  veto files = /.DS_Store/lost+found/&lt;br /&gt;
  delete veto files = true&lt;br /&gt;
  nt acl support = no&lt;br /&gt;
  inherit acls = yes&lt;br /&gt;
  ea support = yes&lt;br /&gt;
  security = user&lt;br /&gt;
  passdb backend = tdbsam&lt;br /&gt;
  map to guest = Bad User&lt;br /&gt;
  vfs objects = catia fruit streams_xattr recycle&lt;br /&gt;
  acl_xattr:ignore system acls = yes&lt;br /&gt;
  recycle:repository = .recycle&lt;br /&gt;
  recycle:keeptree = yes&lt;br /&gt;
  recycle:versions = yes&lt;br /&gt;
  fruit:aapl = yes&lt;br /&gt;
  fruit:metadata = stream&lt;br /&gt;
  fruit:model = MacSamba&lt;br /&gt;
  fruit:veto_appledouble = yes&lt;br /&gt;
  fruit:posix_rename = yes &lt;br /&gt;
  fruit:zero_file_id = yes&lt;br /&gt;
  fruit:wipe_intentionally_left_blank_rfork = yes &lt;br /&gt;
  fruit:delete_empty_adfiles = yes &lt;br /&gt;
  server max protocol = SMB3&lt;br /&gt;
  server min protocol = SMB2&lt;br /&gt;
  workgroup = WORKGROUP    &lt;br /&gt;
  server string = NAS      &lt;br /&gt;
  server role = standalone server&lt;br /&gt;
  dns proxy = no&lt;br /&gt;
 [Harddisk]&lt;br /&gt;
  comment = Raspberry Pi Removable Harddisk                     &lt;br /&gt;
  path = /hdd    &lt;br /&gt;
  browseable = yes          &lt;br /&gt;
  writable = yes            &lt;br /&gt;
  spotlight = yes           &lt;br /&gt;
  valid users = pi       &lt;br /&gt;
  fruit:resource = xattr &lt;br /&gt;
  fruit:time machine = yes&lt;br /&gt;
  fruit:advertise_fullsync = true&lt;br /&gt;
&lt;br /&gt;
Those last two lines can be removed if you are not interested in using the disk as a Time Machine backup for your Apple devices. I will likely not use it, but since this is how I configured my NAS and it was a hassle to figure out how to get it working I thought I’d leave it here for reference. Doesn’t hurt to keep it there.&lt;br /&gt;
&lt;br /&gt;
Let us also configure the avahi-daemon, by creating a config file for the samba service. Avahi will announce the server using Bonjour, making them easily recognizable from macOS (where they automagically show up in the Finder). &lt;br /&gt;
&lt;br /&gt;
 nano /etc/avahi/services/samba.service&lt;br /&gt;
&lt;br /&gt;
This new file should have the following contents:&lt;br /&gt;
&lt;br /&gt;
 &amp;lt;?xml version=&amp;quot;1.0&amp;quot; standalone=&#039;no&#039;?&amp;gt;&lt;br /&gt;
 &amp;lt;!DOCTYPE service-group SYSTEM &amp;quot;avahi-service.dtd&amp;quot;&amp;gt;&lt;br /&gt;
 &amp;lt;service-group&amp;gt;&lt;br /&gt;
 &amp;lt;name replace-wildcards=&amp;quot;yes&amp;quot;&amp;gt;%h&amp;lt;/name&amp;gt;&lt;br /&gt;
 &amp;lt;service&amp;gt;&lt;br /&gt;
 &amp;lt;type&amp;gt;_smb._tcp&amp;lt;/type&amp;gt;&lt;br /&gt;
 &amp;lt;port&amp;gt;445&amp;lt;/port&amp;gt;&lt;br /&gt;
 &amp;lt;/service&amp;gt;&lt;br /&gt;
 &amp;lt;service&amp;gt;&lt;br /&gt;
 &amp;lt;type&amp;gt;_device-info._tcp&amp;lt;/type&amp;gt;&lt;br /&gt;
 &amp;lt;port&amp;gt;0&amp;lt;/port&amp;gt;&lt;br /&gt;
 &amp;lt;txt-record&amp;gt;model=RackMac&amp;lt;/txt-record&amp;gt;&lt;br /&gt;
 &amp;lt;/service&amp;gt;&lt;br /&gt;
 &amp;lt;service&amp;gt;&lt;br /&gt;
 &amp;lt;type&amp;gt;_adisk._tcp&amp;lt;/type&amp;gt;&lt;br /&gt;
 &amp;lt;txt-record&amp;gt;sys=waMa=0,adVF=0x100&amp;lt;/txt-record&amp;gt;&lt;br /&gt;
 &amp;lt;txt-record&amp;gt;dk0=adVN=HDD,adVF=0x82&amp;lt;/txt-record&amp;gt;&lt;br /&gt;
 &amp;lt;/service&amp;gt;&lt;br /&gt;
 &amp;lt;/service-group&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Not that the txt-record containing adVN=HDD can be removed if you are not interested in using the disk as a Time Machine backup. Still, leaving it won’t hurt.&lt;br /&gt;
&lt;br /&gt;
Finally, it’s time to add samba and avahi to the startup, and start the services.&lt;br /&gt;
&lt;br /&gt;
 rc-update add samba default&lt;br /&gt;
 rc-update add avahi-daemon default&lt;br /&gt;
 rc-service samba start&lt;br /&gt;
 rc-service avahi-daemon start&lt;br /&gt;
&lt;br /&gt;
The disk should now be visible from macOS. Remember to click “Connect as…” and enter “pi” as the username and your selected smbpasswd from earlier. Check the box “Remember this password in my keychain” for quicker access next time. Sometimes, due to a bug in Catalina, you may get “The original item cannot be found” when accessing the remote disk. If that happens, force quit Finder, and you should be good to go again. If anyone knows of any other fix to this issue, let me know!&lt;br /&gt;
&lt;br /&gt;
=== Automation ===&lt;br /&gt;
&lt;br /&gt;
This server will be used as a job server. Some of the jobs running will need the psql command from PostgreSQL and some others will be R jobs. Let’s install both, or whatever you need to satisfy your desire. You can skip this step for now if you are undecided about what to run or just need basic services like the built-in shell scripting.&lt;br /&gt;
&lt;br /&gt;
 apk add R postgresql&lt;br /&gt;
&lt;br /&gt;
In order to automate these jobs, we will be using Cronicle. It depends on node.js so we need to install the prerequisites. It’s run script is fetched using curl, so that will also need to be installed.&lt;br /&gt;
&lt;br /&gt;
 apk add nodejs npm curl&lt;br /&gt;
&lt;br /&gt;
The installation is done as follows (it is a oneliner even if it looks broken here).&lt;br /&gt;
&lt;br /&gt;
 curl -s https://raw.githubusercontent.com/jhuckaby/Cronicle/master/bin/install.js | node&lt;br /&gt;
&lt;br /&gt;
I want to use standard ports, so I had to change the config slightly.&lt;br /&gt;
&lt;br /&gt;
 nano /opt/cronicle/conf/config.json&lt;br /&gt;
&lt;br /&gt;
Change base_app_url from port 3012 to 80. Much further down, change http_port from 3012 to 80, and https_port from 3013 to 443. If you want mail to be sent, change smtp_hostname at the beginning of the file to the mail relay you are using. After that, an initialization script needs to be run.&lt;br /&gt;
&lt;br /&gt;
 /opt/cronicle/bin/control.sh setup&lt;br /&gt;
&lt;br /&gt;
We need to get it running at boot time. This is, however, a service that we do not want to “kill” using a PID, so we are going to enable local scripts that start and stop the service in a controlled manner instead.&lt;br /&gt;
&lt;br /&gt;
 rc-update add local default&lt;br /&gt;
 nano /etc/local.d/cronicle.start&lt;br /&gt;
&lt;br /&gt;
This new file should have the following line in it:&lt;br /&gt;
&lt;br /&gt;
 /opt/cronicle/bin/control.sh start&lt;br /&gt;
&lt;br /&gt;
Now we need to create a stop file as well:&lt;br /&gt;
&lt;br /&gt;
 nano /etc/local.d/cronicle.stop&lt;br /&gt;
&lt;br /&gt;
This file should have the contents:&lt;br /&gt;
&lt;br /&gt;
 /opt/cronicle/bin/control.sh stop&lt;br /&gt;
&lt;br /&gt;
In order for the local script daemon to run these, they need to be executable.&lt;br /&gt;
&lt;br /&gt;
 chmod +x /etc/local.d/cronicle.*&lt;br /&gt;
&lt;br /&gt;
With that, let’s secure things.&lt;br /&gt;
&lt;br /&gt;
=== Hardening ===&lt;br /&gt;
&lt;br /&gt;
Now that most configuring is done, it’s time to harden the Pi. First we will install a firewall with some basic login protection using the builtin &#039;limit&#039; in iptables. Assuming you are in the 192.168.1.0/24 range, which was set during setup-alpine, the following should be run. Only clients on the local network are allowed access to shared folders.&lt;br /&gt;
&lt;br /&gt;
 apk add ufw@testing&lt;br /&gt;
 rc-update add ufw default&lt;br /&gt;
 ufw allow 22&lt;br /&gt;
 ufw limit 22/tcp&lt;br /&gt;
 ufw allow 80&lt;br /&gt;
 ufw allow 443&lt;br /&gt;
 ufw allow from 192.168.1.0/24 to any app CIFS&lt;br /&gt;
 ufw allow Bonjour&lt;br /&gt;
&lt;br /&gt;
With the rules in place, it’s time to disallow root login via ssh, and make sure only fresh protocols are used.&lt;br /&gt;
&lt;br /&gt;
 nano /etc/ssh/sshd_config&lt;br /&gt;
&lt;br /&gt;
Change the line that previously said yes to no, and add the other lines at the bottom of the file (borrowed from this security site):&lt;br /&gt;
&lt;br /&gt;
 PermitRootLogin no&lt;br /&gt;
 PrintMotd no&lt;br /&gt;
 Protocol 2&lt;br /&gt;
 HostKey /etc/ssh/ssh_host_ed25519_key&lt;br /&gt;
 HostKey /etc/ssh/ssh_host_rsa_key&lt;br /&gt;
 KexAlgorithms curve25519-sha256@libssh.org,diffie-hellman-group-exchange-sha256&lt;br /&gt;
 Ciphers chacha20-poly1305@openssh.com,aes256-gcm@openssh.com,aes128-gcm@openssh.com,aes256-ctr,aes192-ctr,aes128-ctr&lt;br /&gt;
 MACs hmac-sha2-512-etm@openssh.com,hmac-sha2-256-etm@openssh.com,umac-128-etm@openssh.com,hmac-sha2-512,hmac-sha2-256,umac-128@openssh.com&lt;br /&gt;
&lt;br /&gt;
After that, enable ufw and restart sshd. Note: if something goes wrong here, you will need to plug in a monitor and keyboard again to login locally and fix things.&lt;br /&gt;
&lt;br /&gt;
 ufw enable&lt;br /&gt;
 rc-service sshd restart&lt;br /&gt;
&lt;br /&gt;
Now is a good time to reboot and reconnect to check that everything is working.&lt;br /&gt;
&lt;br /&gt;
 reboot&lt;br /&gt;
&lt;br /&gt;
With root not being able to login, you will instead login as &amp;quot;pi&amp;quot;. It is possible for this user to (temporarily, until exit) elevate privileges with the following command:&lt;br /&gt;
&lt;br /&gt;
 su&lt;br /&gt;
&lt;br /&gt;
Another option is to use sudo, but I will leave it like this for now, and go ahead with setting up some jobs. That’s a story for another article though.&lt;br /&gt;
&lt;br /&gt;
I hope this guide has been of help. It should be of use for anyone tinkering with Alpine on their Raspberries, and likely some parts for those running other Linux flavors on different hardware as well.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Category:Raspberry]]&lt;/div&gt;</summary>
		<author><name>Maestro-jiggiE</name></author>
	</entry>
</feed>