Kategorien

ZFS Snapshots synchronisieren mit zettarepl auf dem Rasperry Pi

Für das NAS zuhause nutze ich FreeNAS und das funktioniert wunderbar. Das dort genutzt ZFS-Dateisystem bietet die wunderbare Möglichkeit, Snapshots anzulegen und durch deren zeitsparende Synchronisierung auf einen anderen Server ein verlässliches Backup einzurichten. Unter FreeNAS kann das komfortabel über das GUI unter Tasks > Replication eingerichtet werden. Da ich allerdings auf einen Rasperry Pi mit FreeBSD als Betriebssystem sichern möchte, ist nur der Push von Backups möglich. Wie sich zeigte, kann ein speziell für das Backup errichtete Nutzerkonto nicht mit ausreichend Privilegien ausgestattet werden, um ein funktionierendes Backup einzurichten. Als root hätte ich es zwar einrichten können, dann wäre allerdings für den Fall, dass jemand Zugriff auf den NAS-Server erhält auch das komplette Backup-System kompromitiert. Somit schaute ich mich nach anderen Lösungen um. Zrep war die erste Wahl und funktioniert auch sehr gut, allerdings habe ich es nicht geschafft, rekursiv zu synchronisieren (siehe Bug). Mit zettarepl, dem Tool das auch in FreeNAS Anwendung findet, startete ich einen neuen, erfolgreichen Versuch. Dazu bin ich wie folgt vorgegangen, um zettarepl in FreeBSD einzurichten:

pkg install python py37-setuptools py37-pytz py37-yaml py37-paramiko py37-croniter py37-coloredlogs py37-jsonschema py37-isodate py37-dateutil
mkdir zettarepl
cd zettarepl
fetch https://github.com/freenas/zettarepl/archive/master.tar.gz
tar xzf master.tar.gz
cd zettarepl-master/
python setup.py install --prefix /usr/local

Dann kopieren der Konfigurationsdatei und entsprechendes Anpassen:

cp examples/pull/ssh-replication.yaml ~/zettarepl_pull_backup.yaml

Dann geht es an das Testen der Pull-Replikation von Snapshots. Dazu in der Konfigurationsdatei die Sektion schedule wie folgt anpassen:

schedule:
  minute: "*"
  hour: "*"
  day-of-month: "*"
  month: "*"
  day-of-week: "*"

Nun kann mit einem

zettarepl -l "debug" run --once ~/zettarepl_pull_backup.yaml

getestet werden, ob alles richtig funktioniert.

Leider funktionierte es irgendwie nicht und ich habe nicht herausgefunden, warum. Nun greife ich auf einen FreeNAS Replication Task zurück. Damit sichert zwar das zu sichernde System selbst auf den Backup-Server (eigentlich sollte es so sein, dass der Backup-Server sich die Daten selbst holt), aber wenigstens funktioniert es so. Dazu habe ich einen speziellen Backup-User eingerichtet (mit entsprechenden ZFS-Privilegien).

Hilfreich und eine Alternative dazu ist auch diese Vorgehensweise mit zrep. Diese setze ich in Verbindung miz zrep-expire ein für ein spezielles zvol.

FreeBSD auf Rasperry Pi aktualisieren

