Odroid HC4 / NAS

Da sich mein Qnap NAS verabschiedet hat, war dies die Gelegenheit ein NAS selber zu bauen.

Anforderungen an Services

Ein NAS bietet heutzutage, nebst dem Speichern von Daten, diverse Services an. Folgendes möchte ich auch auf dem HC4 nutzen:

NAS-Strategie

Als erstes ist es eine gute Idee zu klären, was man mit dem NAS überhaupt erreichen möchte. Hier meine Kriterien:

  • Datenverlust: Die Daten sollen bestmöglich vor Verlust geschützt werden.
  • Verfügbarkeit: Die Daten können auch mal 1-2 Tage nicht verfügbar sein. Mehr als 2 Tage Ausfall sollten es aber nicht sein.

Massnahmen Datenverlust

  • Das NAS soll in einem RAID-1 Verbund laufen. Damit werden die Daten gespiegelt abgespeichert, so dass ein Festplatten-Ausfall einfach abgefedert werden kann.
  • Gleichzeitig werden die “Core-Daten” (alles ausser Musik, Filme etc.) regelmässig zusätzlich auf ein zweites Gerät gespeichert (rsync).

Massnahmen Verfügbarkeit

  • RAID-1 hilft hier ebenfalls, die Daten bleiben bei einem Ausfall einer der beiden Festplatten weiterhin verfügbar.
  • Es kann aber auch sein, dass die Hardware (SD-Karte oder HC4) ausfällt. Die SD-Karte klone ich zu diesem Zweck. So kann ich bei einem Ausfall die SD-Karte einfach austauschen. Beim HC4 wird es aber etwas schwieriger. Ich habe mir zwei HC4 Geräte besorgt. Bei einem Ausfall kann ich entsprechend auch den HC4 sofort ersetzen.

Hardware

Ich habe bereits mit dem Odroid HC2 sehr gute Erfahrungen gemacht. HC4 ist der Nachfolger und bietet neu mehr CPU Leistung, einen 64Bit Prozessor, 4Gb RAM, etc.

Das HC4 Gehäuse

Update 2024: Sie scheinen mittlerweile verstanden zu haben, dass das Originale Case nix bringt. Es gibt mittlerweile von odroid ein HC4 Case Kit, mit welchem man sich ein vernünftiges Case selber zusammenschrauben kann.

Das Gehäuse vom HC4 ist meines Erachtens nicht gelungen. Die Festplatten werden vertikal in den SATA-Anschluss des HC4 eingeschoben. Das ganze ist mir viel zu wackelig. “Serverschrank-Ready” ist dieses Ding so definitiv nicht. Auch frage ich mich, ob es sinnvoll ist, SATA Stecker so zu verwenden. Ich kann mir nicht vorstellen, dass die SATA Stecker des HC4 solide genug sind um häufiges wechseln von Festplatten zu überstehen:

Das SBC Case Builder Gehäuse

Ich drucke mir mit dem 3D Drucker, basierend auf dem Design von SBC Case Builder mein eigenes Gehäuse. Ziel soll es sein, ein Gehäuse zu produzieren, welches auch mit gutem Gewissen in einem Server- oder Netzwerkschrank platziert werden kann:

Der SBC-Build hat aber leider eine kleine Schwäche. Auf der einen Seite, wo sich das Board befindet, kann der Deckel nicht angeschraubt werden. Daraus resultiert, dass beim Stromanschluss ein Spalt von ca 2mm entsteht. Dem habe ich einfach mit einem Kabelbinder entgegengewirkt. Ist nicht schön, aber für den Serverschrankt tut es das allemal:

Alles in allem kann man den HC4 nun mit gutem Gewissen in den Serverschrank stellen:

  • Die Festplatten sind sehr gut fixiert und es wackelt rein gar nichts.
  • Der zweite Lüfter, den ich über den USB-Port betreibe, sorgt für zusätlich gute Belüftung.
  • Der Stock-Lüfter befindet sich übrigens unterhalb des HC4-Boards. Ein Lüfter wurde so montiert, dass er die Luft nach aussen bläst und einer zieht die Luft an.
  • Der Lüftungsregulierer erlaubt es die Touren des Lüfters einzustellen. Ich habe ihn auf ca. 50% eingestellt. Damit wird immer noch gut belüftet und der Lärmpegel hält sich in Grenzen. => Serverschrank-Ready.
  • Ist es schön? => NEIN 😀

Betriebssystem

Der HC4 bietet neu (im Gegensatz noch zum HC2) die Möglichkeit das Betriebssystem auf der SATA-Disk zu installieren. Hardkernel hat dafür den Petitboot Bootloader vorinstalliert. Dieser Bootloader ermöglicht den HC4 Start ohne eingelegte Disk oder SD-Karte. Anschliessend kann über netboot ein Betriebssystem direkt auf einer Disk installiert werden. Ich habe aber für die Installation das Image auf die SD Karte geschreiben und dabei folgende zwei Images getestet:

Die Ubuntu-Version stammt von Hardkernel und ist mit Petitboot kompatibel. Das bedeutet, dass das Betriebssystem (nach 10s wartezeit) von Petitboot erkannt und gebootet wird. Dieses Ubuntu könnte damit z.B. auf einer SATA SSD Disk installiert werden. Das Betriebssystem wird damit dann direkt von der SSD betrieben und nicht auf der SD-Karte.

Armbian hingegen wird von Petitboot nicht erkannt. bei Armbian muss Petitboot komplett entfernt werden. Mit gelöschtem Petitboot versucht der HC4 auf der SD-Karte ein Betriebssystem zu finden und startet dieses dann direkt. Dies hat den Vorteil, dass der Start sofort durchgeführt wird (ohne 10s) Wartezeit. Dafür aber auch den Nachteil, dass das Betriebssystem auf der SD-Karte liegt. SD-Karten sind bekanntlich nicht dafür geeignet ein Betriebssystem (mit vielen writes) zu betreiben.

Ich entscheide mich für eine Installation mit Armbian. Armbian ist leichtgewichtiger als die Hardkernel Ubuntu-Version und auf den HC4 abgestimmt. Armbian ist mir deswegen etwas sympatischer – ist aber eher ein Bauchentscheid als wirklich mit harten Fakten begründet…

Installation Armbian

# flash_eraseall /dev/mtd0
# flash_eraseall /dev/mtd1
# flash_eraseall /dev/mtd2
# flash_eraseall /dev/mtd3
    • => Dadurch wird der SPI-Flash-Speicher gelöscht und der HC4 startet ab sofort direkt von der SD Karte.
  • HC4 mit eingelegter Armbian SD-Karte starten
  • Installations-Anweisungen befolgen

Grund-Installation Armbian ist damit abgeschlossen

Lüfter-Support aktivieren:

vi /etc/fancontrol

Inhalt einfügen:

INTERVAL=10
DEVPATH=hwmon0=devices/virtual/thermal/thermal_zone0 hwmon2=devices/platform/pwm-fan
DEVNAME=hwmon0=cpu_thermal hwmon2=pwmfan
FCTEMPS=hwmon2/pwm1=hwmon0/temp1_input
FCFANS= hwmon2/pwm1=hwmon2/fan1_input
MINTEMP=hwmon2/pwm1=50
MAXTEMP=hwmon2/pwm1=60
MINSTART=hwmon2/pwm1=20
MINSTOP=hwmon2/pwm1=28
MINPWM=hwmon2/pwm1=0
MAXPWM=hwmon2/pwm1=255

Restart fancontrol

sudo systemctl restart fancontrol

Wichtig: Wenn man den Kernel 5.15.x einsetzt, muss die Zeile FCFANS=hwmon2/pwm1=hwmon2/fan1_input entfernt werden.

Reboot Issue

Ein soft reboot (sudo reboot) funktionierte in diesem Zustand nicht. Die Lösung ist hier zu finden:

armbian-config ---> System -> Install -> Install/Update the bootloader on SPI/Flash

Danach bootet armbian sauber nach einem “sudo reboot”.

Wiederherstellen/Update Petitboot

Es besteht die Möglichkeit Petitboot zu aktualisieren bzw. über das gleiche Vorgehen, nach einer Löschung, wieder zu installieren.

Dafür stellt Hardkernel ein Image zur Vefügung:

  • Download aktuelles spiupdate-image unter http://ppa.linuxfactory.or.kr/images/petitboot/odroidhc4/ => Die heute aktuelle Version ist “spiupdate_odroidhc4_20201112.img”
  • Optional:
    • Download letzte Firmware “spiboot-20220317.img
    • Auf der geflashten SD-Karte das File “spiboot.img” durch die neue heruntergeladene Variante ersetzen. Das File muss natürlich nach spiboot.img umbenannt werden.
  • Den HC4 mit dieser SD-Karte booten. Das Firmware-Update wird automatisch durchgeführt.
Hint: Boot ohne Petitboot

Gut zu Wissen ist, dass der HC4 auch ohne das entfernen von Petitboot die Möglichkeit bietet ohne Petitboot zu starten. Dafür muss man einfach den schwarzen Reset-Knopf drücken und gleichzeitig den Stromstecker einstecken. Dann warten, bis der HC4 blau zu blinken beginnt. Damit startet HC4 ohne Petitboot. => Das ist aber natürlich für den täglichen Gebrauch nicht wirklich zu empfehlen.

Installation Festplatten / RAID1

Partition erstellen

Als erstes schliesse ich eine der beiden 8TB Festplatten an und boote das System neu. Nun eine Partition erstellen:

sudo fdisk /dev/sda
g

Dies erstellt eine gpt-Partitionstabelle und wir erhalten das Disk-Label (GUID) => Dieses notieren

  • Nun mit n eine Partition erstellen und alle vorgeschlagenen Standardwerte übernehmen.
  • Am Schluss mit w die Änderungen auf die Platte schreiben.
sudo fdisk -l
  • Zeigt nun die partitionierte Festplatte an
  • Filesystem erstellen

  • Wir erstellen ein Btrfs Filesystem, über welches dann Raid1 umgesetzt wird.
mkfs.btrfs /dev/sda1

Dies erstellt das Filesystem und weist eine UUID zu (UUID notieren).

Die notierten GUID und UUID habe ich mir mit einem P-Touch auf ein Label ausgedruckt und auf die Disk geklebt. Das ermöglicht im späteren Betrieb die Disk einwandfrei zu identifizieren.

Der Disk Identifier kann folgendermassen ermittelt werden

fdisk -l /dev/sda

Subvolumes einrichten

