Skip to content

Repository files navigation

KodiNet

Web application for centralized management of Raspberry Pi running LibreELEC/Kodi.

Monitor player status, control playback, transfer video files from a private storage server to Pi devices, and schedule automated tasks.

The application was originally designed for video file management (/storage/videos folder on the Raspberry Pi). As a result, other file formats have not been tested.

Pour le français, voir README.fr.md


Table of Contents

  1. Prerequisites
  2. Architecture
  3. Quick Install (Docker)
  4. Configuration
  5. Enabling JSON-RPC on Kodi
  6. Private Storage Server
  7. Microsoft Authentication
  8. Application Roles
  9. Features
  10. Local Development
  11. Database Migrations
  12. Security
  13. License

Prerequisites

ComponentMinimum version
Raspberry Pi4B and upper
LibreELEC10.0
Kodi19 (Matrix)
MySQL8.0
Docker + Docker Compose24.0
Microsoft accountAzure AD / Entra ID (organizational)

The system requirements simply reflect the environment for which the application was developed; it may well be possible to use an earlier version of the Raspberry Pi, etc.


Architecture

┌─────────────────────────────────────────┐
│ Internet │
│ │ HTTPS (OIDC Microsoft) │
│ ┌─────▼──────────┐ │
│ │ KodiNet Web │ Blazor Server │
│ │ (container) │ .NET 8 │
│ └──┬──────────┬──┘ │
│ Internal│network │ │
│ ┌───▼───┐ ┌───▼──────────┐ │
│ │ MySQL │ │ Private │ │
│ │ 8.4 │ │ Storage │ │
│ └───────┘ │ (FastAPI) │ │
│ └──────────────┘ │
│ │
│ Local Pi network │
│ ┌────────┐ ┌────────┐ ┌────────┐ │
│ │ Pi 1 │ │ Pi 2 │ │ Pi N │ │
│ │ Kodi │ │ Kodi │ │ Kodi │ │
│ └────────┘ └────────┘ └────────┘ │
└─────────────────────────────────────────┘

Application layers:

KodiNet.Domain Entities, enumerations, pure interfaces
KodiNet.Application DTOs, service interfaces, business logic
KodiNet.Infrastructure EF Core/MySQL, Kodi/SFTP/HTTP clients, encryption
KodiNet.Web Blazor Server, MudBlazor components, pages

Quick Install (Docker)

1. Clone the repository

git clone https://github.com/your-account/kodinet.git
cd kodinet

2. Create the environment file

cp .env.example .env

Edit .env with your values:

# Azure ADAZUREAD_TENANTID=xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxxAZUREAD_CLIENTID=xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxxAZUREAD_CLIENTSECRET=your_azure_secret# DatabaseMYSQL_ROOT_PASSWORD=strong_root_passwordMYSQL_DATABASE=kodinetMYSQL_USER=kodinet_userMYSQL_PASSWORD=strong_db_password# Private storage serverSTORAGE_API_KEY=long_random_storage_api_keySTORAGE_MAX_SIZE_MB=4096

3. Start the stack

docker compose up -d --build

The application is available at http://localhost:8080.

Database migrations are applied automatically on startup.

4. First access

Sign in with a Microsoft account from your organization. The first user to connect automatically receives the Owner role.


Configuration

appsettings.json (structure — values come from .env)

{
"AzureAd": {
"Instance": "https://login.microsoftonline.com/",
"TenantId": "",
"ClientId": "",
"ClientSecret": "",
"CallbackPath": "/signin-oidc"
},
"Storage": {
"BaseUrl": "http://storage:8090",
"ApiKey": "",
"RootPath": "/data"
},
"ConnectionStrings": {
"DefaultConnection": ""
}
}

All sensitive values are injected via Docker environment variables (format Section__Key).

SMTP Configuration (from the UI)

Mail configuration is managed from Settings → SMTP Email, accessible only to the Owner role. The SMTP password is encrypted in the database via AES (DataProtection API).


Enabling JSON-RPC on Kodi

On each Raspberry Pi, from the Kodi interface:

  1. SettingsServicesControl
  2. Enable Allow remote control via HTTP
  3. Optional: set a username and password
  4. Default port is 8080

Private Storage Server

The storage server is included in the Docker stack. It exposes a REST API on port 8090 (accessible only from the web container, not from the outside).

Exposed Endpoints

MethodURLDescription
GET/api/files?path=/folderList folder contents
GET/api/files/download?path=/fileDownload a file
POST/api/files/upload?path=/folderUpload a file (multipart)
POST/api/files/folder?path=/folderCreate a folder
DELETE/api/files?path=/elementDelete a file or folder
PATCH/api/files/renameRename
PATCH/api/files/moveMove

Authentication: X-Api-Key header with the value of STORAGE_API_KEY.

Size Limit

Configurable via STORAGE_MAX_SIZE_MB in .env. Default: 4096 MB (4 GB).

Data Volume

Files are stored in the Docker volume storage_data (persistent). To mount an existing host directory:

# In docker-compose.ymlvolumes:
- /path/on/host/videos:/data

Microsoft Authentication

Create an App Registration in Azure Entra ID

  1. Azure Portal → Azure Active DirectoryApp registrationsNew registration
  2. Name: KodiNet
  3. Supported account types: Accounts in this organizational directory only
  4. Redirect URI: https://your-domain.com/signin-oidc (Web)
  5. After creation, note Application (client) IDAZUREAD_CLIENTID
  6. Directory → Directory (tenant) IDAZUREAD_TENANTID
  7. Certificates & secrets → New client secret → note the value → AZUREAD_CLIENTSECRET

