User Tools

Site Tools


doc:appunti:hardware:raspberrypi_nas

This is an old revision of the document!


Home Mediacenter and NAS with the Raspberry Pi

This is my recipe to build a mediacenter and NAS box using the Raspberry Pi. This is the list of components:

  • Raspberry Pi 4.
  • Seagate IronWolf 3.5 inch Hard disk, 4 Tb.
  • Suptronics.com X835 exapnsion board to connect SATA drives.

Subsystems

Networking

Current release of RaspiOS (we are on Debian 10 Buster) uses dhcpcd to manage networking (see Raspberry Pi TCP/IP Networking). This means that:

  • Use /etc/dhcpcd.conf file to define static IP address or fallback IP address (if DHCP fails). The same file is used to e.g. disable WiFi (wlan0) interface.
  • Do not use /etc/network/interfaces for static or dynamic IP assignment.
  • WiFi ESSIDs and passwords are in /etc/wpa_supplicant/wpa_supplicant.conf.
  • Do not install Network Manager.
  • If a gaphical interface is needed, use lxplug-network.
  • If some package installs the systemd wpa_supplicant.service, disable it or you will have two conflicting wpa_supplicant processes running (execute the systemctl disable wpa_supplicant.service command and reboot).

I want the eth0 interface to have a static IP address beside the one eventually assigned by DHCP (i.e. I want an IP alias on eth0:0). This is useful when I wan connect to the host even in an unknown network. To achieve this when dhcpcd is running, it is necessary to create an user defined hook script. See this page for more details: How to configure an IP alias with dhcpcd.

Mail system

I want a working mail system on the NAS, mainly because I want to eventually receive error messages from the various subsystems, think e.g. at the smartd daemon watching for S.M.A.R.T. hard drive errors…

In the following examples pimedianas is the hostname of my Raspberry Pi Mediacenter NAS. I istalled the postfix package and configured it as satellite system using a SMTP relay host. The relevant settings in /etc/postfix/main.cf are:

myhostname = pimedianas
mydestination = $myhostname, localhost.localdomain, localhost
relayhost = mail.example.org:587
default_transport = smtp
relay_transport = smtp
myorigin = $myhostname
# Rewrite some sender addresses.
sender_canonical_maps = hash:/etc/postfix/sender_canonical_maps
# Relay host requires SASL authentication.
smtp_sasl_auth_enable = yes
smtp_sasl_password_maps = hash:/etc/postfix/sasl_passwd
smtp_sasl_mechanism_filter = plain, login
smtp_sasl_security_options =
smtp_tls_security_level = may

The content of /etc/postfix/sender_canonical_maps will force the MAIL FROM on locally generated mails:

root                       pimedianas@example.org
root@pimedianas            pimedianas@example.org
root@localhost             pimedianas@example.org
root@localhost.localdomain pimedianas@example.org

Write the proper info about localhost in /etc/hosts:

127.0.1.1  localhost.localdomain   localhost

Finally I had to put my SMTP credentials required by the relaying server into /etc/postfix/sasl_passwd:

mail.example.org pimedianas:MyVerySecretPwd

Last but not least, I redirected all the mail for root to my real email address in /etc/aliases:

root:   niccolo@example.org

Remember to compile all the files and restart the service:

postmap /etc/postfix/sasl_passwd
postmap /etc/postfix/sender_canonical_maps
newaliases
systemctl restart postfix.service

Now all the locally generated mails addressed to root, root@pimedianas, root@localhost or root@localhost.localdomain should have the MAIL FROM rewritten as above and forwarded to the external mailbox.

Hard disk management

The smartctl tool from the smartmontools package requires the -d sat option to access the hard disk through the USB bridge with the right protocol.

See all the S.M.A.R.T. data of the drive:

smartctl -d sat -a /dev/sda

To enable the smartd service I had to configure the /etc/smartd.conf:

# Disable DEVICESCAN, which does not work in our environment.
#DEVICESCAN -d removable -n standby -m root -M exec /usr/share/smartmontools/smartd-runner

# Send an email test to <root@localhost> on daemon start.
/dev/sda -d sat -m root@localhost -M test

# Use the suggedested subset of checks, instead of the '-a'.
/dev/sda -d sat \
    -H \                # Check the health with the SMART RETURN STATUS command
    -l selftest \       # Report increasing number of failed Self-Test
    -l error \          # Report increasing errors number in the Summary SMART error log
    -f \                # Check for 'failure' of any Usage Attributes
    -n standby,336 \    # Skip smartd checks during standby (max 336 times, add ',q' for quiet)
    -W 0,50,60 \        # Report Temperature Celsius WARN=50, CRIT=60 (SMART attribute 194)
    -s S/../../1/23 \   # Schedule a short Self-Test at 23:00 of every monday.
    -m root@localhost \ # Send a warning email on failures and errors
    -M daily \          # Repeat email warnings daily
    -M test             # Send an email test on daemon start