Btrfs unterstützt Subvolumes. Btrfs hat ein unabhängiges einhängbares Root-Verzeichnis für das Volume (Subvolume der obersten Ebene) und für jedes Subvolume. Ein Btrfs-Volume kann also mehr als einen einzelnen Dateibaum enthalten. Einen ganze Tree  von Dateibäumen enthalten. Ein Btrfs-Subvolume kann man sich als POSIX-Dateinamensraum vorstellen.

Es ist zum empfehlen Subvolumes für voneinander unabhängige Datenablagen zu verwenden (z.B. Backup, Filme, Musik, etc.)

Als erstes hängen wir das Btrfs Root-Subvolume ein:

sudo mount /dev/sda1 /mnt

Ich erstelle für mich ein Subvolume, welches alle Multimedia-Daten beinhalten soll (Filme, Musik, Bücher, etc.):

btrfs subvolume create /mnt/@backup

Nun das Root-Subvolume wieder aushängen

sudo umount /dev/sda1

Jetzt kann man das erstellte Subvolume direkt in das Filesystem einhängen:

sudo mkdir /mnt/multimedia
sudo vi /etc/fstab
/dev/sda1 /mnt/multimedia btrfs defaults,nofail,noatime,compress=zstd,subvol=@multimedia 0 0

Dieser fstab Eintrag kann anschliessend über die CLI gemountet werden

sudo mount /mnt/multimedia

Komplette Rechte auf /mnt/multimedia setzen

chmod 0777 /mnt/multimedia

Auf diese Art und Weise kann man so viele Subvolumes erstellen wie man eben braucht.

Raid1

Bis jetzt haben wir nur eine HDD installiert. Nachdem das Filesystem angelegt ist funktioniert (an dieser Stelle habe ich auch bereits Samba eingerichtet und getestet), setzen wir die zweite Disk (nach einem shutdown und anschliessendem Neustart) ein und erstellen das Raid1.

Hinweis 1: An dieser Stelle habe ich festgestellt, dass ich die erste HDD in Slot2 des HC4 gesteckt habe. Der SATA-Slot, der sich näher am Stromanschluss/Netzwerkanschluss befindet ist offensichtlich Slot Nr. 2 – Nach dem Restart hat nämlich die zweite HDD /dev/sda zugewiesen bekommen und wodurch dann natürlich das vorhin erstellte Btrfs Filesystem nicht mehr verfügbar war. Nach einem erneuten Stopp, wechsel der Festplatten und Neustart war dieses Problem behoben.

Hinweis 2: Bei der Einrichtung von Raid1 habe ich mich gefragt, ob es denn möglich ist, den Raid-level je nach subvolume zu setzen. Das ist offenbar nicht möglich. Btrfs scheint dies als Feature offen zu haben, es ist aber offenbar seit fast 10 Jahren nichts mehr in diese Richtung gegangen. Also: Nein. 🙂

fdisk verrät mir, wie die neue Festplatte erkannt wurde:

sudo fdisk -l

In meinem Falle ist die neue HDD das Device /dev/sdb.

Nun wird für diese HDD (/dev/sdb) ebenfalls eine gpt-Partition und eine Partition über die gesamte Platte erstellt siehe hier.

Nun teilen wir btrfs mit, dass die neue Platte als Raid-1 Verbund zur ersten Platte verwendet werden soll. Dafür hängen wir alle gemounteten subvolumes erst aus.

sudo umount /mnt/<subvolumes>

Nun hängen wir die gesamte erste Festplatte ein

sudo mount /dev/sda1 /mnt

btrfs die neue Festplatte bekannt machen

sudo btrfs device add /dev/sdb1 /mnt

/dev/sdb in einen Raid1-Verbund aufnehmen. Erklärung:

  • -mconvert= Option, ein neues Profil “raid1” auf die Metadaten des Diskarrays anzuwenden
  • -dconvert = Neues Profil “raid1” auf die Nutzdaten des Diskarrays zu legen
# sudo btrfs balance start -dconvert=raid1 -mconvert=raid1 /mnt
# Done, had to relocate 5 out of 5 chunks

Damit wurde der Raid1 Verbund erstellt. Wenn die zweite HDD  (wie bei mir zu Testzwecken) kleiner als die erste HDD ist, dann wird der Gesamtspeicherplatz neu maimal die Grösse der kleineren Festplatte betragen. Was bei mir auch so korrekt funktioniert hat.

Nun die ganze Festplatte wieder aushängen und die zuvor angelegten subvolumes einhängen (z.B. durch reboot, so dass die fstab Einträge geladen werden).

sudo umount /mnt
sudo reboot

Test / weitere Befehle

Überblick über das Raid

# btrfs fi usage /mnt/<subvolume>

Overall:
Device size: 14.55TiB
Device allocated: 10.06GiB
Device unallocated: 14.54TiB
Device missing: 0.00B
Used: 4.51GiB
Free (estimated): 7.27TiB (min: 7.27TiB)
Free (statfs, df): 7.27TiB
Data ratio: 2.00
Metadata ratio: 2.00
Global reserve: 6.11MiB (used: 0.00B)
Multiple profiles: no

Data,RAID1: Size:3.00GiB, Used:2.25GiB (74.92%)
/dev/sda1 3.00GiB
/dev/sdb1 3.00GiB

Metadata,RAID1: Size:2.00GiB, Used:8.55MiB (0.42%)
/dev/sda1 2.00GiB
/dev/sdb1 2.00GiB

System,RAID1: Size:32.00MiB, Used:16.00KiB (0.05%)
/dev/sda1 32.00MiB
/dev/sdb1 32.00MiB

Unallocated:
/dev/sda1 7.27TiB
/dev/sdb1 7.27TiB

Prüfen der Devices

sudo btrfs fi show /mnt/<subvolume>

Label: none uuid: 0edb47d3-ea4a-4667-b609-223212ec41b1
Total devices 2 FS bytes used 2.26GiB
devid 1 size 7.28TiB used 5.03GiB path /dev/sda1
devid 2 size 7.28TiB used 5.03GiB path /dev/sdb1

Raid 1 – Festplattenwechel

Es ist eine Frage der Zeit, bis eine Festplatte den Geist aufgeben wird. Da wir ein Raid1 haben, sollte dies kein grossen Problem darstellen. Ob das aber funktioniert, muss getestet werden.

Das Vorgehen

  1. System herunterfahren
  2. Defekte HDD entfernen und stattdessen neue HDD in den Slot stecken.
    Als Simulation ersetzte ich die zweite (kleinere) HDD nun mit einer neuen gleichgrossen HDD (8TB)
  3. System hochfahren.
    Nach dem reboot wurden die subvolumes, wie erwartet, nicht mehr gemountet. Ich habe aber auch nirgends einen Hinweis erhalten, dass es ein Problem mit BTRFS gibt (auch nicht in dmesg). An dieser Stelle kann man über fdisk die Devices identifizieren.

    sudo fdisk -l

    Anhand der auf der HDD gekenntzeichneten GUID stelle ich fest, dass die noch funktionierende HDD als /dev/sda und die neue als /dev/sdb erkannt wurde.

  4. RAID im degraded mode mounten.
    Damit die noch funktionierende Festplatte eingehängt werden kann, muss das Raid mit der Option -o degraded eingehängt werden

    sudo mkdir /mnt/temp
    sudo mount -o degraded /dev/sda1 /mnt/temp

    Nun kann überprüft werden, welche Festplatte fehlt (in diesem Falle ID2):

    # sudo btrfs device usage /mnt/temp
    
    /dev/sda1, ID: 1
    Device size: 7.28TiB
    Device slack: 3.50KiB
    Data,RAID1: 3.00GiB
    Metadata,RAID1: 1.00GiB
    System,RAID1: 32.00MiB
    Unallocated: 7.27TiB
    
    missing, ID: 2
    Device size: 0.00B
    Device slack: 0.00B
    Data,RAID1: 3.00GiB
    Metadata,RAID1: 1.00GiB
    System,RAID1: 32.00MiB
    Unallocated: 1.81TiB
  5. Die neue Festplatte partitionieren
    Die neue Festplatte (hier /dev/sdb) muss nun wie her beschrieben partitioniert werden.
  6. RAID wiederherstellen (`btrfs replace`).
    Nun kann die neue Festtplatte in den Raid1 Verbund aufgenommen werden. Hier wird das vermisste Device mit der ID 2, welches sich an /dev/sdb1 in das Raid1, welches an /mnt/temp eingebunden wurde, aufgenommen (siehe auch btrfs Doku).

    sudo btrfs replace start 2 /dev/sdb1 /mnt/temp

    Der replace-Prozess wird im Hintergrund durchgeführt. Das kann einige Stunden dauern. Der Status des replace kann folgendermassen abgerufen werden

    sudo btrfs replace status /mnt/temp/

    Sobald der replace-Prozess beendet wurde (zu überprüfen mit status) kann die neue disk angezeigt werden:

    # sudo btrfs device usage /mnt/temp
    
    /dev/sda1, ID: 1
    Device size: 7.28TiB
    Device slack: 3.50KiB
    Data,single: 3.00GiB
    Data,RAID1: 3.00GiB
    Metadata,single: 2.00GiB
    Metadata,RAID1: 1.00GiB
    System,single: 64.00MiB
    System,RAID1: 32.00MiB
    Unallocated: 7.27TiB
    
    /dev/sdb1, ID: 2
    Device size: 7.28TiB
    Device slack: 5.46TiB
    Data,RAID1: 3.00GiB
    Metadata,RAID1: 1.00GiB
    System,RAID1: 32.00MiB
    Unallocated: 1.81TiB
  7. Jetzt die Redundaz wieder herstellen
    # sudo btrfs balance start -dconvert=raid1,soft -mconvert=raid1,soft /mnt/temp
    # Done, had to relocate 7 out of 12 chunks
  8. System rebooten

Nach dem reboot ist das Raid1 mit der neuen Festplatte wieder hergestellt und alle subvolumes sollten wieder korrekt gemountet sein.

Raid1 vergrössern

Die alte Festplatte hatte in meinem Falle eine Grössen von 2TB, die neue Festplatte hat eine Grösse von 8TB. Damit habe ich 2x 8TB verbaut. Das Raid1 hat aber zu diesem Zeitpunkt immer noch die Grösse der früheren kleineren Festplatte. Wir müssen also nun noch die Grösse des Raids auf den maximal verfügbaren Speicher anheben. Dies geschieht über den resize Befehl:

Dazu muss das Raid wieder als gesamtes unter /mnt/temp gemountet werden und alle subvolumes ausgehängt sein.

