403c215bdd
Secrets are injected from the environment into the rendered configuration before each startup using envsubst. The test now makes use of this feature for the db password.
954 lines
28 KiB
Nix
954 lines
28 KiB
Nix
{ config, lib, pkgs, ... }:
|
|
|
|
with lib;
|
|
|
|
let
|
|
cfg = config.services.codimd;
|
|
|
|
prettyJSON = conf:
|
|
pkgs.runCommand "codimd-config.json" { preferLocalBuild = true; } ''
|
|
echo '${builtins.toJSON conf}' | ${pkgs.jq}/bin/jq \
|
|
'{production:del(.[]|nulls)|del(.[][]?|nulls)}' > $out
|
|
'';
|
|
in
|
|
{
|
|
options.services.codimd = {
|
|
enable = mkEnableOption "the CodiMD Markdown Editor";
|
|
|
|
groups = mkOption {
|
|
type = types.listOf types.str;
|
|
default = [];
|
|
description = ''
|
|
Groups to which the codimd user should be added.
|
|
'';
|
|
};
|
|
|
|
workDir = mkOption {
|
|
type = types.path;
|
|
default = "/var/lib/codimd";
|
|
description = ''
|
|
Working directory for the CodiMD service.
|
|
'';
|
|
};
|
|
|
|
configuration = {
|
|
debug = mkEnableOption "debug mode";
|
|
domain = mkOption {
|
|
type = types.nullOr types.str;
|
|
default = null;
|
|
example = "codimd.org";
|
|
description = ''
|
|
Domain name for the CodiMD instance.
|
|
'';
|
|
};
|
|
urlPath = mkOption {
|
|
type = types.nullOr types.str;
|
|
default = null;
|
|
example = "/url/path/to/codimd";
|
|
description = ''
|
|
Path under which CodiMD is accessible.
|
|
'';
|
|
};
|
|
host = mkOption {
|
|
type = types.str;
|
|
default = "localhost";
|
|
description = ''
|
|
Address to listen on.
|
|
'';
|
|
};
|
|
port = mkOption {
|
|
type = types.int;
|
|
default = 3000;
|
|
example = "80";
|
|
description = ''
|
|
Port to listen on.
|
|
'';
|
|
};
|
|
path = mkOption {
|
|
type = types.nullOr types.str;
|
|
default = null;
|
|
example = "/run/codimd.sock";
|
|
description = ''
|
|
Specify where a UNIX domain socket should be placed.
|
|
'';
|
|
};
|
|
allowOrigin = mkOption {
|
|
type = types.listOf types.str;
|
|
default = [];
|
|
example = [ "localhost" "codimd.org" ];
|
|
description = ''
|
|
List of domains to whitelist.
|
|
'';
|
|
};
|
|
useSSL = mkOption {
|
|
type = types.bool;
|
|
default = false;
|
|
description = ''
|
|
Enable to use SSL server. This will also enable
|
|
<option>protocolUseSSL</option>.
|
|
'';
|
|
};
|
|
hsts = {
|
|
enable = mkOption {
|
|
type = types.bool;
|
|
default = true;
|
|
description = ''
|
|
Whether to enable HSTS if HTTPS is also enabled.
|
|
'';
|
|
};
|
|
maxAgeSeconds = mkOption {
|
|
type = types.int;
|
|
default = 31536000;
|
|
description = ''
|
|
Max duration for clients to keep the HSTS status.
|
|
'';
|
|
};
|
|
includeSubdomains = mkOption {
|
|
type = types.bool;
|
|
default = true;
|
|
description = ''
|
|
Whether to include subdomains in HSTS.
|
|
'';
|
|
};
|
|
preload = mkOption {
|
|
type = types.bool;
|
|
default = true;
|
|
description = ''
|
|
Whether to allow preloading of the site's HSTS status.
|
|
'';
|
|
};
|
|
};
|
|
csp = mkOption {
|
|
type = types.nullOr types.attrs;
|
|
default = null;
|
|
example = literalExample ''
|
|
{
|
|
enable = true;
|
|
directives = {
|
|
scriptSrc = "trustworthy.scripts.example.com";
|
|
};
|
|
upgradeInsecureRequest = "auto";
|
|
addDefaults = true;
|
|
}
|
|
'';
|
|
description = ''
|
|
Specify the Content Security Policy which is passed to Helmet.
|
|
For configuration details see <link xlink:href="https://helmetjs.github.io/docs/csp/"
|
|
>https://helmetjs.github.io/docs/csp/</link>.
|
|
'';
|
|
};
|
|
protocolUseSSL = mkOption {
|
|
type = types.bool;
|
|
default = false;
|
|
description = ''
|
|
Enable to use TLS for resource paths.
|
|
This only applies when <option>domain</option> is set.
|
|
'';
|
|
};
|
|
urlAddPort = mkOption {
|
|
type = types.bool;
|
|
default = false;
|
|
description = ''
|
|
Enable to add the port to callback URLs.
|
|
This only applies when <option>domain</option> is set
|
|
and only for ports other than 80 and 443.
|
|
'';
|
|
};
|
|
useCDN = mkOption {
|
|
type = types.bool;
|
|
default = false;
|
|
description = ''
|
|
Whether to use CDN resources or not.
|
|
'';
|
|
};
|
|
allowAnonymous = mkOption {
|
|
type = types.bool;
|
|
default = true;
|
|
description = ''
|
|
Whether to allow anonymous usage.
|
|
'';
|
|
};
|
|
allowAnonymousEdits = mkOption {
|
|
type = types.bool;
|
|
default = false;
|
|
description = ''
|
|
Whether to allow guests to edit existing notes with the `freely' permission,
|
|
when <option>allowAnonymous</option> is enabled.
|
|
'';
|
|
};
|
|
allowFreeURL = mkOption {
|
|
type = types.bool;
|
|
default = false;
|
|
description = ''
|
|
Whether to allow note creation by accessing a nonexistent note URL.
|
|
'';
|
|
};
|
|
defaultPermission = mkOption {
|
|
type = types.enum [ "freely" "editable" "limited" "locked" "private" ];
|
|
default = "editable";
|
|
description = ''
|
|
Default permissions for notes.
|
|
This only applies for signed-in users.
|
|
'';
|
|
};
|
|
dbURL = mkOption {
|
|
type = types.nullOr types.str;
|
|
default = null;
|
|
example = ''
|
|
postgres://user:pass@host:5432/dbname
|
|
'';
|
|
description = ''
|
|
Specify which database to use.
|
|
CodiMD supports mysql, postgres, sqlite and mssql.
|
|
See <link xlink:href="https://sequelize.readthedocs.io/en/v3/">
|
|
https://sequelize.readthedocs.io/en/v3/</link> for more information.
|
|
Note: This option overrides <option>db</option>.
|
|
'';
|
|
};
|
|
db = mkOption {
|
|
type = types.attrs;
|
|
default = {};
|
|
example = literalExample ''
|
|
{
|
|
dialect = "sqlite";
|
|
storage = "/var/lib/codimd/db.codimd.sqlite";
|
|
}
|
|
'';
|
|
description = ''
|
|
Specify the configuration for sequelize.
|
|
CodiMD supports mysql, postgres, sqlite and mssql.
|
|
See <link xlink:href="https://sequelize.readthedocs.io/en/v3/">
|
|
https://sequelize.readthedocs.io/en/v3/</link> for more information.
|
|
Note: This option overrides <option>db</option>.
|
|
'';
|
|
};
|
|
sslKeyPath= mkOption {
|
|
type = types.nullOr types.str;
|
|
default = null;
|
|
example = "/var/lib/codimd/codimd.key";
|
|
description = ''
|
|
Path to the SSL key. Needed when <option>useSSL</option> is enabled.
|
|
'';
|
|
};
|
|
sslCertPath = mkOption {
|
|
type = types.nullOr types.str;
|
|
default = null;
|
|
example = "/var/lib/codimd/codimd.crt";
|
|
description = ''
|
|
Path to the SSL cert. Needed when <option>useSSL</option> is enabled.
|
|
'';
|
|
};
|
|
sslCAPath = mkOption {
|
|
type = types.listOf types.str;
|
|
default = [];
|
|
example = [ "/var/lib/codimd/ca.crt" ];
|
|
description = ''
|
|
SSL ca chain. Needed when <option>useSSL</option> is enabled.
|
|
'';
|
|
};
|
|
dhParamPath = mkOption {
|
|
type = types.nullOr types.str;
|
|
default = null;
|
|
example = "/var/lib/codimd/dhparam.pem";
|
|
description = ''
|
|
Path to the SSL dh params. Needed when <option>useSSL</option> is enabled.
|
|
'';
|
|
};
|
|
tmpPath = mkOption {
|
|
type = types.str;
|
|
default = "/tmp";
|
|
description = ''
|
|
Path to the temp directory CodiMD should use.
|
|
Note that <option>serviceConfig.PrivateTmp</option> is enabled for
|
|
the CodiMD systemd service by default.
|
|
(Non-canonical paths are relative to CodiMD's base directory)
|
|
'';
|
|
};
|
|
defaultNotePath = mkOption {
|
|
type = types.nullOr types.str;
|
|
default = "./public/default.md";
|
|
description = ''
|
|
Path to the default Note file.
|
|
(Non-canonical paths are relative to CodiMD's base directory)
|
|
'';
|
|
};
|
|
docsPath = mkOption {
|
|
type = types.nullOr types.str;
|
|
default = "./public/docs";
|
|
description = ''
|
|
Path to the docs directory.
|
|
(Non-canonical paths are relative to CodiMD's base directory)
|
|
'';
|
|
};
|
|
indexPath = mkOption {
|
|
type = types.nullOr types.str;
|
|
default = "./public/views/index.ejs";
|
|
description = ''
|
|
Path to the index template file.
|
|
(Non-canonical paths are relative to CodiMD's base directory)
|
|
'';
|
|
};
|
|
hackmdPath = mkOption {
|
|
type = types.nullOr types.str;
|
|
default = "./public/views/hackmd.ejs";
|
|
description = ''
|
|
Path to the hackmd template file.
|
|
(Non-canonical paths are relative to CodiMD's base directory)
|
|
'';
|
|
};
|
|
errorPath = mkOption {
|
|
type = types.nullOr types.str;
|
|
default = null;
|
|
defaultText = "./public/views/error.ejs";
|
|
description = ''
|
|
Path to the error template file.
|
|
(Non-canonical paths are relative to CodiMD's base directory)
|
|
'';
|
|
};
|
|
prettyPath = mkOption {
|
|
type = types.nullOr types.str;
|
|
default = null;
|
|
defaultText = "./public/views/pretty.ejs";
|
|
description = ''
|
|
Path to the pretty template file.
|
|
(Non-canonical paths are relative to CodiMD's base directory)
|
|
'';
|
|
};
|
|
slidePath = mkOption {
|
|
type = types.nullOr types.str;
|
|
default = null;
|
|
defaultText = "./public/views/slide.hbs";
|
|
description = ''
|
|
Path to the slide template file.
|
|
(Non-canonical paths are relative to CodiMD's base directory)
|
|
'';
|
|
};
|
|
uploadsPath = mkOption {
|
|
type = types.str;
|
|
default = "${cfg.workDir}/uploads";
|
|
defaultText = "/var/lib/codimd/uploads";
|
|
description = ''
|
|
Path under which uploaded files are saved.
|
|
'';
|
|
};
|
|
sessionName = mkOption {
|
|
type = types.str;
|
|
default = "connect.sid";
|
|
description = ''
|
|
Specify the name of the session cookie.
|
|
'';
|
|
};
|
|
sessionSecret = mkOption {
|
|
type = types.nullOr types.str;
|
|
default = null;
|
|
description = ''
|
|
Specify the secret used to sign the session cookie.
|
|
If unset, one will be generated on startup.
|
|
'';
|
|
};
|
|
sessionLife = mkOption {
|
|
type = types.int;
|
|
default = 1209600000;
|
|
description = ''
|
|
Session life time in milliseconds.
|
|
'';
|
|
};
|
|
heartbeatInterval = mkOption {
|
|
type = types.int;
|
|
default = 5000;
|
|
description = ''
|
|
Specify the socket.io heartbeat interval.
|
|
'';
|
|
};
|
|
heartbeatTimeout = mkOption {
|
|
type = types.int;
|
|
default = 10000;
|
|
description = ''
|
|
Specify the socket.io heartbeat timeout.
|
|
'';
|
|
};
|
|
documentMaxLength = mkOption {
|
|
type = types.int;
|
|
default = 100000;
|
|
description = ''
|
|
Specify the maximum document length.
|
|
'';
|
|
};
|
|
email = mkOption {
|
|
type = types.bool;
|
|
default = true;
|
|
description = ''
|
|
Whether to enable email sign-in.
|
|
'';
|
|
};
|
|
allowEmailRegister = mkOption {
|
|
type = types.bool;
|
|
default = true;
|
|
description = ''
|
|
Whether to enable email registration.
|
|
'';
|
|
};
|
|
allowGravatar = mkOption {
|
|
type = types.bool;
|
|
default = true;
|
|
description = ''
|
|
Whether to use gravatar as profile picture source.
|
|
'';
|
|
};
|
|
imageUploadType = mkOption {
|
|
type = types.enum [ "imgur" "s3" "minio" "filesystem" ];
|
|
default = "filesystem";
|
|
description = ''
|
|
Specify where to upload images.
|
|
'';
|
|
};
|
|
minio = mkOption {
|
|
type = types.nullOr (types.submodule {
|
|
options = {
|
|
accessKey = mkOption {
|
|
type = types.str;
|
|
description = ''
|
|
Minio access key.
|
|
'';
|
|
};
|
|
secretKey = mkOption {
|
|
type = types.str;
|
|
description = ''
|
|
Minio secret key.
|
|
'';
|
|
};
|
|
endpoint = mkOption {
|
|
type = types.str;
|
|
description = ''
|
|
Minio endpoint.
|
|
'';
|
|
};
|
|
port = mkOption {
|
|
type = types.int;
|
|
default = 9000;
|
|
description = ''
|
|
Minio listen port.
|
|
'';
|
|
};
|
|
secure = mkOption {
|
|
type = types.bool;
|
|
default = true;
|
|
description = ''
|
|
Whether to use HTTPS for Minio.
|
|
'';
|
|
};
|
|
};
|
|
});
|
|
default = null;
|
|
description = "Configure the minio third-party integration.";
|
|
};
|
|
s3 = mkOption {
|
|
type = types.nullOr (types.submodule {
|
|
options = {
|
|
accessKeyId = mkOption {
|
|
type = types.str;
|
|
description = ''
|
|
AWS access key id.
|
|
'';
|
|
};
|
|
secretAccessKey = mkOption {
|
|
type = types.str;
|
|
description = ''
|
|
AWS access key.
|
|
'';
|
|
};
|
|
region = mkOption {
|
|
type = types.str;
|
|
description = ''
|
|
AWS S3 region.
|
|
'';
|
|
};
|
|
};
|
|
});
|
|
default = null;
|
|
description = "Configure the s3 third-party integration.";
|
|
};
|
|
s3bucket = mkOption {
|
|
type = types.nullOr types.str;
|
|
default = null;
|
|
description = ''
|
|
Specify the bucket name for upload types <literal>s3</literal> and <literal>minio</literal>.
|
|
'';
|
|
};
|
|
allowPDFExport = mkOption {
|
|
type = types.bool;
|
|
default = true;
|
|
description = ''
|
|
Whether to enable PDF exports.
|
|
'';
|
|
};
|
|
imgur.clientId = mkOption {
|
|
type = types.nullOr types.str;
|
|
default = null;
|
|
description = ''
|
|
Imgur API client ID.
|
|
'';
|
|
};
|
|
azure = mkOption {
|
|
type = types.nullOr (types.submodule {
|
|
options = {
|
|
connectionString = mkOption {
|
|
type = types.str;
|
|
description = ''
|
|
Azure Blob Storage connection string.
|
|
'';
|
|
};
|
|
container = mkOption {
|
|
type = types.str;
|
|
description = ''
|
|
Azure Blob Storage container name.
|
|
It will be created if non-existent.
|
|
'';
|
|
};
|
|
};
|
|
});
|
|
default = null;
|
|
description = "Configure the azure third-party integration.";
|
|
};
|
|
oauth2 = mkOption {
|
|
type = types.nullOr (types.submodule {
|
|
options = {
|
|
authorizationURL = mkOption {
|
|
type = types.str;
|
|
description = ''
|
|
Specify the OAuth authorization URL.
|
|
'';
|
|
};
|
|
tokenURL = mkOption {
|
|
type = types.str;
|
|
description = ''
|
|
Specify the OAuth token URL.
|
|
'';
|
|
};
|
|
clientID = mkOption {
|
|
type = types.str;
|
|
description = ''
|
|
Specify the OAuth client ID.
|
|
'';
|
|
};
|
|
clientSecret = mkOption {
|
|
type = types.str;
|
|
description = ''
|
|
Specify the OAuth client secret.
|
|
'';
|
|
};
|
|
};
|
|
});
|
|
default = null;
|
|
description = "Configure the OAuth integration.";
|
|
};
|
|
facebook = mkOption {
|
|
type = types.nullOr (types.submodule {
|
|
options = {
|
|
clientID = mkOption {
|
|
type = types.str;
|
|
description = ''
|
|
Facebook API client ID.
|
|
'';
|
|
};
|
|
clientSecret = mkOption {
|
|
type = types.str;
|
|
description = ''
|
|
Facebook API client secret.
|
|
'';
|
|
};
|
|
};
|
|
});
|
|
default = null;
|
|
description = "Configure the facebook third-party integration";
|
|
};
|
|
twitter = mkOption {
|
|
type = types.nullOr (types.submodule {
|
|
options = {
|
|
consumerKey = mkOption {
|
|
type = types.str;
|
|
description = ''
|
|
Twitter API consumer key.
|
|
'';
|
|
};
|
|
consumerSecret = mkOption {
|
|
type = types.str;
|
|
description = ''
|
|
Twitter API consumer secret.
|
|
'';
|
|
};
|
|
};
|
|
});
|
|
default = null;
|
|
description = "Configure the Twitter third-party integration.";
|
|
};
|
|
github = mkOption {
|
|
type = types.nullOr (types.submodule {
|
|
options = {
|
|
clientID = mkOption {
|
|
type = types.str;
|
|
description = ''
|
|
GitHub API client ID.
|
|
'';
|
|
};
|
|
clientSecret = mkOption {
|
|
type = types.str;
|
|
description = ''
|
|
Github API client secret.
|
|
'';
|
|
};
|
|
};
|
|
});
|
|
default = null;
|
|
description = "Configure the GitHub third-party integration.";
|
|
};
|
|
gitlab = mkOption {
|
|
type = types.nullOr (types.submodule {
|
|
options = {
|
|
baseURL = mkOption {
|
|
type = types.str;
|
|
default = "";
|
|
description = ''
|
|
GitLab API authentication endpoint.
|
|
Only needed for other endpoints than gitlab.com.
|
|
'';
|
|
};
|
|
clientID = mkOption {
|
|
type = types.str;
|
|
description = ''
|
|
GitLab API client ID.
|
|
'';
|
|
};
|
|
clientSecret = mkOption {
|
|
type = types.str;
|
|
description = ''
|
|
GitLab API client secret.
|
|
'';
|
|
};
|
|
scope = mkOption {
|
|
type = types.enum [ "api" "read_user" ];
|
|
default = "api";
|
|
description = ''
|
|
GitLab API requested scope.
|
|
GitLab snippet import/export requires api scope.
|
|
'';
|
|
};
|
|
};
|
|
});
|
|
default = null;
|
|
description = "Configure the GitLab third-party integration.";
|
|
};
|
|
mattermost = mkOption {
|
|
type = types.nullOr (types.submodule {
|
|
options = {
|
|
baseURL = mkOption {
|
|
type = types.str;
|
|
description = ''
|
|
Mattermost authentication endpoint.
|
|
'';
|
|
};
|
|
clientID = mkOption {
|
|
type = types.str;
|
|
description = ''
|
|
Mattermost API client ID.
|
|
'';
|
|
};
|
|
clientSecret = mkOption {
|
|
type = types.str;
|
|
description = ''
|
|
Mattermost API client secret.
|
|
'';
|
|
};
|
|
};
|
|
});
|
|
default = null;
|
|
description = "Configure the Mattermost third-party integration.";
|
|
};
|
|
dropbox = mkOption {
|
|
type = types.nullOr (types.submodule {
|
|
options = {
|
|
clientID = mkOption {
|
|
type = types.str;
|
|
description = ''
|
|
Dropbox API client ID.
|
|
'';
|
|
};
|
|
clientSecret = mkOption {
|
|
type = types.str;
|
|
description = ''
|
|
Dropbox API client secret.
|
|
'';
|
|
};
|
|
appKey = mkOption {
|
|
type = types.str;
|
|
description = ''
|
|
Dropbox app key.
|
|
'';
|
|
};
|
|
};
|
|
});
|
|
default = null;
|
|
description = "Configure the Dropbox third-party integration.";
|
|
};
|
|
google = mkOption {
|
|
type = types.nullOr (types.submodule {
|
|
options = {
|
|
clientID = mkOption {
|
|
type = types.str;
|
|
description = ''
|
|
Google API client ID.
|
|
'';
|
|
};
|
|
clientSecret = mkOption {
|
|
type = types.str;
|
|
description = ''
|
|
Google API client secret.
|
|
'';
|
|
};
|
|
};
|
|
});
|
|
default = null;
|
|
description = "Configure the Google third-party integration.";
|
|
};
|
|
ldap = mkOption {
|
|
type = types.nullOr (types.submodule {
|
|
options = {
|
|
providerName = mkOption {
|
|
type = types.str;
|
|
default = "";
|
|
description = ''
|
|
Optional name to be displayed at login form, indicating the LDAP provider.
|
|
'';
|
|
};
|
|
url = mkOption {
|
|
type = types.str;
|
|
example = "ldap://localhost";
|
|
description = ''
|
|
URL of LDAP server.
|
|
'';
|
|
};
|
|
bindDn = mkOption {
|
|
type = types.str;
|
|
description = ''
|
|
Bind DN for LDAP access.
|
|
'';
|
|
};
|
|
bindCredentials = mkOption {
|
|
type = types.str;
|
|
description = ''
|
|
Bind credentials for LDAP access.
|
|
'';
|
|
};
|
|
searchBase = mkOption {
|
|
type = types.str;
|
|
example = "o=users,dc=example,dc=com";
|
|
description = ''
|
|
LDAP directory to begin search from.
|
|
'';
|
|
};
|
|
searchFilter = mkOption {
|
|
type = types.str;
|
|
example = "(uid={{username}})";
|
|
description = ''
|
|
LDAP filter to search with.
|
|
'';
|
|
};
|
|
searchAttributes = mkOption {
|
|
type = types.listOf types.str;
|
|
example = [ "displayName" "mail" ];
|
|
description = ''
|
|
LDAP attributes to search with.
|
|
'';
|
|
};
|
|
userNameField = mkOption {
|
|
type = types.str;
|
|
default = "";
|
|
description = ''
|
|
LDAP field which is used as the username on CodiMD.
|
|
By default <option>useridField</option> is used.
|
|
'';
|
|
};
|
|
useridField = mkOption {
|
|
type = types.str;
|
|
example = "uid";
|
|
description = ''
|
|
LDAP field which is a unique identifier for users on CodiMD.
|
|
'';
|
|
};
|
|
tlsca = mkOption {
|
|
type = types.str;
|
|
example = "server-cert.pem,root.pem";
|
|
description = ''
|
|
Root CA for LDAP TLS in PEM format.
|
|
'';
|
|
};
|
|
};
|
|
});
|
|
default = null;
|
|
description = "Configure the LDAP integration.";
|
|
};
|
|
saml = mkOption {
|
|
type = types.nullOr (types.submodule {
|
|
options = {
|
|
idpSsoUrl = mkOption {
|
|
type = types.str;
|
|
example = "https://idp.example.com/sso";
|
|
description = ''
|
|
IdP authentication endpoint.
|
|
'';
|
|
};
|
|
idpCert = mkOption {
|
|
type = types.path;
|
|
example = "/path/to/cert.pem";
|
|
description = ''
|
|
Path to IdP certificate file in PEM format.
|
|
'';
|
|
};
|
|
issuer = mkOption {
|
|
type = types.str;
|
|
default = "";
|
|
description = ''
|
|
Optional identity of the service provider.
|
|
This defaults to the server URL.
|
|
'';
|
|
};
|
|
identifierFormat = mkOption {
|
|
type = types.str;
|
|
default = "urn:oasis:names:tc:SAML:1.1:nameid-format:emailAddress";
|
|
description = ''
|
|
Optional name identifier format.
|
|
'';
|
|
};
|
|
groupAttribute = mkOption {
|
|
type = types.str;
|
|
default = "";
|
|
example = "memberOf";
|
|
description = ''
|
|
Optional attribute name for group list.
|
|
'';
|
|
};
|
|
externalGroups = mkOption {
|
|
type = types.listOf types.str;
|
|
default = [];
|
|
example = [ "Temporary-staff" "External-users" ];
|
|
description = ''
|
|
Excluded group names.
|
|
'';
|
|
};
|
|
requiredGroups = mkOption {
|
|
type = types.listOf types.str;
|
|
default = [];
|
|
example = [ "Hackmd-users" "Codimd-users" ];
|
|
description = ''
|
|
Required group names.
|
|
'';
|
|
};
|
|
attribute = {
|
|
id = mkOption {
|
|
type = types.str;
|
|
default = "";
|
|
description = ''
|
|
Attribute map for `id'.
|
|
Defaults to `NameID' of SAML response.
|
|
'';
|
|
};
|
|
username = mkOption {
|
|
type = types.str;
|
|
default = "";
|
|
description = ''
|
|
Attribute map for `username'.
|
|
Defaults to `NameID' of SAML response.
|
|
'';
|
|
};
|
|
email = mkOption {
|
|
type = types.str;
|
|
default = "";
|
|
description = ''
|
|
Attribute map for `email'.
|
|
Defaults to `NameID' of SAML response if
|
|
<option>identifierFormat</option> has
|
|
the default value.
|
|
'';
|
|
};
|
|
};
|
|
};
|
|
});
|
|
default = null;
|
|
description = "Configure the SAML integration.";
|
|
};
|
|
};
|
|
|
|
|
|
environmentFile = mkOption {
|
|
type = with types; nullOr path;
|
|
default = null;
|
|
example = "/var/lib/codimd/codimd.env";
|
|
description = ''
|
|
Environment file as defined in <citerefentry>
|
|
<refentrytitle>systemd.exec</refentrytitle><manvolnum>5</manvolnum>
|
|
</citerefentry>.
|
|
|
|
Secrets may be passed to the service without adding them to the world-readable
|
|
Nix store, by specifying placeholder variables as the option value in Nix and
|
|
setting these variables accordingly in the environment file.
|
|
|
|
<programlisting>
|
|
# snippet of CodiMD-related config
|
|
services.codimd.configuration.dbURL = "postgres://codimd:\''${DB_PASSWORD}@db-host:5432/codimddb";
|
|
services.codimd.configuration.minio.secretKey = "$MINIO_SECRET_KEY";
|
|
</programlisting>
|
|
|
|
<programlisting>
|
|
# content of the environment file
|
|
DB_PASSWORD=verysecretdbpassword
|
|
MINIO_SECRET_KEY=verysecretminiokey
|
|
</programlisting>
|
|
|
|
Note that this file needs to be available on the host on which
|
|
<literal>CodiMD</literal> is running.
|
|
'';
|
|
};
|
|
};
|
|
|
|
config = mkIf cfg.enable {
|
|
assertions = [
|
|
{ assertion = cfg.configuration.db == {} -> (
|
|
cfg.configuration.dbURL != "" && cfg.configuration.dbURL != null
|
|
);
|
|
message = "Database configuration for CodiMD missing."; }
|
|
];
|
|
users.groups.codimd = {};
|
|
users.users.codimd = {
|
|
description = "CodiMD service user";
|
|
group = "codimd";
|
|
extraGroups = cfg.groups;
|
|
home = cfg.workDir;
|
|
createHome = true;
|
|
isSystemUser = true;
|
|
};
|
|
|
|
systemd.services.codimd = {
|
|
description = "CodiMD Service";
|
|
wantedBy = [ "multi-user.target" ];
|
|
after = [ "networking.target" ];
|
|
preStart = ''
|
|
${pkgs.envsubst}/bin/envsubst \
|
|
-o ${cfg.workDir}/config.json \
|
|
-i ${prettyJSON cfg.configuration}
|
|
'';
|
|
serviceConfig = {
|
|
WorkingDirectory = cfg.workDir;
|
|
ExecStart = "${pkgs.codimd}/bin/codimd";
|
|
EnvironmentFile = mkIf (cfg.environmentFile != null) [ cfg.environmentFile ];
|
|
Environment = [
|
|
"CMD_CONFIG_FILE=${cfg.workDir}/config.json"
|
|
"NODE_ENV=production"
|
|
];
|
|
Restart = "always";
|
|
User = "codimd";
|
|
PrivateTmp = true;
|
|
};
|
|
};
|
|
};
|
|
}
|