The smartd daemon has a default device polling cycle of 30 minutes, we want to increase this interval otherwise the disk will never reach an inactivity period longer than that. Edit the /etc/default/smartmontools file and set:

smartd_opts="--interval=3600"

Restart the smartd.service and verify that the smartd program is running with that paramter (3600 seconds, i.e. one hour, instead of 30 minutes).

To set the Advanced Power Management level use the -B option, the maximum performance level which permits spin-down of the drive is 127:

hdparm -B 127 /dev/sda

Regardless of the APM level, we can set the hard disk Standby timer (spindown) after 30 minutes of inactivity. See man hdparm for explanation of the number following the -S option (it seems that there is not way to know the timeout once you have set it):

hdparm -S 241 /dev/sda

WARNING: If both APM and the Standby timer are set, then the device shall go to the Standby state when the timer expires or the device’s APM algorithm indicates that the Standby state should be entered. If you want a time exact spin-down, use the -S Standby timer, because APM algorithm (including its spin-down timeout) is device dependant and you cannot control it. See p.19 of ATA/ATAPI Command Set - 2 (ACS-2).

Enable the most quiet acoustic management (it is not supported in my case: 4 Tb Seagate IronWolf):

hdparm -M 128 /dev/sda

Check whether the drive is in standby mode, without waking it up:

smartctl -d sat --nocheck=standby,3 /dev/sda

The meaning of standby,3 is: do not check the disk if it is in SLEEP or STANDBY mode (not spinning), return exit code 3 in this case (you can choose your custom exit code). Beside the exit code, these are the output messages:

Device is in ACTIVE or IDLE mode
Device is in STANDBY mode, exit(3)

WARNING: Reading SMART attributes using the smartctl command will reset the Standby timer, even if using the --nocheck=standby option; i.e. that option will prevent exiting from the standby mode, but if smartctl is executed when standby is not yet active, it will reset the timer and this may prevent entering the standby mode, regardless of that option.

Debian provides the file /etc/hdparm.conf which is handled by the udev on system start to set the required parameters. You can set something like this:

# Enable hard disk standby (spin-down) timeout at 30 minutes.
# It is advisable to disable write cache in this case.
# See man hdparm(8), -S and -W options.
/dev/sda {
        write_cache = off
        spindown_time = 241
}

To enforce the setting immediately, you can execute:

DEVNAME=/dev/sda /lib/udev/hdparm

WARNING: When smartctl report the device being in ACTIVE or IDLE mode, the disk may be actually not spinning.

Letting the hard drive to remain in standby mode

Beware that there are several activities which may awake the driver from its stanby status, among that there are:

  • updatedb - Execute by the /etc/cron.daily/mlocate cronjob, will update the database of files stored on hard disk. Add the directory to be skipped into /etc/updatedb.conf.
  • smartctl - Reading SMART attributes (e.g. disk temperature, errors log) awake the disk. Hou may have periodic checks executed by snmpd, etc.

Audio

I want to use Kodi for HDMI video and audio playback, but I want also occasionally to play music using Music Player Daemon, routing the audio to an external amplifier which has RCA stereo connectors. Once the cables are connected, it is also desiderable to play Kodi videos routing video to HDMI monitor and routing audio to the stereo amplifier.

For the software part, the recommended way is to use Pulseaudio as the backend. In this way, both Kodi and MDP can share the audio hardware at the same time, you are free also to use HDMI audio for Kodi (video) and analog RCA for MPD (audio).

For the hardware part, you can use the digital HDMI audio or the analog 3.5 mm jack (which carries video and stereo audio signals over a CTIA 4 poles connector). For a better audio quality you have to connect and audio hat or an external USB audio sound card; as explained below the integrated audio devices are of unacceptable quality also for an occasional user, let alone an audiophile one!

Audio hardware: Raspberry Pi 4

Digital audio through HDMI

HDMI video and audio cable This is the first natuarl choiche, at least when watching videos using Kodi. I use an old Raspberry Pi 3 as a Kodi media center, connected to an HDMI monitor capable of audio too; the sound quality is acceptable and it is aligned to the medium quality of the speakers inside the monitor. Unfortunately I discovered that the Raspberry Pi 4 has a worse audio quality than the Pi 3: I ear continously pops, clicks and little gaps in the music. I tried to swap the power supply and the HDMI cable with better quality ones, but the problem remains. It seems that the problem is not hardware related, but it is introduced when I add Pulseaudio in the software stack. If I select direct Raspberry PI:HDMI as sound device in Kodi, the audio playback is OK.