sudo umount /mnt/<subvolumes>
sudo mount /dev/sda1 /mnt/temp

Hier müssen wir nun Device ID 2 auf deren maximal verfügbare Grösse vergrössern

# sudo btrfs filesystem resize 2:max /mnt/temp
Resize device id 2 (/dev/sdb1) from 1.82TiB to max

Nun zeigt btrfs device usage auch für das Device 2 die korrekte Grössen an (unallocated):

#sudo btrfs device usage /mnt/temp

/dev/sda1, ID: 1
Device size: 7.28TiB
Device slack: 3.50KiB
Data,RAID1: 3.00GiB
Metadata,RAID1: 2.00GiB
System,RAID1: 32.00MiB
Unallocated: 7.27TiB

/dev/sdb1, ID: 2
Device size: 7.28TiB
Device slack: 3.50KiB
Data,RAID1: 3.00GiB
Metadata,RAID1: 2.00GiB
System,RAID1: 32.00MiB
Unallocated: 7.27TiB

Damit stehen nun die gesamten 8TB als Raid zur Verfügung.

Über diesen Prozess kann übrigens das Raid durch neuere grössere Festplatten ersetzt werden. Der HC4 unterstütz bis zu 12 TB grosse Festplatten. Es besteht also noch Luft nach oben 🙂

Btrfs Wartung

Damit das Btrfs-Filesystem gut “in Schuss” bleibt, ist es notwendig etwas in die Wartung dessen zu investieren.  Wartungsaufgaben können mit dieser Script-Sammlung automatisiert werden (Scrubben, Ausbalancieren, Trimmen oder Defragmentieren).

Installation btrfsmaintenance

sudo apt-get update
sudo apt-get install btrfsmaintenance

Dies installiert btrfsmaintenance

  • Skripte unter /usr/share/btrfsmaintenance
  • Konfig-File unter /etc/default/btrfsmaintenance

Anpassen Konfig-File

sudo vi /etc/default/btrfsmaintenance

=> Setze auto um alle btfrs subvolumes abzudecken.
BTRFS_BALANCE_MOUNTPOINTS="auto"
BTRFS_SCRUB_MOUNTPOINTS="auto"

Installieren der cron-job Skripte.

sudo /usr/share/btrfsmaintenance/btrfsmaintenance-refresh-cron.sh
Refresh script btrfs-scrub.sh for monthly
Refresh script btrfs-defrag.sh for none
Refresh script btrfs-balance.sh for weekly
Refresh script btrfs-trim.sh for none

Samba

Damit das NAS Files im Netzwerk bereitstellen kann, benötigt es natürlich den entsprechenden Dienst. Mit Armbian könnten wir hier natürlich aus den vollen schöpfen. Aber ich begnüge mich mit Samba:

sudo apt-get install samba

Die einzelnen subvolumes sollen mittles Samba im Netzwerk verfügbar gemacht werden. Pro Subvolume muss entsprechend ein Linux-User erstellt werden, der sich aber nicht am System selber anmelden kann:

sudo useradd -s /bin/false multimedia
sudo smbpasswd -a multimedia

Gruppe erstellen und user multimedia zuweisen

sudo groupadd multimedia
sudo usermod -a -G multimedia multimedia

Nun die Samba Konfiguration durchführen

sudo mv /etc/samba/smb.conf /etc/samba/smb.orig
sudo vi /etc/samba/smb.conf

Inhalt

[global]
workgroup = WORKGROUP
server string = %h server (Samba, HC4_NAS)
security = user
map to guest = never

[multimedia]
path = /mnt/multimedia
public = yes
writable = yes
comment = hc4 nas: multimedia share
printable = no
guest ok = no
force group = multimedia
valid users = multimedia
create mask = 0660
directory mask = 0770

Nun Samba Dienste neu starten. Anschliessend steht das Sama-Share ‘multimedia’ zur Verfügung:

sudo systemctl restart smbd.service
sudo systemctl restart nmbd.service

Das Share kann nun z.B. unter Ubuntu in Dateibrowser mit

smb://<ip>/multimedia/

unter Verwendung des Users ‘multimedia’ & Passwort verbunden werden.

FTP Server

HC4 soll auch einen FTP Server bereitstellen. Ich installier dafür PureFTPd. Die Installation habe ich hier bereits einmal beschrieben.

Video-Überwachung

Für die Video Überwachung setzte ich Shinoi ein. Die Installation wird hier beschrieben.

Bibliotheksverwaltung für eReader

Für die Bibliotheksverwaltung setze ich Calibre ein. Hier wird die Installation beschrieben.

Fazit

Wenig überraschend lassen sich alle Services eines Standard-NAS nachbauen.

Daten-Transfer Performance

Das Kopieren von sehr grossen Files (20 à ca. 10GB) oder auch gleichzeitig vielen kleineren Files ( 300 à 10MB) ergeben eine Durchschnittsgeschwindigkeit von 55-57MB/s. Damit befinden wir uns in dem, für die eingesetzten HDDs, erwarteten Rahmen. Hardkernel verspricht beim Einsatz von SSDs Werte von bis zu 100MB/s. Wer das notwendige Budget hat => go4it 😉

Festplattenwechsel

Ein Festplattenwechsel hat ohne Probleme und ohne Datenverlust funktioniert.

Performance allgemein

Die Performance des HC4 reicht für die von mir eingesetzten Services locker aus. Für die Video-Überwachung habe ich 4 Neztwerk-Kameras installiert, welche alle durchwegs im recording Modus laufen, also Daueraufnahmen machen und gleichzeitig den Stream auch noch an diverse Clients weiterleiten. Trotzdem läuft der HC4 ziemlich unbeeindruckt auf rund 5-10% CPU und ca 20% RAM-Auslastung. Die Temperaturen belaufen sich auf rund 55°C (CPU) und 45°C (Storage).

Systemd Startreihenfolge der Services

Nach einigen Monaten Laufzeit ist aufgefallen, dass das System öfters nach einem Reboot nicht mehr korrekt funktioniert hat. Zum einen musste ich die korrektur des “Reboot Issues” wieder durchführen. Diese Anpassung ging wohl nach einem apt-get upgrade verloren.

Das andere Problem war dass das Mounten der btrfs Verzeichnisse teilweise länger dauerte, als das starten der systemd Services. Das führte zur unschönen Situation, dass das System nach einem Reboot im Status “degraded” hängen blieb, weil benötigte Verzeichnisse noch nicht gemountet waren. Hier habe ich beschrieben, wie ich diese Problematik gelöst habe.

Links

ioBroker: Node.js Update / Reinstallation ioBroker

Update 20.2.2024

Neu ist das Update von node auf dem iobroker deutlich vereinfacht worden. Siehe auch hier und hier:

Siehe auch alle Consolen-Commands für iobroker hier.

iob stop             ## für iob fix muss iobroker gestoppt sein
iob fix
iob nodejs-update xx ## (mit xx eine GERADE Major Node.js version - Ungerade Versionen sind Entwicklerversionen)
sudo reboot

iob upgrade          ## bei Bedarf gleich alle Adapter mit aktualisieren

Deprecated:

Ich betreibe seit einigen Jahren ioBroker, welches auf nodejs basiert. Heute war es an der Zeit die Nodejs Version von 8 auf 12 anzuheben, was leider nicht ganz ohne Probleme funktionierte. Hier fasse ich kurz zusammen, welche Schritte bei meiner Installation nötig waren. Die Schritte basieren auf diesem Howto.

Die einzige, im Howto beschriebenen und für mich funktionierende Lösung für das Update war, die komplette Reinstallation des ioBrokers. Dabei wird zuerst die neue Node.js Version installiert. Dann ein Backup des iobroker-data Verzeichnisses gezogen, die ioBroker-Installation gelöscht, neu installiert und dann das Backup wieder zurück gespielt:

Installation neue Node.js Version 12

cd /opt/iobroker
iobroker stop
cd

# install nodejs
curl -sLf https://deb.nodesource.com/setup_12.x | sudo -E bash -
sudo apt-get install -y nodejs

# install iobroker
curl -sLf https://iobroker.net/install.sh | bash -

Bei einer Aktualisierung von Node.js müssen bereits installierte JavaScript- Module im ioBroker-Ordner aktualisiert werden, da sonst Fehler bei deren Ausführung auftreten. Hier traten bei mir dann die Probleme auf. Die einzige bei mir funktionierende Lösung war, den ioBkoker neu zu installieren:

Backup und Neuinstallation ioBroker

  • Backup des iobroker-data Verzeichnisses nach “Home” ziehen
  • Die alte Installation löschen
  • ioBroker neu installieren
cp -r /opt/iobroker/iobroker-data ~/iobroker-data 
sudo rm -r /opt/iobroker/ 
sudo mkdir /opt/iobroker
cd /opt/iobroker
curl -sL https://iobroker.net/install.sh | bash -

ioBroker wird nach der Installation wieder gestartet. Wir stoppen ioBroker deswegen wieder:

iobroker stop

Nun löschen wir das neu erstellte iobroker-data Verzeichnis und kopieren das Backup

rm -r /opt/iobroker/iobroker-data
cp -r ~/iobroker-data /opt/iobroker/iobroker-data

Während meinen Installations-Bemühungen habe ich festgestellt, dass die Berechtigungen immer wieder durcheinander gehen. Es existiert deswegen ein korrektur-Script, welches die Berechtigungen des ioBrokers wieder gerade zieht. Es ist ratsam dieses jetzt durchzuführen:

cd /opt/iobroker
curl -sL https://iobroker.net/fix.sh | bash -

Jetzt den ioBroker neu starten

iobroker start

Der Start kann jetzt sehr lange dauern. Der ioBroker merkt jetzt, dass die Adapter (gem. Backup) fehlen und installiert diese neu nach.

Um zu schauen, wo die Installation steht, kann man das log konsultieren

tail -f /opt/iobroker/log/iobroker.current.log

Ein Adapter (zigbee) liess sich jetzt immer noch nicht installieren. Diesen habe ich dann noch manuell installiert:

cd /opt/iobroker
iobroker stop
sudo -H npm install iobroker.zigbee --unsafe-perm

Ganz zum Schluss dann nochmals die Berechitigungen gerade ziehen, um sicher zu gehen…

cd /opt/iobroker
curl -sL https://iobroker.net/fix.sh | bash -

Das wars. Jetzt den Raspi neu booten und sich über die neue ioBroker-Installation freuen 🙂

sudo reboot

Influxdb V2 Löschen von bestimmten Einträgen