Leider lässt sich FreeBSD auf dem Rasperry Pi nicht mit freebsd-update aktualisieren, da dort leider die Unterstützung für arm-Architekturen fehlt. In Anlehnung an einen Post im FreeBSD-Forum habe ich nun FreeBSD auf dem Rasperry Pi 3 wie folgt aktualisiert, um den langwierigen build-Prozess zu umgehen.

  1. Clone-Version installieren
    mkdir -p /usr/local/etc/pkg/repos/
    vi /usr/local/etc/pkg/repos/FreeBSD.conf

    Dann dort folgenden Inhalt eintragen:

    FreeBSD: {
      url: "pkg+http://pkg.FreeBSD.org/${ABI}/latest",
    }

    und mit

    pkg install clone

    die richtige Version von clone installieren.

  2. Backup des aktuellen OS (SD-Karte auf externe USB-Festplatte)
    In meinem Fall das Backup-Drive mounten:

    zfs mount remote_backup

    Wechseln ins Backup-Verzeichnis:

    cd /remote_backup/backup_haning

    Über

    geom disk list

    herausfinden, welches das Systemvolume ist (hier SD-Karte mmcsd0) und dann den Parameter if im folgenden Befehl anpassen, um die Backup-Datei zu erzeugen:

    dd if=/dev/mmcsd0 of=haning_2020-07-12.img bs=1M status=progress

    Backup dann wie folgt testen:

    mdconfig -a -u 0 -t vnode -f /remote_backup/backup_haning/haning_2020-07-12.img
    mount -o noatime /dev/md0s1 /media
    ls /media
    umount /media
    mdconfig -d -u 0
  3. FreeBSD aktualisieren auf den neusten Stand
    Unter FreeBSD Releases, die aktuellste Version herausfinden und dann unter https://download.freebsd.org/ftp/releases/arm64/aarch64/ISO-IMAGES/ die entsprechende Version suchen

    cd /remote_backup/backup_haning/images
    fetch https://download.freebsd.org/ftp/releases/arm64/aarch64/ISO-IMAGES/12.1/FreeBSD-12.1-RELEASE-arm64-aarch64-RPI3.img.xz
    xz -d FreeBSD-12.1-RELEASE-arm64-aarch64-RPI3.img.xz
    mdconfig -a -u 0 -t vnode -f /remote_backup/backup_haning/images/FreeBSD-12.1-RELEASE-arm64-aarch64-RPI3.img
    mount -o noatime,ro /dev/md0s2a /media
    clone -c rwoff -s -x /usr/home:/usr/local:/usr/ports:/usr/obj:/usr/src /media/usr /usr &
    clone -c rwoff -s /media/sbin /sbin &
    clone -c rwoff -s /media/rescue /rescue &
    clone -c rwoff -s -x crontab:exports:fstab:group:hosts:shells:localtime:master.passwd:motd:ntp.conf:passwd:pwd.db:rc.conf:rc.local:resolv.conf:spwd.db:ssh:ssl:unbound:aliases:dma:mailer/mailer.conf /media/etc /etc &
    clone -c rwoff -s -x /boot/loader.conf:/boot:modules:/boot/msdos /media/boot /boot &
    clone -c rwoff -s /media/bin /bin &
    clone -c rwoff -s /media/libexec /libexec &
    clone -c rwoff -s /media/lib /lib &
    

    Dann mit dem Befehl

    jobs

    prüfen, bis alle Befehle im Hintergrund fertiggestellt wurden.

    umount /media
    mdconfig -d -u 0
    zfs umount remote_backup

    Dann neu starten mit

    shutdown -r now
  4. Bitte überspringen – nur als Erinnerung für mich: verschlüsselte USB-Festplatte einbinden mit
    geli attach -k /root/remote_backup_wd_elements_10tb.key /dev/da0p2
    zpool import remote_backup
    zfs umount remote_backup
    zfs mount remote_backup
  5. Boot-Partition aktualisieren und Pakete installieren wie z.B. dma
    mdconfig -a -u 0 -t vnode -f /remote_backup/backup_haning/images/FreeBSD-12.1-RELEASE-arm64-aarch64-RPI3.img
    mount_msdosfs -o noatime /dev/md0s1 /media
    clone -c rwoff -s /media /boot/msdos
    umount /media
    mdconfig -d -u 0
    pkg install dma
    shutdown -r now
  6. Pakete installieren
    Paketquelle wieder richtig setzen mit

    rm /usr/local/etc/pkg/repos/FreeBSD.conf

    Jetzt fehlen eventuell die aus der Vergangenheit vorhandenen Pakete. Diese lassen sich installieren mit

    pkg update
    pkg upgrade

MP3 und andere Audiodateien unter Linux umwandeln, um sie schneller abzuspielen

Podcasts sind eine tolle Sache und ich höre sie wahnsinnig gerne beim Autofahren. Um die Zeit noch effektiver zu nutzen, möchte ich manche Audiodateien bei erhöhter Geschwindigkeit hören. Das unterstüzten mittlerweile viele Podcast-Spieler auf dem Handy von Hause aus – nur leider nicht das Entertainment-System von meinem Auto. Und genau deshalb habe ich einen Weg gesucht, um die Podcast-Dateien schnell und komfortabel unter Linux im Batchmodus umzuwandeln, so dass sie mit einer höheren Geschwindigkeit vom USB-Stick abgespielt werden.

