Tuesday, December 5, 2023

Setting up home NAS - Part 6 - Raspberry Pi as Plex Media Server

This is the continuation of the "Setting up home NAS" series. Better read the below posts to get context.
Setting up home NAS - Part 6 - Raspberry Pi as Media Server using Plex (This post)


This post discuss how to enable Plex media server on Raspberry Pi and use within home network.


At high level we have to do the below steps
  • Enable Plex package sources and install Plex
  • Browse to http://raspberrypi:32400/web and associate with our Plex account
  • Configure the Plex to include our media folders
Let's start.

Enable Plex package sources and install Plex

Below goes the Linux commands to do the same. It needs to be run on Raspberry.

sudo apt-get update
sudo apt-get upgrade
# Enable the package install over https
sudo apt-get install apt-transport-https
# Adding the Plex GPG key
sudo curl https://downloads.plex.tv/plex-keys/PlexSign.key | sudo apt-key add -
# Add the Plex package sources to the apt.
# It basically creats a file with the deb ...
sudo echo deb https://downloads.plex.tv/repo/deb public main | sudo tee /etc/apt/sources.list.d/plexmediaserver.list
# We’re going to update our package list and install from the newly added repository.
sudo apt-get update
sudo apt-get install plexmediaserver

Added some comments to understand. In case of queries, please add comments. Once Plex is installed we need to configure.

Browse and associate with Plex Account

First naviate to http://raspberrypi:32400/web . The port 32400 is the default port for Plex. Please make sure the protocol prefix is http not https. It will load the screen as follows.

Note that the URL changed from our RaspberryPi host name to app.plex.tv after some redirects. Click on sign-in and use approprate method. Once signed in, it will redirect back to the page as shows below.

At this point our local RaspberryPi hosted Plex is connected to the credential we provided.

This is simply saying how it works. Once you click on got it. It asks for the Plex pass.

It we can, better support them by buying the pass. Yes, it supports totally free mode as well. We can click on close button to skip payment. Up on closing it will take to server setup.

We can see it can expose our media accissible from internet. In order to do that we need a router that is supporting UPnP or NAT-PMP feature. Also the port forwarding to 32400 ¹. This tutorial is moving forward to restrct access only with the home network, not internet. In case we change our mind, it can enable later as well.

The next step is to add our media folders to the Plex.

Click on the add library 

This tutorial is adding an audio library of type Music.
The library name will be Music. Click next.
Click on 'Browse for Media Folder' to get the media folder selection screen.

Browse the folders or enter the path to our folder containing audio files. This is the path in Raspberry. The path in the screenshot is where the external hard drive is mounted that contains files. Click on the "Add" button and will land on the next screen.
Click on the add library to add finish adding folder to Plex.

The same task of adding folder(s) can be done after completing the initial setup also. Click on Next.

At last we are done by clicking the "Done" button. It is time to navigate to the Plex that we setup. Browse to http://raspberrypi:32400/web and we will reach the screen as below. 
Again please note the Url protocol is http not the secure https.
What ever content we are seeing in our home page is free to watch from Plex. They change over time. These are not from our Raspberry Pi server. In order to see the personal contents hosted on Raspberry Pi, click the More button.
Here comes our personal content. Remember we created the Music library during the setup, that is what visible here.

Now it is time to access it via the Plex web site. Naviagate to https://app.plex.tv in the browser.
We can see our personal contents added to Raspberry Plex server here as well. Even the web site is app.plex.tv, it is able to get data from Raspberry due to the connection we established between our Plex credentials and the Plex server during the setup.

In case there are issues like secure connection issue as shown above, we need to wait till the DNS is propagated. Plex is using some documented magic² to retrieve the contents from Raspberry Pi to their web site and apps through our home network.
Since it is magic sometimes it won't work due to specifics of settings in our network such as router configuration. If all works fine, we can browse https://app.plex.tv and view the contents. Also, it works with the other  Plex app supported media players such as smart TVs, mobiles etc...

Configure to include our media folders

If we need to add other folders to Plex, mouse over the name of server (here it is Raspberrypi) use the + button and point to the right media folders in Raspberry Pi.

Media organization

Note that when we add the folder, Plex has to do indexing behind the scene to a database³. Depending on the storage speed and Raspberry specs, indexing time varies. After indexing only the media files will start showing up in the UI.
When we add new media files or remove, we need to run scanning again to update the Plex index.

