diff --git a/configurations/nos/modules/homepage.nix b/configurations/nos/modules/homepage.nix index e3c48d6b..0abde8b8 100644 --- a/configurations/nos/modules/homepage.nix +++ b/configurations/nos/modules/homepage.nix @@ -1,6 +1,14 @@ -{config, ...}: { +{ + config, + pkgs, + self, + ... +}: { services.homepage-dashboard = { enable = true; + + package = self.packages.${pkgs.system}.homepage; + listenPort = 3020; environmentFile = config.sops.secrets.homepage.path; diff --git a/packages/default.nix b/packages/default.nix index 20af2f3b..217b2e17 100644 --- a/packages/default.nix +++ b/packages/default.nix @@ -11,6 +11,8 @@ inherit (inputs) gpu-screen-recorder-src; }; + homepage = pkgs.callPackage ./homepage {}; + libratbag = pkgs.callPackage ./libratbag { inherit (inputs) libratbag-src; }; diff --git a/packages/homepage/default.nix b/packages/homepage/default.nix new file mode 100644 index 00000000..21d83801 --- /dev/null +++ b/packages/homepage/default.nix @@ -0,0 +1,95 @@ +{ + buildNpmPackage, + fetchFromGitHub, + nodePackages, + python3, + stdenv, + cctools, + IOKit ? {}, + lib, + enableLocalIcons ? true, + git, +}: let + inherit (lib) optionals optionalString; + + installLocalIcons = import ./icons.nix {inherit fetchFromGitHub;}; + + pname = "homepage-dashboard"; + version = "0.10.1"; +in + buildNpmPackage { + inherit pname version; + + src = fetchFromGitHub { + owner = "gethomepage"; + repo = "homepage"; + rev = "v${version}"; + hash = "sha256-7nduDXrpfigu63rka56fx6KxfrlH2+80iTZDZolZfY8="; + }; + + npmDepsHash = "sha256-AW7lNkvQeeHkAf6Q23912LiSHJMelR9+4KVSKdlFqd0="; + + preBuild = '' + mkdir -p config + ''; + + postBuild = '' + # Add a shebang to the server js file, then patch the shebang. + sed -i '1s|^|#!/usr/bin/env node\n|' .next/standalone/server.js + patchShebangs .next/standalone/server.js + ''; + + nativeBuildInputs = [git] ++ optionals stdenv.hostPlatform.isDarwin [cctools]; + + buildInputs = + [ + nodePackages.node-gyp-build + ] + ++ optionals stdenv.hostPlatform.isDarwin [IOKit]; + + env.PYTHON = "${python3}/bin/python"; + + installPhase = '' + runHook preInstall + + mkdir -p $out/{share,bin} + + cp -r .next/standalone $out/share/homepage/ + cp -r public $out/share/homepage/public + + mkdir -p $out/share/homepage/.next + cp -r .next/static $out/share/homepage/.next/static + + chmod +x $out/share/homepage/server.js + + # This patch must be applied here, as it's patching the `dist` directory + # of NextJS. Without this, homepage-dashboard errors when trying to + # write its prerender cache. + # + # This patch ensures that the cache implementation respects the env + # variable `HOMEPAGE_CACHE_DIR`, which is set by default in the + # wrapper below. + pushd $out + git apply ${./prerender_cache_path.patch} + popd + + makeWrapper $out/share/homepage/server.js $out/bin/homepage \ + --set-default PORT 3000 \ + --set-default HOMEPAGE_CONFIG_DIR /var/lib/homepage-dashboard \ + --set-default HOMEPAGE_CACHE_DIR /var/cache/homepage-dashboard + + ${optionalString enableLocalIcons installLocalIcons} + + runHook postInstall + ''; + + doDist = false; + + meta = { + description = "Highly customisable dashboard with Docker and service API integrations"; + changelog = "https://github.com/gethomepage/homepage/releases/tag/v${version}"; + mainProgram = "homepage"; + homepage = "https://gethomepage.dev"; + license = lib.licenses.gpl3; + }; + } diff --git a/packages/homepage/icons.nix b/packages/homepage/icons.nix new file mode 100644 index 00000000..ee9961e8 --- /dev/null +++ b/packages/homepage/icons.nix @@ -0,0 +1,13 @@ +{fetchFromGitHub, ...}: let + dashboardIcons = fetchFromGitHub { + owner = "walkxcode"; + repo = "dashboard-icons"; + rev = "be82e22c418f5980ee2a13064d50f1483df39c8c"; # Until 2024-07-21 + hash = "sha256-z69DKzKhCVNnNHjRM3dX/DD+WJOL9wm1Im1nImhBc9Y="; + }; +in '' + mkdir -p $out/share/homepage/public/icons + cp ${dashboardIcons}/png/* $out/share/homepage/public/icons + cp ${dashboardIcons}/svg/* $out/share/homepage/public/icons + cp ${dashboardIcons}/LICENSE $out/share/homepage/public/icons/ +'' diff --git a/packages/homepage/prerender_cache_path.patch b/packages/homepage/prerender_cache_path.patch new file mode 100644 index 00000000..05746b56 --- /dev/null +++ b/packages/homepage/prerender_cache_path.patch @@ -0,0 +1,18 @@ +diff --git a/share/homepage/node_modules/next/dist/server/lib/incremental-cache/file-system-cache.js b/share/homepage/node_modules/next/dist/server/lib/incremental-cache/file-system-cache.js +index b1b74d8..a46c80b 100644 +--- a/share/homepage/node_modules/next/dist/server/lib/incremental-cache/file-system-cache.js ++++ b/share/homepage/node_modules/next/dist/server/lib/incremental-cache/file-system-cache.js +@@ -5,11 +5,12 @@ Object.defineProperty(exports, "__esModule", { + exports.default = void 0; + var _lruCache = _interopRequireDefault(require("next/dist/compiled/lru-cache")); + var _path = _interopRequireDefault(require("../../../shared/lib/isomorphic/path")); ++var path = require('node:path'); + class FileSystemCache { + constructor(ctx){ + this.fs = ctx.fs; + this.flushToDisk = ctx.flushToDisk; +- this.serverDistDir = ctx.serverDistDir; ++ this.serverDistDir = path.join(process.env.HOMEPAGE_CACHE_DIR, "homepage"); + this.appDir = !!ctx._appDir; + if (ctx.maxMemoryCacheSize) { + this.memoryCache = new _lruCache.default({