diff --git a/nixos/doc/manual/release-notes/rl-2505.section.md b/nixos/doc/manual/release-notes/rl-2505.section.md index a98c55885f5f..1950f41ef455 100644 --- a/nixos/doc/manual/release-notes/rl-2505.section.md +++ b/nixos/doc/manual/release-notes/rl-2505.section.md @@ -192,6 +192,8 @@ - [Orthanc](https://orthanc.uclouvain.be/) a lightweight, RESTful DICOM server for healthcare and medical research. Available as [services.orthanc](#opt-services.orthanc.enable). +- [Docling Serve](https://github.com/docling-project/docling-serve) running [Docling](https://github.com/docling-project/docling) as an API service. Available as [services.docling-serve](#opt-services.docling-serve.enable). + - [Pareto Security](https://paretosecurity.com/) is an alternative to corporate compliance solutions for companies that care about security but know it doesn't have to be invasive. Available as [services.paretosecurity](#opt-services.paretosecurity.enable) - [ipfs-cluster](https://ipfscluster.io/), Pinset orchestration for IPFS. Available as [services.ipfs-cluster](#opt-services.ipfs-cluster.enable) diff --git a/nixos/modules/module-list.nix b/nixos/modules/module-list.nix index 998c935fb8d7..5fb875c16ab4 100644 --- a/nixos/modules/module-list.nix +++ b/nixos/modules/module-list.nix @@ -790,6 +790,7 @@ ./services/misc/dictd.nix ./services/misc/disnix.nix ./services/misc/docker-registry.nix + ./services/misc/docling-serve.nix ./services/misc/domoticz.nix ./services/misc/duckdns.nix ./services/misc/duckling.nix diff --git a/nixos/modules/services/misc/docling-serve.nix b/nixos/modules/services/misc/docling-serve.nix new file mode 100644 index 000000000000..e717c1fe5e80 --- /dev/null +++ b/nixos/modules/services/misc/docling-serve.nix @@ -0,0 +1,115 @@ +{ + config, + lib, + pkgs, + ... +}: +let + inherit (lib) types; + + cfg = config.services.docling-serve; +in +{ + options = { + services.docling-serve = { + enable = lib.mkEnableOption "Docling Serve server"; + package = lib.mkPackageOption pkgs "docling-serve" { }; + + host = lib.mkOption { + type = types.str; + default = "127.0.0.1"; + example = "0.0.0.0"; + description = '' + The host address which the Docling Serve server HTTP interface listens to. + ''; + }; + + port = lib.mkOption { + type = types.port; + default = 5001; + example = 11111; + description = '' + Which port the Docling Serve server listens to. + ''; + }; + + environment = lib.mkOption { + type = types.attrsOf types.str; + default = { + DOCLING_SERVE_ENABLE_UI = "True"; + }; + example = '' + { + DOCLING_SERVE_ENABLE_UI = "False"; + } + ''; + description = '' + Extra environment variables for Docling Serve. + For more details see + ''; + }; + + environmentFile = lib.mkOption { + description = '' + Environment file to be passed to the systemd service. + Useful for passing secrets to the service to prevent them from being + world-readable in the Nix store. + ''; + type = lib.types.nullOr lib.types.path; + default = null; + example = "/var/lib/secrets/doclingServeSecrets"; + }; + + openFirewall = lib.mkOption { + type = types.bool; + default = false; + description = '' + Whether to open the firewall for Docling Serve. + This adds `services.Docling Serve.port` to `networking.firewall.allowedTCPPorts`. + ''; + }; + }; + }; + + config = lib.mkIf cfg.enable { + systemd.services.docling-serve = { + description = "Running Docling as an API service"; + wantedBy = [ "multi-user.target" ]; + after = [ "network.target" ]; + + environment = cfg.environment; + + serviceConfig = { + ExecStart = "${lib.getExe cfg.package} run --host \"${cfg.host}\" --port ${toString cfg.port}"; + EnvironmentFile = lib.optional (cfg.environmentFile != null) cfg.environmentFile; + PrivateTmp = true; + DynamicUser = true; + DevicePolicy = "closed"; + LockPersonality = true; + PrivateUsers = true; + ProtectHome = true; + ProtectHostname = true; + ProtectKernelLogs = true; + ProtectKernelModules = true; + ProtectKernelTunables = true; + ProtectControlGroups = true; + RestrictNamespaces = true; + RestrictRealtime = true; + SystemCallArchitectures = "native"; + UMask = "0077"; + CapabilityBoundingSet = ""; + RestrictAddressFamilies = [ + "AF_INET" + "AF_INET6" + "AF_UNIX" + ]; + ProtectClock = true; + ProtectProc = "invisible"; + }; + }; + + networking.firewall = lib.mkIf cfg.openFirewall { allowedTCPPorts = [ cfg.port ]; }; + }; + + meta.maintainers = with lib.maintainers; [ drupol ]; +} diff --git a/nixos/tests/all-tests.nix b/nixos/tests/all-tests.nix index d1fe552bbc1f..f6857b54fc83 100644 --- a/nixos/tests/all-tests.nix +++ b/nixos/tests/all-tests.nix @@ -367,6 +367,7 @@ in docker-tools-nix-shell = runTest ./docker-tools-nix-shell.nix; docker-tools-cross = handleTestOn [ "x86_64-linux" "aarch64-linux" ] ./docker-tools-cross.nix { }; docker-tools-overlay = handleTestOn [ "x86_64-linux" ] ./docker-tools-overlay.nix { }; + docling-serve = runTest ./docling-serve.nix; documize = handleTest ./documize.nix { }; documentation = pkgs.callPackage ../modules/misc/documentation/test.nix { inherit nixosLib; }; doh-proxy-rust = handleTest ./doh-proxy-rust.nix { }; diff --git a/nixos/tests/docling-serve.nix b/nixos/tests/docling-serve.nix new file mode 100644 index 000000000000..ff31e003283b --- /dev/null +++ b/nixos/tests/docling-serve.nix @@ -0,0 +1,28 @@ +{ lib, ... }: +let + mainPort = "5001"; +in +{ + name = "docling-serve"; + meta = with lib.maintainers; { + maintainers = [ drupol ]; + }; + + nodes = { + machine = + { ... }: + { + services.docling-serve = { + enable = true; + }; + }; + }; + + testScript = '' + machine.start() + + machine.wait_for_unit("docling-serve.service") + machine.wait_for_open_port(${mainPort}) + machine.succeed("curl http://127.0.0.1:${mainPort}") + ''; +} diff --git a/pkgs/by-name/do/docling-serve/package.nix b/pkgs/by-name/do/docling-serve/package.nix index 79d8d642a03a..df0fb39a4724 100644 --- a/pkgs/by-name/do/docling-serve/package.nix +++ b/pkgs/by-name/do/docling-serve/package.nix @@ -1,3 +1,8 @@ -{ python3Packages }: +{ python3Packages, nixosTests }: -python3Packages.toPythonApplication python3Packages.docling-serve +(python3Packages.toPythonApplication python3Packages.docling-serve) +// { + passthru.tests = { + docling-serve = nixosTests.docling-serve; + }; +}