infrastructure/machines/nixos/compute01/docuseal/module.nix
Tom Hubrecht f77e011c11
All checks were successful
Build all the nodes / netcore00 (push) Successful in 21s
Build all the nodes / netcore01 (push) Successful in 21s
Build all the nodes / netaccess01 (push) Successful in 22s
Build all the nodes / netcore02 (push) Successful in 22s
Build all the nodes / ap01 (push) Successful in 36s
Build the shell / build-shell (push) Successful in 27s
Run pre-commit on all files / pre-commit (push) Successful in 31s
Build all the nodes / hypervisor01 (push) Successful in 1m4s
Build all the nodes / build01 (push) Successful in 1m6s
Build all the nodes / hypervisor02 (push) Successful in 1m10s
Build all the nodes / storage01 (push) Successful in 1m12s
Build all the nodes / geo01 (push) Successful in 1m14s
Build all the nodes / tower01 (push) Successful in 1m12s
Build all the nodes / hypervisor03 (push) Successful in 1m14s
Build all the nodes / rescue01 (push) Successful in 1m14s
Build all the nodes / web03 (push) Successful in 1m4s
Build all the nodes / web01 (push) Successful in 1m33s
Build all the nodes / geo02 (push) Successful in 1m55s
Build all the nodes / bridge01 (push) Successful in 1m57s
Build all the nodes / web02 (push) Successful in 1m59s
Build all the nodes / cof02 (push) Successful in 2m6s
Build all the nodes / vault01 (push) Successful in 1m1s
Build all the nodes / compute01 (push) Successful in 9m38s
fix(docuseal): Actually import the module
Minor cleanup as well
2025-04-14 13:16:29 +02:00

229 lines
5.3 KiB
Nix

# SPDX-FileCopyrightText: 2025 Tom Hubrecht <tom.hubrecht@dgnum.eu>
#
# SPDX-License-Identifier: EUPL-1.2
{
config,
lib,
pkgs,
utils,
...
}:
let
inherit (lib)
getExe'
mkEnableOption
mkIf
mkOption
mkPackageOption
optional
optionalAttrs
;
inherit (lib.types)
attrsOf
bool
nullOr
oneOf
package
path
port
str
;
inherit (utils) escapeSystemdExecArgs;
cfg = config.services.docuseal;
in
{
options.services.docuseal = {
enable = mkEnableOption "docuseal, an open source DocuSign alternative";
package = mkPackageOption pkgs "docuseal" { };
host = mkOption {
type = str;
description = ''
Hostname of the web server.
'';
};
port = mkOption {
type = port;
default = 3000;
description = ''
Listening port for the web server.
'';
};
environment = mkOption {
type = attrsOf (
nullOr (oneOf [
package
path
str
])
);
description = ''
Evironment variables available to Docuseal.
'';
};
environmentFile = mkOption {
type = nullOr path;
default = null;
description = ''
Path to a file containing environment variables.
'';
};
redis = {
createLocally = mkOption {
type = bool;
default = true;
description = ''
Whether to create a local redis automatically.
'';
};
};
interactScript = mkOption {
type = package;
default = pkgs.writeShellApplication {
name = "docuseal";
runtimeInputs = [
cfg.package
config.systemd.package
pkgs.util-linux
];
text = ''
MainPID=$(systemctl show -p MainPID --value docuseal.service)
nsenter -e -a -w -t "$MainPID" -G follow -S follow "$@"
'';
};
description = ''
Script to run docuseal tasks.
'';
};
};
config = mkIf cfg.enable {
services = {
docuseal.environment =
{
RAILS_ENV = "production";
WORKDIR = "/var/lib/docuseal";
DATABASE_URL = "postgresql:///docuseal?host=/run/postgresql";
HOST = cfg.host;
PORT = builtins.toString cfg.port;
}
// (optionalAttrs cfg.redis.createLocally {
REDIS_URL = "unix://${config.services.redis.servers.docuseal.unixSocket}";
});
postgresql = {
enable = true;
ensureDatabases = [ "docuseal" ];
ensureUsers = [
{
name = "docuseal";
ensureDBOwnership = true;
}
];
};
redis.servers.docuseal = mkIf cfg.redis.createLocally {
enable = true;
};
};
environment.systemPackages = [ cfg.interactScript ];
systemd.services.docuseal = {
description = "Docuseal";
after = [
"network.target"
"postgresql.target"
] ++ (optional cfg.redis.createLocally "redis.service");
wantedBy = [ "multi-user.target" ];
inherit (cfg) environment;
path = [ cfg.package ];
serviceConfig =
{
CacheDirectory = "docuseal";
CacheDirectoryMode = "0700";
DynamicUser = true;
EnvironmentFile = optional (cfg.environmentFile != null) cfg.environmentFile;
ExecStart = escapeSystemdExecArgs [
(getExe' cfg.package "bundle")
"exec"
"puma"
"-C"
"${cfg.package}/config/puma.rb"
"--dir"
cfg.package
];
LogsDirectory = "docuseal";
LogsDirectoryMode = "0700";
StateDirectory = "docuseal";
StateDirectoryMode = "0700";
SupplementaryGroups = optional cfg.redis.createLocally "redis-docuseal";
SystemCallFilter = [
"@system-service"
"~@privileged"
];
User = "docuseal";
UMask = "0077";
WorkingDirectory = "/var/lib/docuseal";
# Proc filesystem
ProcSubset = "pid";
ProtectProc = "invisible";
# 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";
}
// optionalAttrs (cfg.port < 1024) {
AmbientCapabilities = [ "CAP_NET_BIND_SERVICE" ];
CapabilityBoundingSet = [ "CAP_NET_BIND_SERVICE" ];
};
};
};
}