papra: init at 26.2.2, nixos/papra: init (#485134)

This commit is contained in:
Sandro
2026-04-04 18:46:16 +00:00
committed by GitHub
4 changed files with 207 additions and 0 deletions
@@ -52,6 +52,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).
+1
View File
@@ -1729,6 +1729,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/pdfding.nix
./services/web-apps/peering-manager.nix
+103
View File
@@ -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 ];
};
}
+101
View File
@@ -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 ];
};
})