Die Standard-Syntax von Influxdb V2 ist “Flux”. Um mit Flux bestimmte Einträge aus einem measurement (Tabelle) zu entfernen, muss man den Timestamp verwenden:

  1. Login auf Influx Host als root=> influx kann nun mit “influx <statement>” angesprochen werden.
  2. Löschen von allen Einträgen aus
    • dem Bucket iobroker
    • Tabelle javascript.0.Solarpower.Huawei.Meter.ReverseActiveEnergy
    • vom 7.2.2024 19:00 und 7.2.2024 19:15
influx delete --bucket iobroker --start 2024-02-07T19:00:00.000Z --stop 2024-02-07T19:15:00.000Z --predicate '_measurement="javascript.0.Solarpower.Huawei.Meter.ReverseActiveEnergy"'

Um sicherzustellen, dass auch die richtigen Einträge erwischt werden, bitte zuerst über den Data Exlorer die Daten anzeigen lassen:

from(bucket: "iobroker")

  |> range(start: v.timeRangeStart, stop: v.timeRangeStop)

  |> filter(fn: (r) => r["_measurement"] == "javascript.0.Solarpower.Huawei.Meter.ReverseActiveEnergy")

  |> filter(fn: (r) => r["_field"] == "value")

  |> aggregateWindow(every: v.windowPeriod, fn: mean, createEmpty: false)

  |> yield(name: "mean")

Huawei Sun2000 Wechselrichter mit Telegraf und Grafana

Seit einigen Tagen werkelt bei mir eine PV-Anlage:

  • 2 Wechselrichter SUN2000-10KTL-M1
    • Bietet ein eigenes WLAN Netz (zwecks Konfiguration des Wechselrichters)
  • Einen Dongle (SDongleA) auf dem Master Wechselrichter für FusionSolar App
    • Bietet sowohl ein WLAN Adapter sowie
    • direkter LAN-Anschluss
    • Beides über DHCP

Ziel

Die Werte werden soweit ok auf das FusionSolar Portal von Huawei. Aber ich möchte gerne alle Werte direkt lokal beziehen und auf Grafana darstellen. Hier logge ich meine Erfahrungen und irgendwann hoffentlich auch eine Erfolgsmeldungen.

Good to know

  • Der Wechselrichter selber erstellt ein eigenes WLAN zwecks Konfiguration des Geräts.
  • Der Dongle am Wechselrichter ermöglicht es auf ein vorhandenes WLAN zu verbinden oder ein Netzwerkkabel auf einen Router anzuschliessen. Hauptziel dieses Dongels ist es wohl, die Daten auf FusionApp bzw. in die Cloud zu bringen. Der Dongle selber bietet auch die Möglichkeit Daten per “Modbus TCP” abzufragen. Diese Schnittstelle ist aber sehr unausgereift. Erste Tests mit Telegraf (modbus plugin) haben gezeigt, dass regelmässige Abfragen (z.B. alle 5s) nicht gehen (i/o timeout). Grund dafür ist wahrscheinlich, dass nach der Modubs-Anmeldung 2s gewartet werden muss, bis die erste Register-Abfrage durchgeführt werden kann (eine Huawei Eigenheit). Ich gehe aktuell davon aus, dass Telegraf damit (wenig überraschend) nicht umgehen kann.
  • Die Daten können auch per Modbus TCP am Wechselrichter selber abgefragt werden, sofern man sich mit dem WLAN des Wechselrichters verbunden hat.

Modbus TCP vs Huawei

Man könnte meinen, dass Huawei etwas auf “Kriegsfuss” mit Modbus TCP ist. Regelmässige Abfragen mit Standard Modbus-Clients (z.B. Telegraf oder ioBroker Modbus) schlagen die meiste Zeit fehl. Hier wird davon berichtet, dass die Modbus-Ansteuerung vom Huawei Sun2000 Wechselrichter über TCP etwas speziell sei. Nach dem öffnen des TCP-Ports muss offenbar noch eine 2s Pause eingehalten werden, da sonst keine Daten zurück geliefert werden. Auch wird nicht jede Modbus-TCP-Anfrage mit den angeforderten Registern beantwortet. Huawei melden in diesem Falle “Slave device busy (retry request again later)”.

Modbus auf Wechselrichter aktivieren

Damit der Wechselrichter mit Modubs TCP kommuniziert, muss dies erstmal aktiviert werden. Das geht einerseits über die FusionSolar App (Menupunkt “ich>Inbetriebnahme des Geräts”). Hier einfach das Gerät auswählen. Anschliessend wird versucht auf das Gerät zuzugreifen. Auch wenn da steht “Inbetriebnahme des Geräts” wird einfach nur das “Konfigurations-App” gestartet. Ich vermute mal, dass in der FusionSolar App die App Sun2000 integriert ist. Also keine Angst haben, dass da ein zusätzliches Gerät in Betrieb genommen wird.

Die andere Variante ist, wie erwähnt, die Sun2000 App. Diese ermöglicht ebenfalls die Verbindung mit dem Wechselrichter-WLAN.

Beide Apps sind über den Huawei App Store erhältlich. Ich habe es leider nicht auf anderen Wegen geschafft die APKs zu beziehen. => Also Appstore Installieren, App beziehen und Appstore (hoffentlich für immer) wieder deinstallieren.

Wichtig:
Der Wechselrichter muss mindestens über Firmware Version V200R001C00SPC115 verfügen. Falls nicht, muss die Firmware aktualisiert werden. Das geht über die FusionSolar App. Hierfür braucht es aber explizit einen Installer-Account. Wenn ihr diesen nicht habt, muss dies der Installateur nachholen.

Wenn man über den Wechselrichter modbus verwendet, benötigt man den Port 6607 anstelle von 502!

DD-WRT

Routing von Port 6607 von 192.168.3.3 nach 192.168.200.1 (“WAN” Adresse des Routers nach Wechselrichter)

Routing auf dd-wrt um die IP-Adresse aus 192.168.3/24 als 192.168.200.2 (ip Adresse des WLAN-Clients) aussehen zu lassen

root@DD-WRT:~# iptables -I PREROUTING -t nat -p tcp -d 192.168.3.3 --dport 6607 -j DNAT --to-destination 192.168.200.1:6607
root@DD-WRT:~# iptables -I POSTROUTING -t nat -d 192.168.200.1 -s 192.168.3/24 -p tcp --dport 6607 -j SNAT --to 192.168.200.2

Damit sollte anschliessend ein Telnet Test aus dem 192.168.3./24 Netz  nach 192.168.200.1 (Port 6607) erfolgreich sein:

telnet 192.168.3.3 6607

Damit diese Regeln auch nach Reboot überleben, kann man sie auf dd-wrt Command-Shell GUI (Administration – Commands) eintragen und Speichern. Danach sollten die Regeln auch nach einem Reboot aktiv sein.

Modbus auf SDongleA aktivieren

Auf die gleiche Art und Weise soll auch Modbus TCP auf dem Dongle aktiviert werden. Den Dongle kann man sowohl per WLAN als auch per LAN-Kabel anschliessen. Ich habe beide Varianten (versuchsweise) installiert. Der Dongle kann sowohl WLAN als auch LAN gleichzeitig betreiben.

Wenn der Dongle sich mit dem Heimnetz verbunden hat, war es für mich anschliessend aber nicht mehr möglich, das Dongle-Eigene WLAN zu sehen. Der Dongle scheint das eigene WLAN abzuschalten, sobald man sich per LAN verbindet.

Wichtige Attribute PV Anlage

KennzahlenBezeichnungModubs Register
Netzbezug (-) / Netzeinspeisung (+)Der jeweils letzte Wert aus
Huawei.Meter.ActivePower (W)
Meter.ActivePower
37113 (W)
PV – Aktuelle ProduktionAddition von
– Huawei.Inverter.1.InputPower (kW), letzter Wert +
– Huawei.Inverter.2.InputPower (kW), letzter Wert
Inverter.x.InputPower
32064 (kW)
Aktuelle Hauslast / Verbrauch HausDerived.HouseConsumption (W), letzter Wert

Berechnet aus:
(Huawei.Inverter.1.ActivePower (kW) * 1000 + Huawei.Inverter.2.ActivePower (kW) * 1000) –
Huawei.Meter.ActivePower
Inverter.x.ActivePower 32080 (kW)

Meter.ActivePower
37113 (W)
Aktuelle Leistung pro InverterHuawei.Inverter.x.ActivePower (kW) Inverter.x.ActivePower 32080 (kW)
Produktion / PV Produktion pro InverterHuawei.Inverter.x.AccumulatedEnergyYield (kWh)Huawei.Inverter.x.AccumulatedEnergyYield
32106 (kWh)
NetzeinspeisungHuawei.Meter.PositiveActiveEnergyHuawei.Meter.PositiveActiveEnergy
37119 (kWh)
Eigenverbrauch aus PVTagessummen aus Huawei.Inverter.x.AccumulatedEnergyYield –
Tagessumme aus Huawei.Meter.PositiveActiveEnergy
Huawei.Inverter.x.AccumulatedEnergyYield
32106 (kWh)

Huawei.Meter.PositiveActiveEnergy
37119 (kWh)
Eigenverbrauch aus PV in %100 * Eigenverbrauch aus PV / Produktion
Netzeinspeisung in &100 * Heutige Netzeinspeisung / Produktion
Netzbezug (akkumuliert)Huawei.Meter.ReverseActiveEnergy (kWh)37121 (kWh)
Direktverbrauch aus PVTagessummen aus
Huawei.Inverter.x.DailyEnergyYield

Tagessumme aus
Huawei.Meter.PositiveActiveEnergy
Inverter.x.DailyEnergyYield
32114 (kWh)

Huawei.Meter.PositiveActiveEnergy
37119 (kWh)
Verbrauch aus Netz in %EigenverbrauchAusPV:
Produktion PV: Tagessummen aus
Huawei.Inverter.x.AccumulatedEnergyYield (kWh)

Netzeinspeisung Huawei.Meter.PositiveActiveEnergy


Gesamtverbrauch:
EigenverbrauchAusPV +
Netzbezug
Huawei.Meter.ReverseActiveEnergy)

