This is the multi-page printable view of this section.
Click here to print.
Return to the regular view of this page.
LibreELEC
One of the best systems for a handling media is LibreELEC. It’s both a Kodi box and a server appliance that’s resistant to abuse. With the right hardware (like a ROCKPro64 or Waveshare) it also makes an excellent portable server for traveling.
Deployment
Download an image from https://libreelec.tv/downloads and flash as directed. Enable SSH during the initial setup.
Storage
RAID is a useful feature but only BTRFS works directly. This is fine, but with a little extra work you can add MergerFS, a popular option for combining disks.
BTRFS
Create the RAID set on another PC. If your disks are of different sizes you can use the ‘single’ profile, but leave the metadata mirrored.
sudo mkfs.btrfs -f -L pool -d single -m raid1 /dev/sda /dev/sdb /dev/etc...
After attaching to LibreELEC, the array will be automatically mounted at /media/pool
based on label pool
you specified above.
MergerFS
This is a good option if you just want to combine disks and unlike most other RAID technologies, if you loose a disk the rest will keep going. Many people combine this with SnapRAID for off-line parity.
But it’s a bit more work.
Cooling
You may want to manage the fan. The RockPro64 has a PWM fan header and LibreELEC loads the pwm_fan module.
Kodi Manual Start
The kodi process can use a significant amount of CPU even at rest. If you’re using this primarily as a file server you can disable kodi from starting automatically.
cp /usr/lib/systemd/system/kodi.service /storage/.config/system.d/kodi-alt.service
systemctl mask kodi
To start kodi, you can enter systemctl start kodi-alt
Remotes
Plug in a cheap Fm4 style remote and it ‘just works’ with kodi. But if you want to customize some remote buttons, say to start kodi manually, you still can.
Enable SMB
To share your media, simply copy the sample file, remove all the preconfigured shares (unless you want them), and add one for your storage pool. Then just enable Samba and reboot (so the file is picked up)
cp /storage/.config/samba.conf.sample /storage/.config/samba.conf
vi /storage/.config/samba.conf
[media]
path = /storage/pool
available = yes
browseable = yes
public = yes
writeable = yes
Config --> LibreELEC --> Services --> Enable Samba
Enable HotSpot
Config --> LibreELEC --> Network --> Wireless Networks
Enable Active and Wireless Access Point and it just works!
Enable Docker
This is a good way handle things like Jellyfin or Plex if you must. In the GUI, go to add-ons, search for the items below and install.
- docker
- LinuxServer.io
- Docker Image Updater
Then you must make sure the docker starts starts after the storage is up or the containers will see an empty folder instead of a mounted one.
vi /storage/.config/system.d/service.system.docker.service
[Unit]
...
...
After=network.target storage-pool.mount
If that fails, you can also tell docker to wait a bit
ExecStartPre=/usr/bin/sleep 120
Remote Management
You may be called upon to look at something remotely. Sadly, there’s no remote access to the GUI but you can use things like autossh
to create a persistent remote tunnel, or wireguard
to create a VPN connection. Wireguard is usually better.
2 - AutoSSH
This allows you to setup and monitor a remote tunnel as the easiest wat to manage remote clients is to let them come to you. To accomplish this, we’ll set up a server, create client keys, test a reverse tunnel, and setup autossh.
The Server
This is simply a server somewhere that everyone can reach via SSH. Create a normal user account with a password and home directory, such as with adduser remote
. We will be connecting from our clients for initial setup with this.
The Client
Use SSH to connect to the LibreELEC client, generate a ssh key pair and copy it to the remote server
If all went well you can back out and then test logging in with no password. Make sure to do this and accept the key so th
The Reverse Tunnel
SSH normally connects your terminal to a remote server. Think of this as a encrypted tunnel where your keystrokes are sent to the server and it’s responses are sent back to you. You can send more than your keystrokes, however. You can take any port on your system and send it as well In our case, we’ll take port 22 (where ssh just happens to be listening) and send it to the rendezvous server on port 2222. SSH will continue to accept local connections while also taking connections from the remote port we are tunneling in.
# On the client, issue this command to connect the (-R)remote port 2222 to localhost:22, i.e. the ssh server on the client
ssh -N -R 2222:localhost:22 -o ServerAliveInterval=240 -o ServerAliveCountMax=2 [email protected]
# Leave that running while you login to the rendezvois server and test if you can now ssh to the client by connecting to the forwarded port.
ssh [email protected]
ssh root@localhost -p 2222
# Now exit both and set up Autossh below
Autossh
Autossh is a daemon that monitors ssh sessions to make sure they’re up and operational, restarting them as needed, and this is exactly what we need to make sure the ssh session from the client stays up. To run this as a service, a systemd service file is needed. For LibreELEC, these are in /storage/.config.
vi /storage/.config/system.d/autossh.service
[Unit]
Description=autossh
Wants=network-online.target
After=network-online.target
[Service]
Type=simple
User=root
EnvironmentFile=/storage/.config/autossh
ExecStart=/storage/.kodi/addons/virtual.system-tools/bin/autossh $SSH_OPTIONS
Restart=always
RestartSec=60
[Install]
WantedBy=multi-user.target
vi /storage/.config/autossh
AUTOSSH_POLL=60
AUTOSSH_FIRST_POLL=30
AUTOSSH_GATETIME=0
AUTOSSH_PORT=22034
SSH_OPTIONS="-N -R 2222:localhost:22 [email protected] -i /storage/.ssh/id_rsa"
systemctl enable autossh.service
systemctl start autossh.service
systemctl status autossh.service
At this point, the client has a SSH connection to your server on port 22, opened port 2222 the ssh server and forwarded that back to it’s own ssh server. You can now connect by:
If not, check the logs for errors and try again.
journalctl -b 0 --no-pager | less
Remote Control
Now that you have the client connected, you can use your Rendezvous Server as a Jump Host to access things on the remote client such as it’s web interface and even the console via VNC. Your connection will generally take the form of:
ssh localport:libreelec:libreelec_port -J rendezvoisServer redevoisServer -p autosshPort
The actual command is hard to read as are going through the rendezvois server twice and connecting to localhost on the destination.
3 - Building
This works best in an Ubuntu container.
LibreELECT Notes
Installed but no sata hdd. Found this
RPi4 has zero support for PCIe devices so why is it “embarrasing” for LE to omit support for PCIe SATA things in our RPi4 image?
Feel free to send a pull-request to GitHub enabling the kernel config that’s needed.
https://forum.libreelec.tv/thread/27849-sata-controller-error/
Went though thier resouces
beginners guid to git https://wiki.libreelec.tv/development/git-tutorial#forking-and-cloning
building basics https://wiki.libreelec.tv/development/build-basics
specific build commands https://wiki.libreelec.tv/development/build-commands/build-commands-le-12.0.x
and then failed because jammy wasn’t compatibile enough
Created a jammy container and restarted
https://ubuntu.com/server/docs/lxc-containers
sudo lxc-create –template download –name u1
ubuntu
jammy
amd64
sudo lxc-start –name u1 –daemon
sudo lxc-attach u1
Used some of the notes from
https://www.artembutusov.com/libreelec-raid-support/
Did as fork, clone and a
git fetch –all
but couldnt get all the downloads as alsa.org site was down
On a side note, these are needed in the config.txt so that USB works
otg_mode=1,dtoverlay=dwc2,dr_mode=host
https://www.jeffgeerling.com/blog/2020/usb-20-ports-not-working-on-compute-module-4-check-your-overlays
I tried a menuconfig and selected ..sata? and got
CONFIG_ATA=m <
CONFIG_ATA_VERBOSE_ERROR=y <
CONFIG_ATA_FORCE=y
CONFIG_ATA_SFF=y
CONFIG_ATA_BMDMA=y
Better compare the .config file again
Edited and commited a config.txt but it didn’t show up in the image. Possibly the wrong file or theres another way to realize that chagne
Enabled the SPI interface
https://raspberrypi.stackexchange.com/questions/48228/how-to-enable-spi-on-raspberry-pi-3
https://wiki.libreelec.tv/configuration/config_txt
sudo apt install lxc
# This didn't work for some reason
sudo lxc-create --template download --name u1 --dist ubuntu --release jammy --arch amd64
sudo lxc-create --template download --name u1
sudo lxc-start --name u1 --daemon
sudo lxc-attach u1
# Now inside, build
apt update
apt upgrade
apt-get install gcc make git wget
apt-get install bc patchutils bzip2 gawk gperf zip unzip lzop g++ default-jre u-boot-tools texinfo xfonts-utils xsltproc libncurses5-dev xz-utils
# login and fork so you can clone more easily. Some problem with the creds
cd
git clone https://github.com/agattis/LibreELEC.tv
cd LibreELEC.tv/
git fetch --all
git tag
git remote add upstream https://github.com/LibreELEC/LibreELEC.tv.git
git fetch --all
git checkout libreelec-12.0
git checkout -b CM4-AHCI-Add
PROJECT=RPi ARCH=aarch64 DEVICE=RPi4 tools/download-tool
ls
cat /etc/passwd
pwd
ls /home/
ls /home/ubuntu/
ls
cd ..
mv LibreELEC.tv/ /home/ubuntu/
cd /home/ubuntu/
ls -lah
chown -R ubuntu:ubuntu LibreELEC.tv/
ls -lah
cd LibreELEC.tv/
ls
ls -lah
cd
sudo -i -u ubuntu
ip a
cat /etc/resolv.conf
ip route
sudo -i -u ubuntu
apt install tmux
sudo -i -u ubuntu tmux a
# And back home you can write
ls -lah ls/u1/rootfs/home/ubuntu/LibreELEC.tv/target/
5 - MergerFS
This is a good option if you just want to combine disks and unlike most other RAID technologies, if you loose a disk the rest will keep going. Many people combine this with SnapRAID for off-line parity.
Prepare and Exempt Disks
Prepare and exempt the file systems from auto-mounting1 so you can supply your own mount options and make sure they are up before you start MergerFS.
Make sure to wipe the disks before using as wipefs and fdisk are not available in LibreELEC.
# Assuming the disks are wiped, format and label each disk the same
mkfs.ext4 /dev/sda
e2label /dev/sda pool-member
# Copy the udev rule for editing
cp /usr/lib/udev/rules.d/95-udevil-mount.rules /storage/.config/udev.rules.d
vi /storage/.config/udev.rules.d/95-udevil-mount.rules
Edit this section by adding the pool-member label from above
# check for special partitions we dont want mount
IMPORT{builtin}="blkid"
ENV{ID_FS_LABEL}=="EFI|BOOT|Recovery|RECOVERY|SETTINGS|boot|root0|share0|pool-member", GOTO="exit"
Test this by rebooting and making sure the drives are not mounted.
Add Systemd Mount Units
Each filesystem requires a mount unit like below. Create one for each drive named disk1, disk2, etc. Note: The name of the file is import and to mount /storage/disk1
the name of the file must be storage-disk1.mount
vi /storage/.config/system.d/storage-disk1.mount
[Unit]
Description=Mount sda
Requires=dev-sda.device
After=dev-sda.device
[Mount]
What=/dev/sda
Where=/storage/disk1
Type=ext4
Options=rw,noatime,nofail
[Install]
WantedBy=multi-user.target
systemctl enable --now storage-disk1.mount
Download and Test MergerFS
MergerFS isn’t available as an add-on, but you can get it directly from the developer. LibreELEC (or CoreELEC) on ARM have a 32 bit[^2] user space so you’ll need the armhf version.
wget https://github.com/trapexit/mergerfs/releases/latest/download/mergerfs-static-linux_armhf.tar.gz
tar --extract --file=./mergerfs-static-linux_armhf.tar.gz --strip-components=3 usr/local/bin/mergerfs
mkdir bin
mv mergerfs bin/
Mount the drives and run a test like below. Notice the escaped *
. That’s needed at the command line to prevent shell globbing.
mkdir /storage/pool
/storage/bin/mergerfs /storage/disk\* /storage/pool/
Create the MergerFS Service
vi /storage/.config/system.d/mergerfs.service
[Unit]
Description = MergerFS Service
After=storage-disk1.mount storage-disk2.mount storage-disk3.mount storage-disk4.mount
Requires=storage-disk1.mount storage-disk2.mount storage-disk3.mount storage-disk4.mount
[Service]
Type=forking
ExecStart=/storage/bin/mergerfs -o category.create=mfs,noatime /storage/disk* /storage/pool/
ExecStop=umount /storage/pool
[Install]
WantedBy=default.target
systemctl enable --now mergerfs.service
Your content should now be available in /storage/pool
after boot.
6 - Remotes
Most remotes just work. Newer ones emulate a keyboard and send well-known multimedia keys like ‘play’ and ‘volume up’. If you want to change what a button does, you can tell Kodi what to do pretty easily. In addition, LibreELEC also supports older remotes using eventlircd
and popular ones are already configured. You can add unusual ones as well as get normal remotes to perform arbitrary actions when kodi isn’t running (like telling the computer to start kodi or shutdown cleanly).
Modern Remotes
If you plug in a remote receiver and the kernel makes reference to a keyboard you have a modern remote and Kodi will talk to it directly.
dmesg
input: BESCO KSL81P304 Keyboard as ...
hid-generic 0003:2571:4101.0001: input,hidraw0: USB HID v1.11 Keyboard ...
If you want to change a button action, put kodi into log mode, tail the logfile, and press the button in question to see what event is detected.
# Turn on debug
kodi-send -a toggledebug
# Tail the logfile
tail -f /storage/.kodi/temp/kodi.log
debug <general>: Keyboard: scancode: 0xac, sym: 0xac, unicode: 0x00, modifier: 0x0
debug <general>: HandleKey: browser_home (0xf0b6) pressed, window 10000, action is ActivateWindow(Home)
In this example, we pressed the ‘home’ button on the remote. That was detected as a keyboard press of the browser_home
key. This is just one of many defined keys like ’email’ and ‘calculator’ that can be present on a keyboard. Kodi has a default action of that and you can see what it is in the system keymap
# View the system keyboard map to see what's happening by default
cat /usr/share/kodi/system/keymaps/keyboard.xml
To change what happens, create a user keymap. Any entries in it will override the default.
# Create a user keymap that takes you to 'Videos' instead of 'Home'
vi /storage/.kodi/userdata/keymaps/keyboard.xml
<keymap>
<global>
<keyboard>
<browser_home>ActivateWindow(Videos)</browser_home>
</keyboard>
</global>
</keymap>
kodi-send -a reloadkeymaps
Legacy Remotes
How They Work
Some receivers don’t send well-known keys. For these, there’s eventlircd
. LibreELEC has a list of popular remotes that fall into this category and will dynamically use it as needed. For instance, pair an Amazon Fire TV remote and udev
will fire, match a rule in /usr/lib/udev/rules.d/98-eventlircd.rules
, and launch eventlircd
with the buttons mapped in /etc/eventlircd.d/aftvsremote.evmap
.
These will interface with Kodi using it’s “LIRC” (Linux Infrared Remote Contoll) interface. And just like with keyboards, there’s a set of well-known remote keys Kodi will accept. Some remotes don’t know about these so eventlircd
does some pre-translation before relaying to Kodi. If you look in the aftvsremote.evmap
file for example, you’ll see that KEY_HOMEPAGE = KEY_HOME
.
To find out if your remote falls into this category, enable logging, tail the log, and if your remote has been picked up for handling by eventlircd
you’ll see some entries like this.
debug <general>: LIRC: - NEW 66 0 KEY_HOME devinput (KEY_HOME)
debug <general>: HandleKey: percent (0x25) pressed, window 10000, action is PreviousMenu
In the first line, Kodi notes that it’s LIRC interface received a KEY_HOME button press. (Eventlircd
actually translated it, but that happened before kodi saw anything.) In the second line, Kodi says it received the key ‘percent’, and preformed the action ‘Back’. The part where Kodi says ‘percent (0x25)’ was pressed seems resistent to documentation, but the action of PreviousMenu is the end result. The main question is why?
Turns out that Kodi has a pre-mapping file for events relayed to it from LIRC systems. There’s a mapping for ‘KEY_HOME’ that kodi translates to the well-known key ‘start’. Then Kodi checks the normal keymap file and ‘start’ translates to the Kodi action ‘Back’
Take a look at the system LIRC mapping file to see for yourself.
# The Lircmap file has the Kodi well-known button (start) surrounding the original remote command (KEY_HOME)
grep KEY_HOME /usr/share/kodi/system/Lircmap.xml
<start>KEY_HOME</start>
Then take a look at the normal mapping file to see how start get’s handled
# The keymap file has the well-known Kodi button surrounding the Kodi action,
grep start /usr/share/kodi/system/keymaps/remote.xml
<start>PreviousMenu</start>
You’ll actually see quite a few things are mapped to ‘start’ as it does different things depending on what part of Kodi you are accessing at the time.
You have a few options an they are listed here in increasing complexity. Specifically, you can
- Edit the keymap
- Edit the Lircmap and keymap
- Edit the eventlircd evmap
Edit the Keymap
To change what the KEY_HOME button does you can create a user keymap like before and override it. It just needs a changed from keyboard to remote for entering through the LIRC interface. In this example we’ve set it to actually take you home via the kodi function ActivateWindow(Home).
vi /storage/.kodi/userdata/keymaps/remote.xml
<keymap>
<global>
<remote>
<start>ActivateWindow(Home)</start>
</remote>
</global>
</keymap>
Edit the Lircmap and Keymap
This can occasionally cause problems though - such as when you have another button that already gets translated to start and you want it to keep working the same. In this case, you make an edit at the Lircmap level to translate KEY_HOME to some other button first, then map that button to the action you want. (You can’t put the Kodi function above in the Lircmap file so you have to do a double hop.)
First, let’s determine what the device name should be with the irw
command.
irw
# Hit a button and the device name will be at the end
66 0 KEY_HOME devinput
Now let’s pick a key. My remote doesn’t have a ‘red’ key, so lets hijack that one. Note the device name devinput
from the above.
vi /storage/.kodi/userdata/Lircmap.xml
<lircmap>
<remote device="devinput">
<red>KEY_HOME</red>
</remote>
</lircmap>
Then map the key restart kodi (the keymap reload command doesn’t handle Lircmap)
vi /storage/.kodi/userdata/keymaps/remote.xml
<keymap>
<global>
<remote>
<red>ActivateWindow(Home)</red>
</remote>
</global>
</keymap>
Edit the Eventlircd Evmap
You can also change what evenlircd
does. If LibreELEC wasn’t a read-only filesystem you’d have done this first. But you can do it with a but more work than the above if you prefer.
# Copy the evmap files
cp -r /etc/eventlircd.d /storage/.config/
# Override where the daemon looks for it's configs
systemctl edit --full eventlircd
# change the ExecStart line to refer to the new location - add vvv to the end for more log info
ExecStart=/usr/sbin/eventlircd -f --evmap=/storage/.config/eventlircd.d --socket=/run/lirc/lircd -vvv
# Restart, replug the device and grep the logs to see what evmap is in use
systemctl restart eventlircd
journalctl | grep evmap
# Edit that map to change how home is mapped (yours may not use the default map)
vi /storage/.config/eventlircd.d/default.evmap
Sometimes, you’ll have a button that does nothing at all.
debug <general>: LIRC: - NEW ac 0 KEY_HOMEPAGE devinput (KEY_HOMEPAGE)
debug <general>: HandleKey: 0 (0x0, obc255) pressed, window 10016, action is
In this example Kodi received the KEY_HOMEPAGE button, consulted it’s Lircmap.xml
and didn’t find anything. This is because eventlircd
didn’t recognize the remote and translate it to KEY_HOME like before. That’s OK, we can just add a user LIRC mapping. If you look through the system file you’ll see things like ‘KEY_HOME’ are tto the ‘start’ button. So let’s do the same.
vi /storage/.kodi/userdata/Lircmap.xml
<lircmap>
<remote device="devinput">
<start>KEY_HOMEPAGE</start>
</remote>
</lircmap>
Check the log and you’ll see that you now get
debug <general>: LIRC: - NEW ac 0 KEY_HOMEPAGE devinput (KEY_HOMEPAGE)
debug <general>: HandleKey: 251 (0xfb, obc4) pressed, window 10025, action is ActivateWindow(Home)
Remotes Outside Kodi
You may want a remote to work outside of kodi too - say because you want to start kodi with a remote button. If you have a modern remote that eventlircd
didn’t capture, you must first add your remote to the list of udev rules.
Capture The Remote
First you must identify the remote with lsusb
. It’s probably the only non-hub device listed.
lsusb
...
...
Bus 006 Device 002: ID 2571:4101 BESCO KSL81P304
^ ^
Vendor ID -------------/ \--------- Model ID
...
Then, copy the udev
rule file and add a custom rule for your remote.
cp /usr/lib/udev/rules.d/98-eventlircd.rules /storage/.config/udev.rules.d/
vi /storage/.config/udev.rules.d/98-eventlircd.rules
...
...
...
ENV{ID_USB_INTERFACES}=="", IMPORT{builtin}="usb_id"
# Add the rule under the above line so the USB IDs are available.
# change the numbers to match the ID from lsusb
ENV{ID_VENDOR_ID}=="2571", ENV{ID_MODEL_ID}=="4101", \
ENV{eventlircd_enable}="true", \
ENV{eventlircd_evmap}="default.evmap"
...
Now, reboot, turn on logging and see what the buttons show up as. You can also install the system tools
add-on in kodi, and at the command line, stop kodi
and the eventlircd
service, then run evtest
and press some buttons. You should see something like
Testing ... (interrupt to exit)
Event: time 1710468265.112925, type 4 (EV_MSC), code 4 (MSC_SCAN), value c0223
Event: time 1710468265.112925, type 1 (EV_KEY), code 172 (KEY_HOMEPAGE), value 1
Event: time 1710468265.112925, -------------- SYN_REPORT ------------
Event: time 1710468265.200987, type 4 (EV_MSC), code 4 (MSC_SCAN), value c0223
Event: time 1710468265.200987, type 1 (EV_KEY), code 172 (KEY_HOMEPAGE), value 0
Event: time 1710468265.200987, -------------- SYN_REPORT ------------
Now that you have seen the event, you must have the irexec
process watching for it to take action. Luckily, LibreELEC already includes it.
vi /storage/.config/system.d/irexec.service
[Unit]
Description=IR Remote irexec config
After=eventlircd.service
Wants=eventlircd.service
[Service]
ExecStart=/usr/bin/irexec --daemon /storage/.lircrc
Type=forking
[Install]
WantedBy=multi-user.target
We’ll create a the config file next. The config is the command or script to run. systemctl start kodi
in our case.
begin
prog = irexec
button = KEY_HOMEPAGE
config = systemctl start kodi
end
Let’s enable and start it up
systemctl enable --now irexec
Go ahead and stop kodi, then press the KEY_HOMEPAGE button on your remote. Try config entries like echo start kodi > /storage/test-results
if you have issues and wonder if it’s running.
Notes
You may notice that eventlircd is always running, even if it has no remotes. That’s of a unit file is in
/usr/lib/systemd/system/multi-user.target.wants/. I’m not sure of why this is the case when there is no remote in play.
https://discourse.osmc.tv/t/cant-create-a-keymap-for-a-remote-control-button-which-is-connected-by-lircd/88819/6