diff --git a/devices/homie/default.nix b/devices/homie/default.nix
index b8c3aa18..399fb54e 100644
--- a/devices/homie/default.nix
+++ b/devices/homie/default.nix
@@ -55,5 +55,6 @@ in {
     sshd.enable = true;
   };
 
+  khepri.enable = true;
   services.kmscon.enable = true;
 }
diff --git a/devices/homie/modules/home-assistant/default.nix b/devices/homie/modules/home-assistant/default.nix
index 8017e55f..5ed36529 100644
--- a/devices/homie/modules/home-assistant/default.nix
+++ b/devices/homie/modules/home-assistant/default.nix
@@ -4,6 +4,7 @@
     ./bluetooth.nix
     ./firmware.nix
     ./frontend.nix
+    ./netdaemon
     ./spotify.nix
     ./timer.nix
   ];
diff --git a/devices/homie/modules/home-assistant/netdaemon/.envrc b/devices/homie/modules/home-assistant/netdaemon/.envrc
new file mode 100644
index 00000000..7ce9ad6f
--- /dev/null
+++ b/devices/homie/modules/home-assistant/netdaemon/.envrc
@@ -0,0 +1 @@
+use flake "$FLAKE#netdaemon"
diff --git a/devices/homie/modules/home-assistant/netdaemon/.gitignore b/devices/homie/modules/home-assistant/netdaemon/.gitignore
new file mode 100644
index 00000000..7de5508b
--- /dev/null
+++ b/devices/homie/modules/home-assistant/netdaemon/.gitignore
@@ -0,0 +1,2 @@
+obj
+bin
diff --git a/devices/homie/modules/home-assistant/netdaemon/apps/AppModel/YamlConfigApp/YamlConfigApp.cs b/devices/homie/modules/home-assistant/netdaemon/apps/AppModel/YamlConfigApp/YamlConfigApp.cs
new file mode 100644
index 00000000..73185228
--- /dev/null
+++ b/devices/homie/modules/home-assistant/netdaemon/apps/AppModel/YamlConfigApp/YamlConfigApp.cs
@@ -0,0 +1,19 @@
+namespace AppModel;
+
+/// <summary>
+///     Showcases how to instance apps with yaml and use automatic configuration population
+/// </summary>
+[NetDaemonApp]
+public class HelloYamlApp
+{
+    public HelloYamlApp(IHaContext ha, IAppConfig<HelloConfig> config)
+    {
+        ha.CallService("notify", "persistent_notification",
+            data: new {message = config.Value.HelloMessage, title = "Hello yaml app!"});
+    }
+}
+
+public class HelloConfig
+{
+    public string? HelloMessage { get; set; }
+}
\ No newline at end of file
diff --git a/devices/homie/modules/home-assistant/netdaemon/apps/AppModel/YamlConfigApp/YamlConfigApp.yaml b/devices/homie/modules/home-assistant/netdaemon/apps/AppModel/YamlConfigApp/YamlConfigApp.yaml
new file mode 100644
index 00000000..d709335c
--- /dev/null
+++ b/devices/homie/modules/home-assistant/netdaemon/apps/AppModel/YamlConfigApp/YamlConfigApp.yaml
@@ -0,0 +1,2 @@
+AppModel.HelloConfig:
+  HelloMessage: Hello from yaml
\ No newline at end of file
diff --git a/devices/homie/modules/home-assistant/netdaemon/apps/GlobalUsings.cs b/devices/homie/modules/home-assistant/netdaemon/apps/GlobalUsings.cs
new file mode 100644
index 00000000..b2d698e3
--- /dev/null
+++ b/devices/homie/modules/home-assistant/netdaemon/apps/GlobalUsings.cs
@@ -0,0 +1,6 @@
+// Common usings for NetDaemon apps
+global using System;
+global using System.Reactive.Linq;
+global using Microsoft.Extensions.Logging;
+global using NetDaemon.AppModel;
+global using NetDaemon.HassModel;
diff --git a/devices/homie/modules/home-assistant/netdaemon/apps/HassModel/HelloWorld/HelloWorld.cs b/devices/homie/modules/home-assistant/netdaemon/apps/HassModel/HelloWorld/HelloWorld.cs
new file mode 100644
index 00000000..2b57d13c
--- /dev/null
+++ b/devices/homie/modules/home-assistant/netdaemon/apps/HassModel/HelloWorld/HelloWorld.cs
@@ -0,0 +1,16 @@
+// Use unique namespaces for your apps if you going to share with others to avoid
+// conflicting names
+
+namespace HassModel;
+
+/// <summary>
+///     Hello world showcase using the new HassModel API
+/// </summary>
+[NetDaemonApp]
+public class HelloWorldApp
+{
+    public HelloWorldApp(IHaContext ha)
+    {
+        ha.CallService("notify", "persistent_notification", data: new {message = "Notify me", title = "Hello world!"});
+    }
+}
\ No newline at end of file
diff --git a/devices/homie/modules/home-assistant/netdaemon/appsettings.json b/devices/homie/modules/home-assistant/netdaemon/appsettings.json
new file mode 100644
index 00000000..4d475992
--- /dev/null
+++ b/devices/homie/modules/home-assistant/netdaemon/appsettings.json
@@ -0,0 +1,17 @@
+{
+    "Logging": {
+        "LogLevel": {
+            "Default": "Debug",
+            "Microsoft": "Warning"
+        },
+        "ConsoleThemeType": "Ansi"
+    },
+    "NetDaemon": {
+        "ApplicationConfigurationFolder": "./apps"
+    },
+    "CodeGeneration": {
+        "Namespace": "HomeAssistantGenerated",
+        "OutputFile": "HomeAssistantGenerated.cs",
+        "UseAttributeBaseClasses" : "false"
+    }
+}
diff --git a/devices/homie/modules/home-assistant/netdaemon/default.nix b/devices/homie/modules/home-assistant/netdaemon/default.nix
new file mode 100644
index 00000000..a7fb97ed
--- /dev/null
+++ b/devices/homie/modules/home-assistant/netdaemon/default.nix
@@ -0,0 +1,68 @@
+{
+  config,
+  self,
+  pkgs,
+  ...
+}: let
+  inherit (config.sops) secrets;
+
+  compiled = pkgs.callPackage ./package.nix {};
+in {
+  khepri.compositions."netdaemon" = {
+    networks.netdaemon = {external = true;};
+
+    services."netdaemon4" = {
+      image = import ./images/netdaemon.nix pkgs;
+      restart = "always";
+
+      environmentFiles = [secrets.netdaemon.path];
+      environment = {
+        HomeAssistant__Host = "homie.nelim.org";
+        HomeAssistant__Port = "443";
+        HomeAssistant__Ssl = "true";
+        NetDaemon__ApplicationAssembly = "netdaemon.dll";
+        Logging__LogLevel__Default = "Information"; # use Information/Debug/Trace/Warning/Error
+        TZ = "America/New_York";
+      };
+
+      volumes = ["${compiled}/lib/netdaemon-config:/data"];
+      networks = ["netdaemon"];
+    };
+  };
+
+  services.home-assistant = {
+    customComponents = builtins.attrValues {
+      inherit
+        (self.legacyPackages.${pkgs.system}.hass-components)
+        netdaemon
+        ;
+    };
+  };
+
+  environment.systemPackages = [
+    (pkgs.writeShellApplication {
+      name = "updateNuDeps";
+      runtimeInputs = [pkgs.dotnet-sdk_8];
+      text = ''
+        # Update the codegen
+        dotnet tool update -g NetDaemon.HassModel.CodeGen
+
+        # Update all nugets to latest versions
+        regex='PackageReference Include="([^"]*)" Version="([^"]*)"'
+
+        find . -type f -name '*.csproj' | while read -r file; do
+            # Extract unique package names from the .csproj file
+            packages=$(grep -oP "$regex" "$file" | sed -E 's/.*Include="([^"]*)".*/\1/' | sort -u)
+
+            # Loop through each package and update
+            for package in $packages; do
+                echo -e "\033[35mUpdate $file package: $package\033[0m"
+                dotnet add "$file" package "$package"
+            done
+        done
+
+        ${compiled.passthru.fetch-deps} .
+      '';
+    })
+  ];
+}
diff --git a/devices/homie/modules/home-assistant/netdaemon/deps.nix b/devices/homie/modules/home-assistant/netdaemon/deps.nix
new file mode 100644
index 00000000..0aa55661
--- /dev/null
+++ b/devices/homie/modules/home-assistant/netdaemon/deps.nix
@@ -0,0 +1,304 @@
+# This file was automatically generated by passthru.fetch-deps.
+# Please dont edit it manually, your changes might get overwritten!
+{fetchNuGet}: [
+  (fetchNuGet {
+    pname = "Cronos";
+    version = "0.8.4";
+    hash = "sha256-L9rLcqnQybPoJCcg60h49bjXfqEarM9SFHqOJUMvxz8=";
+  })
+  (fetchNuGet {
+    pname = "Microsoft.Extensions.Configuration";
+    version = "8.0.0";
+    hash = "sha256-9BPsASlxrV8ilmMCjdb3TiUcm5vFZxkBnAI/fNBSEyA=";
+  })
+  (fetchNuGet {
+    pname = "Microsoft.Extensions.Configuration.Abstractions";
+    version = "8.0.0";
+    hash = "sha256-4eBpDkf7MJozTZnOwQvwcfgRKQGcNXe0K/kF+h5Rl8o=";
+  })
+  (fetchNuGet {
+    pname = "Microsoft.Extensions.Configuration.Binder";
+    version = "8.0.0";
+    hash = "sha256-GanfInGzzoN2bKeNwON8/Hnamr6l7RTpYLA49CNXD9Q=";
+  })
+  (fetchNuGet {
+    pname = "Microsoft.Extensions.Configuration.Binder";
+    version = "8.0.2";
+    hash = "sha256-aGB0VuoC34YadAEqrwoaXLc5qla55pswDV2xLSmR7SE=";
+  })
+  (fetchNuGet {
+    pname = "Microsoft.Extensions.Configuration.CommandLine";
+    version = "8.0.0";
+    hash = "sha256-fmPC/o8S+weTtQJWykpnGHm6AKVU21xYE/CaHYU7zgg=";
+  })
+  (fetchNuGet {
+    pname = "Microsoft.Extensions.Configuration.EnvironmentVariables";
+    version = "8.0.0";
+    hash = "sha256-+bjFZvqCsMf2FRM2olqx/fub+QwfM1kBhjGVOT5HC48=";
+  })
+  (fetchNuGet {
+    pname = "Microsoft.Extensions.Configuration.FileExtensions";
+    version = "8.0.0";
+    hash = "sha256-BCxcjVP+kvrDDB0nzsFCJfU74UK4VBvct2JA4r+jNcs=";
+  })
+  (fetchNuGet {
+    pname = "Microsoft.Extensions.Configuration.Json";
+    version = "8.0.0";
+    hash = "sha256-Fi/ijcG5l0BOu7i96xHu96aN5/g7zO6SWQbTsI3Qetg=";
+  })
+  (fetchNuGet {
+    pname = "Microsoft.Extensions.Configuration.UserSecrets";
+    version = "8.0.0";
+    hash = "sha256-/yj5QaEzeRStvOFoBpPRPXlEehGtr2E6/rJb+OEPIK8=";
+  })
+  (fetchNuGet {
+    pname = "Microsoft.Extensions.DependencyInjection";
+    version = "8.0.0";
+    hash = "sha256-+qIDR8hRzreCHNEDtUcPfVHQdurzWPo/mqviCH78+EQ=";
+  })
+  (fetchNuGet {
+    pname = "Microsoft.Extensions.DependencyInjection.Abstractions";
+    version = "8.0.0";
+    hash = "sha256-75KzEGWjbRELczJpCiJub+ltNUMMbz5A/1KQU+5dgP8=";
+  })
+  (fetchNuGet {
+    pname = "Microsoft.Extensions.DependencyInjection.Abstractions";
+    version = "8.0.1";
+    hash = "sha256-lzTYLpRDAi3wW9uRrkTNJtMmaYdtGJJHdBLbUKu60PM=";
+  })
+  (fetchNuGet {
+    pname = "Microsoft.Extensions.DependencyModel";
+    version = "8.0.1";
+    hash = "sha256-m8daXRK1Qn9y2c8SmtWu9ysLHwFJtEWiUQoAnMalw7s=";
+  })
+  (fetchNuGet {
+    pname = "Microsoft.Extensions.Diagnostics";
+    version = "8.0.0";
+    hash = "sha256-fBLlb9xAfTgZb1cpBxFs/9eA+BlBvF8Xg0DMkBqdHD4=";
+  })
+  (fetchNuGet {
+    pname = "Microsoft.Extensions.Diagnostics.Abstractions";
+    version = "8.0.0";
+    hash = "sha256-USD5uZOaahMqi6u7owNWx/LR4EDrOwqPrAAim7iRpJY=";
+  })
+  (fetchNuGet {
+    pname = "Microsoft.Extensions.FileProviders.Abstractions";
+    version = "8.0.0";
+    hash = "sha256-uQSXmt47X2HGoVniavjLICbPtD2ReQOYQMgy3l0xuMU=";
+  })
+  (fetchNuGet {
+    pname = "Microsoft.Extensions.FileProviders.Physical";
+    version = "8.0.0";
+    hash = "sha256-29y5ZRQ1ZgzVOxHktYxyiH40kVgm5un2yTGdvuSWnRc=";
+  })
+  (fetchNuGet {
+    pname = "Microsoft.Extensions.FileSystemGlobbing";
+    version = "8.0.0";
+    hash = "sha256-+Oz41JR5jdcJlCJOSpQIL5OMBNi+1Hl2d0JUHfES7sU=";
+  })
+  (fetchNuGet {
+    pname = "Microsoft.Extensions.Hosting";
+    version = "8.0.0";
+    hash = "sha256-sKHa+w4/pMeQb5RRFqLtMTUJy5H6hSIGWchbH2pxSrg=";
+  })
+  (fetchNuGet {
+    pname = "Microsoft.Extensions.Hosting.Abstractions";
+    version = "8.0.0";
+    hash = "sha256-0JBx+wwt5p1SPfO4m49KxNOXPAzAU0A+8tEc/itvpQE=";
+  })
+  (fetchNuGet {
+    pname = "Microsoft.Extensions.Http";
+    version = "8.0.0";
+    hash = "sha256-UgljypOLld1lL7k7h1noazNzvyEHIJw+r+6uGzucFSY=";
+  })
+  (fetchNuGet {
+    pname = "Microsoft.Extensions.Logging";
+    version = "8.0.0";
+    hash = "sha256-Meh0Z0X7KyOEG4l0RWBcuHHihcABcvCyfUXgasmQ91o=";
+  })
+  (fetchNuGet {
+    pname = "Microsoft.Extensions.Logging.Abstractions";
+    version = "8.0.0";
+    hash = "sha256-Jmddjeg8U5S+iBTwRlVAVLeIHxc4yrrNgqVMOB7EjM4=";
+  })
+  (fetchNuGet {
+    pname = "Microsoft.Extensions.Logging.Abstractions";
+    version = "8.0.1";
+    hash = "sha256-TYce3qvMr92JbAZ62ATBsocaH0joJzw0px0tYGZ9N0U=";
+  })
+  (fetchNuGet {
+    pname = "Microsoft.Extensions.Logging.Configuration";
+    version = "8.0.0";
+    hash = "sha256-mzmstNsVjKT0EtQcdAukGRifD30T82BMGYlSu8k4K7U=";
+  })
+  (fetchNuGet {
+    pname = "Microsoft.Extensions.Logging.Console";
+    version = "8.0.0";
+    hash = "sha256-bdb9YWWVn//AeySp7se87/tCN2E7e8Gx2GPMw28cd9c=";
+  })
+  (fetchNuGet {
+    pname = "Microsoft.Extensions.Logging.Debug";
+    version = "8.0.0";
+    hash = "sha256-AJunzYBZM2wCg86hnPnMrBuWIIyW/4PnIVoDSU969cA=";
+  })
+  (fetchNuGet {
+    pname = "Microsoft.Extensions.Logging.EventLog";
+    version = "8.0.0";
+    hash = "sha256-vXBm4yhWGP4uow0CqstuqOkxO8yeZEM15JTTenjPbhc=";
+  })
+  (fetchNuGet {
+    pname = "Microsoft.Extensions.Logging.EventSource";
+    version = "8.0.0";
+    hash = "sha256-kaR7YOlq5s8W9nZDtH/lKtnfGbrgOuQY4DUPcA2lcj0=";
+  })
+  (fetchNuGet {
+    pname = "Microsoft.Extensions.Options";
+    version = "8.0.0";
+    hash = "sha256-n2m4JSegQKUTlOsKLZUUHHKMq926eJ0w9N9G+I3FoFw=";
+  })
+  (fetchNuGet {
+    pname = "Microsoft.Extensions.Options.ConfigurationExtensions";
+    version = "8.0.0";
+    hash = "sha256-A5Bbzw1kiNkgirk5x8kyxwg9lLTcSngojeD+ocpG1RI=";
+  })
+  (fetchNuGet {
+    pname = "Microsoft.Extensions.Primitives";
+    version = "8.0.0";
+    hash = "sha256-FU8qj3DR8bDdc1c+WeGZx/PCZeqqndweZM9epcpXjSo=";
+  })
+  (fetchNuGet {
+    pname = "NetDaemon.AppModel";
+    version = "24.37.1";
+    hash = "sha256-KQKTm0+4itReyulWfYMLKX1uXBv8tMNMxyI+TdOnK/s=";
+  })
+  (fetchNuGet {
+    pname = "NetDaemon.Client";
+    version = "24.37.1";
+    hash = "sha256-xxOsjKFtD0cSMOr7if+bRQq6y5yR7//FruIVMXSiEww=";
+  })
+  (fetchNuGet {
+    pname = "NetDaemon.Extensions.Logging";
+    version = "24.37.1";
+    hash = "sha256-JLDREBFhOOtveJu3JtwJR3ZIkQmrwMRrHt7mwmXy7dw=";
+  })
+  (fetchNuGet {
+    pname = "NetDaemon.Extensions.Scheduling";
+    version = "24.37.1";
+    hash = "sha256-f+IvbPAMfK4yA7bi56SI/+1hol/6oBbz6AMkJ2OCAOc=";
+  })
+  (fetchNuGet {
+    pname = "NetDaemon.Extensions.Tts";
+    version = "24.37.1";
+    hash = "sha256-R4bFaR2mUct39njcbK2m7xeuDIZeRqHdvsjp3hFBdfQ=";
+  })
+  (fetchNuGet {
+    pname = "NetDaemon.HassModel";
+    version = "24.37.1";
+    hash = "sha256-eIOk6/LImCTjTC4cwWBpATqxiQUQxbsRXAcR6Mz7LKs=";
+  })
+  (fetchNuGet {
+    pname = "NetDaemon.HassModel.CodeGen";
+    version = "24.37.0";
+    hash = "sha256-+YSo9/FkkDLfymWrzf4OjMwE31qjAbbFjmF7L5Aj2Bg=";
+  })
+  (fetchNuGet {
+    pname = "NetDaemon.HassModel.Integration";
+    version = "24.37.1";
+    hash = "sha256-6e7oQFRs15dT0+cQxgyQWwWgmHNdFzlCnyJzmfPe5b8=";
+  })
+  (fetchNuGet {
+    pname = "NetDaemon.Runtime";
+    version = "24.37.1";
+    hash = "sha256-GwMx6f+lIoM1OznORs0Wkoc6HLalILFK1OS6Vcz1BuI=";
+  })
+  (fetchNuGet {
+    pname = "Serilog";
+    version = "3.1.1";
+    hash = "sha256-L263y8jkn7dNFD2jAUK6mgvyRTqFe39i1tRhVZsNZTI=";
+  })
+  (fetchNuGet {
+    pname = "Serilog";
+    version = "4.0.0";
+    hash = "sha256-j8hQ5TdL1TjfdGiBO9PyHJFMMPvATHWN1dtrrUZZlNw=";
+  })
+  (fetchNuGet {
+    pname = "Serilog.AspNetCore";
+    version = "8.0.2";
+    hash = "sha256-cRZHG2bqrESOxPVxq2v+mHx+oZBzZEPksrleGVXO1p0=";
+  })
+  (fetchNuGet {
+    pname = "Serilog.Extensions.Hosting";
+    version = "8.0.0";
+    hash = "sha256-OEVkEQoONawJF+SXeyqqgU0OGp9ubtt9aXT+rC25j4E=";
+  })
+  (fetchNuGet {
+    pname = "Serilog.Extensions.Logging";
+    version = "8.0.0";
+    hash = "sha256-GoWxCpkdahMvYd7ZrhwBxxTyjHGcs9ENNHJCp0la6iA=";
+  })
+  (fetchNuGet {
+    pname = "Serilog.Formatting.Compact";
+    version = "2.0.0";
+    hash = "sha256-c3STGleyMijY4QnxPuAz/NkJs1r+TZAPjlmAKLF4+3g=";
+  })
+  (fetchNuGet {
+    pname = "Serilog.Settings.Configuration";
+    version = "8.0.2";
+    hash = "sha256-iHRQt6vDk85/6HpMXiJluAwhkjgwEnL3IKavfDgFX0k=";
+  })
+  (fetchNuGet {
+    pname = "Serilog.Sinks.Console";
+    version = "6.0.0";
+    hash = "sha256-QH8ykDkLssJ99Fgl+ZBFBr+RQRl0wRTkeccQuuGLyro=";
+  })
+  (fetchNuGet {
+    pname = "Serilog.Sinks.Debug";
+    version = "2.0.0";
+    hash = "sha256-/PLVAE33lTdUEXdahkI5ddFiGZufWnvfsOodQsFB8sQ=";
+  })
+  (fetchNuGet {
+    pname = "Serilog.Sinks.File";
+    version = "5.0.0";
+    hash = "sha256-GKy9hwOdlu2W0Rw8LiPyEwus+sDtSOTl8a5l9uqz+SQ=";
+  })
+  (fetchNuGet {
+    pname = "System.Diagnostics.DiagnosticSource";
+    version = "8.0.0";
+    hash = "sha256-+aODaDEQMqla5RYZeq0Lh66j+xkPYxykrVvSCmJQ+Vs=";
+  })
+  (fetchNuGet {
+    pname = "System.Diagnostics.EventLog";
+    version = "8.0.0";
+    hash = "sha256-rt8xc3kddpQY4HEdghlBeOK4gdw5yIj4mcZhAVtk2/Y=";
+  })
+  (fetchNuGet {
+    pname = "System.IO.Pipelines";
+    version = "8.0.0";
+    hash = "sha256-LdpB1s4vQzsOODaxiKstLks57X9DTD5D6cPx8DE1wwE=";
+  })
+  (fetchNuGet {
+    pname = "System.Reactive";
+    version = "6.0.1";
+    hash = "sha256-Lo5UMqp8DsbVSUxa2UpClR1GoYzqQQcSxkfyFqB/d4Q=";
+  })
+  (fetchNuGet {
+    pname = "System.Text.Encodings.Web";
+    version = "8.0.0";
+    hash = "sha256-IUQkQkV9po1LC0QsqrilqwNzPvnc+4eVvq+hCvq8fvE=";
+  })
+  (fetchNuGet {
+    pname = "System.Text.Json";
+    version = "8.0.0";
+    hash = "sha256-XFcCHMW1u2/WujlWNHaIWkbW1wn8W4kI0QdrwPtWmow=";
+  })
+  (fetchNuGet {
+    pname = "System.Text.Json";
+    version = "8.0.4";
+    hash = "sha256-g5oT7fbXxQ9Iah1nMCr4UUX/a2l+EVjJyTrw3FTbIaI=";
+  })
+  (fetchNuGet {
+    pname = "YamlDotNet";
+    version = "16.1.2";
+    hash = "sha256-J8fZ6rRFiNsAYDxHFskAjC2fP+K2XrewDs50jAKEWTY=";
+  })
+]
diff --git a/devices/homie/modules/home-assistant/netdaemon/images/netdaemon.nix b/devices/homie/modules/home-assistant/netdaemon/images/netdaemon.nix
new file mode 100644
index 00000000..0d641159
--- /dev/null
+++ b/devices/homie/modules/home-assistant/netdaemon/images/netdaemon.nix
@@ -0,0 +1,8 @@
+pkgs:
+pkgs.dockerTools.pullImage rec {
+  imageName = "netdaemon/netdaemon4";
+  imageDigest = "sha256:2ccb8dce2a7a5bba14bd90030640f09a91adccb472e16168ad06ae1f752430ae";
+  sha256 = "1qj2yrbhcr162ikfv3jbh4qvb17p7vzxva5z3r5vhhimayr24dn4";
+  finalImageName = imageName;
+  finalImageTag = "24.37.1";
+}
diff --git a/devices/homie/modules/home-assistant/netdaemon/netdaemon.csproj b/devices/homie/modules/home-assistant/netdaemon/netdaemon.csproj
new file mode 100644
index 00000000..a98da190
--- /dev/null
+++ b/devices/homie/modules/home-assistant/netdaemon/netdaemon.csproj
@@ -0,0 +1,37 @@
+<Project Sdk="Microsoft.NET.Sdk">
+
+    <PropertyGroup>
+        <OutputType>Exe</OutputType>
+        <TargetFramework>net8.0</TargetFramework>
+        <LangVersion>12.0</LangVersion>
+        <Nullable>enable</Nullable>
+        <RootNamespace>netdaemon</RootNamespace>
+    </PropertyGroup>
+
+    <ItemGroup>
+        <None Update="$(MSBuildProjectDir)appsettings.Development.json">
+            <CopyToOutputDirectory>Always</CopyToOutputDirectory>
+            <CopyToPublishDirectory>Never</CopyToPublishDirectory>
+        </None>
+        <None Update="$(MSBuildProjectDir)appsettings.json">
+            <CopyToOutputDirectory>Always</CopyToOutputDirectory>
+        </None>
+        <None Update="$(MSBuildProjectDir)**\*.yaml">
+            <CopyToOutputDirectory>Always</CopyToOutputDirectory>
+            <CopyToPublishDirectory>PreserveNewest</CopyToPublishDirectory>
+        </None>
+    </ItemGroup>
+    <Target Name="AfterPublishMessage" AfterTargets="Publish">
+        <Message Text="Publish done! Copy all content in directory: $(PublishDir) to the `/config/netdaemon4' folder for add-on or your custom folder to deploy." Importance="high" />
+    </Target>
+
+    <ItemGroup>
+        <PackageReference Include="NetDaemon.AppModel" Version="24.37.1" />
+        <PackageReference Include="NetDaemon.Runtime" Version="24.37.1" />
+        <PackageReference Include="NetDaemon.HassModel" Version="24.37.1" />
+        <PackageReference Include="NetDaemon.Client" Version="24.37.1" />
+        <PackageReference Include="NetDaemon.Extensions.Scheduling" Version="24.37.1" />
+        <PackageReference Include="NetDaemon.Extensions.Logging" Version="24.37.1" />
+        <PackageReference Include="NetDaemon.Extensions.Tts" Version="24.37.1" />
+    </ItemGroup>
+</Project>
diff --git a/devices/homie/modules/home-assistant/netdaemon/package.nix b/devices/homie/modules/home-assistant/netdaemon/package.nix
new file mode 100644
index 00000000..9adfd66b
--- /dev/null
+++ b/devices/homie/modules/home-assistant/netdaemon/package.nix
@@ -0,0 +1,22 @@
+{
+  buildDotnetModule,
+  dotnetCorePackages,
+}:
+buildDotnetModule {
+  pname = "netdaemon-config";
+  version = "0.0.0";
+
+  src =
+    builtins.filterSource
+    (file: type:
+      (type != "directory")
+      || (baseNameOf file != "default.nix" && baseNameOf file != "package.nix"))
+    ./.;
+
+  projectFile = "netdaemon.csproj";
+  nugetDeps = ./deps.nix;
+
+  dotnet-sdk = dotnetCorePackages.sdk_8_0;
+  dotnet-runtime = dotnetCorePackages.runtime_8_0;
+  executables = [];
+}
diff --git a/devices/homie/modules/home-assistant/netdaemon/program.cs b/devices/homie/modules/home-assistant/netdaemon/program.cs
new file mode 100644
index 00000000..17a1e227
--- /dev/null
+++ b/devices/homie/modules/home-assistant/netdaemon/program.cs
@@ -0,0 +1,35 @@
+using System.Reflection;
+using Microsoft.Extensions.Hosting;
+using NetDaemon.Extensions.Logging;
+using NetDaemon.Extensions.Scheduler;
+using NetDaemon.Extensions.Tts;
+using NetDaemon.Runtime;
+// Add next line if using code generator
+//using HomeAssistantGenerated;
+
+#pragma warning disable CA1812
+
+try
+{
+    await Host.CreateDefaultBuilder(args)
+        .UseNetDaemonAppSettings()
+        .UseNetDaemonDefaultLogging()
+        .UseNetDaemonRuntime()
+        .UseNetDaemonTextToSpeech()
+        .ConfigureServices((_, services) =>
+            services
+                .AddAppsFromAssembly(Assembly.GetExecutingAssembly())
+                .AddNetDaemonStateManager()
+                .AddNetDaemonScheduler()
+                // Add next line if using code generator
+                // .AddHomeAssistantGenerated()
+        )
+        .Build()
+        .RunAsync()
+        .ConfigureAwait(false);
+}
+catch (Exception e)
+{
+    Console.WriteLine($"Failed to start host... {e}");
+    throw;
+}
diff --git a/flake.lock b/flake.lock
index 7b6029c8..1310b5c8 100644
--- a/flake.lock
+++ b/flake.lock
@@ -993,6 +993,22 @@
         "type": "github"
       }
     },
