hoarder: rename to karakeep, nixos/karakeep: init module (#399603)

This commit is contained in:
Marcus Ramberg
2025-04-22 08:19:44 +02:00
committed by GitHub
12 changed files with 264 additions and 37 deletions
+1
View File
@@ -1565,6 +1565,7 @@
./services/web-apps/isso.nix
./services/web-apps/jirafeau.nix
./services/web-apps/jitsi-meet.nix
./services/web-apps/karakeep.nix
./services/web-apps/kasmweb/default.nix
./services/web-apps/kanboard.nix
./services/web-apps/kavita.nix
@@ -0,0 +1,225 @@
{
config,
lib,
pkgs,
...
}:
let
cfg = config.services.karakeep;
karakeepEnv = lib.mkMerge [
{ DATA_DIR = "/var/lib/karakeep"; }
(lib.mkIf cfg.meilisearch.enable {
MEILI_ADDR = "http://127.0.0.1:${toString config.services.meilisearch.listenPort}";
})
(lib.mkIf cfg.browser.enable {
BROWSER_WEB_URL = "http://127.0.0.1:${toString cfg.browser.port}";
})
cfg.extraEnvironment
];
environmentFiles = [
"/var/lib/karakeep/settings.env"
] ++ (lib.optional (cfg.environmentFile != null) cfg.environmentFile);
in
{
options = {
services.karakeep = {
enable = lib.mkEnableOption "Enable the Karakeep service";
package = lib.mkPackageOption pkgs "karakeep" { };
extraEnvironment = lib.mkOption {
description = ''
Environment variables to pass to Karakaeep. This is how most settings
can be configured. Changing DATA_DIR is possible but not supported.
See https://docs.karakeep.app/configuration/
'';
type = lib.types.attrsOf lib.types.str;
default = { };
example = lib.literalExpression ''
{
PORT = "1234";
DISABLE_SIGNUPS = "true";
DISABLE_NEW_RELEASE_CHECK = "true";
}
'';
};
environmentFile = lib.mkOption {
type = lib.types.nullOr lib.types.path;
default = null;
description = ''
An optional path to an environment file that will be used in the web and workers
services. This is useful for loading private keys.
'';
example = "/var/lib/karakeep/secrets.env";
};
browser = {
enable = lib.mkOption {
description = ''
Enable the karakeep-browser service that runs a chromium instance in
the background with debugging ports exposed. This is necessary for
certain features like screenshots.
'';
type = lib.types.bool;
default = true;
};
port = lib.mkOption {
description = "The port the browser should run on.";
type = lib.types.port;
default = 9222;
};
exe = lib.mkOption {
description = "The browser executable (must be Chrome-like).";
type = lib.types.str;
default = "${pkgs.chromium}/bin/chromium";
defaultText = lib.literalExpression "\${pkgs.chromium}/bin/chromium";
example = lib.literalExpression "\${pkgs.google-chrome}/bin/google-chrome-stable";
};
};
meilisearch = {
enable = lib.mkOption {
type = lib.types.bool;
default = true;
description = ''
Enable Meilisearch and configure Karakeep to use it. Meilisearch is
required for text search.
'';
};
};
};
};
config = lib.mkIf cfg.enable {
environment.systemPackages = [ cfg.package ];
users.groups.karakeep = { };
users.users.karakeep = {
isSystemUser = true;
group = "karakeep";
};
services.meilisearch = lib.mkIf cfg.meilisearch.enable {
enable = true;
};
systemd.services.karakeep-init = {
description = "Initialize Karakeep Data";
wantedBy = [ "multi-user.target" ];
after = [ "network.target" ];
partOf = [ "karakeep.service" ];
path = [ pkgs.openssl ];
script = ''
umask 0077
if [ ! -f "$STATE_DIRECTORY/settings.env" ]; then
cat <<EOF >"$STATE_DIRECTORY/settings.env"
# Generated by NixOS Karakeep module
MEILI_MASTER_KEY=$(openssl rand -base64 36)
NEXTAUTH_SECRET=$(openssl rand -base64 36)
EOF
fi
export DATA_DIR="$STATE_DIRECTORY"
exec "${cfg.package}/lib/karakeep/migrate"
'';
serviceConfig = {
Type = "oneshot";
RemainAfterExit = true;
User = "karakeep";
Group = "karakeep";
StateDirectory = "karakeep";
PrivateTmp = "yes";
};
};
systemd.services.karakeep-workers = {
description = "Karakeep Workers";
wantedBy = [ "multi-user.target" ];
after = [
"network.target"
"karakeep-init.service"
];
partOf = [ "karakeep.service" ];
path = [
pkgs.monolith
pkgs.yt-dlp
];
environment = karakeepEnv;
serviceConfig = {
User = "karakeep";
Group = "karakeep";
ExecStart = "${cfg.package}/lib/karakeep/start-workers";
StateDirectory = "karakeep";
EnvironmentFile = environmentFiles;
PrivateTmp = "yes";
};
};
systemd.services.karakeep-web = {
description = "Karakeep Web";
wantedBy = [ "multi-user.target" ];
after = [
"network.target"
"karakeep-init.service"
"karakeep-workers.service"
];
partOf = [ "karakeep.service" ];
environment = karakeepEnv;
serviceConfig = {
ExecStart = "${cfg.package}/lib/karakeep/start-web";
User = "karakeep";
Group = "karakeep";
StateDirectory = "karakeep";
EnvironmentFile = environmentFiles;
PrivateTmp = "yes";
};
};
systemd.services.karakeep-browser = lib.mkIf cfg.browser.enable {
wantedBy = [ "multi-user.target" ];
after = [ "network.target" ];
partOf = [ "karakeep.service" ];
script = ''
export HOME="$CACHE_DIRECTORY"
exec ${cfg.browser.exe} \
--headless --no-sandbox --disable-gpu --disable-dev-shm-usage \
--remote-debugging-address=127.0.0.1 \
--remote-debugging-port=${toString cfg.browser.port} \
--hide-scrollbars \
--user-data-dir="$STATE_DIRECTORY"
'';
serviceConfig = {
Type = "simple";
Restart = "on-failure";
CacheDirectory = "karakeep-browser";
StateDirectory = "karakeep-browser";
DevicePolicy = "closed";
DynamicUser = true;
LockPersonality = true;
NoNewPrivileges = true;
PrivateDevices = true;
PrivateTmp = true;
PrivateUsers = true;
ProtectClock = true;
ProtectControlGroups = true;
ProtectHostname = true;
ProtectKernelLogs = true;
ProtectKernelModules = true;
ProtectKernelTunables = true;
ProtectSystem = "strict";
RestrictNamespaces = true;
RestrictRealtime = true;
};
};
};
meta = {
maintainers = [ lib.maintainers.three ];
};
}
@@ -1,5 +0,0 @@
#!/usr/bin/env bash
set -eu -o pipefail
HOARDER_LIB_PATH=
NODEJS=
exec "$NODEJS/bin/node" "$HOARDER_LIB_PATH/apps/cli/dist/index.mjs" "$@"
+5
View File
@@ -0,0 +1,5 @@
#!/usr/bin/env bash
set -eu -o pipefail
KARAKEEP_LIB_PATH=
NODEJS=
exec "$NODEJS/bin/node" "$KARAKEEP_LIB_PATH/apps/cli/dist/index.mjs" "$@"
@@ -1,10 +1,10 @@
#!/usr/bin/env bash
set -eu -o pipefail
HOARDER_LIB_PATH=
KARAKEEP_LIB_PATH=
RELEASE=
NODE_ENV=production
[[ -d "$DATA_DIR" ]] # Ensure DATA_DIR is defined and exists
export RELEASE NODE_ENV
exec "$HOARDER_LIB_PATH/node_modules/.bin/tsx" "$HOARDER_LIB_PATH/packages/db/migrate.ts" "$@"
exec "$KARAKEEP_LIB_PATH/node_modules/.bin/tsx" "$KARAKEEP_LIB_PATH/packages/db/migrate.ts" "$@"
@@ -1,6 +1,6 @@
#!/usr/bin/env bash
set -eu -o pipefail
HOARDER_LIB_PATH=
KARAKEEP_LIB_PATH=
RELEASE=
NODEJS=
NODE_ENV=production
@@ -8,4 +8,4 @@ NODE_ENV=production
[[ -d "$DATA_DIR" ]] # Ensure DATA_DIR is defined and exists
export RELEASE NODE_ENV
exec "$NODEJS/bin/node" "$HOARDER_LIB_PATH/apps/web/.next/standalone/apps/web/server.js"
exec "$NODEJS/bin/node" "$KARAKEEP_LIB_PATH/apps/web/.next/standalone/apps/web/server.js"
@@ -1,11 +1,11 @@
#!/usr/bin/env bash
set -eu -o pipefail
HOARDER_LIB_PATH=
KARAKEEP_LIB_PATH=
RELEASE=
NODE_ENV=production
NODE_PATH="$HOARDER_LIB_PATH/apps/workers"
NODE_PATH="$KARAKEEP_LIB_PATH/apps/workers"
[[ -d "$DATA_DIR" ]] # Ensure DATA_DIR is defined and exists
export RELEASE NODE_ENV NODE_PATH
exec "$HOARDER_LIB_PATH/node_modules/.bin/tsx" "$HOARDER_LIB_PATH/apps/workers/index.ts"
exec "$KARAKEEP_LIB_PATH/node_modules/.bin/tsx" "$KARAKEEP_LIB_PATH/apps/workers/index.ts"
@@ -14,14 +14,14 @@ let
pnpm = pnpm_9;
in
stdenv.mkDerivation (finalAttrs: {
pname = "hoarder";
version = "0.23.0";
pname = "karakeep";
version = "0.23.2";
src = fetchFromGitHub {
owner = "hoarder-app";
repo = "hoarder";
owner = "karakeep-app";
repo = "karakeep";
tag = "v${finalAttrs.version}";
hash = "sha256-ro2+jXfp83JfQ9HQr0imy7aohSFbH5J6Wx5bxhMT5TM=";
hash = "sha256-Cm6e1XEmMHzQ3vODxa9+Yuwt+9zLvQ9S7jmwAozjA/k=";
};
patches = [
@@ -52,7 +52,7 @@ stdenv.mkDerivation (finalAttrs: {
'';
};
hash = "sha256-FzQPBIwe7OQ1KHaMtWaFe+RI+pXko5Ly11/jOmYSuFA=";
hash = "sha256-HZb11CAbnlGSmP/Gxyjncd/RuIWkPv3GvwYs9QZ12Ss=";
};
buildPhase = ''
runHook preBuild
@@ -81,56 +81,56 @@ stdenv.mkDerivation (finalAttrs: {
installPhase = ''
runHook preInstall
mkdir -p $out/share/doc/hoarder
cp README.md LICENSE $out/share/doc/hoarder
mkdir -p $out/share/doc/karakeep
cp README.md LICENSE $out/share/doc/karakeep
# Copy necessary files into lib/hoarder while keeping the directory structure
# Copy necessary files into lib/karakeep while keeping the directory structure
LIB_TO_COPY="node_modules apps/web/.next/standalone apps/cli/dist apps/workers packages/db packages/shared packages/trpc"
HOARDER_LIB_PATH="$out/lib/hoarder"
KARAKEEP_LIB_PATH="$out/lib/karakeep"
for DIR in $LIB_TO_COPY; do
mkdir -p "$HOARDER_LIB_PATH/$DIR"
cp -a $DIR/{.,}* "$HOARDER_LIB_PATH/$DIR"
chmod -R u+w "$HOARDER_LIB_PATH/$DIR"
mkdir -p "$KARAKEEP_LIB_PATH/$DIR"
cp -a $DIR/{.,}* "$KARAKEEP_LIB_PATH/$DIR"
chmod -R u+w "$KARAKEEP_LIB_PATH/$DIR"
done
# NextJS requires static files are copied in a specific way
# https://nextjs.org/docs/pages/api-reference/config/next-config-js/output#automatically-copying-traced-files
cp -r ./apps/web/public "$HOARDER_LIB_PATH/apps/web/.next/standalone/apps/web/"
cp -r ./apps/web/.next/static "$HOARDER_LIB_PATH/apps/web/.next/standalone/apps/web/.next/"
cp -r ./apps/web/public "$KARAKEEP_LIB_PATH/apps/web/.next/standalone/apps/web/"
cp -r ./apps/web/.next/static "$KARAKEEP_LIB_PATH/apps/web/.next/standalone/apps/web/.next/"
# Copy and patch helper scripts
for HELPER_SCRIPT in ${./helpers}/*; do
HELPER_SCRIPT_NAME="$(basename "$HELPER_SCRIPT")"
cp "$HELPER_SCRIPT" "$HOARDER_LIB_PATH/"
substituteInPlace "$HOARDER_LIB_PATH/$HELPER_SCRIPT_NAME" \
--replace-warn "HOARDER_LIB_PATH=" "HOARDER_LIB_PATH=$HOARDER_LIB_PATH" \
cp "$HELPER_SCRIPT" "$KARAKEEP_LIB_PATH/"
substituteInPlace "$KARAKEEP_LIB_PATH/$HELPER_SCRIPT_NAME" \
--replace-warn "KARAKEEP_LIB_PATH=" "KARAKEEP_LIB_PATH=$KARAKEEP_LIB_PATH" \
--replace-warn "RELEASE=" "RELEASE=${finalAttrs.version}" \
--replace-warn "NODEJS=" "NODEJS=${nodejs}"
chmod +x "$HOARDER_LIB_PATH/$HELPER_SCRIPT_NAME"
patchShebangs "$HOARDER_LIB_PATH/$HELPER_SCRIPT_NAME"
chmod +x "$KARAKEEP_LIB_PATH/$HELPER_SCRIPT_NAME"
patchShebangs "$KARAKEEP_LIB_PATH/$HELPER_SCRIPT_NAME"
done
# The cli should be in bin/
mkdir -p $out/bin
mv "$HOARDER_LIB_PATH/hoarder-cli" $out/bin/
mv "$KARAKEEP_LIB_PATH/karakeep" $out/bin/
runHook postInstall
'';
postFixup = ''
# Remove large dependencies that are not necessary during runtime
rm -rf $out/lib/hoarder/node_modules/{@next,next,@swc,react-native,monaco-editor,faker,@typescript-eslint,@microsoft,@typescript-eslint,pdfjs-dist}
rm -rf $out/lib/karakeep/node_modules/{@next,next,@swc,react-native,monaco-editor,faker,@typescript-eslint,@microsoft,@typescript-eslint,pdfjs-dist}
# Remove broken symlinks
find $out -type l ! -exec test -e {} \; -delete
'';
meta = {
homepage = "https://github.com/hoarder-app/hoarder";
description = "Self-hostable bookmark-everything app with a touch of AI for the data hoarders out there";
homepage = "https://karakeep.app/";
description = "Self-hostable bookmark-everything app (links, notes and images) with AI-based automatic tagging and full text search";
license = lib.licenses.agpl3Only;
maintainers = [ lib.maintainers.three ];
mainProgram = "hoarder-cli";
mainProgram = "karakeep";
platforms = lib.platforms.linux;
};
})
+1
View File
@@ -818,6 +818,7 @@ mapAliases {
haven-cli = throw "'haven-cli' has been removed due to the official announcement of the project closure. Read more at https://havenprotocol.org/2024/12/12/project-closure-announcement"; # Added 2025-02-25
HentaiAtHome = hentai-at-home; # Added 2024-06-12
hll2390dw-cups = throw "The hll2390dw-cups package was dropped since it was unmaintained."; # Added 2024-06-21
hoarder = throw "'hoarder' has been renamed to 'karakeep'"; # Added 2025-04-21
hop-cli = throw "hop-cli has been removed as the service has been shut-down"; # Added 2024-08-13
hpp-fcl = coal; # Added 2024-11-15
ht-rust = throw "'ht-rust' has been renamed to/replaced by 'xh'"; # Converted to throw 2024-10-17