100 * Gesamtverbrauch / EigenverbrauchAusPV
Verbrauch aus PV in % (Autarkiegrad)
PV-ErzeugungActive Power Inverter + Battery Power
Aktueller PV-Ertrag
Das was aktuell vom Dach kommt:
Input Power32064
Aktuelle Leistung vom “Dach” in WattInverter.Input_Power
PV-GesamtertragAccumulated energy yield32106
PV-TagesertragDaily energy yield32114
PV Tagesverbrauch – Wieviel kWh wurden heute direkt aus der PV Produktion bezogen (Autarkie)Inverter.[1,2].DailyEnergyYield – GridExportToday
PV Gesamteigenverbrauch / Direktverbrauch aus PVAccumulated energy yield – abzüglich Gesamtexport ins Netz (Positive active electricity)32106 – 37119
Heutiger NetzbezugSolarpower.Derived.GridImportToday
Netzbezug/Einspeisung
Bezug oder Einspeisung vom/zum Versorger in Watt.
Positive Werte = Bezug, negative Werte = Einspeisung
Meter.Active_Power
37113
Aktuelle Einspeisung des Inverters in das Hausnetz.
Also die aktuelle “Leistung” des Hauses in Watt
Addition aus PV Erzeugung und ggf. Batterie-Entladung
Inverter.Active_Power
Hauslast aktuellActive Power Inverter – Meter.Active_Power32080 – 37113
Gesamtexport ins Netz (verkauft)Positive active energy37119 (kWh)
Gesamtimport aus dem Netz (gekauft)Reverse Active Energy37121 (kWh)
Gesamtverbrauch StromPV-Gesamtertrag + Gesamtexport ins Netz + 37121 Reverse active Power (Ges.import aus Netz)
PV1_Voltage und PV1_Current: Aktuelle Spannung und Strom von String, U * I = P, somit ergibt sich daraus, wieviel Leistung der String aktuell liefert in Watt
Akku-Ladestand: Energy storage37004
Akku-Ladung des Tagescurrent day charge capacity37015
Akku-Entladung des Tagescurrent day discharge capacity37017
Aktuelle Leistung an der Batterie in Watt, negative Zahlen = Batterie wird entladen, positive Zahlen = Batterie wird geladenBattery_Power
Ladezustand in %Battery_SOC

Links

HC2 Armbian und Logitech Media Server / OS auf HD

Hier beschreibe ich, wie man eine HC2 mit Armbian installiert und einem Logitech Media Server darauf betreibt.

HC2 Armbian Image & Installation HD

Die Installation von Armbian ist eigentlich “outofthebox”. Da die HC2 aber über eine SD Karte verfügt und die Lebensdauer entsprechend beschränkt ist, ist es von Vorteil, die in der HC2 eingebaute Disk als OS-Disk zu verwenden. Man kann leider die HC2 nicht über die HD Vollkommen boot-fähig machen. Fast nicht. Ich beschreibe hier, wie ich das gelöst habe:

Image / SD

  • Download (Focal-Image) & Installation: https://www.armbian.com/odroid-xu4/
  • SSH Standard Login: root  Password: 1234
    • Starte  das Dienstprogramm armbian-config und
    • gehe in den Bereich System -> DTB und
    • wähle die optimierte Kartenkonfiguration für Odroid HC1. Die gleiche Konfiguration gilt auch für HC2 und MC1.

Disc / HD

  • Erstelle auf der HD zwei Partitionen. Eine für das Betriebssystem (40G) und eine für die Daten (Rest)
  • HD identifizieren
sudo fdisk -l
  • Partitionen erstellen
sudo fdisk /dev/sda
d= delete partition
n= create partition
w=write partition
  • recheck
sudo fdisk -l
  • Erstelle Formatierung
sudo mkfs.ext4 -L os /dev/sda1
sudo mkfs.ext4 -L data /dev/sda2
  • Erstelle Mount-Verzeichnisse
sudo mkdir /osFiles
sudo mkdir /mnt/files
  • /etc/fstab anpassen: Mount Patitionen
#Mounts
/dev/sda1 /osFiles ext4 defaults,noatime,nodiratime,commit=600,errors=remount-ro 0 1
/dev/sda2 /mnt/files ext4 defaults,noatime,nodiratime,commit=600,errors=remount-ro 0 1
  • Reboot
  • Files auf neue OS-Partition (/osFiles) kopieren.
    Achtung: Alle Services (wie den logitechmediaserver) vorher beenden
sudo rsync -aAXHv --exclude={"/dev/*","/proc/*","/sys/*","/tmp/*","/run/*","/mnt/*","/media/*","/lost+found","/osFiles"} / /osFiles
  • SDA uuid (UUID) herausfinden:
sudo blkid

/dev/sda1: LABEL="os" UUID="975a0396-5016-42b3-a66e-fe5276a36797" TYPE="ext4" PARTUUID="262deb28-e8fe-5d4d-b3a4-808b44571e85"
  • Im boot.ini die neue UUID setzen bzw. ersetzen:
sudo vi /boot/boot.ini
.
setenv rootdev "UUID=975a0396-5016-42b3-a66e-fe5276a36797"
.
  • reboot.
  • Wenn alles geklappt hat, sollte neu von sda1 gebootet werden. Check:
mount | grep '/ '
  • sollte folgendes ausgeben
/dev/sda1 on / type ext4 (rw,noatime,errors=remount-ro,commit=600,data=ordered)
  • Über armbian-config können neue U-boot Versionen eingespielt werden. Diese müssen weiterhin auf die SD-Karte gespiehlt werden. Deswegen soll das /boot Verzeichnis weiterhin auf die SD-Karte zeigen:
  • Microsd karte wieder einbinden.
  • erstelle  /mnt/microsd:
sudo mkdir /mnt/microsd
  • fstab erweitern
  • Editiere /etc/fstab, und füge hinzu:

/dev/mmcblk0p1 /mnt/microsd auto defaults 0 0 
/mnt/microsd/boot /boot none defaults,bind 0 0
  • Mount durchführen und prüfen ob korrekt gemountet wird
sudo mount /mnt/microsd && sudo mount /boot
  • Wenn Check:
mount | grep '/boot '
  • sollte folgendes ausgeben
/dev/mmcblk0p1 on /boot type ext4 (rw,relatime)
  • Wenn alles ok ist
sudo reboot

Damit läuft das System nun (grösstenteils 😉 ) auf der HD anstelle der SD. Das entlastet die SD enorm und führt zu einem längeren Leben der SD Karte.

lame installieren:

sudo apt-get install lame

ffmpeg installieren:

sudo apt-get install ffmpeg

RAM-Logging deaktivieren

Armbian installiert out-of-the-box ein RAM-Logging. Dabei wird 50MB Diskplatz als RAM verwendet und nach /var/log gemounted. Für kleine Systeme kann das Sinn machen. Ich verwende hier aber eine 2TB SSD und benötige damit keine RAM-Disk. Insbesondere, weil es immer mal wieder zu Problemen kam, welche in einem System-Freeze endeten. Dabei wurde die RAM-Disk bis 100% gefüllt was dann letzten Endes in einen System-Freeze mündete. Hier wird beschreiben, wie man diese RAM-Disk deaktiviert.

LMS Installation

LMS Download-Link: https://forums.slimdevices.com/showthread.php?98711-Logitech-Media-Server-Versions

Damit der LMS auf dem Armbian Focal läuft, müssen die Perl-Pakete selber kompiliert werden:

cd ~
sudo apt install nasm make gcc rsync patch g++ libc-bin zlib1g-dev libgd-dev libmodule-install-perl
git clone https://github.com/Logitech/slimserver-vendor.git
cd slimserver-vendor/CPAN/
./buildme.sh

Jetzt LMS downloaden und installieren

cd ~
wget http://downloads.slimdevices.com/nightly/8.1/lms/c9adb5f63e54ec0d72e6266e75fb73989f4be345/logitechmediaserver_8.1.2~1614990085_arm.deb
sudo apt install ./logitechmediaserver_8.1.2~1614990085_arm.deb

Den LMS stoppen, da er noch nicht läuft. siehe

tail -f /var/log/squeezeboxserver/server.log
sudo service logitechmediaserver stop

Nun die compilierten Perl-Binaries nach LMS kopieren:

sudo cp -r ~/slimserver-vendor/CPAN/build/arch/5.30/arm-linux-gnueabihf-thread-multi-64int /usr/share/squeezeboxserver/CPAN/arch/5.30/

Und den Logitech Media Server wieder starten

sudo service logitechmediaserver start

Das wars. Damit rennt der LMS auf einer HC2. Brower starten und link aufrufen:

http://ip-adresse:9000

Deezer-Plugin / Titel stoppen rund 50s vor Ende

Beim Einsatz des Deezer-Plugins ergab sich das Problem, dass die Songs rund 50s vor Ende des Titels stoppten und die Wiedergabe zum nächsten Titel spang. Dies kann behoben werden, indem beim LMS die AAC/AAC Wiedergabe deaktiviert wird:Siehe auch: https://github.com/Logitech/slimserver/issues/130#issuecomment-1212912369

ZRAM – Speicher erhöhen