+    "netdaemon-src": {
+      "flake": false,
+      "locked": {
+        "lastModified": 1712514313,
+        "narHash": "sha256-wu6tdrk7GvAI3jjA02Ka59qjZm+X7h0xDeqc3qHUe84=",
+        "owner": "net-daemon",
+        "repo": "integration",
+        "rev": "d3b7606530ddcaf189ed6f75569e923b22896679",
+        "type": "github"
+      },
+      "original": {
+        "owner": "net-daemon",
+        "repo": "integration",
+        "type": "github"
+      }
+    },
     "nh": {
       "inputs": {
         "nixpkgs": [
@@ -1561,6 +1577,7 @@
         "mpv-persist-properties-src": "mpv-persist-properties-src",
         "mpv-pointer-event-src": "mpv-pointer-event-src",
         "mpv-touch-gestures-src": "mpv-touch-gestures-src",
+        "netdaemon-src": "netdaemon-src",
         "nh": "nh",
         "nix-fast-build": "nix-fast-build",
         "nix-gaming": "nix-gaming",
@@ -1619,11 +1636,11 @@
         ]
       },
       "locked": {
-        "lastModified": 1726701157,
-        "narHash": "sha256-2b4UqC8zswsskPdOumII0ZyLgy5nKdya2Due82/yXJ8=",
+        "lastModified": 1728144135,
+        "narHash": "sha256-myzkfIOzgBW6LP4XHl5NdOrlVnV+qZ05Kr/+WNlugeM=",
         "ref": "refs/heads/main",
-        "rev": "0751670349b9908d33fa21c3d3f15675f8565e44",
-        "revCount": 78,
+        "rev": "5a156258eb132caaf4325aec6b21504d79d45c12",
+        "revCount": 79,
         "type": "git",
         "url": "ssh://git@git.nelim.org/matt1432/nixos-secrets"
       },
diff --git a/flake.nix b/flake.nix
index 160c1cf9..4894f91d 100644
--- a/flake.nix
+++ b/flake.nix
@@ -241,6 +241,12 @@
       repo = "mpv-touch-gestures";
       type = "github";
     };
