From cf594a3b838f1f00c457dd08d41b7d6836d27de7 Mon Sep 17 00:00:00 2001 From: Felix Buehler Date: Tue, 24 Oct 2023 23:33:27 +0200 Subject: [PATCH] nixos/docuseal: init --- nixos/modules/module-list.nix | 1 + nixos/modules/services/web-apps/docuseal.nix | 196 +++++++++++++++++++ nixos/tests/all-tests.nix | 2 + nixos/tests/docuseal-postgres.nix | 46 +++++ nixos/tests/docuseal-sqlite.nix | 26 +++ 5 files changed, 271 insertions(+) create mode 100644 nixos/modules/services/web-apps/docuseal.nix create mode 100644 nixos/tests/docuseal-postgres.nix create mode 100644 nixos/tests/docuseal-sqlite.nix diff --git a/nixos/modules/module-list.nix b/nixos/modules/module-list.nix index 5b285ee24580..098c86a21af3 100644 --- a/nixos/modules/module-list.nix +++ b/nixos/modules/module-list.nix @@ -1567,6 +1567,7 @@ ./services/web-apps/dex.nix ./services/web-apps/discourse.nix ./services/web-apps/documize.nix + ./services/web-apps/docuseal.nix ./services/web-apps/dokuwiki.nix ./services/web-apps/dolibarr.nix ./services/web-apps/drupal.nix diff --git a/nixos/modules/services/web-apps/docuseal.nix b/nixos/modules/services/web-apps/docuseal.nix new file mode 100644 index 000000000000..64467666df18 --- /dev/null +++ b/nixos/modules/services/web-apps/docuseal.nix @@ -0,0 +1,196 @@ +{ + lib, + pkgs, + config, + ... +}: + +let + cfg = config.services.docuseal; + + env = { + RAILS_ENV = "production"; + NODE_ENV = "production"; + WORKDIR = "/var/lib/docuseal"; + + PORT = toString (cfg.port); + HOST = cfg.host; + + REDIS_URL = "redis://${cfg.redis.host}:${toString cfg.redis.port}"; + } + // cfg.extraConfig; +in +{ + options.services.docuseal = { + enable = lib.mkEnableOption "DocuSeal, open source document signing"; + + package = lib.mkPackageOption pkgs "docuseal" { }; + + secretKeyBaseFile = lib.mkOption { + description = '' + Path to file containing the secret key base. + A new secret key base can be generated by running: + + `openssl rand -hex 64` + + If this file does not exist, it will be created with a new secret key base. + ''; + default = "/var/lib/docuseal/secrets/secret-key-base"; + type = lib.types.path; + }; + + host = lib.mkOption { + description = "DocuSeal host."; + type = lib.types.str; + default = "127.0.0.1"; + }; + + port = lib.mkOption { + description = "DocuSeal port."; + type = lib.types.port; + default = 3000; + }; + + extraConfig = lib.mkOption { + type = lib.types.attrs; + default = { }; + description = '' + Extra environment variables to pass to DocuSeal services. + ''; + }; + + extraEnvFiles = lib.mkOption { + type = with lib.types; listOf path; + default = [ ]; + description = '' + Extra environment files to pass to DocuSeal services. Useful for passing down environmental secrets. + e.g. DATABASE_URL + ''; + example = [ "/etc/docuseal/s3config.env" ]; + }; + + redis = { + createLocally = lib.mkOption { + type = lib.types.bool; + default = true; + description = "Whether to create a local redis automatically."; + }; + + name = lib.mkOption { + type = lib.types.str; + default = "docuseal"; + description = '' + Name of the redis server. Only used if `createLocally` is set to true. + ''; + }; + + host = lib.mkOption { + type = lib.types.str; + default = "localhost"; + description = '' + Redis server address. + ''; + }; + + port = lib.mkOption { + type = lib.types.port; + default = 6379; + description = "Port of the redis server."; + }; + }; + }; + + config = lib.mkIf cfg.enable { + + assertions = [ + { + assertion = cfg.redis.createLocally -> cfg.redis.host == "localhost"; + message = "the redis host must be localhost if services.docuseal.redis.createLocally is set to true"; + } + ]; + + systemd.services.docuseal = { + description = "DocuSeal server"; + wantedBy = [ "multi-user.target" ]; + environment = env; + serviceConfig = { + Type = "simple"; + ExecStartPre = pkgs.writeShellScript "docuseal-pre-script" '' + cat > /var/lib/docuseal/docuseal.env <= 1024); + ProtectClock = true; + ProtectHostname = true; + ProtectKernelLogs = true; + ProtectKernelModules = true; + ProtectKernelTunables = true; + ProtectControlGroups = true; + RestrictAddressFamilies = [ + "AF_UNIX" + "AF_INET" + "AF_INET6" + "AF_NETLINK" + ]; + RestrictNamespaces = true; + LockPersonality = true; + MemoryDenyWriteExecute = false; + RestrictRealtime = true; + RestrictSUIDSGID = true; + RemoveIPC = true; + PrivateMounts = true; + # System Call Filtering + SystemCallArchitectures = "native"; + } + // lib.optionalAttrs (cfg.port < 1024) { + AmbientCapabilities = [ "CAP_NET_BIND_SERVICE" ]; + CapabilityBoundingSet = [ "CAP_NET_BIND_SERVICE" ]; + }; + }; + + services.redis = lib.optionalAttrs cfg.redis.createLocally { + servers."${cfg.redis.name}" = { + enable = true; + port = cfg.redis.port; + }; + }; + }; + + meta.maintainers = with lib.maintainers; [ stunkymonkey ]; +} diff --git a/nixos/tests/all-tests.nix b/nixos/tests/all-tests.nix index e471baaf7849..13dc43068609 100644 --- a/nixos/tests/all-tests.nix +++ b/nixos/tests/all-tests.nix @@ -465,6 +465,8 @@ in docling-serve = runTest ./docling-serve.nix; documentation = pkgs.callPackage ../modules/misc/documentation/test.nix { inherit nixosLib; }; documize = runTest ./documize.nix; + docuseal-psql = runTest ./docuseal-postgres.nix; + docuseal-sqlite = runTest ./docuseal-sqlite.nix; doh-proxy-rust = runTest ./doh-proxy-rust.nix; dokuwiki = runTest ./dokuwiki.nix; dolibarr = runTest ./dolibarr.nix; diff --git a/nixos/tests/docuseal-postgres.nix b/nixos/tests/docuseal-postgres.nix new file mode 100644 index 000000000000..2cdd337a9135 --- /dev/null +++ b/nixos/tests/docuseal-postgres.nix @@ -0,0 +1,46 @@ +{ lib, ... }: +{ + name = "docuseal"; + meta.maintainers = with lib.maintainers; [ + etu + stunkymonkey + ]; + + nodes.machine = + { pkgs, ... }: + { + services.docuseal = { + enable = true; + port = 80; + secretKeyBaseFile = pkgs.writeText "secret" "23bec595a1658d136d532af1365b40024b662c0862e9cdf14fd22c0afaeb0dd6322b114fa35bd82e564bae44a896b5abef3a66afd61e1382b8ebd579e2c5c17f"; + extraConfig.DATABASEURL = "postgresql://docuseal:db-secret@127.0.0.1:5432/docuseal"; + }; + services.postgresql = { + package = pkgs.postgresql; + enable = true; + ensureDatabases = [ "docuseal" ]; + ensureUsers = [ + { + name = "docuseal"; + ensureDBOwnership = true; + } + ]; + initialScript = pkgs.writeText "postgresql-password" '' + CREATE ROLE docuseal WITH LOGIN PASSWORD 'db-secret' CREATEDB; + ''; + }; + + systemd.services."docuseal-config" = { + requires = [ "postgresql.service" ]; + after = [ "postgresql.service" ]; + }; + }; + + testScript = '' + machine.wait_for_unit("multi-user.target") + machine.wait_for_unit("docuseal.service") + machine.wait_for_open_port(80) + response = machine.succeed("curl -vvv -s -H 'Host: docuseal' http://127.0.0.1:80/setup") + assert "\n DocuSeal | Open Source Document Signing\n" in response, "page didn't load successfully" + ''; +} diff --git a/nixos/tests/docuseal-sqlite.nix b/nixos/tests/docuseal-sqlite.nix new file mode 100644 index 000000000000..fcce7edf7127 --- /dev/null +++ b/nixos/tests/docuseal-sqlite.nix @@ -0,0 +1,26 @@ +{ lib, ... }: +{ + name = "docuseal"; + meta.maintainers = with lib.maintainers; [ + etu + stunkymonkey + ]; + + nodes.machine = + { pkgs, ... }: + { + services.docuseal = { + enable = true; + port = 80; + secretKeyBaseFile = pkgs.writeText "secret" "23bec595a1658d136d532af1365b40024b662c0862e9cdf14fd22c0afaeb0dd6322b114fa35bd82e564bae44a896b5abef3a66afd61e1382b8ebd579e2c5c17f"; + }; + }; + + testScript = '' + machine.wait_for_unit("multi-user.target") + machine.wait_for_unit("docuseal.service") + machine.wait_for_open_port(80) + response = machine.succeed("curl -vvv -s -H 'Host: docuseal' http://127.0.0.1:80/setup") + assert "\n DocuSeal | Open Source Document Signing\n" in response, "page didn't load successfully" + ''; +}