If there is more interest, have a look at the below references. Have fun with Plex.


Tuesday, November 28, 2023

Azure @ Enterprise - Generate JWT using Service Principal +Certificate via MSAL.PS

One of the previous posts in this blog was to get JWT using the Service principal + certificate combination¹. The Az.Acount PowerShell module was used to achieve the task. That approach signs into Azure as the service principal and generates JWT. This post is to get the JWT without logging in.


Microsoft Authentication Library is to interact with the Microsoft security system recently renamed Microsoft Entra². 

There are also client-side libraries to interact with it from different languages. MSAL.PS is the library to do the same from PowerShell. Though the MSAL.PS³ is superseded by Azure Az PowerShell SDK⁴, it is still worth giving a try.

The below code shows how we can get the JWT using MSAL.PS.
The code is mostly straightforward but requires some basic understanding of the Azure security model, scope etc.

Making HTTP resource calls

Once we have the JWT, it can be used to invoke HTTP calls or to execute a SQL Query.
$token = Get-MsalToken @creds
$reqHeaders = @{
    'Authorization' = $token.CreateAuthorizationHeader()

$requestUrl = "<YOUR RESOURCE URL>"
Invoke-RestMethod -Uri $requestUrl -Headers $reqHeaders

The interesting thing is that the post published 2 years ago uses the up-to-date and officially supported method.
Happy working with legacy codebase.


¹ - https://joymonscode.blogspot.com/2021/09/azure-enterprise-powershell-log-in-as.html

² - https://learn.microsoft.com/en-us/entra/fundamentals/new-name | https://devblogs.microsoft.com/identity/aad-rebrand/

³ - https://github.com/AzureAD/MSAL.PS

⁴ - https://learn.microsoft.com/en-us/powershell/azure/new-azureps-module-az

Tuesday, November 21, 2023

SharePoint Online - Custom Raw Http calls using Graph SDK v5

The Graph SDK is a nuget library to interact with Graph API from .Net applications. Earlier this year they released¹ Graph .Net SDK v5. That highly simplified the coding with fewer lines than v4 but has breaking changes from v4 even in the basic interactions. The good part is that the Graph SDKs simplify the HTTP operations to Graph API but in some cases, we may need to deal with Raw HTTP calls. 

This post discusses such scenarios. A basic idea about Kiota and building API clients using Kiota² is helpful to easily understand the code.

Problem - Custom Url

Support we are dealing with the cutting edge of Graph API, sometimes the API or property in the result may not be available in the Graph SDK as the SDK needs some time to catch up. Unfortunately, no examples can be included due to NDA. In such cases, we need to craft the URL ourselves but we don't need to deal with the authentication. How can we customize the URL in Graph SDK with the result object using the known types in Graph SDK?


Below is the notebook³ that has the code
Hope the code is self-explanatory. The catch here is the V5 SDK will serialize the result for us. Here we are getting the known Drive object

Problem - Custom URL and Raw JSON results

Sometimes we need to deal with totally custom URLs and the result JSON. In such scenarios, we can only leverage the authentication mechanism of Graph SDK only not even the result object. How can we have a custom HTTP URL and raw JSON result using Graph SDK?

Solution - Using IRequestAdapter

One way is to use the IRequestAdapter and have NativeResponseHandler. The code in a notebook is below. This uses a dummy object to satisfy the adapter and get the JSON via NativeResponseHander.

Solution - Using native HttpClient

The above does not fully give the native experience. To get the feel of native experience we can have the below approach that uses familiar HttpClient.

Please have a look at the warning.


¹ - https://devblogs.microsoft.com/microsoft365dev/microsoft-graph-net-sdk-v5-is-now-generally-available/

² - https://learn.microsoft.com/en-us/openapi/kiota/quickstarts/dotnet

³ - https://github.com/dotnet-demos/graph-sdk-sharepoint-online-notebooks/blob/main/custom-rawhttp-calls.ipynb

⁴ - https://github.com/dotnet-demos/graph-sdk-sharepoint-online-notebooks/blob/main/custom-rawhttp-IRequestAdapter-json.ipynb

⁵ - https://github.com/dotnet-demos/graph-sdk-sharepoint-online-notebooks/blob/main/custom-rawhttp-HttpClient-json.ipynb