+    netdaemon-src = {
+      flake = false;
+      owner = "net-daemon";
+      repo = "integration";
+      type = "github";
+    };
     nh = {
       inputs.nixpkgs.follows = "nixpkgs";
       owner = "viperML";
diff --git a/inputs.nix b/inputs.nix
index 1203779e..979b71eb 100644
--- a/inputs.nix
+++ b/inputs.nix
@@ -196,6 +196,11 @@ let
       owner = "make-all";
       repo = "tuya-local";
     }
+    {
+      name = "netdaemon-src";
+      owner = "net-daemon";
+      repo = "integration";
+    }
     {
       name = "spotifyplus-src";
       owner = "thlucas1";
diff --git a/legacyPackages/hass-components/default.nix b/legacyPackages/hass-components/default.nix
index 02db5d18..1308e10e 100644
--- a/legacyPackages/hass-components/default.nix
+++ b/legacyPackages/hass-components/default.nix
@@ -4,6 +4,7 @@ pkgs.lib.makeScope pkgs.newScope (hass: let
     hass.callPackage file (inputs // extraArgs // {});
 in {
   extended-ollama-conversation = buildHassComponent ./extended-ollama-conversation {};
+  netdaemon = buildHassComponent ./netdaemon {};
   spotifyplus = import ./spotifyplus ({inherit buildHassComponent;} // inputs);
   tuya-local = buildHassComponent ./tuya-local {};
 })
diff --git a/legacyPackages/hass-components/netdaemon/default.nix b/legacyPackages/hass-components/netdaemon/default.nix
new file mode 100644
index 00000000..91e30fac
--- /dev/null
+++ b/legacyPackages/hass-components/netdaemon/default.nix
@@ -0,0 +1,21 @@
+{
+  netdaemon-src,
+  buildHomeAssistantComponent,
+  python3Packages,
+  ...
+}: let
+  inherit (builtins) fromJSON readFile;
+
+  manifest = fromJSON (readFile "${netdaemon-src}/custom_components/netdaemon/manifest.json");
+in
+  buildHomeAssistantComponent {
+    owner = "net-daemon";
+
+    inherit (manifest) domain version;
+
+    src = netdaemon-src;
+
+    propagatedBuildInputs = with python3Packages; [
+      awesomeversion
+    ];
+  }
diff --git a/outputs.nix b/outputs.nix
index ebcd990f..0ad157ed 100644
--- a/outputs.nix
+++ b/outputs.nix
@@ -157,6 +157,12 @@
         ];
       };
 
+      netdaemon = pkgs.mkShell {
+        packages = [
+          pkgs.dotnet-sdk_8
+        ];
+      };
+
       node = pkgs.mkShell {
         packages =
           (builtins.attrValues {