From 189afacd24afc35ab8e9ce821a7b512be6d912e9 Mon Sep 17 00:00:00 2001 From: Mario <191101255+wariuccio@users.noreply.github.com> Date: Thu, 29 Jan 2026 20:46:19 +0000 Subject: [PATCH 1/2] papra: init at 26.2.2 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-Authored-By: bitbloxhub <45184892+bitbloxhub@users.noreply.github.com> Co-Authored-By: Sandro Jäckel --- pkgs/by-name/pa/papra/package.nix | 101 ++++++++++++++++++++++++++++++ 1 file changed, 101 insertions(+) create mode 100644 pkgs/by-name/pa/papra/package.nix diff --git a/pkgs/by-name/pa/papra/package.nix b/pkgs/by-name/pa/papra/package.nix new file mode 100644 index 000000000000..2853e4f2cf82 --- /dev/null +++ b/pkgs/by-name/pa/papra/package.nix @@ -0,0 +1,101 @@ +{ + makeBinaryWrapper, + nodejs, + node-gyp, + fetchPnpmDeps, + fetchFromGitHub, + pnpm_10, + pnpmConfigHook, + stdenv, + lib, + vips, + pkg-config, + python3, +}: +let + pnpm = pnpm_10; +in +stdenv.mkDerivation (finalAttrs: { + pname = "papra"; + version = "26.2.2"; + src = fetchFromGitHub { + owner = "papra-hq"; + repo = "papra"; + tag = "@papra/app@${finalAttrs.version}"; + hash = "sha256-0MIar+fBwXRE8LlVLZDx/C0GOYVpobDTqFwkMs2k06Y="; + }; + + nativeBuildInputs = [ + makeBinaryWrapper + nodejs + node-gyp + python3 + pkg-config + pnpmConfigHook + pnpm + ]; + + buildInputs = [ + vips + ]; + + env.SHARP_FORCE_GLOBAL_LIBVIPS = 1; + env.npm_config_nodedir = nodejs; + + postPatch = '' + substituteInPlace apps/papra-server/src/modules/app/static-assets/static-assets.routes.ts \ + --replace-fail "./public" "$out/lib/public" \ + --replace-fail "public/index.html" "$out/lib/public/index.html" + ''; + + buildPhase = '' + runHook preBuild + + pnpm config set inject-workspace-packages true + + pushd node_modules/sharp + pnpm run install + popd + + pnpm --filter "@papra/app-client..." run build + pnpm --filter "@papra/app-server..." run build + + runHook postBuild + ''; + + installPhase = '' + runHook preInstall + + mkdir -p $out/{bin,lib} + + pnpm deploy --filter=@papra/app-server --prod $out/lib/ + + mkdir -p $out/lib/public + cp -r apps/papra-client/dist/* $out/lib/public/ + + makeWrapper "${lib.getExe nodejs}" $out/bin/papra \ + --add-flags "$out/lib/dist/index.js" \ + --set "NODE_PATH" $out/lib/node_modules + + runHook postInstall + ''; + + pnpmDeps = fetchPnpmDeps { + inherit (finalAttrs) pname version src; + pnpm = pnpm; + fetcherVersion = 3; + hash = "sha256-NQakyRlL6deG13yt+FlmVcVvEkNWHW0Lhf/3NecfwaE="; + pnpmWorkspaces = [ + "@papra/app-client..." + "@papra/app-server..." + ]; + }; + + meta = { + description = "Open-source document management platform designed to help you organize, secure, and archive your files effortlessly."; + homepage = "https://papra.app/"; + changelog = "https://github.com/papra-hq/papra/releases"; + license = lib.licenses.agpl3Only; + maintainers = with lib.maintainers; [ wariuccio ]; + }; +}) From ed235bc82584f15120b5480e38a4157640dcee43 Mon Sep 17 00:00:00 2001 From: Mario <191101255+wariuccio@users.noreply.github.com> Date: Thu, 29 Jan 2026 20:47:10 +0000 Subject: [PATCH 2/2] nixos/papra: init MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-Authored-By: Sandro Jäckel --- .../manual/release-notes/rl-2605.section.md | 2 + nixos/modules/module-list.nix | 1 + nixos/modules/services/web-apps/papra.nix | 103 ++++++++++++++++++ 3 files changed, 106 insertions(+) create mode 100644 nixos/modules/services/web-apps/papra.nix diff --git a/nixos/doc/manual/release-notes/rl-2605.section.md b/nixos/doc/manual/release-notes/rl-2605.section.md index dea390ae8dfc..63052e584eb7 100644 --- a/nixos/doc/manual/release-notes/rl-2605.section.md +++ b/nixos/doc/manual/release-notes/rl-2605.section.md @@ -20,6 +20,8 @@ - [reaction](https://reaction.ppom.me/), a daemon that scans program outputs for repeated patterns, and takes action. A common usage is to scan ssh and webserver logs, and to ban hosts that cause multiple authentication errors. A modern alternative to fail2ban. Available as [services.reaction](#opt-services.reaction.enable). +- [papra](https://papra.app/), an open-source document management platform designed to help you organize, secure, and archive your files effortlessly. Available as [services.papra](#opt-services.papra.enable). + - [rqbit](https://github.com/ikatson/rqbit), a bittorrent client written in Rust. It has HTTP API and Web UI, and can be used as a library. Available as [services.rqbit](#opt-services.rqbit.enable). - [Tailscale Serve](https://tailscale.com/kb/1552/tailscale-services), configure Tailscale Serve for exposing local services to your tailnet. Available as [services.tailscale.serve](#opt-services.tailscale.serve.enable). diff --git a/nixos/modules/module-list.nix b/nixos/modules/module-list.nix index a6913729e510..e44b06d76c51 100644 --- a/nixos/modules/module-list.nix +++ b/nixos/modules/module-list.nix @@ -1709,6 +1709,7 @@ ./services/web-apps/openwebrx.nix ./services/web-apps/outline.nix ./services/web-apps/pairdrop.nix + ./services/web-apps/papra.nix ./services/web-apps/part-db.nix ./services/web-apps/peering-manager.nix ./services/web-apps/peertube-runner.nix diff --git a/nixos/modules/services/web-apps/papra.nix b/nixos/modules/services/web-apps/papra.nix new file mode 100644 index 000000000000..8ee55736f1eb --- /dev/null +++ b/nixos/modules/services/web-apps/papra.nix @@ -0,0 +1,103 @@ +{ + config, + pkgs, + lib, + ... +}: +let + cfg = config.services.papra; + defaultUser = "papra"; + defaultGroup = "papra"; + defaultEnv = { + SERVER_SERVE_PUBLIC_DIR = true; + PORT = 1221; + DATABASE_URL = "file:/var/lib/papra/db.sqlite"; + DOCUMENT_STORAGE_FILESYSTEM_ROOT = "/var/lib/papra/local-documents"; + }; +in +{ + options = { + services.papra = { + enable = lib.mkEnableOption "Papra"; + + user = lib.mkOption { + default = defaultUser; + type = lib.types.str; + description = "User under which Papra runs."; + }; + + group = lib.mkOption { + default = defaultGroup; + type = lib.types.str; + description = '' + If the default user "${defaultUser}" is configured then this is the primary + group of that user. + ''; + }; + + package = lib.mkPackageOption pkgs "papra" { }; + + environment = lib.mkOption { + type = + with lib.types; + attrsOf (oneOf [ + str + int + float + bool + path + package + ]); + default = defaultEnv; + example = { + PORT = 1221; + }; + description = "Environment variables to set for the service."; + }; + + environmentFile = lib.mkOption { + type = with lib.types; nullOr path; + default = null; + description = "Environment file, usefult to provide secrets to the service"; + }; + }; + }; + config = lib.mkIf cfg.enable { + users = { + users = lib.optionalAttrs (cfg.user == defaultUser) { + "${defaultUser}" = { + description = "Papra service user"; + isSystemUser = true; + group = cfg.group; + }; + }; + groups = lib.optionalAttrs (cfg.group == defaultGroup) { + "${defaultGroup}" = { }; + }; + }; + + systemd.services.papra = { + wantedBy = [ "multi-user.target" ]; + serviceConfig = { + Restart = "on-failure"; + ExecStartPre = "${lib.getExe pkgs.tsx} ${cfg.package}/lib/src/scripts/migrate-up.script.ts"; + ExecStart = "${cfg.package}/bin/papra"; + User = cfg.user; + Group = cfg.group; + StateDirectory = "papra"; + EnvironmentFile = cfg.environmentFile; + }; + environment = + let + environmentwithDefaults = defaultEnv // cfg.environment; + in + (lib.mapAttrs ( + _: s: if lib.isBool s then lib.boolToString s else toString s + ) environmentwithDefaults); + }; + }; + + meta = { + maintainers = with lib.maintainers; [ wariuccio ]; + }; +}