{ config, options, lib, pkgs, utils, ... }:
let
json = pkgs.formats.json {};
cfg = config.services.discourse;
opt = options.services.discourse;
# Keep in sync with https://github.com/discourse/discourse_docker/blob/main/image/base/slim.Dockerfile#L5
upstreamPostgresqlVersion = lib.getVersion pkgs.postgresql_13;
postgresqlPackage = if config.services.postgresql.enable then
config.services.postgresql.package
else
pkgs.postgresql;
postgresqlVersion = lib.getVersion postgresqlPackage;
# We only want to create a database if we're actually going to connect to it.
databaseActuallyCreateLocally = cfg.database.createLocally && cfg.database.host == null;
tlsEnabled = cfg.enableACME
|| cfg.sslCertificate != null
|| cfg.sslCertificateKey != null;
in
{
options = {
services.discourse = {
enable = lib.mkEnableOption (lib.mdDoc "Discourse, an open source discussion platform");
package = lib.mkOption {
type = lib.types.package;
default = pkgs.discourse;
apply = p: p.override {
plugins = lib.unique (p.enabledPlugins ++ cfg.plugins);
};
defaultText = lib.literalExpression "pkgs.discourse";
description = lib.mdDoc ''
The discourse package to use.
'';
};
hostname = lib.mkOption {
type = lib.types.str;
default = config.networking.fqdnOrHostName;
defaultText = lib.literalExpression "config.networking.fqdnOrHostName";
example = "discourse.example.com";
description = lib.mdDoc ''
The hostname to serve Discourse on.
'';
};
secretKeyBaseFile = lib.mkOption {
type = with lib.types; nullOr path;
default = null;
example = "/run/keys/secret_key_base";
description = lib.mdDoc ''
The path to a file containing the
`secret_key_base` secret.
Discourse uses `secret_key_base` to encrypt
the cookie store, which contains session data, and to digest
user auth tokens.
Needs to be a 64 byte long string of hexadecimal
characters. You can generate one by running
```
openssl rand -hex 64 >/path/to/secret_key_base_file
```
This should be a string, not a nix path, since nix paths are
copied into the world-readable nix store.
'';
};
sslCertificate = lib.mkOption {
type = with lib.types; nullOr path;
default = null;
example = "/run/keys/ssl.cert";
description = lib.mdDoc ''
The path to the server SSL certificate. Set this to enable
SSL.
'';
};
sslCertificateKey = lib.mkOption {
type = with lib.types; nullOr path;
default = null;
example = "/run/keys/ssl.key";
description = lib.mdDoc ''
The path to the server SSL certificate key. Set this to
enable SSL.
'';
};
enableACME = lib.mkOption {
type = lib.types.bool;
default = cfg.sslCertificate == null && cfg.sslCertificateKey == null;
defaultText = lib.literalMD ''
`true`, unless {option}`services.discourse.sslCertificate`
and {option}`services.discourse.sslCertificateKey` are set.
'';
description = lib.mdDoc ''
Whether an ACME certificate should be used to secure
connections to the server.
'';
};
backendSettings = lib.mkOption {
type = with lib.types; attrsOf (nullOr (oneOf [ str int bool float ]));
default = {};
example = lib.literalExpression ''
{
max_reqs_per_ip_per_minute = 300;
max_reqs_per_ip_per_10_seconds = 60;
max_asset_reqs_per_ip_per_10_seconds = 250;
max_reqs_per_ip_mode = "warn+block";
};
'';
description = lib.mdDoc ''
Additional settings to put in the
{file}`discourse.conf` file.
Look in the
[discourse_defaults.conf](https://github.com/discourse/discourse/blob/master/config/discourse_defaults.conf)
file in the upstream distribution to find available options.
Setting an option to `null` means
“define variable, but leave right-hand side empty”.
'';
};
siteSettings = lib.mkOption {
type = json.type;
default = {};
example = lib.literalExpression ''
{
required = {
title = "My Cats";
site_description = "Discuss My Cats (and be nice plz)";
};
login = {
enable_github_logins = true;
github_client_id = "a2f6dfe838cb3206ce20";
github_client_secret._secret = /run/keys/discourse_github_client_secret;
};
};
'';
description = lib.mdDoc ''
Discourse site settings. These are the settings that can be
changed from the UI. This only defines their default values:
they can still be overridden from the UI.
Available settings can be found by looking in the
[site_settings.yml](https://github.com/discourse/discourse/blob/master/config/site_settings.yml)
file of the upstream distribution. To find a setting's path,
you only need to care about the first two levels; i.e. its
category and name. See the example.
Settings containing secret data should be set to an
attribute set containing the attribute
`_secret` - a string pointing to a file
containing the value the option should be set to. See the
example to get a better picture of this: in the resulting
{file}`config/nixos_site_settings.json` file,
the `login.github_client_secret` key will
be set to the contents of the
{file}`/run/keys/discourse_github_client_secret`
file.
'';
};
admin = {
skipCreate = lib.mkOption {