2022-11-28 21:45:34 +00:00
|
|
|
overlay: { config, lib, pkgs, ... }:
|
2020-01-19 21:53:58 +00:00
|
|
|
|
|
|
|
with lib;
|
|
|
|
let
|
|
|
|
cfg = config.services.docspell-restserver;
|
2022-12-12 16:25:21 +00:00
|
|
|
# Extract the config without the extraConfig attribute. It will be merged later
|
|
|
|
declared_config = attrsets.filterAttrs (n: v: n != "extraConfig") cfg;
|
2020-01-19 21:53:58 +00:00
|
|
|
user = if cfg.runAs == null then "docspell" else cfg.runAs;
|
|
|
|
configFile = pkgs.writeText "docspell-server.conf" ''
|
|
|
|
{"docspell": {"server":
|
2022-12-12 16:25:21 +00:00
|
|
|
${builtins.toJSON (lib.recursiveUpdate declared_config cfg.extraConfig)}
|
2020-01-19 21:53:58 +00:00
|
|
|
}}
|
|
|
|
'';
|
|
|
|
defaults = {
|
|
|
|
app-name = "Docspell";
|
|
|
|
app-id = "rest1";
|
|
|
|
base-url = "http://localhost:7880";
|
2021-11-17 23:18:54 +00:00
|
|
|
internal-url = "http://localhost:7880";
|
2020-06-23 22:04:10 +00:00
|
|
|
max-item-page-size = 200;
|
2020-08-04 20:45:35 +00:00
|
|
|
max-note-length = 180;
|
2020-09-05 14:00:19 +00:00
|
|
|
show-classification-settings = true;
|
2020-01-19 21:53:58 +00:00
|
|
|
bind = {
|
|
|
|
address = "localhost";
|
|
|
|
port = 7880;
|
|
|
|
};
|
2022-03-18 23:19:27 +00:00
|
|
|
server-options = {
|
|
|
|
enable-http-2 = false;
|
|
|
|
max-connections = 1024;
|
|
|
|
response-timeout = "45s";
|
|
|
|
};
|
2022-02-19 22:37:45 +00:00
|
|
|
logging = {
|
|
|
|
minimum-level = "Info";
|
2022-02-23 22:26:11 +00:00
|
|
|
format = "Fancy";
|
2022-05-21 20:02:42 +00:00
|
|
|
levels = {
|
|
|
|
"docspell" = "Info";
|
|
|
|
"org.flywaydb" = "Info";
|
|
|
|
"binny" = "Info";
|
|
|
|
"org.http4s" = "Info";
|
|
|
|
};
|
2022-02-19 22:37:45 +00:00
|
|
|
};
|
2020-05-25 13:32:03 +00:00
|
|
|
integration-endpoint = {
|
|
|
|
enabled = false;
|
|
|
|
priority = "low";
|
2020-10-26 21:35:25 +00:00
|
|
|
source-name = "integration";
|
2020-05-25 13:32:03 +00:00
|
|
|
allowed-ips = {
|
2020-06-17 19:23:27 +00:00
|
|
|
enabled = false;
|
2020-05-25 13:32:03 +00:00
|
|
|
ips = [ "127.0.0.1" ];
|
|
|
|
};
|
|
|
|
http-basic = {
|
|
|
|
enabled = false;
|
|
|
|
realm = "Docspell Integration";
|
|
|
|
user = "docspell-int";
|
|
|
|
password = "docspell-int";
|
|
|
|
};
|
|
|
|
http-header = {
|
|
|
|
enabled = false;
|
|
|
|
header-name = "Docspell-Integration";
|
|
|
|
header-value = "some-secret";
|
|
|
|
};
|
|
|
|
};
|
2021-01-04 14:16:32 +00:00
|
|
|
admin-endpoint = {
|
|
|
|
secret = "";
|
|
|
|
};
|
2020-06-25 21:56:44 +00:00
|
|
|
full-text-search = {
|
|
|
|
enabled = false;
|
2022-04-13 07:32:55 +00:00
|
|
|
backend = "solr";
|
2020-06-25 21:56:44 +00:00
|
|
|
solr = {
|
|
|
|
url = "http://localhost:8983/solr/docspell";
|
|
|
|
commit-within = 1000;
|
|
|
|
log-verbose = false;
|
|
|
|
def-type = "lucene";
|
|
|
|
q-op = "OR";
|
|
|
|
};
|
2022-03-21 13:58:15 +00:00
|
|
|
postgresql = {
|
|
|
|
use-default-connection = false;
|
|
|
|
jdbc = {
|
|
|
|
url = "jdbc:postgresql://server:5432/db";
|
|
|
|
user = "pguser";
|
|
|
|
password = "";
|
|
|
|
};
|
2022-11-28 21:45:34 +00:00
|
|
|
pg-config = { };
|
2022-03-21 13:58:15 +00:00
|
|
|
pg-query-parser = "websearch_to_tsquery";
|
|
|
|
pg-rank-normalization = [ 4 ];
|
|
|
|
};
|
2020-06-25 21:56:44 +00:00
|
|
|
};
|
2020-01-19 21:53:58 +00:00
|
|
|
auth = {
|
|
|
|
server-secret = "hex:caffee";
|
|
|
|
session-valid = "5 minutes";
|
2020-12-14 13:51:56 +00:00
|
|
|
remember-me = {
|
|
|
|
enabled = true;
|
|
|
|
valid = "30 days";
|
|
|
|
};
|
2020-01-19 21:53:58 +00:00
|
|
|
};
|
2022-04-11 18:53:48 +00:00
|
|
|
download-all = {
|
|
|
|
max-files = 500;
|
|
|
|
max-size = "1400M";
|
|
|
|
};
|
2021-09-06 12:25:10 +00:00
|
|
|
openid = {
|
|
|
|
enabled = false;
|
|
|
|
display = "";
|
|
|
|
provider = {
|
|
|
|
provider-id = null;
|
|
|
|
client-id = null;
|
|
|
|
client-secret = null;
|
|
|
|
scope = "profile";
|
|
|
|
authorize-url = null;
|
|
|
|
token-url = null;
|
2022-05-21 20:02:42 +00:00
|
|
|
user-url = null;
|
2021-09-06 12:25:10 +00:00
|
|
|
sign-key = "";
|
|
|
|
sig-algo = "RS256";
|
|
|
|
};
|
|
|
|
user-key = "preferred_username";
|
|
|
|
collective-key = "lookup:preferred_username";
|
|
|
|
};
|
2020-01-19 21:53:58 +00:00
|
|
|
backend = {
|
2020-06-13 13:10:00 +00:00
|
|
|
mail-debug = false;
|
2020-01-19 21:53:58 +00:00
|
|
|
jdbc = {
|
|
|
|
url = "jdbc:h2:///tmp/docspell-demo.db;MODE=PostgreSQL;DATABASE_TO_LOWER=TRUE;AUTO_SERVER=TRUE";
|
|
|
|
user = "sa";
|
|
|
|
password = "";
|
|
|
|
};
|
|
|
|
signup = {
|
|
|
|
mode = "open";
|
|
|
|
new-invite-password = "";
|
|
|
|
invite-time = "3 days";
|
|
|
|
};
|
|
|
|
files = {
|
|
|
|
chunk-size = 524288;
|
2022-11-28 21:45:34 +00:00
|
|
|
valid-mime-types = [ ];
|
2020-01-19 21:53:58 +00:00
|
|
|
};
|
2022-05-21 20:02:42 +00:00
|
|
|
addons = {
|
|
|
|
enabled = false;
|
|
|
|
allow-impure = true;
|
2022-11-28 21:45:34 +00:00
|
|
|
allowed-urls = [ "*" ];
|
|
|
|
denied-urls = [ ];
|
2022-05-21 20:02:42 +00:00
|
|
|
};
|
2020-01-19 21:53:58 +00:00
|
|
|
};
|
|
|
|
};
|
2022-11-28 21:45:34 +00:00
|
|
|
in
|
|
|
|
{
|
2020-01-19 21:53:58 +00:00
|
|
|
|
|
|
|
## interface
|
|
|
|
options = {
|
|
|
|
services.docspell-restserver = {
|
|
|
|
enable = mkOption {
|
|
|
|
default = false;
|
|
|
|
description = "Whether to enable docspell.";
|
|
|
|
};
|
|
|
|
runAs = mkOption {
|
|
|
|
type = types.nullOr types.str;
|
|
|
|
default = null;
|
|
|
|
description = ''
|
|
|
|
Specify a user for running the application. If null, a new
|
|
|
|
user is created.
|
|
|
|
'';
|
|
|
|
};
|
2020-09-08 16:07:04 +00:00
|
|
|
jvmArgs = mkOption {
|
|
|
|
type = types.listOf types.str;
|
2022-11-28 21:45:34 +00:00
|
|
|
default = [ ];
|
2020-09-08 16:07:04 +00:00
|
|
|
example = [ "-J-Xmx1G" ];
|
|
|
|
description = "The options passed to the executable for setting jvm arguments.";
|
|
|
|
};
|
|
|
|
|
2020-01-19 21:53:58 +00:00
|
|
|
|
|
|
|
app-name = mkOption {
|
|
|
|
type = types.str;
|
|
|
|
default = defaults.app-name;
|
|
|
|
description = "The name used in the web ui and in notification mails.";
|
|
|
|
};
|
|
|
|
|
|
|
|
app-id = mkOption {
|
|
|
|
type = types.str;
|
|
|
|
default = defaults.app-id;
|
|
|
|
description = ''
|
|
|
|
This is the id of this node. If you run more than one server, you
|
|
|
|
have to make sure to provide unique ids per node.
|
|
|
|
'';
|
|
|
|
};
|
|
|
|
|
|
|
|
base-url = mkOption {
|
|
|
|
type = types.str;
|
|
|
|
default = defaults.base-url;
|
|
|
|
description = ''
|
|
|
|
This is the base URL this application is deployed to. This is used
|
|
|
|
to create absolute URLs and to configure the cookie.
|
|
|
|
'';
|
|
|
|
};
|
|
|
|
|
2021-11-17 23:18:54 +00:00
|
|
|
internal-url = mkOption {
|
|
|
|
type = types.str;
|
|
|
|
default = defaults.internal-url;
|
|
|
|
description = ''
|
|
|
|
This url is the base url for reaching this server internally.
|
|
|
|
While you might set `base-url` to some external address (like
|
|
|
|
mydocs.myserver.com), the `internal-url` must be set such that
|
|
|
|
other nodes can reach this server.
|
|
|
|
'';
|
|
|
|
};
|
|
|
|
|
2020-06-13 22:48:19 +00:00
|
|
|
max-item-page-size = mkOption {
|
|
|
|
type = types.int;
|
|
|
|
default = defaults.max-item-page-size;
|
|
|
|
description = ''
|
|
|
|
This is a hard limit to restrict the size of a batch that is
|
|
|
|
returned when searching for items. The user can set this limit
|
|
|
|
within the client config, but it is restricted by the server to
|
|
|
|
the number defined here. An admin might choose a lower number
|
|
|
|
depending on the available resources.
|
|
|
|
'';
|
|
|
|
};
|
|
|
|
|
2020-08-04 20:45:35 +00:00
|
|
|
max-note-length = mkOption {
|
|
|
|
type = types.int;
|
|
|
|
default = defaults.max-note-length;
|
|
|
|
description = ''
|
|
|
|
The number of characters to return for each item notes when
|
|
|
|
searching. Item notes may be very long, when returning them with
|
|
|
|
all the results from a search, they add quite some data to return.
|
|
|
|
In order to keep this low, a limit can be defined here.
|
|
|
|
'';
|
|
|
|
};
|
|
|
|
|
2020-09-05 14:00:19 +00:00
|
|
|
show-classification-settings = mkOption {
|
|
|
|
type = types.bool;
|
|
|
|
default = defaults.show-classification-settings;
|
|
|
|
description = ''
|
|
|
|
This defines whether the classification form in the collective
|
|
|
|
settings is displayed or not. If all joex instances have document
|
|
|
|
classification disabled, it makes sense to hide its settings from
|
|
|
|
users.
|
|
|
|
'';
|
|
|
|
};
|
|
|
|
|
2020-01-19 21:53:58 +00:00
|
|
|
bind = mkOption {
|
2022-11-28 21:45:34 +00:00
|
|
|
type = types.submodule ({
|
2020-01-19 21:53:58 +00:00
|
|
|
options = {
|
|
|
|
address = mkOption {
|
|
|
|
type = types.str;
|
|
|
|
default = defaults.bind.address;
|
|
|
|
description = "The address to bind the REST server to.";
|
|
|
|
};
|
|
|
|
port = mkOption {
|
|
|
|
type = types.int;
|
|
|
|
default = defaults.bind.port;
|
|
|
|
description = "The port to bind the REST server";
|
|
|
|
};
|
|
|
|
};
|
|
|
|
});
|
|
|
|
default = defaults.bind;
|
|
|
|
description = "Address and port bind the rest server.";
|
|
|
|
};
|
|
|
|
|
2022-03-18 23:19:27 +00:00
|
|
|
server-options = mkOption {
|
2022-11-28 21:45:34 +00:00
|
|
|
type = types.submodule ({
|
2022-03-18 23:19:27 +00:00
|
|
|
options = {
|
|
|
|
enable-http-2 = mkOption {
|
|
|
|
type = types.bool;
|
|
|
|
default = defaults.server-options.enable-http-2;
|
|
|
|
description = "Whether to enable http2";
|
|
|
|
};
|
|
|
|
max-connections = mkOption {
|
|
|
|
type = types.int;
|
|
|
|
default = defaults.server-options.max-connections;
|
|
|
|
description = "Maximum number of client connections";
|
|
|
|
};
|
|
|
|
response-timeout = mkOption {
|
|
|
|
type = types.str;
|
|
|
|
default = defaults.server-options.response-timeout;
|
|
|
|
description = "Timeout when waiting for the response.";
|
|
|
|
};
|
|
|
|
};
|
|
|
|
});
|
|
|
|
default = defaults.server-options;
|
|
|
|
description = "Tuning the http server";
|
|
|
|
};
|
|
|
|
|
2022-02-19 22:37:45 +00:00
|
|
|
logging = mkOption {
|
2022-11-28 21:45:34 +00:00
|
|
|
type = types.submodule ({
|
2022-02-19 22:37:45 +00:00
|
|
|
options = {
|
|
|
|
minimum-level = mkOption {
|
|
|
|
type = types.str;
|
|
|
|
default = defaults.logging.minimum-level;
|
|
|
|
description = "The minimum level for logging to control verbosity.";
|
|
|
|
};
|
|
|
|
format = mkOption {
|
|
|
|
type = types.str;
|
|
|
|
default = defaults.logging.format;
|
|
|
|
description = "The log format. One of: Fancy, Plain, Json or Logfmt";
|
|
|
|
};
|
2022-05-21 20:02:42 +00:00
|
|
|
levels = mkOption {
|
|
|
|
type = types.attrs;
|
|
|
|
default = defaults.logging.levels;
|
|
|
|
description = "Set of logger and their levels";
|
|
|
|
};
|
2022-02-19 22:37:45 +00:00
|
|
|
};
|
|
|
|
});
|
|
|
|
default = defaults.logging;
|
|
|
|
description = "Settings for logging";
|
|
|
|
};
|
|
|
|
|
2020-01-19 21:53:58 +00:00
|
|
|
auth = mkOption {
|
2022-11-28 21:45:34 +00:00
|
|
|
type = types.submodule ({
|
2020-01-19 21:53:58 +00:00
|
|
|
options = {
|
|
|
|
server-secret = mkOption {
|
|
|
|
type = types.str;
|
|
|
|
default = defaults.auth.server-secret;
|
|
|
|
description = ''
|
|
|
|
The secret for this server that is used to sign the authenicator
|
|
|
|
tokens. If multiple servers are running, all must share the same
|
|
|
|
secret. You can use base64 or hex strings (prefix with b64: and
|
|
|
|
hex:, respectively).
|
|
|
|
'';
|
|
|
|
};
|
|
|
|
session-valid = mkOption {
|
|
|
|
type = types.str;
|
|
|
|
default = defaults.auth.session-valid;
|
|
|
|
description = ''
|
|
|
|
How long an authentication token is valid. The web application
|
|
|
|
will get a new one periodically.
|
|
|
|
'';
|
2020-12-14 13:51:56 +00:00
|
|
|
};
|
|
|
|
remember-me = mkOption {
|
2022-11-28 21:45:34 +00:00
|
|
|
type = types.submodule ({
|
2020-12-14 13:51:56 +00:00
|
|
|
options = {
|
|
|
|
enabled = mkOption {
|
|
|
|
type = types.bool;
|
|
|
|
default = defaults.auth.remember-me.enabled;
|
|
|
|
description = "Whether to enable remember me.";
|
|
|
|
};
|
|
|
|
valid = mkOption {
|
|
|
|
type = types.str;
|
|
|
|
default = defaults.auth.remember-me.valid;
|
|
|
|
description = "The time a remember-me token is valid.";
|
|
|
|
};
|
|
|
|
};
|
|
|
|
});
|
|
|
|
default = defaults.auth.remember-me;
|
|
|
|
description = "Settings for Remember-Me";
|
2020-01-19 21:53:58 +00:00
|
|
|
};
|
|
|
|
};
|
|
|
|
});
|
|
|
|
default = defaults.auth;
|
|
|
|
description = "Authentication";
|
|
|
|
};
|
|
|
|
|
2022-04-11 18:53:48 +00:00
|
|
|
download-all = mkOption {
|
2022-11-28 21:45:34 +00:00
|
|
|
type = types.submodule ({
|
2022-04-11 18:53:48 +00:00
|
|
|
options = {
|
|
|
|
max-files = mkOption {
|
|
|
|
type = types.int;
|
|
|
|
default = defaults.download-all.max-files;
|
|
|
|
description = "How many files to allow in a zip.";
|
|
|
|
};
|
|
|
|
max-size = mkOption {
|
|
|
|
type = types.str;
|
|
|
|
default = defaults.download-all.max-size;
|
|
|
|
description = "The maximum (uncompressed) size of the zip file contents.";
|
|
|
|
};
|
|
|
|
};
|
|
|
|
});
|
|
|
|
default = defaults.download-all;
|
|
|
|
description = "";
|
|
|
|
};
|
|
|
|
|
2021-09-06 12:25:10 +00:00
|
|
|
openid = mkOption {
|
|
|
|
type = types.listOf (types.submodule {
|
|
|
|
options = {
|
|
|
|
enabled = mkOption {
|
|
|
|
type = types.bool;
|
|
|
|
default = defaults.openid.enabled;
|
|
|
|
description = "Whether to use these settings.";
|
|
|
|
};
|
|
|
|
display = mkOption {
|
|
|
|
type = types.str;
|
|
|
|
default = defaults.openid.display;
|
|
|
|
example = "via Keycloak";
|
|
|
|
description = "The name for the button on the login page.";
|
|
|
|
};
|
|
|
|
user-key = mkOption {
|
|
|
|
type = types.str;
|
|
|
|
default = defaults.openid.user-key;
|
|
|
|
description = "The key to retrieve the username";
|
|
|
|
};
|
|
|
|
collective-key = mkOption {
|
|
|
|
type = types.str;
|
|
|
|
default = defaults.openid.collective-key;
|
|
|
|
description = "How to retrieve the collective name.";
|
|
|
|
};
|
|
|
|
provider = mkOption {
|
|
|
|
type = (types.submodule {
|
|
|
|
options = {
|
|
|
|
provider-id = mkOption {
|
|
|
|
type = types.str;
|
|
|
|
default = defaults.openid.provider.provider-id;
|
|
|
|
example = "keycloak";
|
|
|
|
description = "The id of the provider, used in the URL and to distinguish other providers.";
|
|
|
|
};
|
|
|
|
client-id = mkOption {
|
|
|
|
type = types.str;
|
|
|
|
default = defaults.openid.provider.client-id;
|
|
|
|
description = "The client-id as registered at the OP.";
|
|
|
|
};
|
|
|
|
client-secret = mkOption {
|
|
|
|
type = types.str;
|
|
|
|
default = defaults.openid.provider.client-secret;
|
|
|
|
description = "The client-secret as registered at the OP.";
|
|
|
|
};
|
|
|
|
scope = mkOption {
|
|
|
|
type = types.str;
|
|
|
|
default = defaults.openid.provider.scope;
|
|
|
|
description = "A scope to define what data to return from OP";
|
|
|
|
};
|
|
|
|
authorize-url = mkOption {
|
|
|
|
type = types.str;
|
|
|
|
default = defaults.openid.provider.authorize-url;
|
|
|
|
description = "The URL used to authenticate the user";
|
|
|
|
};
|
|
|
|
token-url = mkOption {
|
|
|
|
type = types.str;
|
|
|
|
default = defaults.openid.provider.token-url;
|
|
|
|
description = "The URL used to retrieve the token.";
|
|
|
|
};
|
|
|
|
user-url = mkOption {
|
2022-05-21 20:02:42 +00:00
|
|
|
type = types.nullOr types.str;
|
2021-09-06 12:25:10 +00:00
|
|
|
default = defaults.openid.provider.user-url;
|
|
|
|
description = "The URL to the user-info endpoint.";
|
|
|
|
};
|
|
|
|
sign-key = mkOption {
|
|
|
|
type = types.str;
|
|
|
|
default = defaults.openid.provider.sign-key;
|
|
|
|
description = "The key for verifying the jwt signature.";
|
|
|
|
};
|
|
|
|
sig-algo = mkOption {
|
|
|
|
type = types.str;
|
|
|
|
default = defaults.openid.provider.sig-algo;
|
|
|
|
description = "The expected algorithm used to sign the token.";
|
|
|
|
};
|
|
|
|
};
|
|
|
|
});
|
|
|
|
default = defaults.openid.provider;
|
|
|
|
description = "The config for an OpenID Connect provider.";
|
|
|
|
};
|
|
|
|
};
|
|
|
|
});
|
2022-11-28 21:45:34 +00:00
|
|
|
default = [ ];
|
2021-09-06 12:25:10 +00:00
|
|
|
description = "A list of OIDC provider configurations.";
|
|
|
|
};
|
|
|
|
|
2020-05-25 13:32:03 +00:00
|
|
|
integration-endpoint = mkOption {
|
2022-11-28 21:45:34 +00:00
|
|
|
type = types.submodule ({
|
2020-05-25 13:32:03 +00:00
|
|
|
options = {
|
|
|
|
enabled = mkOption {
|
|
|
|
type = types.bool;
|
|
|
|
default = defaults.integration-endpoint.enabled;
|
|
|
|
description = "Whether the endpoint is globally enabled or disabled.";
|
|
|
|
};
|
|
|
|
priority = mkOption {
|
|
|
|
type = types.str;
|
|
|
|
default = defaults.integration-endpoint.priority;
|
|
|
|
description = "The priority to use when submitting files through this endpoint.";
|
|
|
|
};
|
2020-10-26 21:35:25 +00:00
|
|
|
source-name = mkOption {
|
|
|
|
type = types.str;
|
|
|
|
default = defaults.integration-endpoint.source-name;
|
|
|
|
description = ''
|
|
|
|
The name used for the item "source" property when uploaded through this endpoint.
|
|
|
|
'';
|
|
|
|
};
|
2020-05-25 13:32:03 +00:00
|
|
|
allowed-ips = mkOption {
|
2022-11-28 21:45:34 +00:00
|
|
|
type = types.submodule ({
|
2020-05-25 13:32:03 +00:00
|
|
|
options = {
|
|
|
|
enabled = mkOption {
|
|
|
|
type = types.bool;
|
|
|
|
default = defaults.integration-endpoint.allowed-ips.enabled;
|
|
|
|
description = "Enable/Disable this protection";
|
|
|
|
};
|
|
|
|
ips = mkOption {
|
|
|
|
type = types.listOf types.str;
|
|
|
|
default = defaults.integration-endpoint.allowed-ips.ips;
|
|
|
|
description = "The ips/ip patterns to allow";
|
|
|
|
};
|
|
|
|
};
|
|
|
|
});
|
|
|
|
default = defaults.integration-endpoint.allowed-ips;
|
|
|
|
description = ''
|
|
|
|
IPv4 addresses to allow access. An empty list, if enabled,
|
|
|
|
prohibits all requests. IP addresses may be specified as simple
|
|
|
|
globs: a part marked as `*' matches any octet, like in
|
|
|
|
`192.168.*.*`. The `127.0.0.1' (the default) matches the
|
|
|
|
loopback address.
|
|
|
|
'';
|
|
|
|
};
|
|
|
|
http-basic = mkOption {
|
2022-11-28 21:45:34 +00:00
|
|
|
type = types.submodule ({
|
2020-05-25 13:32:03 +00:00
|
|
|
options = {
|
|
|
|
enabled = mkOption {
|
|
|
|
type = types.bool;
|
|
|
|
default = defaults.integration-endpoint.http-basic.enabled;
|
|
|
|
description = "Enable/Disable this protection";
|
|
|
|
};
|
|
|
|
realm = mkOption {
|
|
|
|
type = types.str;
|
|
|
|
default = defaults.integration-endpoint.http-basic.realm;
|
|
|
|
description = "The realm name to provide to the client.";
|
|
|
|
};
|
|
|
|
user = mkOption {
|
|
|
|
type = types.str;
|
|
|
|
default = defaults.integration-endpoint.http-basic.user;
|
|
|
|
description = "The user name to check.";
|
|
|
|
};
|
|
|
|
password = mkOption {
|
|
|
|
type = types.str;
|
|
|
|
default = defaults.integration-endpoint.http-basic.password;
|
|
|
|
description = "The password to check.";
|
|
|
|
};
|
|
|
|
};
|
|
|
|
});
|
|
|
|
default = defaults.integration-endpoint.http-basic;
|
|
|
|
description = ''
|
|
|
|
Requests are expected to use http basic auth when uploading files.
|
|
|
|
'';
|
|
|
|
};
|
|
|
|
http-header = mkOption {
|
2022-11-28 21:45:34 +00:00
|
|
|
type = types.submodule ({
|
2020-05-25 13:32:03 +00:00
|
|
|
options = {
|
|
|
|
enabled = mkOption {
|
|
|
|
type = types.bool;
|
|
|
|
default = defaults.integration-endpoint.http-header.enabled;
|
|
|
|
description = "Enable/Disable this protection";
|
|
|
|
};
|
|
|
|
header-name = mkOption {
|
|
|
|
type = types.str;
|
|
|
|
default = defaults.integration-endpoint.http-header.header-name;
|
|
|
|
description = "The header to extract from the request.";
|
|
|
|
};
|
|
|
|
header-value = mkOption {
|
|
|
|
type = types.str;
|
|
|
|
default = defaults.integration-endpoint.http-basic.header-value;
|
|
|
|
description = "The value of the header to check.";
|
|
|
|
};
|
|
|
|
};
|
|
|
|
});
|
|
|
|
default = defaults.integration-endpoint.http-header;
|
|
|
|
description = ''
|
|
|
|
Requests are expected to supply some specific header when
|
|
|
|
uploading files.
|
|
|
|
'';
|
|
|
|
};
|
|
|
|
};
|
|
|
|
});
|
|
|
|
default = defaults.integration-endpoint;
|
|
|
|
description = ''
|
|
|
|
This endpoint allows to upload files to any collective. The
|
|
|
|
intention is that local software integrates with docspell more
|
|
|
|
easily. Therefore the endpoint is not protected by the usual
|
|
|
|
means.
|
|
|
|
|
|
|
|
For security reasons, this endpoint is disabled by default. If
|
|
|
|
enabled, you can choose from some ways to protect it. It may be a
|
|
|
|
good idea to further protect this endpoint using a firewall, such
|
|
|
|
that outside traffic is not routed.
|
|
|
|
|
|
|
|
NOTE: If all protection methods are disabled, the endpoint is not
|
|
|
|
protected at all!
|
|
|
|
'';
|
|
|
|
};
|
|
|
|
|
2021-01-04 14:16:32 +00:00
|
|
|
admin-endpoint = mkOption {
|
2022-11-28 21:45:34 +00:00
|
|
|
type = types.submodule ({
|
2021-01-04 14:16:32 +00:00
|
|
|
options = {
|
|
|
|
secret = mkOption {
|
|
|
|
type = types.str;
|
|
|
|
default = defaults.admin-endpoint.secret;
|
|
|
|
description = "The secret used to call admin endpoints.";
|
|
|
|
};
|
|
|
|
};
|
|
|
|
});
|
|
|
|
default = defaults.admin-endpoint;
|
|
|
|
description = "An endpoint for administration tasks.";
|
|
|
|
};
|
|
|
|
|
2020-06-25 21:56:44 +00:00
|
|
|
full-text-search = mkOption {
|
2022-11-28 21:45:34 +00:00
|
|
|
type = types.submodule ({
|
2020-06-25 21:56:44 +00:00
|
|
|
options = {
|
|
|
|
enabled = mkOption {
|
|
|
|
type = types.bool;
|
|
|
|
default = defaults.full-text-search.enabled;
|
|
|
|
description = ''
|
|
|
|
The full-text search feature can be disabled. It requires an
|
|
|
|
additional index server which needs additional memory and disk
|
|
|
|
space. It can be enabled later any time.
|
|
|
|
'';
|
|
|
|
};
|
2022-04-13 07:32:55 +00:00
|
|
|
backend = mkOption {
|
|
|
|
type = types.str;
|
|
|
|
default = defaults.full-text-search.backend;
|
|
|
|
description = "The backend to use, either solr or postgresql";
|
|
|
|
};
|
2020-06-25 21:56:44 +00:00
|
|
|
solr = mkOption {
|
2022-11-28 21:45:34 +00:00
|
|
|
type = types.submodule ({
|
2020-06-25 21:56:44 +00:00
|
|
|
options = {
|
|
|
|
url = mkOption {
|
|
|
|
type = types.str;
|
|
|
|
default = defaults.full-text-search.solr.url;
|
|
|
|
description = "The URL to solr";
|
|
|
|
};
|
|
|
|
commit-within = mkOption {
|
|
|
|
type = types.int;
|
|
|
|
default = defaults.full-text-search.solr.commit-within;
|
|
|
|
description = "Used to tell solr when to commit the data";
|
|
|
|
};
|
|
|
|
log-verbose = mkOption {
|
|
|
|
type = types.bool;
|
|
|
|
default = defaults.full-text-search.solr.log-verbose;
|
|
|
|
description = "If true, logs request and response bodies";
|
|
|
|
};
|
|
|
|
def-type = mkOption {
|
|
|
|
type = types.str;
|
|
|
|
default = defaults.full-text-search.solr.def-type;
|
|
|
|
description = ''
|
|
|
|
The defType parameter to lucene that defines the parser to
|
|
|
|
use. You might want to try "edismax" or look here:
|
2021-05-31 11:25:57 +00:00
|
|
|
https://solr.apache.org/guide/8_4/query-syntax-and-parsing.html#query-syntax-and-parsing
|
2020-06-25 21:56:44 +00:00
|
|
|
'';
|
|
|
|
};
|
|
|
|
q-op = mkOption {
|
|
|
|
type = types.str;
|
|
|
|
default = defaults.full-text-search.solr.q-op;
|
|
|
|
description = "The default combiner for tokens. One of {AND, OR}.";
|
|
|
|
};
|
|
|
|
};
|
|
|
|
});
|
|
|
|
default = defaults.full-text-search.solr;
|
|
|
|
description = "Configuration for the SOLR backend.";
|
|
|
|
};
|
2022-03-21 13:58:15 +00:00
|
|
|
|
|
|
|
postgresql = mkOption {
|
2022-11-28 21:45:34 +00:00
|
|
|
type = types.submodule ({
|
2022-03-21 13:58:15 +00:00
|
|
|
options = {
|
|
|
|
use-default-connection = mkOption {
|
|
|
|
type = types.bool;
|
|
|
|
default = defaults.full-text-search.postgresql.use-default-connection;
|
|
|
|
description = "Whether to use the primary db connection.";
|
|
|
|
};
|
|
|
|
jdbc = mkOption {
|
|
|
|
type = types.submodule ({
|
|
|
|
options = {
|
|
|
|
url = mkOption {
|
|
|
|
type = types.str;
|
|
|
|
default = defaults.jdbc.url;
|
|
|
|
description = ''
|
|
|
|
The URL to the database.
|
|
|
|
'';
|
|
|
|
};
|
|
|
|
user = mkOption {
|
|
|
|
type = types.str;
|
|
|
|
default = defaults.jdbc.user;
|
|
|
|
description = "The user name to connect to the database.";
|
|
|
|
};
|
|
|
|
password = mkOption {
|
|
|
|
type = types.str;
|
|
|
|
default = defaults.jdbc.password;
|
|
|
|
description = "The password to connect to the database.";
|
|
|
|
};
|
|
|
|
};
|
|
|
|
});
|
|
|
|
default = defaults.full-text-search.postgresql.jdbc;
|
|
|
|
description = "Database connection settings";
|
|
|
|
};
|
|
|
|
pg-config = mkOption {
|
|
|
|
type = types.attrs;
|
|
|
|
default = defaults.full-text-search.postgresql.pg-config;
|
|
|
|
description = "";
|
|
|
|
};
|
|
|
|
pg-query-parser = mkOption {
|
|
|
|
type = types.str;
|
|
|
|
default = defaults.full-text-search.postgresql.pg-query-parser;
|
|
|
|
description = "";
|
|
|
|
};
|
|
|
|
pg-rank-normalization = mkOption {
|
|
|
|
type = types.listOf types.int;
|
|
|
|
default = defaults.full-text-search.postgresql.pg-rank-normalization;
|
|
|
|
description = "";
|
|
|
|
};
|
|
|
|
};
|
|
|
|
});
|
|
|
|
default = defaults.full-text-search.postgresql;
|
|
|
|
description = "PostgreSQL for fulltext search";
|
|
|
|
};
|
2020-06-25 21:56:44 +00:00
|
|
|
};
|
|
|
|
});
|
|
|
|
default = defaults.full-text-search;
|
|
|
|
description = "Configuration for full-text search.";
|
|
|
|
};
|
|
|
|
|
2020-01-19 21:53:58 +00:00
|
|
|
backend = mkOption {
|
2022-11-28 21:45:34 +00:00
|
|
|
type = types.submodule ({
|
2020-01-19 21:53:58 +00:00
|
|
|
options = {
|
2020-06-13 13:10:00 +00:00
|
|
|
mail-debug = mkOption {
|
|
|
|
type = types.bool;
|
|
|
|
default = defaults.backend.mail-debug;
|
|
|
|
description = ''
|
2022-11-28 21:45:34 +00:00
|
|
|
Enable or disable debugging for e-mail related functionality. This
|
|
|
|
applies to both sending and receiving mails. For security reasons
|
|
|
|
logging is not very extensive on authentication failures. Setting
|
|
|
|
this to true, results in a lot of data printed to stdout.
|
2020-06-13 13:10:00 +00:00
|
|
|
'';
|
|
|
|
};
|
2020-01-19 21:53:58 +00:00
|
|
|
jdbc = mkOption {
|
|
|
|
type = types.submodule ({
|
|
|
|
options = {
|
|
|
|
url = mkOption {
|
|
|
|
type = types.str;
|
|
|
|
default = defaults.backend.jdbc.url;
|
|
|
|
description = ''
|
|
|
|
The URL to the database. By default a file-based database is
|
|
|
|
used. It should also work with mariadb and postgresql.
|
|
|
|
|
|
|
|
Examples:
|
|
|
|
"jdbc:mariadb://192.168.1.172:3306/docspell"
|
|
|
|
"jdbc:postgresql://localhost:5432/docspell"
|
|
|
|
"jdbc:h2:///home/dbs/docspell.db;MODE=PostgreSQL;DATABASE_TO_LOWER=TRUE;AUTO_SERVER=TRUE"
|
|
|
|
|
|
|
|
'';
|
|
|
|
};
|
|
|
|
user = mkOption {
|
|
|
|
type = types.str;
|
|
|
|
default = defaults.backend.jdbc.user;
|
|
|
|
description = "The user name to connect to the database.";
|
|
|
|
};
|
|
|
|
password = mkOption {
|
|
|
|
type = types.str;
|
|
|
|
default = defaults.backend.jdbc.password;
|
|
|
|
description = "The password to connect to the database.";
|
|
|
|
};
|
|
|
|
};
|
|
|
|
});
|
|
|
|
default = defaults.backend.jdbc;
|
|
|
|
description = "Database connection settings";
|
|
|
|
};
|
|
|
|
signup = mkOption {
|
|
|
|
type = types.submodule ({
|
|
|
|
options = {
|
|
|
|
mode = mkOption {
|
|
|
|
type = types.str;
|
|
|
|
default = defaults.backend.signup.mode;
|
|
|
|
description = ''
|
|
|
|
The mode defines if new users can signup or not. It can have
|
|
|
|
three values:
|
|
|
|
|
|
|
|
- open: every new user can sign up
|
|
|
|
- invite: new users can sign up only if they provide a correct
|
|
|
|
invitation key. Invitation keys can be generated by the
|
|
|
|
server.
|
|
|
|
- closed: signing up is disabled.
|
|
|
|
'';
|
|
|
|
};
|
|
|
|
new-invite-password = mkOption {
|
|
|
|
type = types.str;
|
|
|
|
default = defaults.backend.signup.new-invite-password;
|
|
|
|
description = ''
|
|
|
|
If mode == 'invite', a password must be provided to generate
|
|
|
|
invitation keys. It must not be empty.
|
|
|
|
'';
|
|
|
|
};
|
|
|
|
invite-time = mkOption {
|
|
|
|
type = types.str;
|
|
|
|
default = defaults.backend.signup.invite-time;
|
|
|
|
description = ''
|
|
|
|
If mode == 'invite', this is the period an invitation token is
|
|
|
|
considered valid.
|
|
|
|
'';
|
|
|
|
};
|
|
|
|
};
|
|
|
|
});
|
2020-01-22 22:11:02 +00:00
|
|
|
default = defaults.backend.signup;
|
2020-01-19 21:53:58 +00:00
|
|
|
description = "Registration settings";
|
|
|
|
};
|
|
|
|
files = mkOption {
|
2022-11-28 21:45:34 +00:00
|
|
|
type = types.submodule ({
|
2020-01-19 21:53:58 +00:00
|
|
|
options = {
|
|
|
|
chunk-size = mkOption {
|
|
|
|
type = types.int;
|
|
|
|
default = defaults.backend.files.chunk-size;
|
|
|
|
description = ''
|
|
|
|
Defines the chunk size (in bytes) used to store the files.
|
|
|
|
This will affect the memory footprint when uploading and
|
|
|
|
downloading files. At most this amount is loaded into RAM for
|
|
|
|
down- and uploading.
|
|
|
|
|
|
|
|
It also defines the chunk size used for the blobs inside the
|
|
|
|
database.
|
|
|
|
'';
|
|
|
|
};
|
|
|
|
valid-mime-types = mkOption {
|
|
|
|
type = types.listOf types.str;
|
|
|
|
default = defaults.backend.files.valid-mime-types;
|
|
|
|
description = ''
|
|
|
|
The file content types that are considered valid. Docspell
|
|
|
|
will only pass these files to processing. The processing code
|
|
|
|
itself has also checks for which files are supported and which
|
|
|
|
not. This affects the uploading part and is a first check to
|
|
|
|
avoid that 'bad' files get into the system.
|
|
|
|
'';
|
|
|
|
};
|
|
|
|
};
|
|
|
|
});
|
|
|
|
default = defaults.backend.files;
|
2022-11-28 21:45:34 +00:00
|
|
|
description = "Settings for how files are stored.";
|
2020-01-19 21:53:58 +00:00
|
|
|
};
|
2022-05-21 20:02:42 +00:00
|
|
|
addons = mkOption {
|
2022-11-28 21:45:34 +00:00
|
|
|
type = types.submodule ({
|
2022-05-21 20:02:42 +00:00
|
|
|
options = {
|
|
|
|
enabled = mkOption {
|
|
|
|
type = types.bool;
|
|
|
|
default = defaults.backend.addons.enabled;
|
|
|
|
description = "Enable this feature";
|
|
|
|
};
|
|
|
|
allow-impure = mkOption {
|
|
|
|
type = types.bool;
|
|
|
|
default = defaults.backend.addons.allow-impure;
|
|
|
|
description = "Allow impure addons";
|
|
|
|
};
|
|
|
|
allowed-urls = mkOption {
|
|
|
|
type = types.listOf types.str;
|
|
|
|
default = defaults.backend.addons.allowed-urls;
|
|
|
|
description = "Url patterns of addons to be allowed";
|
|
|
|
};
|
|
|
|
denied-urls = mkOption {
|
|
|
|
type = types.listOf types.str;
|
|
|
|
default = defaults.backend.addons.denied-urls;
|
|
|
|
description = "Url patterns to deny to install";
|
|
|
|
};
|
|
|
|
};
|
|
|
|
});
|
|
|
|
default = defaults.backend.addons;
|
|
|
|
description = "Addon config";
|
|
|
|
};
|
2020-01-19 21:53:58 +00:00
|
|
|
};
|
|
|
|
});
|
|
|
|
default = defaults.backend;
|
|
|
|
description = "Configuration for the backend";
|
|
|
|
};
|
2022-12-12 16:25:21 +00:00
|
|
|
extraConfig = mkOption {
|
|
|
|
type = types.attrs;
|
|
|
|
description = "Extra configuration for docspell server. Overwrites values in case of a conflict.";
|
|
|
|
default = { };
|
|
|
|
example = ''
|
|
|
|
{
|
|
|
|
files = {
|
|
|
|
default-store = "minio";
|
|
|
|
stores = {
|
|
|
|
minio = {
|
|
|
|
enabled = true;
|
|
|
|
};
|
|
|
|
};
|
|
|
|
};
|
|
|
|
}
|
|
|
|
'';
|
|
|
|
};
|
2020-01-19 21:53:58 +00:00
|
|
|
};
|
|
|
|
};
|
|
|
|
|
|
|
|
## implementation
|
|
|
|
config = mkIf config.services.docspell-restserver.enable {
|
|
|
|
|
2022-11-28 21:45:34 +00:00
|
|
|
nixpkgs.overlays = [ overlay ];
|
2020-01-19 21:53:58 +00:00
|
|
|
users.users."${user}" = mkIf (cfg.runAs == null) {
|
|
|
|
name = user;
|
2021-06-07 21:35:43 +00:00
|
|
|
isSystemUser = true;
|
2020-03-01 20:34:11 +00:00
|
|
|
createHome = true;
|
|
|
|
home = "/var/docspell";
|
2020-01-19 21:53:58 +00:00
|
|
|
description = "Docspell user";
|
2021-12-21 21:00:09 +00:00
|
|
|
group = user;
|
2020-01-19 21:53:58 +00:00
|
|
|
};
|
2022-11-28 21:45:34 +00:00
|
|
|
users.groups."${user}" = mkIf (cfg.runAs == null) { };
|
2021-12-21 21:00:09 +00:00
|
|
|
|
2020-01-19 21:53:58 +00:00
|
|
|
|
|
|
|
systemd.services.docspell-restserver =
|
2022-11-28 21:45:34 +00:00
|
|
|
let
|
|
|
|
args = builtins.concatStringsSep " " cfg.jvmArgs;
|
|
|
|
cmd = "${pkgs.docspell-server}/bin/docspell-restserver ${args} -- ${configFile}";
|
|
|
|
in
|
|
|
|
{
|
|
|
|
description = "Docspell Rest Server";
|
|
|
|
after = [ "networking.target" ];
|
|
|
|
wantedBy = [ "multi-user.target" ];
|
|
|
|
path = [ pkgs.gawk ];
|
|
|
|
preStart = ''
|
2020-01-19 21:53:58 +00:00
|
|
|
'';
|
|
|
|
|
2022-11-28 21:45:34 +00:00
|
|
|
script =
|
|
|
|
"${pkgs.su}/bin/su -s ${pkgs.bash}/bin/sh ${user} -c \"${cmd}\"";
|
|
|
|
};
|
2020-01-19 21:53:58 +00:00
|
|
|
};
|
|
|
|
}
|