I prefer to avoid the HDMI audio output mainly because the audio of the HDMI monitor is of poor quality, but another problem is that if the monitor goes into standby (as Kodi does, when you don't play anything), also the audio goes standby. In this condition even the Music Player Damon cannot play to HDMI.

In my opinion, HDMI audio on the Raspberry Pi 4 with Pulseaudio is of unacceptable quality.

Analog audio through the 3.5 mm jack

Audio cable CTIA 3.5 mm jack - RCA stereo The second choice is to use the analog audio through the 3.5 mm jack. I purchased a CTIA 4 poles jack mic/phones splitter and an audio cable with 3.5 mm stereo jack at one end and RCA connecttors at the other. In this way I can connect the Raspberry Pi 4 to my stereo amplifier. The resulting audio volume is too low that I have to push the amplifier volume to the max, just to ear something. The result is unacceptable; pushing the volume so high you start earing the electrical noise and it is impossible to listen to at even medium loudness. The 100% volume level exiting from the Raspberry Pi 4 is equivalent to approximately 50% of the volume of my smartphone, when attached at the same cable.

As far as I know, and according to many articles on the net, there is not solution to this problem.

Using an externa USB sound card

For a decent audio quality, I decided that the only acceptable solution is to relay on an external USB sound card connected to my stereo amplifier. I choosed a model based on the C-Media Electronics chip (USB Id 0d8c:0024), which comes with two standard RCA connectors. The device is compatible with ALSA so the Pulseaudio system can select it per default, setting the following in /etc/pulse/client.conf:

# Audio to USB audio device:
default-sink = alsa_output.usb-C-Media_Electronics_Inc._USB_Advanced_Audio_Device-00.analog-stereo

Audio software: Pulseaudio

As stated above, I want to play audio both with Kodi and with MPD. Both requires libpulse0, so the rigth way should be to use the pulseaudio subsystem. I installed also mplayer for testing purpose:

apt-get install pulseaudio mplayer

The Kodi program will be run using the kodi Unix user, so add the user to the required groups to grant the required permissions:

adduser kodi audio
adduser kodi pulse
adduser kodi pulse-access

Become the kodi user, start the PulseAudio server and list the available sinks (audio output devices):

su - kodi
pulseaudio --start
pacmd list-sinks

WARNING: after the pulseaudio --start command, the daemon is running by the kodi user; the daemon will eventually die if the user log-out or if not-used for a while. You can inspect the daemon activity by adding the options --log-target=newfile:/home/kodi/pulseaudio.log --log-level=debug.

On the Raspberry Pi I get only the HDMI port and the analog jack:

index: 0
    name: <alsa_output.platform-bcm2835_audio.digital-stereo>
    ...
    ports:
        hdmi-output-0: HDMI ...
index: 1
    name: <alsa_output.platform-bcm2835_audio.analog-stereo>
    ...
    ports:
        analog-output: Analog Output ...

To set the default audio device used by PylseAudio clients, add the following lines to /etc/pulse/client.conf (need root):

# Audio to the HDMI port:
default-sink = alsa_output.platform-bcm2835_audio.digital-stereo
# Audio to the analog (jack) port:
#default-sink = alsa_output.platform-bcm2835_audio.analog-stereo
# Audio to USB audio device:
#default-sink = alsa_output.usb-C-Media_Electronics_Inc._USB_Advanced_Audio_Device-00.analog-stereo

To check the current volume use the pactl list sinks command:

pactl list sinks
Sink #0
    State: SUSPENDED
    Name: alsa_output.platform-bcm2835_audio.digital-stereo
    ...
    Mute: no
    Volume: front-left: 65536 / 100% / 0.00 dB,   front-right: 65536 / 100% / 0.00 dB
            balance 0.00
    ...

Eventually turn off the mute status and set the required volume:

# Set Mute: no
pacmd set-sink-mute "alsa_output.platform-bcm2835_audio.digital-stereo" 0
# Set Volume: 50%
pacmd set-sink-volume "alsa_output.platform-bcm2835_audio.digital-stereo" 32768

Finally check that the audio is working as kodi user:

mplayer -ao pulse /usr/share/sounds/alsa/Front_Center.wav

PulseAudio as a system-wide service

PulseAudio developers say that running PulseAudio as a system-wide service is a bad idea, but in this case I think it is what is needed, because:

  • Local users do not exist.
  • Desktop session does not exist.
  • Music Player Daemon (MPD) is executed as a systemd service and it needs to access the audio device.
  • Kodi is executed via the kodi-standalone command, as a systemd service and it needs o access the audio device too.

We need a Systemd unit file to run the daemon /etc/systemd/system/pulseaudio.service:

[Unit]
Description=PulseAudio system server

[Service]
Type=notify
ExecStart=/usr/bin/pulseaudio --daemonize=no --system --realtime --log-target=journal

[Install]
WantedBy=multi-user.target kodi.service mpd.service

Systemd service can be of type forking, simple or notify, which one is the best? From the pulseaudio(1) man page we can know that there is the --system option to be used for a system-wide instance, in that case we should use also the --daemonize=no for systemd notification to work. So the proper way seems to be the Type=notify

Then we can enable and start the service (verify that the pulseaudio daemon is running by the pulse user):

systemctl daemon-reload 
systemctl enable pulseaudio.service
systemctl start pulseaudio.service

From now on, every user with group access to audio, pulse and pulse-access, can play to PulseAudio system.

FIXME: When Pulseaudio is running as a system user, some commands like pacmd does not work for the user, because they search files under /run/user/<UID>/pulse/, which instead are under /run/pulse/. It is possibile to make symlinks to solve the problem or…

To enable PulseAudio as a system-wide service, several recipes exist on the Net, many of them are plain wrong:

Use PulseAudio with Kodi

With the PulseAudio running as a system service, you can start Kodi and go to SettingsSystemAudio = Audio output device and select PULSE: Default. Here you can also switch between HDMI and stereo jack:

  • PULSE: Built-in Audio Digital Stereo, HDMI / DisplayPort
  • PULSE: Built-in Audio Analog Stereo, Analog Output

The audio devices PI:HDMI, PI:Analogue and PI:HDMI and Analogue should not be longer used, because they can conflict with the PulseAudio process which is using them.

Music Player Daemon

To play music we choosed to install the Music Player Daemon (mpd) and a text based client FIXME: ncmpc or ncmpcpp, which one?

The mpd configuration file is /etc/mpd.conf, the relevant settings are:

music_directory         "/var/lib/mpd/music"
bind_to_address         "::"

audio_output {
        type            "pulse"
        name            "pulse audio"
}

The mpd user must be addedd to the relevant groups: audio, pulse and pulse-access.

Kodi

Installed the packages:

  • kodi
  • kodi-bin - Contains the executable kodi-standalone, which is the one to execute.
  • kodi-peripheral-joystick - Necessary to add support for the gamepad.
  • kodi-eventclients-kodi-send - Contains the kodi-send tool, used to control Kodi from the command line.

We create an user called kodi which belongs to the groups: audio, video, input, pulse and pulse-access. To execute kodi as a Systemd service we created an Unit file /etc/systemd/system/kodi.service:

[Unit]
Description = Kodi Media Center

# if you don't need the MySQL DB backend, this should be sufficient
After = systemd-user-sessions.service network.target sound.target

# if you need the MySQL DB backend, use this block instead of the previous
# After = systemd-user-sessions.service network.target sound.target mysql.service
# Wants = mysql.service

[Service]
User = kodi
Group = kodi
Type = simple
ExecStart = /usr/bin/kodi-standalone
Restart = always
RestartSec = 15

[Install]
WantedBy = multi-user.target

The service must be enabled and started.

Kodi Add-ons

We don't want to depend on auto-download, audo-updates, etc. So we manually download the zip file for each app-on on the local filesystem. To allow installation in this way, it is required to enable System SettingsAdd-onsUnknown sources. Finally we can do Kodi Main ManuAdd-onsMy add-onsInstall from zip file.

Despite installing the add-on from a zip file, any required add-ons not present into the system will be automatically downloaded from the net and installed. Fortunately you can find the zip files of this additional add-ons into the $HOME/.kodi/addons/packages/ directory, so you can backup them for later use.

Music

Beside Kodi, which has its own functions to play music, I want also the functions offered by the Music Player Daemon; so I installed the Debian packages:

  • mpd - The Music Player Daemon, the underlying daemon which actually plays music.
  • ncmpc - It is a MPD client for text terminals, based on ncurses.

Transfer rate

We measured the transfer rate from other home NASes, just to figure out how much time is required to transfer 500 Gb of data. The receiving NAS is the Raspberry Pi 4 with a Seagate 4 Tb IronWolf 3.5 inch hard disk connected through the X835 USB3 interface. The network is limited to 100 Mbit transfer rate, due to the limit of the LAN switch.

NAS model Disk model Transfer rate (Mbit) 500 Gb transfer time (hours)
LaCie d2 Network WDC WD10EFRX-68FYTN0, 1Tb, 5400 rpm 13 87.5
QNAP TS-120 Hitachi Deskstar 7K1000.B, 1Tb, 7200 rpm 98 12.7

Web References

doc/appunti/hardware/raspberrypi_nas.1615361248.txt.gz · Last modified: 2021/03/10 07:27 by niccolo