Dazu benötigt man unter Ubuntu nur ein Paket: ffmpeg. Wenn man eine etwas bessere Qualität haben möchte, kann man alternativ eine Kombination aus verschiedenen Programmen einsetzen. Dazu benötigt man dann die Pakete: sox, libsox-fmt-mp3, python-mutagen sowie das Programm mid3cp. Letzteres bekommt man unter ubuntu, wenn man diese Datei in github in /usr/bin schiebt und ausführbar macht.

Wenn man diese Voraussetzungen geschaffen hat, kann man mit folgendem Skript sehr komfortabel alle Audio-Dateien in einem Verzeichnis komplett umwandeln.

#!/usr/bin/env bash
# 
# Simple shell script to speed up audio files to 1.5 playing speed
# with ffmpeg
#
#==========================================================
#
#contains username separated by newline
INPUTDIR="/mnt/markus/Downloads/Sorted/Mp3Z/Podcasts/export/dk"
#Directory to link training files to
OUTPUTDIR=/mnt/output/dk
USE_FFMPEG=true
# ffmpeg binary 
FFMPEG_COMMAND=/usr/bin/ffmpeg
SOX_COMMAND=/usr/bin/sox
MID3CP_COMMAND=/usr/bin/mid3cp

echo `date` Begin Audio Conversion
find "${INPUTDIR}" -type f -regextype posix-egrep -regex '.*\.(mp3|m4a|ogg)$' -print0 | sort -z | while read -d $'\0' AUDIO
do
	echo `date` Converting File $AUDIO
	filename=$(basename -- "$AUDIO")
	extension="${filename##*.}"
	filename="${filename%.*}_speed"
	if [ ! -d "$OUTPUTDIR/$dir/" ]; then
		mkdir -p "$OUTPUTDIR/$dir/"
	fi
	if [ -f "$OUTPUTDIR/$dir$filename.$extension" ]; then
		echo `date` Skipping.. "$OUTPUTDIR/$dir$filename.$extension" exists already
	else
		if [[ "${extension,,}" != "mp3" ]] || [ "$USE_FFMPEG" == "true" ] ; then
			echo `date` Generating "$OUTPUTDIR/$dir$filename.$extension" with ffmpeg
			</dev/null $FFMPEG_COMMAND -i "$AUDIO" -v quiet -loglevel panic -filter:a "atempo=1.5" -vn "$OUTPUTDIR/$dir$filename.$extension"
		else
			echo `date` Generating "$OUTPUTDIR/$dir$filename.$extension" with sox
			# variant with sox to change speed and pitch
			#$SOX_COMMAND "$AUDIO" "$OUTPUTDIR/$dir$filename.$extension" speed 1.5 pitch -700
			# variant with sox to change tempo
			$SOX_COMMAND "$AUDIO" "$OUTPUTDIR/$dir$filename.$extension" tempo 1.5
			echo Copying ID3 Tag from original file
			$MID3CP_COMMAND "$AUDIO" "$OUTPUTDIR/$dir$filename.$extension"
		fi
	fi
done

Webscraping mit CasperJS und PhantomJS auf einem FreeNAS 11 Jail

Wir setzen einen neuen FreeNAS-Jail auf und loggen uns im Jail ein. Dann aktualisieren wir erstmal das System

pkg update
pkg upgrade

Anschließend installieren wir PhantomJS und python mit einem

pkg install phantomjs python

Da es für CasperJS kein Paket gibt, nehmen wir den Umweg über npm.

pkg install node
pkg install www/npm
npm install -g casperjs

Mit einem

phantomjs --version
casperjs --version

kann man antesten, ob es funktioniert.

Logitech Media Server auf FreeNAS 11

Installation des Logitech Media Servers im Jail