Required Permissions

No Graph permissions required — KodiNet only uses basic OIDC authentication (OpenID + profile + email).


Application Roles

Roles are managed from Settings → Users. They are stored in the internal database, independently of Azure AD.

RoleAttributeRights
OwnerUnique — non-revocable — not assignable from the UIAll Admin rights + SMTP config + theme management + import/export + ownership transfer
AdminManaged by OwnerPi management, establishments, users, scheduler, notifications
OperatorManaged by AdminKodi player control, file transfers
ViewerManaged by AdminRead-only — Pi status monitoring

First Owner

The first user to sign in to the application automatically receives the Owner role. This mechanism only triggers once (when the user_roles table is empty).

Ownership Transfer

From Settings → Users, the "Transfer Owner Role" button allows the Owner to delegate their role to another user. The current Owner is immediately signed out after the transfer.


Features

Dashboard

  • Pi grid with real-time status (Playing / Idle / Offline / Incompatible)
  • Filter by establishment, status, text search
  • Sort by name, status, establishment (ascending/descending)
  • Bulk Pi import from CSV file
  • Global stats in the header bar (total / playing / offline)

CSV import format for Pi:

name,ip_address,location,model,kodi_user,kodi_password,kodi_port,ssh_user,ssh_password,ssh_port,video_folder
Hall Pi A,192.168.1.10,North Building,Pi 4B,kodi,password,8080,pi,password,22,/storage/videos

Pi Detail Panel

Info & Status tab

  • Kodi status, version, CPU temperature, free memory, disk space
  • Volume control
  • Configuration details

Player & Files tab

  • Play/pause, previous/next track, stop
  • Repeat mode (Off / One / All)
  • File browsing via SFTP
  • File upload from browser to Pi
  • File renaming
  • Direct link to Kodi web interface

Private Storage

  • Browse the storage server file tree
  • Upload video files from the browser
  • Create folders, rename, move, delete
  • Send selected files to one or more Pi (background transfer)
  • Transfer queue with progress tracking
  • Storage operations log (import, deletion, rename, move)

Settings

Users (Admin) — Role management and cron notification activation per user

Establishments (Admin) — CRUD for establishments + CSV import/export

Scheduler (Admin)

  • KodiRestarter job: restarts idle players (Idle/Stopped) and plays the video folder on repeat
  • KodiRebooter job: reboots the LibreELEC system on all Pi
  • Cron expression configuration per job
  • Enable/disable per job
  • Execution history with per-Pi detail

Themes (Owner) — Create, edit, delete custom themes

SMTP Email (Owner) — Mail server configuration (AES encryption for password)

Themes

4 built-in themes: Ruby (bordeaux), Ocean (petrol blue), Amber (warm wood). Each theme has light and dark modes. The mode (System / Light / Dark) is remembered per device in localStorage.

Multilingual

The interface is available in French and English. Language is selected from the user menu (avatar icon in the top right). The choice is persisted per user account and synchronized across all connected devices.


Local Development

Prerequisites

  • .NET 8 SDK
  • MySQL 8.0 (local or Docker)
  • Python 3.12+ (for the storage server)

Getting Started

# Clone
git clone https://github.com/mathiasbenner/kodinet.git
cd kodinet
# Restore packages
dotnet restore KodiNet.sln
# Configure local secrets (never commit these)cd KodiNet.Web
dotnet user-secrets set"AzureAd:TenantId""your-tenant-id"
dotnet user-secrets set"AzureAd:ClientId""your-client-id"
dotnet user-secrets set"AzureAd:ClientSecret""your-secret"
dotnet user-secrets set"ConnectionStrings:DefaultConnection""Server=localhost;..."
dotnet user-secrets set"Storage:ApiKey""your-key"# Start the storage server (optional)cd ../KodiNet.API
pip install -r requirements.txt
python main.py
# Start the applicationcd ../KodiNet.Web
dotnet run

docker-compose.override.yml (dev only, gitignored)

services:
db:
ports:
- "3306:3306"# direct access from the IDEweb:
environment:
ASPNETCORE_ENVIRONMENT: Development

Database Migrations

Migrations are applied automatically on application startup.

To create a new migration after modifying an entity:

dotnet ef migrations add MigrationName \
--project KodiNet.Infrastructure \
--startup-project KodiNet.Web

Security

  • Authentication: Microsoft OIDC — only accounts from your Azure AD organization can sign in
  • Authorization: application roles stored in database, loaded via IClaimsTransformation
  • Kodi/SSH credentials: encrypted in database via AES (DataProtection API)
  • SMTP password: encrypted in database via AES
  • Storage API Key: injected via environment variable, never exposed client-side
  • Docker network: MySQL and storage server on internal: true network — inaccessible from outside
  • No secrets in the repository: .env and appsettings.*.json are gitignored

License

MIT — see LICENSE.

Main dependencies and their licenses:

PackageLicense
MudBlazorMIT
Microsoft.Identity.WebMIT
Entity Framework CoreMIT
Pomelo.EntityFrameworkCore.MySqlMIT
SSH.NETMIT
CronosMIT

About

Web application for centralized management of Raspberry Pi running LibreELEC/Kodi.

Topics

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Used by

Contributors

Languages