When the raspberry pi 4 came out I got the idea of using it as a sort of smart TV box. I wanted something that was more under my control and flexible than the TV’s own “smart” system. In the blog I write about how I built my home media center with a bunch of raspberry pi’s, and the problems I got along the way.

My setup

  • Samsung smart TV
    • TV remote (works with kodibox through HDMI)
  • Kodibox (raspberry pi 4b 4GB bundle)
    • HDMI connected to smart TV
    • Keyboard
    • Connected to network
  • PiNAS (raspberry pi 4b 4GB)
    • 2 TB USB3 HDD
    • 32 GB MicroSD card
    • Official power supply
    • Connected to network
  • Pibackup (raspberry pi 4b 4GB)
    • 2 TB USB3 HDD
    • 32 GB MicroSD card
    • Official power supply
    • Connected to network

Software

Kodibox:

PiNAS:

Pibackup:

Laptop:

  • Nextcloud app
  • Thunderbird addons: Cardbook (for CardDAV), Lighting (for CalDAV)
  • Wireguard

Mobile:

  • Wireguard app
  • Nextcloud app
  • DAVx5

Functions:

  • Contact sync between laptop and mobile (Nextcloud+Thunderbird/Cardbook+DAVx5)
  • Calendar sync between laptop and mobile (Nextcloud+Thunderbird/Lighting+DAVx5)
  • Sync of important files from my laptop so they’re safe from SSD crash
  • Automatic backups (rsnapshot)
  • Streaming my movies, music and series from PiNAS to TV through Kodibox (Samba, Kodi)
  • Private git repositories (SSH remote to PiNAS)
  • All accessible from outside my home network through Wireguard (and only through Wireguard)
  • All above in a private way where I control the data, and it doesn’t leave my home

Pros

  • All private, control over your data
  • Pretty fun project to learn about cool protocols such as Wireguard
  • Your data accessible anywhere, like a private cloud
  • A solution to streaming media to TV without corporate stuff like inserted advertisements

Cons

  • Lots of work and troubleshooting
  • Things can break suddenly

Do you really want this?

Be aware that I ended up putting a lot of time and energy into this, and sometimes got very frustrated along the way. Stuff like a bug in Kodi that kept forgetting my credentials, slow performance with Nextcloud and problems kodi understanding my media library took a lot of work to settle out. In the meantime, the Kodi Youtube addon broke which also required manual intervention. If you’re not willing to put in the time to fix your own issues, I’d recommend just getting a Chromecast or something instead. If you’re willing, then read on so I can help you prevent some of the things I was stuck on for hours.

How to

Kodi 1/2

The first thing I set up was the Kodibox. The basics are rather easy, you put LibreElec on a microSD card, plug it into the smart TV, start it, and it should work! See LibreElec installation.

Note that for me I could control it with the Smart TV’s controller. Awesome feature! Might require you to use a HDMI cable and port that supports these features though. I’d still recommend plugging in a USB keyboard as well for when you need to type something (bad experience with an attempt at using a bluetooth keyboard).

Bare kodi is rather lame, it doesn’t have much media to show you. Some basic addons I installed:

PiNAS

Even with those addons, of course you want to be able to view personal media. To do this, I had the idea of creating a DIY NAS system with another raspberry pi.

I quickly got the idea to run Nextcloud on it so it could be used to manage my personal data as well.

I installed Raspbian Lite and used SSH for further configuration. For security and convenience, make sure you install your SSH public key and disable SSH passwords.

I installed Wireguard and tested it with my laptop and mobile. The wireguard android app is really nice. In contrast, the Linux command line interface takes some getting used to. Wireguard will allow me to securely access the PiNAS from outside my network. I only need to forward UDP port 443 on my router to my PiNAS. This way I the attack surface is rather small. I don’t need to expose the Nextcloud web app to the internet.

I installed Nextcloud and configured it with nginx. I made the data directory a link to /srv/nextcloud-data, and had mounted my external HDD to /srv.

For security, I wanted to use HTTPS. Of course my nextcloud wasn’t exposed to the internet. To be able to get a certificate anyway with the following trick:

  • Forward port 80 to PiNAS
  • Create a basic nginx site config with the following content in /etc/nginx/sites-available:
server {
	listen <internal-ip>:80;
	root /var/www/acme;
	server_name nas.thomasvanderberg.nl;

	location / {
		try_files $uri $uri/ =404;
	}
}
  • In the Let’s Encrypt pre-hook, enable the site (create symlink to it in /etc/nginx/sites-enabled) and reload nginx to make the acme site available
  • Get the certificate
  • In the post-hook, disable the site again

