Files
nixpkgs/nixos/modules/services/web-apps/karakeep.nix
Cody Allen 35f17c1723 nixos/karakeep: remove meilisearch workaround for dumpless upgrade
The Karakeep module previously set the `experimental_dumpless_upgrade`
setting, which was renamed in meilisearch 1.51.0, which is causing
meilisearch to fail to parse its config file and crash.

This setting was renamed for the meilisearch module in #548169, but the
Karakeep module was also configuring this setting. Per the karakeep
module's comment, this option was intended to be removed once dumpless
upgrades were the default in meilisearch, so I've removed this option.

Resolves #548609
2026-08-05 06:38:36 -04:00

231 lines
6.5 KiB
Nix

{
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/environment-variables>
'';
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 = {
enable = cfg.meilisearch.enable;
};
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 = {
NEXT_CACHE_DIR = "%C/karakeep";
}
// karakeepEnv;
serviceConfig = {
ExecStart = "${cfg.package}/lib/karakeep/start-web";
User = "karakeep";
Group = "karakeep";
CacheDirectory = "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 ];
};
}