{ config, lib, pkgs, self, ... }: let cfg = config.eink.dashboard; dashboardSrc = self + "/dashboard"; dashboardBuild = pkgs.buildNpmPackage { pname = "eink-dashboard"; version = "0.1.0"; src = dashboardSrc; # Re-generate this hash with: # nix run nixpkgs#prefetch-npm-deps -- dashboard/package-lock.json npmDepsHash = "sha256-UticV62t7/CYZ1nVZPNxUZn38WhQ4mHmYT3V90D01OU="; buildPhase = '' runHook preBuild npm run build runHook postBuild ''; installPhase = '' runHook preInstall mkdir -p $out cp -r build package.json $out/ cp -r node_modules $out/ runHook postInstall ''; }; in { options.eink.dashboard = { enable = lib.mkEnableOption "SvelteKit e-paper dashboard"; port = lib.mkOption { type = lib.types.port; default = 3000; }; caldavUrl = lib.mkOption { type = lib.types.str; default = "https://mail.rubenhensen.nl/dav/cal/"; description = "Base URL of the CalDAV server. Stalwart serves CalDAV at /dav/cal/, distinct from CardDAV at /dav/card/."; }; caldavUser = lib.mkOption { type = lib.types.str; default = "ruben@rubenhensen.nl"; }; }; config = lib.mkIf cfg.enable { systemd.services.eink-dashboard = { description = "E-paper dashboard (SvelteKit)"; after = [ "network-online.target" ]; wants = [ "network-online.target" ]; wantedBy = [ "multi-user.target" ]; environment = { HOST = "127.0.0.1"; PORT = toString cfg.port; CALDAV_URL = cfg.caldavUrl; CALDAV_USER = cfg.caldavUser; NODE_ENV = "production"; }; serviceConfig = { # CalDAV password loaded as a systemd credential. Provision the # encrypted file under /var/lib/eink/secrets/caldav-password # (or use sops-nix). See README. LoadCredential = [ "caldav-password:/var/lib/eink/secrets/caldav-password" ]; DynamicUser = true; StateDirectory = "eink-dashboard"; ExecStart = "${pkgs.nodejs}/bin/node ${dashboardBuild}/build/index.js"; Restart = "always"; RestartSec = "5s"; }; }; }; }