The first application that I have deployed in my homelab is the home surveillance capture and feed system. I needed to set up surveillance cameras at home mainly because of my baby daughter. There are so many cameras to buy from the market with everything set up nicely and can even provide live feed through their apps, but I just DON’T trust their security at all! There are so so many hacks, not just for cameras at home, and also cameras at corprations. So I have decided to roll my own system and keep everything within my home network.

Here is the overview of my setup:

First of all, all the cameras are put behind my firewall with both incoming and outgoing traffic blocked. The cameras live feed can be grabbed by rtsp, so initially I have set up ffmpeg runners to grab them directly and save to NAS, with 5 minute chunks. Each ffmpeg runner is running in its own pod on my k3s cluster, under a deployment so if the camera goes down the runner will just automatically restart. Such is the power of self healing cluster!

However as I started to add the live feed app called Home Portal, with only ffmpeg runners managing the feeds become troublesome. Then I found this awesome project called NodeMediaServer. I could write a simple nodejs app, consolidate all feeds onto it and publish HLS feed for the Home Portal and rtmp feed for the ffmpeg runners.

The next thing to think about is securing the feed as it will be exposed to public so that I can stream it when I am not at home. NodeMediaServer transcodes to HLS using ffmpeg, so I can enable AES encryption with the hls_key_info_file option of ffmpeg.

Now the feed is encrypted, the encryption key can only be delivered to users that are authenticated and authorized. I don’t want to maintain a user database or authentication and authorization services at home. Homelab isn’t suited to host everything, for example such sensitive credential data are better left for specialized services. Luckily there are free solutions. Auth0 is a great identity service and it supports OAuth, so I can use my own Google account to authenticate and configure authorization rules on Auth0. The secret key put behind a simple nodejs server that checks the requests for the key with Auth0 tokens. Voilà, I have added authentication and authorization on top of encryption!

But there are two problems with HLS playback with this scheme:

  1. In iOS HLS player doesn’t support POST request with the key URI published in the HLS playlist, so the auth token needs to be added as a param to the URI.
  2. ffmpeg doesn’t know the token when it creates the key URI

Luckily there is a great post by someone of Microsoft explaining a scheme to fix these two problems. It’s quite clever and the only additional thing for me is to implement a proxy server that rewrites the key URI.

After all these work, I finally have a live feed that’s both secure and easy to use!