The hooks:

thomas@pinas:/etc/letsencrypt/renewal-hooks/pre $ cat add-acme.sh 
#!/bin/sh
ln -s /etc/nginx/sites-available/acme /etc/nginx/sites-enabled/acme
nginx -s reload
thomas@pinas:/etc/letsencrypt/renewal-hooks/pre $ cd ../post
thomas@pinas:/etc/letsencrypt/renewal-hooks/post $ cat remove-acme.sh 
#!/bin/sh
rm /etc/nginx/sites-enabled/acme
nginx -s reload

This way, the attack surface is as low as possible and I still get a valid certificate for nas.thomasvanderberg.nl.

To be able to use this in Wireguard, I added an entry on my laptop in /etc/hosts to bind nas.thomasvanderberg.nl to the Wireguard IP of my PiNAS. To support this on mobile (where I cannot edit the hosts file) I also setup dnsmasq on my PiNAS and added the /etc/hosts entry on the PiNAS side.

Kodi 2/2

I had first thought that the nextcloud WebDAV would be good enough for streaming, but sadly found out it is simply too slow. After a lot of conflict, I found out it’s better to use SMB instead.

Samba is rather simple to configure, I used this guide. I set it up so the Nextcloud files are accessible through SMB as well:

[nextcloud]
path = /srv/nextcloud-data/thomas/files
valid users = thomas
read only = yes

To allow access to the thomas user I had to create a group nextclouddata, assign it to thomas, and make all files in /srv/nextcloud-data have this group. I also made all directories under there setgid so that new files will also be accessible to the nextclouddata group.

I had a lot of trouble configuring the SMB shares on Kodi though. It seems there was a bug that forgot the SMB password on every reset. In the end I found it was better to do this on LibreElec level: mounting network shares in LibreElec (Edit: this link has bitrotted. So at the end of the article I added my mount file including important comments. See Attachment). This was much better. Kodi doesn’t even know these are remote network file shares, and just sees it as files on the regular file system.

Kodi will be able to access your movies, series and music through SMB. You can add them as media sources. Be sure that you’re tagging all your music or Kodi will pretend it doesn’t exist. Also make sure your movies have correct names and year numbers in the title. Don’t add any extra clips because kodi will pick them up and suddenly think you have the most ridiculous movies in your library. Kodi library mangement sucks, and it’s probably what frustrated me most about it. Oh well.

Continued

Well I think that’s enough for now. You can see already it was quite some effort to set this up, and I haven’t even gone into detail for most things ;)

In secret this is a guide for myself in case I ever need to fix or redo something, I have it somewhat documented on my blog.

Maybe later I’ll add a bit about how I got contact sync etc. etc. on my laptop and mobile phone.

Attachment SMB mount file configuration

Saved as /storage/.config/system.d/storage-nas.mount

Likely required a systemd command to install. Like systemctl enable storage-nas.mount

# This is a sample service script to mount CIFS/SAMBA shares.
# Please read carefully the comments in this file. For production usage
# you can remove all comments (lines beginning with "#") from this file.


[Unit]
# The description should be used to explain what this servicefile is for
Description=connect to smb://nas.thomasvanderberg.nl/nextcloud

# if we do network mounts like here we *require* 'network-online.service'
# which checks if the network is online
Requires=network-online.service

# our scripts must start *after* 'network-online.service', on timeout and if
# 'network-online.service' fails we can not mount and this scripts fails too
After=network-online.service

# usually we mount networks shares because we want they avaible *before* XBMC starts.
# so XBMC has access to this mounts from beginning. Note: this slows down the boot!
Before=kodi.service


[Mount]
# The share we want mount
What=//nas.thomasvanderberg.nl/nextcloud

# Where we want mount this share
Where=/storage/nas

# Any options you usually use with the "-o" parameter in the mount command
Options=username=<removed>,password=<removed>

# filesystem type
Type=cifs


[Install]
# The target is used by 'systemctl enable <name_of_this_file.mount>' to link
# this service to a runlevel for starting on boot. usually 'multi-user.target'
# is ok here.
WantedBy=multi-user.target

# Important:
# this file must be renamed to <mountpoint>.mount where <mountpoint>, is the FULL path
# where the share will be mounted but slashes "/" MUST BE REPLACED with dashes "-" with .mount
# as extension.
# This means, if we want mount to "/storage/music2" (see above "Where=/storage/music2")
# then this file must be renamed to 'storage-music2.mount' and can be enabled via ssh with the
# command 'systemctl enable storage-music2.mount'