1
0
Fork 1
mirror of https://github.com/NixOS/nixpkgs.git synced 2025-06-08 02:38:11 +09:00

nixos/draupnir: init

Co-authored-by: emilylange <git@emilylange.de>
Co-authored-by: Martin Weinelt <hexa@darmstadt.ccc.de>
Co-authored-by: teutat3s <10206665+teutat3s@users.noreply.github.com>
This commit is contained in:
Rory& 2024-04-25 12:54:37 +00:00 committed by emilylange
parent 7019863e6e
commit 4b153aad5d
No known key found for this signature in database
GPG key ID: 0AD773CE46FD0F87
5 changed files with 331 additions and 0 deletions

View file

@ -749,6 +749,15 @@
"module-services-davis-basic-usage": [
"index.html#module-services-davis-basic-usage"
],
"module-services-draupnir": [
"index.html#module-services-draupnir"
],
"module-services-draupnir-setup": [
"index.html#module-services-draupnir-setup"
],
"module-services-draupnir-setup-ems": [
"index.html#module-services-draupnir-setup-ems"
],
"module-services-castopod": [
"index.html#module-services-castopod"
],

View file

@ -22,6 +22,8 @@
- [Broadcast Box](https://github.com/Glimesh/broadcast-box), a WebRTC broadcast server. Available as [services.broadcast-box](options.html#opt-services.broadcast-box.enable).
- [Draupnir](https://github.com/the-draupnir-project/draupnir), a Matrix moderation bot. Available as [services.draupnir](#opt-services.draupnir.enable).
- [SuiteNumérique Docs](https://github.com/suitenumerique/docs), a collaborative note taking, wiki and documentation web platform and alternative to Notion or Outline. Available as [services.lasuite-docs](#opt-services.lasuite-docs.enable).
## Backward Incompatibilities {#sec-release-25.11-incompatibilities}

View file

@ -757,6 +757,7 @@
./services/matrix/conduit.nix
./services/matrix/continuwuity.nix
./services/matrix/dendrite.nix
./services/matrix/draupnir.nix
./services/matrix/hebbot.nix
./services/matrix/hookshot.nix
./services/matrix/lk-jwt-service.nix

View file

@ -0,0 +1,62 @@
# Draupnir (Matrix Moderation Bot) {#module-services-draupnir}
This chapter will show you how to set up your own, self-hosted
[Draupnir](https://github.com/the-draupnir-project/Draupnir) instance.
As an all-in-one moderation tool, it can protect your server from
malicious invites, spam messages, and whatever else you don't want.
In addition to server-level protection, Draupnir is great for communities
wanting to protect their rooms without having to use their personal
accounts for moderation.
The bot by default includes support for bans, redactions, anti-spam,
server ACLs, room directory changes, room alias transfers, account
deactivation, room shutdown, and more. (This depends on homeserver configuration and implementation.)
See the [README](https://github.com/the-draupnir-project/draupnir#readme)
page and the [Moderator's guide](https://the-draupnir-project.github.io/draupnir-documentation/moderator/setting-up-and-configuring)
for additional instructions on how to setup and use Draupnir.
For [additional settings](#opt-services.draupnir.settings)
see [the default configuration](https://github.com/the-draupnir-project/Draupnir/blob/main/config/default.yaml).
## Draupnir Setup {#module-services-draupnir-setup}
First create a new unencrypted, private room which will be used as the management room for Draupnir.
This is the room in which moderators will interact with Draupnir and where it will log possible errors and debugging information.
You'll need to set this room ID or alias in [services.draupnir.settings.managementRoom](#opt-services.draupnir.settings.managementRoom).
Next, create a new user for Draupnir on your homeserver, if one does not already exist.
The Draupnir Matrix user expects to be free of any rate limiting.
See [Synapse #6286](https://github.com/matrix-org/synapse/issues/6286)
for an example on how to achieve this.
If you want Draupnir to be able to deactivate users, move room aliases, shut down rooms, etc.
you'll need to make the Draupnir user a Matrix server admin.
Now invite the Draupnir user to the management room.
Draupnir will automatically try to join this room on startup.
```nix
{
services.draupnir = {
enable = true;
settings = {
homeserverUrl = "https://matrix.org";
managementRoom = "!yyy:example.org";
};
secrets = {
accessToken = "/path/to/secret/containing/access-token";
};
};
}
```
### Element Matrix Services (EMS) {#module-services-draupnir-setup-ems}
If you are using a managed ["Element Matrix Services (EMS)"](https://ems.element.io/)
server, you will need to consent to the terms and conditions. Upon startup, an error
log entry with a URL to the consent page will be generated.

View file

@ -0,0 +1,257 @@
{
config,
options,
lib,
pkgs,
...
}:
let
cfg = config.services.draupnir;
opt = options.services.draupnir;
format = pkgs.formats.yaml { };
configFile = format.generate "draupnir.yaml" cfg.settings;
inherit (lib)
literalExpression
mkEnableOption
mkOption
mkPackageOption
mkRemovedOptionModule
mkRenamedOptionModule
types
;
in
{
imports = [
# Removed options for those migrating from the Mjolnir module
(mkRenamedOptionModule
[ "services" "draupnir" "dataPath" ]
[ "services" "draupnir" "settings" "dataPath" ]
)
(mkRenamedOptionModule
[ "services" "draupnir" "homeserverUrl" ]
[ "services" "draupnir" "settings" "homeserverUrl" ]
)
(mkRenamedOptionModule
[ "services" "draupnir" "managementRoom" ]
[ "services" "draupnir" "settings" "managementRoom" ]
)
(mkRenamedOptionModule
[ "services" "draupnir" "accessTokenFile" ]
[ "services" "draupnir" "secrets" "accessToken" ]
)
(mkRemovedOptionModule [ "services" "draupnir" "pantalaimon" ] ''
`services.draupnir.pantalaimon.*` has been removed because it depends on the deprecated and vulnerable
libolm library for end-to-end encryption and upstream support for Pantalaimon in Draupnir is limited.
See <https://the-draupnir-project.github.io/draupnir-documentation/bot/encryption> for details.
If you nontheless require E2EE via Pantalaimon, you can configure `services.pantalaimon-headless.instances`
yourself and use that with `services.draupnir.settings.pantalaimon` and `services.draupnir.secrets.pantalaimon.password`.
'')
];
options.services.draupnir = {
enable = mkEnableOption "Draupnir, a moderations bot for Matrix";
package = mkPackageOption pkgs "draupnir" { };
settings = mkOption {
example = literalExpression ''
{
homeserverUrl = "https://matrix.org";
managementRoom = "#moderators:example.org";
autojoinOnlyIfManager = true;
automaticallyRedactForReasons = [ "spam" "advertising" ];
}
'';
description = ''
Free-form settings written to Draupnir's configuration file.
See [Draupnir's default configuration](https://github.com/the-draupnir-project/Draupnir/blob/main/config/default.yaml) for available settings.
'';
default = { };
type = types.submodule {
freeformType = format.type;
options = {
homeserverUrl = mkOption {
type = types.str;
example = "https://matrix.org";
description = ''
Base URL of the Matrix homeserver that provides the Client-Server API.
::: {.note}
When using Pantalaimon, set this to the Pantalaimon URL and
{option}`${opt.settings}.rawHomeserverUrl` to the public URL.
:::
'';
};
rawHomeserverUrl = mkOption {
type = types.str;
example = "https://matrix.org";
default = cfg.settings.homeserverUrl;
defaultText = literalExpression "config.${opt.settings}.homeserverUrl";
description = ''
Public base URL of the Matrix homeserver that provides the Client-Server API when using the Draupnir's
[Report forwarding feature](https://the-draupnir-project.github.io/draupnir-documentation/bot/homeserver-administration#report-forwarding).
::: {.warning}
When using Pantalaimon, do not set this to the Pantalaimon URL!
:::
'';
};
managementRoom = mkOption {
type = types.str;
example = "#moderators:example.org";
description = ''
The room ID or alias where moderators can use the bot's functionality.
The bot has no access controls, so anyone in this room can use the bot - secure this room!
Do not enable end-to-end encryption for this room, unless set up with Pantalaimon.
::: {.warning}
When using a room alias, make sure the alias used is on the local homeserver!
This prevents an issue where the control room becomes undefined when the alias can't be resolved.
:::
'';
};
dataPath = mkOption {
type = types.path;
readOnly = true;
default = "/var/lib/draupnir";
description = ''
The path Draupnir will store its state/data in.
::: {.warning}
This option is read-only.
:::
::: {.note}
If you want to customize where this data is stored, use a bind mount.
:::
'';
};
};
};
};
secrets = {
accessToken = mkOption {
type = types.nullOr types.path;
default = null;
description = ''
File containing the access token for Draupnir's Matrix account
to be used in place of {option}`${opt.settings}.accessToken`.
'';
};
pantalaimon.password = mkOption {
type = types.nullOr types.path;
default = null;
description = ''
File containing the password for Draupnir's Matrix account when used in
conjunction with Pantalaimon to be used in place of
{option}`${opt.settings}.pantalaimon.password`.
::: {.warning}
Take note that upstream has limited Pantalaimon and E2EE support:
<https://the-draupnir-project.github.io/draupnir-documentation/bot/encryption> and
<https://the-draupnir-project.github.io/draupnir-documentation/shared/dogfood#e2ee-support>.
:::
'';
};
web.synapseHTTPAntispam.authorization = mkOption {
type = types.nullOr types.path;
default = null;
description = ''
File containing the secret token when using the Synapse HTTP Antispam module
to be used in place of
{option}`${opt.settings}.web.synapseHTTPAntispam.authorization`.
See <https://the-draupnir-project.github.io/draupnir-documentation/bot/synapse-http-antispam> for details.
'';
};
};
};
config = lib.mkIf cfg.enable {
assertions = [
{
# Removed option for those migrating from the Mjolnir module - mkRemovedOption module does *not* work with submodules.
assertion = !(cfg.settings ? protectedRooms);
message = "Unset ${opt.settings}.protectedRooms, as it is unsupported on Draupnir. Add these rooms via `!draupnir rooms add` instead.";
}
];
systemd.services.draupnir = {
description = "Draupnir - a moderation bot for Matrix";
wants = [
"network-online.target"
"matrix-synapse.service"
"conduit.service"
"dendrite.service"
];
after = [
"network-online.target"
"matrix-synapse.service"
"conduit.service"
"dendrite.service"
];
wantedBy = [ "multi-user.target" ];
startLimitIntervalSec = 0;
serviceConfig = {
ExecStart = toString (
[
(lib.getExe cfg.package)
"--draupnir-config"
configFile
]
++ lib.optionals (cfg.secrets.accessToken != null) [
"--access-token-path"
"%d/access_token"
]
++ lib.optionals (cfg.secrets.pantalaimon.password != null) [
"--pantalaimon-password-path"
"%d/pantalaimon_password"
]
++ lib.optionals (cfg.secrets.web.synapseHTTPAntispam.authorization != null) [
"--http-antispam-authorization-path"
"%d/http_antispam_authorization"
]
);
WorkingDirectory = "/var/lib/draupnir";
StateDirectory = "draupnir";
StateDirectoryMode = "0700";
ProtectHome = true;
PrivateDevices = true;
Restart = "on-failure";
RestartSec = "5s";
DynamicUser = true;
LoadCredential =
lib.optionals (cfg.secrets.accessToken != null) [
"access_token:${cfg.secrets.accessToken}"
]
++ lib.optionals (cfg.secrets.pantalaimon.password != null) [
"pantalaimon_password:${cfg.secrets.pantalaimon.password}"
]
++ lib.optionals (cfg.secrets.web.synapseHTTPAntispam.authorization != null) [
"http_antispam_authorization:${cfg.secrets.web.synapseHTTPAntispam.authorization}"
];
};
};
};
meta = {
doc = ./draupnir.md;
maintainers = with lib.maintainers; [
RorySys
emilylange
];
};
}