Um den Logitech Media Server auf FreeNAS 11 zu betreiben bin ich wie folgt vorgegangen:

  1. Anleitung zum Bauen des Logitech Media Servers aus dem Forum befolgen (hierzu habe ich ein separates Jail verwendet). Diese Anleitung funktioniert auch unter FreeNAS 11.
  2. Eigenen Jail für den Logitech Media Server erstellen (Name: lms)
  3. Das erzeugte Paket in den neu erstellten Jail kopieren. Den folgenden Befehl auf der FreeNAS Konsole ausführen
    cp /mnt/data0/jails/lms_build/tmp/LMS/logitechmediaserver-7.9.0-FreeBSD.tar /mnt/jails/lms/tmp/
  4. Analoge Schritte aus dem Forum befolgen
    pkg update
    pkg upgrade
    pw groupadd -n lms -g 30001
    pw useradd -n lms -u 30001 -g lms -s /usr/sbin/nologin -c "Logitech Media Server" -d /nonexistent
    mkdir /usr/local/lms
    tar xf /tmp/logitechmediaserver-7.9.0-FreeBSD.tar -C /usr/local/lms
    mv /usr/local/lms/logitechmediaserver-7.9.0-FreeBSD/* /usr/local/lms
    rmdir /usr/local/lms/logitechmediaserver-7.9.0-FreeBSD/
    chown -R lms:lms /usr/local/lms
    rm /usr/bin/perl
    rm /usr/bin/perl5
    ln -s -f /usr/local/bin/perl5.24.3 /usr/bin/perl
    ln -s -f /usr/local/bin/perl5.24.3 /usr/bin/perl5
  5. Init-Skript /etc/rc.d/lms zum automatischen Start des Logitech Media Servers mit folgenden Inhalt erstellen:
    #!/bin/sh
    
    # This script is a modified version of:
    # $FreeBSD: branches/RELENG_9_2_0/audio/squeezeboxserver/files/squeezeboxserver.in 302141 2012-08-05 23:19:36Z dougb $
    
    # PROVIDE: lms
    # REQUIRE: LOGIN
    # KEYWORD: shutdown
    
    # Add the following lines to /etc/rc.conf to enable lms on startup:
    # lms_enable="YES"
    
    # Optional configuration parameters:
    # Directory where lms writes it's logs to.
    # lms_logdir="/var/log/lms"
    #
    # Directory where lms stores it's cache files.
    # lms_cachedir="/var/db/lms/cache"
    #
    # Directory where lms stores it's configuration.
    # lms_prefsdir="/var/db/lms/prefs"
    #
    # Directory where lms stores the playlists. THIS NEEDS TO BE CONFIGURED THROUGH THE UI.
    # lms_playlistdir="/var/db/lms/playlists"
    #
    # Additional parameters, e.g. "--noimage --novideo"
    # lms_flags=""
    #
    # The charset lms uses.
    # lms_charset="UTF-8"
    #
    # The LC_CTYPE envvar which is necessary to get rid of the warning
    # """
    # Your locale was detected as C, you may have problems with non-Latin filenames.
    # Consider changing your LANG variable to the correct locale, i.e. en_US.utf8.
    # """
    # See https://forums.freenas.org/index.php?threads/logitech-media-server-for-freenas-9-2-1-1.19044/page-3#post-132872
    # lms_lc_ctype="en_US.UTF.8"
    
    . /etc/rc.subr
    
    name=lms
    rcvar=lms_enable
    
    pidfile=/var/run/${name}/${name}.pid
    lms_user=lms
    lms_group=lms
    
    load_rc_config ${name}
    
    : ${lms_enable="NO"}
    : ${lms_logdir="/var/log/${name}"}
    : ${lms_cachedir="/var/db/${name}/cache"}
    : ${lms_prefsdir="/var/db/${name}/prefs"}
    : ${lms_playlistdir="/var/db/${name}/playlists"}
    : ${lms_flags=""}
    : ${lms_charset="UTF-8"}
    : ${lms_lc_ctype="en_US.UTF-8"}
    
    command_interpreter=/usr/bin/perl
    command=/usr/local/lms/slimserver.pl
    command_args="\
    --daemon \
    --pidfile=${pidfile} \
    --logdir=${lms_logdir} \
    --cachedir=${lms_cachedir} \
    --prefsdir=${lms_prefsdir} \
    --charset=${lms_charset} \
    ${lms_flags}"
    
    start_precmd="lms_start_precmd"
    stop_postcmd="lms_stop_postcmd"
    
    lms_start_precmd()
    {
            export LC_CTYPE="${lms_lc_ctype}"
    
            if [ ! -d "${pidfile%/*}" ]; then
                    install -d -o ${lms_user} -g ${lms_group} ${pidfile%/*};
            fi
    
            if [ ! -d "${lms_logdir}" ]; then
                    install -d -o ${lms_user} -g ${lms_group} "${lms_logdir}";
            fi
    
            if [ ! -d "${lms_cachedir}" ]; then
                    install -d -o ${lms_user} -g ${lms_group} "${lms_cachedir}";
            fi
    
            if [ ! -d "${lms_prefsdir}" ]; then
                    install -d -o ${lms_user} -g ${lms_group} "${lms_prefsdir}";
            fi
    
            if [ ! -d "${lms_playlistdir}" ]; then
                    install -d -o ${lms_user} -g ${lms_group} "${lms_playlistdir}";
            fi
    }
    
    lms_stop_postcmd()
    {
            pids=`pgrep -u ${lms_user}`
            if [ -n "${pids}" ]; then
                    sleep 1
                    kill $pids > /dev/null 2>&1
            fi
            pids=`pgrep -u ${lms_user}`
            if [ -n "${pids}" ]; then
                    wait_for_pids $pids
            fi
    }
    
    run_rc_command "$1"
  6. Sicherstellen, dass das Init-Skript ausführbar ist
    chmod +x /etc/rc.d/lms
  7. Datei /etc/rc.conf editieren und die folgende Zeile ergänzen
    lms_enable=“YES“
  8. Zusätzlich erforderliche Verzeichnisse erstellen und Rechte anpassen
    mkdir -p /var/log/lms /var/db/lms/cache /var/db/lms/prefs /var/db/lms/playlists
    chown -R lms:lms /var/log/lms /var/db/lms/cache /var/db/lms/prefs /var/db/lms/playlists
  9. Benötigtes perl Package installieren
    pkg install p5-IO-Socket-SSL
  10. Logitech Media Server starten
    /etc/rc.d/lms start
  11. Binaries zur Umwandlung im richtigen Ordner hinterlegen und ausführbar machen
    cp /usr/local/lms/Bin/i386-freebsd-64int/* /usr/local/lms/Bin/
    chmod +x faad flac sls wvunpack

Erweiterung des Dateispektrums des Logitech Media Servers

Der Logitech Media Server benötigt nnoch weitere Binaries, um zusätzliche Formate umzuwandeln z.B. Monkey’s Audio (APE). aus diesem Grund habe ich die folgenden Programme nachinstalliert

pkg install mac
ln -s /usr/local/bin/mac /usr/local/lms/Bin/mac

Will man Cue-Sheets mit APE-Dateien verwenden, benötigt man ffmpeg. Der für mich einfachste Weg war, ein statisches Binary herunterzuladen und in FreeNAS Linux Kompatibilität herzustellen. Dazu unter System -> Tunable den Punkt Add Tunable auswählen und folgende Variablen setzen
Variable: linux_load
Value: YES
Type: Loader
Type: rc.conf
Enabled: yes
Um einen Neustart zu vermeiden, manuell das entsprechende Modul laden (FreeNAS Konsole):

kldload linux

Dann statisches ffmpeg herunterladen und entsprechend verschieben

fetch https://johnvansickle.com/ffmpeg/builds/ffmpeg-git-32bit-static.tar.xz
tar xf ffmpeg-git-32bit-static.tar.xz -C /usr/local/lms/Bin
mv /usr/local/lms/Bin/ffmpeg-git-20170929-32bit-static/ffmpeg /usr/local/lms/Bin

Testen, ob ffmpeg ausgeführt werden kann

/usr/local/lms/Bin/ffmpeg

Jetzt noch wie in meinem anderen Blogartikel beschrieben die convert.conf anpassen und das Skript ffmpeg_wrapper in /usr/local/lms/Bin/ ablegen. Da dieses nur mit der bash funktioniert, diese Shell nachinstallieren

pkg install bash

und die erste Zeile von ffmpeg_wrapper in

#!/usr/local/bin/bash

anpassen. Außerdem wird noch lame benötigt

cd /usr/ports/audio/lame
pkg install gmake gcc
make install
ln -s /usr/local/bin/lame /usr/local/lms/Bin/lame

Zum Schluss noch entsprechend der Anleitung die Datei /usr/local/lms/Slim/Formats/APE.pm anpassen.