Bei einem System mit wenig RAM-Speicher kann es Sinn machen, den zram Speicher zu erhöhen (siehe https://forum.armbian.com/topic/5565-zram-vs-swap/page/2/#comment-61082)

sudo vi /etc/default/armbian-zram-confi
# configuration values for the armbian-zram-config service
#
# enable the armbian-zram-config service?
ENABLED=true

# Zram swap enabled by default, unless set to disabled
# SWAP=false

# percentage of zram used as swap compared to physically available DRAM.
# Huge overcommitment (300) is possible and sometimes desirable. See
# https://forum.armbian.com/topic/5565-zram-vs-swap/?do=findComment&comment=61082
# and don't forget to adjust $MEM_LIMIT_PERCENTAGE below too.
# ZRAM_PERCENTAGE=50
ZRAM_PERCENTAGE=300

# percentage of DRAM available to zram. If this amount is exceeded the zram
# devices used for swap simply behave as if the device is full. You need to
# adjust/increase this value only if you want to work with massive memory
# overcommitment (ZRAM_PERCENTAGE exceeding 150 for example)
# MEM_LIMIT_PERCENTAGE=50
MEM_LIMIT_PERCENTAGE=300

# create how many zram devices max for swap
# ZRAM_MAX_DEVICES=4

# Which algorithm for zram based swapping. Seems lzo is best choice on ARM:
# https://forum.armbian.com/topic/8161-swap-on-sbc/?do=findComment&comment=61668
# SWAP_ALGORITHM=lzo

# Which algorithm to choose for zram based ramlog partition
# RAMLOG_ALGORITHM=zstd

# Which algorithm to choose for zram based /tmp
# TMP_ALGORITHM=zstd

# Size for zram based /tmp, total memory / 2 by default
# TMP_SIZE=500M

# If defined a separate partition will be used as zram backing device. Be CAREFUL
# which partition you assign and read starting from CONFIG_ZRAM_WRITEBACK in
# https://www.kernel.org/doc/Documentation/blockdev/zram.txt
# ZRAM_BACKING_DEV=/dev/nvme0n2

Links

MySQL Verbindungen mit SSL verschlüsseln – Ubuntu 14.04 / 18.04 / Mysql 5.6.28

Hier wird erklärt, wie ein MySQL Client eine verschlüsselte Verbindung zu einem MySQL Server, der mit Ubuntu 14.04 und Mysql-Server 5.6.28 betrieben wird, aufgebaut werden kann.

SSL Zertifikate erstellen

Es werden Zertifikate mit 2048 Bits und einer Gültigkeit von 3650 Tagen erstellt. Nach diesem Zeitraum müssen die Zertifikate verlängert oder neu erstellt werden.

Bitte nicht vergessen, dass der Common Name (CN) vom Client und Server Zertifikat unterschiedlich ist. z.B. servername.intelli.ch und client.intelli.ch

cd /etc/mysql/
# Generate a CA key and certificate with SHA1 digest 
openssl genrsa 2048 > ca-key.pem 
openssl req -sha1 -new -x509 -nodes -days 3650 -key ca-key.pem > ca-cert.pem 

# Create server key and certficate with SHA1 digest, sign it and convert 
# the RSA key from PKCS #8 (OpenSSL 1.0 and newer) to the old PKCS #1 format 
openssl req -sha1 -newkey rsa:2048 -days 3650 -nodes -keyout server-key.pem > server-req.pem 
openssl x509 -sha1 -req -in server-req.pem -days 3650 -CA ca-cert.pem -CAkey ca-key.pem -set_serial 01 > server-cert.pem 
openssl rsa -in server-key.pem -out server-key.pem 

# Create client key and certificate with SHA digest, sign it and convert 
# the RSA key from PKCS #8 (OpenSSL 1.0 and newer) to the old PKCS #1 format 
openssl req -sha1 -newkey rsa:2048 -days 3650 -nodes -keyout client-key.pem > client-req.pem 
openssl x509 -sha1 -req -in client-req.pem -days 3650 -CA ca-cert.pem -CAkey ca-key.pem -set_serial 01 > client-cert.pem 
openssl rsa -in client-key.pem -out client-key.pem
chmod 400 /etc/mysql/*.pem
chown mysql /etc/mysql/*.pem

SSL Konfiguration aktivieren

In der MySQL Konfiguration (/etc/mysql/my.cnf) muss SSL mit den zugehörigen Zertifikaten aktiviert werden.

ssl-ca=/etc/mysql/ca-cert.pem
ssl-cert=/etc/mysql/server-cert.pem
ssl-key=/etc/mysql/server-key.pem

Nun MySql-Server neu starten

sudo service mysql restart

Es kann auf der DB überprüft werden, ob die Konfiguration richtig übernommen wurde:

mysql > show variables like '%ssl%';

+---------------+----------------------------------+
| Variable_name | Value                            |
+---------------+----------------------------------+
| have_openssl  | YES                              |
| have_ssl      | YES                              |
| ssl_ca        | /etc/mysql/ca-cert.pem           |
| ssl_capath    |                                  |
| ssl_cert      | /etc/mysql/server-cert.pem       |
| ssl_cipher    |                                  |
| ssl_key       | /etc/mysql/server-key.pem        |
+---------------+----------------------------------+

SSL Verschlüsselung für MySQL User aktivieren

Es gibt folgende Möglichkeiten bei der Rechtevergabe für Benutzer in Bezug auf SSL:

  • REQUIRE X509: ein beliebiges gültiges SSL Client Zertifikat kann verwendet werden
  • REQUIRE ISSUER / REQUIRE SUBJECT: ein beliebiges gültiges SSL Client Zertifikat reicht nicht aus, es muss von einer mit ISSUER spezifizierten CA kommen und/oder ein bestimmtes SUBJECT enthalten.
  • REQUIRE SSL: die Verbindung muss über SSL verschlüsselt aufgebaut werden, die Authenfizierung kann sowohl via Passwort als auch über ein SSL Client Zertifikat erfolgen.

Im Folgenden Beispiel wird der User “ssluser” erstellt der alle Rechte (ALL PRIVILEGES) auf alle Datenbanken (*.*) am “localhost” hat und ein gültiges SSL Client Zertifikat vorweisen muss.

GRANT ALL PRIVILEGES ON *.* TO 'ssluser'@'localhost' IDENTIFIED BY 'topsecret' REQUIRE X509;

Client SSL erzwingen

grant all privileges on database.* to 'username'@'hostaddress' identified by 'password' require SSL;

oder 

GRANT USAGE ON *.* TO 'ralph'@'%' REQUIRE SSL;

Verschlüsselte MySQL Verbindung testen

cd /etc/mysql/
mysql -ussluser -p -h127.0.0.1 --ssl-ca=ca-cert.pem --ssl-cert=client-cert.pem --ssl-key=client-key.pem

Hint: Auf Ubuntu 18.04 schlug dieser Befehl mit dem Feher “SSL connection error: SSL_CTX_set_default_verify_paths failed” fehl. Das liegt daran, weil der lokale User mit dem dieser mysql-Befehl ausgeführt wird, keine Berechtigung auf die Zertifikate hat. Um den Test trotzdem machen zu können, kann der Befehl mit sudo ausgeführt werden.

Die SSL Keys müssen wenn der Zugriff von einem entfernten Host aus erfolgen soll natürlich vorher dorthin kopiert werden.

Mittels dem Befehl SHOW STATUS LIKE 'Ssl_cipher'; kann sich der Verschlüsselungsstatus des verbundenen MySQL Clients angezeigt werden lassen.

mysql > SHOW STATUS LIKE 'Ssl_cipher';

+---------------+--------------------+
| Variable_name | Value              |
+---------------+--------------------+
| Ssl_cipher    | DHE-RSA-AES256-SHA | 
+---------------+--------------------+
1 row in set (0.00 sec)
mysql> SHOW STATUS LIKE 'Ssl_version';

+---------------+---------+
| Variable_name | Value   |
+---------------+---------+
| Ssl_version   | TLSv1.1 |
+---------------+---------+
1 row in set (0.01 sec)

Überprüfe alle Server-Connections

Es kann auch überprüft werden ob ALLE Verbindungen zum Mysql-Server auch wirklich mit SSL Connecten.

Mit folgendem Befehl kann überprüft werden ob und welche User mit SSL mit dem Mysql-Server kommunizieren:

SELECT sbt.variable_value AS tls_version,  t2.variable_value AS cipher, processlist_user AS user, processlist_host AS host FROM performance_schema.status_by_thread AS sbt JOIN performance_schema.threads AS t ON t.thread_id = sbt.thread_id JOIN performance_schema.status_by_thread AS t2 ON t2.thread_id = t.thread_id WHERE sbt.variable_name = 'Ssl_version' and t2.variable_name = 'Ssl_cipher' ORDER BY tls_version;

Links

Influxdb v2 auf Proxmox (LXC)

Hier beschreibe ich eine Möglichkeit eine Influxdb auf Proxmox containerbasiert zu installieren.

  1. Login Proxmox
  2. Proxmox-Host Shell anwählen => Commando Prompt wird angezeigt
  3. Folgenden Befehl eingeben (aus https://tteck.github.io/Proxmox/)
    bash -c "$(wget -qLO - https://github.com/tteck/Proxmox/raw/main/ct/influxdb.sh)"
    • Settings: “Advanced”
    • OS: Wähle Debian>Ubuntu 22.04 (LTS)
    • Container Type: Unprivileged
    • Password: Setze Root Passwort
    • Container ID: default belassen
    • Hostname: influxdbV2
    • Disk Size in GB: 8
    • CPU Cores: 2
    • RAM in MiB: 2048
    • Bridge: vmbr0
    • IP Adress: dhcp
    • IPv6: enable
    • MTU Size: blank
    • DNS Search Domain: blank
    • DNS Server IP: 192.168.3.1
    • MAC Address: blank
    • Vlan: blank
    • Enable Root SSH Access: yes
    • Enable Verbose Mode: no
    • Create InfluxDB LXC: yes

  • Als nächstes kann ausgewählt werden, welche Influxdb Version installiert werden soll. Hier wähle ich Version 2.
  • Telegraf installiere ich auch gleich mit.
  • Damit ist die Installation auch schon abgeschlossen.
  • Als nächstes überprüfen ob der Container korrekt erstellt wurde.

InfluxDB Configuration

  • Öffne einen Browser mit Link “http://<ip Adresse des Containers>:8086
  • Es öffnet sich die Browser-Oberfläche von Influxdb V2
  • Get Startet
  • Username: admin
  • Passwort: => passwort
  • Organisation Name: Home
  • Initial Bucket Name: iobroker
  • Kopiere den Operater API Token an einen sicheren Ort
  • Let’s get startet!

Damit ist die InfluxDB als LXC Container installiert und grundsätzlich konfiguriert.

Migriere Influxdb V1 Bucket nach Influxdb V2

Nun möchte ich bestehendes Bucket einer Influxdb V1.8 in die neue Influxdb V2 migrieren.

  • SSH Login auf Influxdb V1
  • Folgender Befehl schreibt das Bucket in ein Line Protokoll File (auszuführen als root user):
    influx_inspect export -database iobroker -datadir /mnt/files/influxdb/data -waldir /mnt/files/influxdb/wal -compress -out iobroker.line.gz
  • Das erstelle File “iobroker.line.gz” auf die Zielmaschine kopieren
    scp iobroker.line.gz <user>@<ipadresse des LXC Containers>:
  • Jetzt mit ssh auf der Zielmaschine einloggen
  • das iobroker.line.gz entpacken
    gzip -d iobroker.line.gz
  • Bevor das entpackte File jetzt importiert werden kann, musste ich dieses noch manipulieren.
    vi iobroker.line
    Den gesamten Header löschen:
    #INFLUXDB EXPORT: 2023-01-01T01:59:59+01:00 - 2262-04-12T00:47:16+01:00
    #DDL
    CREATE DATABASE iobroker WITH NAME autogen
    #DML
    #CONTEXT-DATABASE:iobroker
    #CONTEXT-RETENTION-POLICY:autogen
    #writing tsm data
  • Jetzt das file iobroker.line importieren
    influx write -b iobroker --org Home --token <token> -f iobroker.line

Links:

Panel für Hausautomation – 2. Versuch

Nachdem mein erster Versuch ein Panel für die Hausautomation zu erstellen, gescheitert ist (siehe https://www.dev-metal.ch/?p=1586) ist dies nun der zweite Versuch. Das Grundsetting ist das gleiche  geblieben:

Hardware:

Installation

Neu verwende ich nicht fullpageos sondern das raspberry pi OS. Die Full-Version in der 64bit Variante.

Raspberry Pi Installation wie gewohnt durch schreiben eines SD-Images. Ich aktiviere dabei den SSH-Server gleich mit. Ich konfiguriere das OS auch so, dass ein autologin stattfindet. Am Ende eines Bootvorgangs gelangt man damit direkt auf den eingeloggten Desktop.

Welectron gibt an, dass man für die Installation auf einem Raspberry Pi folgende Anpassungen an der /boot/config.txt vornehmen muss:

# uncomment to force a specific HDMI mode (this will force VGA)
hdmi_group=2
hdmi_mode=82
hdmi_cvt 1920 1080 60 6 0 0 0

Diese Anpassungen waren aber in meinem Falle gar nicht nötig. Das Panel wurde sofort korrekt erkannt.

X11VNC Server

Da es sich hierbei um ein Panel handelt, sind Tastatur und Maus nicht fix montiert. Entsprechend macht es Sinn, das Gerät per Remote steuern zu können. Das wird mit X11VNC-Server umgesetzt. X11VNC ermöglicht es existierende X11-Sessions per VNC weiterzuleiten:

x11vnc installieren

sudo apt-get update
sudo apt-get install x11vnc

Server testeshalber starten

x11vnc -usepw -forever -display :0

Beim ersten Start wird das Setzen eines Passwortes verlangt. Hier entsprechend eines setzen.

Nun noch sicherstellen, dass der X11VNC-Server beim booten bzw. beim Login des Users

nano /home/pi/.config/autostart/x11vnc.desktop

Folgende Zeilen eingeben

[Desktop Entry]
Type=Application
Name=X11VNC
Exec=x11vnc -usepw -forever -display :0
StartupNotify=false

Raspberry Pi neu starten.

sudo reboot

Ab sofort ist der VNC-Server verfügbar. Ein Client kann nun mit

 vncviewer <ip>:0

auf den Raspberry Pi zugreifen.

Chromium installieren

Chromium bietet einen Kiosk-Mode. Dieser wurde bei fullpageos auch verwendet. Ich verwende der Einfachheit halber den gleichen Browser, mit den gleichen Start-Parametern:

Installieren:

 sudo apt-get install raspberrypi-ui-mods chromium-browser

Damit die Mouse-Curser entfernt werden können, muss noch unclutter installiert werden

 sudo apt-get install unclutter

Ein Config-Verzeichnis im eigenen ~/ erstellen:

 mkdir -p /home/pi/.config/lxsession/LXDE-pi/

Script aufsetzen

 nano /home/pi/.config/lxsession/LXDE-pi/autostart

und folgendermassen befüllen

# @xset s off ^[#(Screensaver ausschalten) Geht alternativ auch über die Oberfläche.
@xset -dpms #(Energiesparmodus deaktivieren) Geht alternativ auch über die Systemeinstellungen
# @xset s noblank #(Screensaver ausschalten)
@chromium-browser --v=0 --kiosk --touch-events=enabled --disable-pinch --noerrdialogs --simulate-outdated-no-au='Tue, 31 Dec 2099 23:59:59 GMT' --disable-session-crashed-bubble --disable-component-update --overscroll-history-navigation=0 --disable-features=Translate --app=http://primary-spacelynk.home.arpa/scada-vis
@unclutter -idle 0 # besagt, dass der Mouse-Curser 0s nach der letzten Aktivierung ausgeblendet werden soll

Ich lasse hier bewusst den Screensaver an (auskommentieren von @xset s off und #@xset s noblank). Das Panel soll schwarz werden, sobald es eine weile nicht gebraucht wird.

xscreensaver

Xscreensaver soll nach einigen Minuten inaktivität das Panel auf “Blank” setzen, also einen schwarzen Bildschirm an das Panel senden.

Installation

sudo apt-get install xscreensaver

Komplettes entfernen des Maus-Cursors

Unclutter entfernt den Maus-Cursor nicht komplett. Es blendet den Cursor lediglich nach x.xx sekunden inaktivität wieder aus. Wenn man aber auf das Touchpanel streicht, bleibt der Cursor auch dann sichtbar, wenn man -idle 0 konfiguriert hat.

Man kann die Maus auch komplett ausblenden. Damit ist dann aber die Maus auch  nicht verfügbar, wenn man auf dem Raspi eine Maus anschliesst:

vi /etc/lightdm/lightdm.conf
#xserver-command=X 
neu:  xserver-command=X -nocursor

xdotool

xdotool bietet die Möglichkeit per command-line (ssh) Maus und Tastatur-events an die x-session zu senden:

sudo apt-get install xdotool

Folgendes Script (geklaut bei fullpageos) setzt das Chromium-Fenster aktiv und senden ein refresh (ctrl+f5)

#!/bin/bash
export DISPLAY=:0
sleep 1
WID=$(xdotool search --onlyvisible --class chromium|head -1)
xdotool windowactivate ${WID}
xdotool key ctrl+F5

xdotool key F11

Mausklicks für Kamera-Auswahl

Wenn es an der Türe klingelt, soll das Panel automatisch auf der Visualisierung das Kamerabild einblenden. Dies kann man nun mit xdotool wunderbar umsetzen. Folgendes Script simuliert zwei Toches auf dem Panel und wählt damit das gewünschte Kamerabild automatisch aus. Dieses Script wird von der Kamera getriggert, sobald jemand die Klingel getätigt hat:

#!/bin/bash
export DISPLAY=:0
sleep 1
WID=$(xdotool search --onlyvisible --class chromium|head -1)
xdotool windowactivate ${WID}

### Select Kamera-Menu
xdotool mousemove 1720 900 click 1
sleep .5

### Select Mobotix Camera
xdotool mousemove 250 200 click 1

 

Reboot to Chromium/Desktop

Falls ich mal den Desktop per VNC benötige, habe ich mir zwei bash-scripte geschrieben, welche das autostart-File entfernt und duchbootet (bootToDesktop.sh) oder das autostart-File nach /home/pi/.config/lxsession/LXDE-pi/ schreibt und bootet (bootToChromium.sh).

Problembehebungen

Wayland Display Server / ydotool

Wenn man xdotool unter Wayland (z.B. Ubuntu 22.04) verwendet kann das Problem auftauchen, dass xdotool den “Black-Screen” nicht wieder deaktiviert. Will hiessen, dass die Mausbewegungen und Clicks zwar ausgeführt werden, der Bildschirm selber aber Schwarz bleibt, wenn er mal in den “Tiefschlaf” gefallen ist. Abhilfe bringt dann ydotool:

ydotool kann nicht aus den Quellen installiert werden (veraltet). Stattdessen hier eine Anleitung, wie man ydotool aus Github selber bildet:

Nach der Installation konnte ydotool immer noch nicht als normaler User ausgeführt werden, weil das Socket-File nicht gefunden wird. Hier die Lösung dafür:

Schlussendlich habe ich einfach in meinen xdotool-Files erst einen ydotool command ausgeführt. Dieser aktiviert den Screen. Anschliessend führe ich mit xdotool fort:

#!/bin/bash
export DISPLAY=:0
YDOTOOL_SOCKET="/tmp/.ydotool_socket" ydotool mousemove --absolute -- 1720 800

sleep .5

WID=$(xdotool search --onlyvisible --class chromium|head -1)
xdotool windowactivate ${WID}

### Select Kamera-Menu
xdotool mousemove 1720 800 click 1

sleep .1

### Select Axis Kinderzimmer Camera
xdotool mousemove 900 600 click 1

 

SWAP Speicher erhöhen

Es zeigt sich, dass Chromium sehr Speicherhungrig ist und das Anzeigen von sehr grossen Grafana-Panels das System zum erliegen bringen kann. Deswegen habe ich den SWAP Speicher auf 2048 erhöht: https://pimylifeup.com/raspberry-pi-swap-file/

WLAN Verbindung (Stabilität) verbessern

Der Standard WLAN Adapter des Raspberry PIs 4 ist zwar schnell aber seine Reichweite ist nicht wirklich gut. Deswegen verwende ich einen WLAN USB-Stick, der auch vom System bereits automatisch erkannt und eingebunden wurde (als Wlan1). Um sicherzustellen, dass der Raspi nur über diesen Wlan1 Adapter kommuniziert habe ich zu einem kleinen Trick gegriffen. Unter

/etc/wpa_supplicant/wpa_supplicant.conf

kann bekanntlich das WLAN konfiguriert werden. Alle Wlan Adapter verwenden diese Konfig-File.

Man kann aber auch mehrere solcher Konfig-Files anlegen und diese den Adaptern zuweisen. Dies nach dem Muster wpa_supplicant-“$interface”.conf

Um Wlan0 nicht mehr reden zu lassen, habe ich ein File wpa_supplicant-wlan0.conf ohne entsprechende Netzwerk-Konfig erstellt.

cp wpa_supplicant.conf wpa_supplicant-wlan0.conf

Das wlan0 File sieht dann so aus:

ctrl_interface=DIR=/var/run/wpa_supplicant GROUP=netdev
update_config=1
country=CH

network={
}

Damit wird für den Adapter Wlan0 dieses Konfig-File verwendet, welches sich entsprechend gar nicht verbindet. Alle anderen Wlan Adapter verwendet weiterhin wpa_supplicant.conf. Damit verbindet sich Wlan1 und Wlan0 bleibt stumm.

Optionale Info: HDMI Power off

Mein Panel besitzt eine Hintergrundbeleuchtung. Dieses blieb bei fullpageos  an, wenn xscreensaver einen Blank-Screen sendete. Dies konnte ich folgendermassen ausschalten:

sudo vcgencmd display_power 0  # HDMI Power off
sudo vcgencmd display_power 1  # HDMI Power on

Kios-Mode verlassen

  • Über VNC verbinden und  Alt+F4 drücken oder
  • über SSH mit ps -ef | grep chromium die Prozess-ID herausfinden und den Prozess killen.

 

Links

 

Armbian SD Karte klonen

Ich verwende für mein HC4 NAS ein Armbian, welches auf einer SD Karte installiert ist. Zwecks Backup wird diese SD Karte geklont.

Hier habe ich bereits beschreiben, wie man ein Klon für ein Raspberry Pi OS durchführen kann.

Für das Klonen der Armbian SD Karte wollte ich eigentlich ein Image wie hier beschreiben erstellen und dieses dann auf eine neue SD-Karte schreiben. Leider schlug dies fehl. Egal ob das Image mit dd, usbimager oder mit Win32DiskImager erstellt wurde. Die Ziel SD-Karte konnte anschliessend den HC4 nicht booten (Kernel Panic). Es schien als ob die zu klonende SD-Karte bereits so fehlerhaft ist, dass ein 1:1 Klon auf Bit-Ebene nicht mehr geht (reine Spekulation. Ich weiss auch nicht ob das überhaupt möglich wäre).

Nichts desto trotz habe ich deswegen die Strategie gewechselt und das Image aus dem laufenden Betrieb gezogen. Hier habe ich das für den Raspberry Pi bereits beschrieben. Für Armbian braucht es aber ein anderes Script. Hier bin ich fündig geworden

Hotclone Script (siehe auch hier )

#!/bin/bash
#----------------------------------------------------
# armbian_hotclone.sh
#
# Copies the sdcard your Armbian system is running from 
# to a new sdcard in an USB-attached card reader. 
#
# The new sdcard can be of any size as long as it can hold 
# the data content of the original card.
#
# The cloned card should be tested after creation to ensure
# it can be used for desaster recovery.
#
# c) Rodolfo 2016-06-19 enjoy !
#-----------------------------------------------------
#

ARMBIAN_ORIG=/dev/mmcblk0
ARMBIAN_CLONE=/dev/sdd

# Clone partial image of original SDcard ( bootstuff + partition table + start of first partition )
# we just copy 4M to account for strange partition alignment

dd if=$ARMBIAN_ORIG of=$ARMBIAN_CLONE bs=1M count=4

# Delete invalid partition of target SDCARD and create/format new ext4-partition

umount $ARMBIAN_CLONE"1"
echo -e "p\nd\nn\n\n\n\n\np\nw\nq\n" | fdisk $ARMBIAN_CLONE 
echo -e "y\n" | mkfs.ext4 $ARMBIAN_CLONE"1"

# Target mount

mkdir /mnt/armbian_clone
mount $ARMBIAN_CLONE"1" /mnt/armbian_clone
rm -r /mnt/armbian_clone/* # cleanup lost+found

# System copy to SDcard

time rsync -avSz --exclude=/dev/* --exclude=/proc/* --exclude=/sys/* --exclude=/media/* \
--exclude=/mnt/* --exclude=/run/* --exclude=/tmp/* / /mnt/armbian_clone

sync

umount $ARMBIAN_CLONE"1"

Ablauf

  1. Starte Armbian und schliesse einen SD-Card Adapter an
  2. Lege eine leere SD-Karte in den SD-Card Adapter
  3. Füre “sudo fdisk -l” aus und ermittle das Device => bei mir war es /dev/sdd
  4. Ändere den Script-Parameter ARMBIAN_CLONE entsprechend auf
    ARMBIAN_CLONE=/dev/sdd
    Auf diese SD-Karte soll das Skript den Klone ausführen
  5. Rufe das Script auf
    sudo ./armbian_hotclone.sh
    Das Script formatiert die SD-Karte und kopiert Bootloader, Partition-Table sowie die Daten auf die neue Karte.
  6. Am Schluss muss noch die UUID auf der geklonten Karte angepasst werden. Dafür
    blkid
    aufrufen und die UUID der neuen Karte notieren.
  7. Diese UUID muss in folgenden Files auf der geklonten Karte angepasst werden
    1. /boot/armbianEnv.txt
    2. /etc/fstab
  8. Damit sollte die geklonte Karte einsatzbereit sein

Auf diese Weise ist ein Klon der Armbian SD-Karte doch noch gelungen.

Shinobi auf HC4

Mein neues HC4 NAS möchte ich gerne auch als Überwachungs-Station verwenden. Ich entscheide mich Shinobi eine Chance zu geben.

Da Shinobi eine MariaDB einsetzt, wird es hier etwas “unseriös”. Dies, weil ich das Betriebssystem auf dem HC4 auf einer SD Karte betreibe. Eine Datenbank auf einer SD-Karte zu betreiben ist bekanntlich eine sehr schlechte Idee. Deswegen werde ich das Daten-Verzeichnis von mariaDB nach der Installation auf die HDD Disk verlegen (siehe Installation). Das wird zwar die Geschwindigkeit der DB reduzieren, aber dafür  auch die “Anzahl writes” auf die SD-Karte.

Im weiteren ist Armbian nicht unter dem offiziell unterstützen OS. Es wird Ubuntu empfohlen. Armbian bassiert aber wie Ubuntu auf Debian. Es besteht also eine Chance… 😉

Installation

Hier habe ich Installations-Instruktionen für Shinobi auf Armbian gefunden:

https://i12bretro.github.io/tutorials/0548.html

sudo apt update
sudo apt upgrade -y
sudo apt install git -y
cd ~git clone https://gitlab.com/Shinobi-Systems/Shinobi.git Shinobi
cd Shinobi
sudo chmod +x INSTALL/ubuntu.sh
  • mariadb installieren (y) und passwort setzen
  • shinobi Datenbank installieren (y)
  • State Shinobi on boot (y)

===> Installation beendet.

NodeJs

Während der Installation wurde ich darauf hingewiesen, dass die aktuell installierte Version von nodejs veraltet ist. Auf armbian “jammy” ist aktuell Verison 12 installiert. Ich installiere nun Version 16 (LTS-Version), welche von shinobi empfohlen wird:

Achtung, bevor die Installation der neuen VErsion durchgeführt werden kann, sollte die alte nodejs Version deinstalliert werden:

sudo apt-get purge nodejs
sudo apt-get autoremove

Anschliessend den Instruktionen von Shinobi folgen:

https://hub.shinobi.video/articles/view/JX1o76s8R8Lm56D

MariaDb Datenverzeichnis wechseln (armbian)

Da ich die mariadb auf einer SD-Karte betreibe, verschiebe die die Datenverzeichnisse auf die HDD:

Als erstes überprüfen wir, wo sich das Datenverzeichnis von MariaDb befindet

sudo mysql -u root -p
MariaDB [(none)]> select @@datadir;
+-----------------+
| @@datadir |
+-----------------+
| /var/lib/mysql/ |
+-----------------+
1 row in set (0.000 sec)
MariaDB [(none)]> exit

Offenkundig liegt es unter /var/lib/mysql. Dieses Verzeichnis müssen wir nun auf unser gewünschtes Ziel hin syncronisieren.

Dazu erstmal die DB stoppen

sudo service mariadb stop

Ich habe mir für das Zielverzeichnis ein subvolume auf btrfs erstellt. Die Daten sollen neu auf “/mnt/program_data/mariadb/data” geschrieben werden:

sudo rsync -av /var/lib/mysql /mnt/program_data/mariadb/data

Zur Sicherheit das alte Datenverzeichnis umbenennen

sudo mv /var/lib/mysql /var/lib/mysql.bak

Jetzt “biegen” wir das data Verzeichnis der MariaDB Konfiguration auf das neue Ziel um.

sudo vi /etc/mysql/mariadb.conf.d/50-server.cnf
[mysqld]
. . .
datadir=/mnt/program_data/mariadb/data/mysql
socket=/mnt/program_data/mariadb/data/mysql/mysql.sock
sudo vi /etc/mysql/mariadb.conf.d/50-client.cnf
[client]
socket=/mnt/program_data/mariadb/data/mysql/mysql.sock

[client-mariadb]

Jetzt mariadb neu starten

sudo service mariadb start

und status überprüfen

sudo service mariadb status

Und nun noch überprüfen ob mariadb die änderung übernommen hat:

sudo mysql -u root -p
MariaDB [(none)]> select @@datadir;
+---------------------------------------+
| @@datadir |
+---------------------------------------+
| /mnt/program_data/mariadb/data/mysql/ |
+---------------------------------------+
1 row in set (0.000 sec)
MariaDB [(none)]> exit

MariaDB Runlevel

Da ich die DB auf einem btrfs mount verschoben habe, muss sichergestellt sein, dass MariaDB erst dann gestartet wird, wenn die mounts im System verfügbar sind. Es ist daher nötig, die Reihenfolge der Services zu beeinflussen. Hier habe ich beschrieben wie ich das konkret umgesetzt habe.

Konfiguration shinobi

Über die Admin-Oberfläche einloggen:

http://192.168.x.x:8080/super
  • Passwort von admin@shinobi.video ändern unter “Preferences” ändern.
  • Neuer Account unter “Accounts” erstellen.

Die Videos sollen auf meinem HC4 auf den HDD gespeichert werden, nicht auf dem default “video”, welches shinobi vorgibt. Dazu in der Config “Streamdir” und “VideoDir” anpassenAnschliessend reboot oder Shinobi Restart.

Jetzt über der Benutzer-Oberfläche mit dem eben erstellen User einloggen.

http://192.168.x.x:8080

Anschliessend diesen punkten folgen:

Was ist zu tun nach einer Shinobi-Installation?

Restart Shinobi

Wenn sich Shinobi aus irgendeinem Grunde aufgehängt hat, kann man den Service neu starten:

cd ~/Shinobi
sudo pm2 restart all

Logs

Die Shinobi-Logs sind über PM2 einsehbar

sudo pm2 logs

Steams

Einder der Gründe wieso ich mich für Shinobi entschieden habe, ist die Möglichkeit alle Streams für externe Anwendungen (z.B. zum Einbinden als iFrame) zu verwenden. Hier ein Link auf die Dokumentation, wie die Streams eingebunden werden können.

Temporär vs. Permanenter API-Key

Ich hatte zu Beginn das Problem, dass nach jedem Shinobi Restart die Stream-Adresse geändert hat. Konkret ändert der API-Key unter welchem auf den Stream zugegriffen werden kann. Hier findet man die Lösung. Offenbar gibt es ein temporärer API-Key, der bei verwendet wird, wenn man auf der Kamera-Übersichtsseite einen Stream anwählt. Und dann gibt es noch einen permanenten API-Key. Diesen muss man einmalig erstellen. Dabei kann man auch den Zugriff auf eine bestimmte IP eingrenzen. Für die Einbindung des Streams in eine andere Applikation muss der permanente API-Key verwendet werden.

Links

Shinobi Closed Circuit TV (CCTV): Creating a Video Monitoring System Using the ODROID-HC2

https://i12bretro.github.io/tutorials/0548.html

How To Configure a Linux Service to Start Automatically After a Crash or Reboot – Part 2: Reference

https://docs.shinobi.video/