Unverified Commit 4f32864e authored by Matthew Croughan's avatar Matthew Croughan Committed by GitHub
Browse files

docuseal: init at 2.1.7 (#266880)

parents a81810ef cf594a3b
Loading
Loading
Loading
Loading
+2 −0
Original line number Diff line number Diff line
@@ -134,6 +134,8 @@

- [lemurs](https://github.com/coastalwhite/lemurs), a customizable TUI display/login manager. Available at [services.displayManager.lemurs](#opt-services.displayManager.lemurs.enable).

- [docuseal](https://github.com/docusealco/docuseal), a DocuSign alternative. Create, fill, and sign digital documents. Available at [services.docuseal](#opt-services.docuseal.enable).

- [paisa](https://github.com/ananthakumaran/paisa), a personal finance tracker and dashboard. Available as [services.paisa](#opt-services.paisa.enable).

- [conman](https://github.com/dun/conman), a serial console management program. Available as [services.conman](#opt-services.conman.enable).
+1 −0
Original line number Diff line number Diff line
@@ -1571,6 +1571,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
+196 −0
Original line number Diff line number Diff line
{
  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 <<EOF
          SECRET_KEY_BASE="$(cat ${cfg.secretKeyBaseFile})"
          EOF
        '';
        ExecStart = "${cfg.package}/bin/rails server --pid=/var/lib/docuseal/docuseal.pids";
        Restart = "always";
        EnvironmentFile = [ "docuseal.env" ] ++ cfg.extraEnvFiles;
        # Runtime directory and mode
        RuntimeDirectory = "docuseal";
        RuntimeDirectoryMode = "0750";
        # System Call Filtering
        SystemCallFilter = [
          "@system-service"
          "~@privileged"
        ];
        # User and group
        DynamicUser = true;
        # Working directory
        WorkingDirectory = "/var/lib/docuseal";
        # State directory and mode
        StateDirectory = "docuseal";
        StateDirectoryMode = "0750";
        # Logs directory and mode
        LogsDirectory = "docuseal";
        LogsDirectoryMode = "0750";
        # Proc filesystem
        ProcSubset = "pid";
        ProtectProc = "invisible";
        # Access write directories
        UMask = "0027";
        # Capabilities
        CapabilityBoundingSet = "";
        # Security
        NoNewPrivileges = true;
        # Sandboxing
        ProtectSystem = "strict";
        ProtectHome = true;
        PrivateTmp = true;
        PrivateDevices = true;
        PrivateUsers = (cfg.port >= 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 ];
}
+2 −0
Original line number Diff line number Diff line
@@ -468,6 +468,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;
+46 −0
Original line number Diff line number Diff line
{ 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 "<title>\n  DocuSeal | Open Source Document Signing\n</title>" in response, "page didn't load successfully"
  '';
}
Loading