From 4fffcb73ec38ee62d63096d3e65a4b3c0ae8b1f3 Mon Sep 17 00:00:00 2001 From: Rory& Date: Thu, 25 Apr 2024 08:25:35 +0000 Subject: [PATCH 01/18] maintainers: add RorySys --- maintainers/maintainer-list.nix | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/maintainers/maintainer-list.nix b/maintainers/maintainer-list.nix index 1f25d3342016e70..c364fbf626c788d 100644 --- a/maintainers/maintainer-list.nix +++ b/maintainers/maintainer-list.nix @@ -17503,6 +17503,13 @@ githubId = 76747196; name = "Robert Rose"; }; + RorySys = { + email = "root@rory.gay"; + github = "TheArcaneBrony"; + githubId = 13570458; + matrix = "@emma:rory.gay"; # preferred + name = "Rory&"; + }; rosehobgoblin = { name = "J. L. Bowden"; github = "rosehobgoblin"; From 1e396ac3f519781e295b1d0dc0dbc3b915ca96ab Mon Sep 17 00:00:00 2001 From: Rory& Date: Thu, 25 Apr 2024 08:45:02 +0000 Subject: [PATCH 02/18] draupnir: init at 2.0.0-beta.4 --- pkgs/by-name/dr/draupnir/hashes.json | 3 + pkgs/by-name/dr/draupnir/package.json | 81 ++++++++++++++++++++++ pkgs/by-name/dr/draupnir/package.nix | 97 +++++++++++++++++++++++++++ pkgs/by-name/dr/draupnir/update.sh | 39 +++++++++++ 4 files changed, 220 insertions(+) create mode 100644 pkgs/by-name/dr/draupnir/hashes.json create mode 100644 pkgs/by-name/dr/draupnir/package.json create mode 100644 pkgs/by-name/dr/draupnir/package.nix create mode 100755 pkgs/by-name/dr/draupnir/update.sh diff --git a/pkgs/by-name/dr/draupnir/hashes.json b/pkgs/by-name/dr/draupnir/hashes.json new file mode 100644 index 000000000000000..f574d7ce11c786a --- /dev/null +++ b/pkgs/by-name/dr/draupnir/hashes.json @@ -0,0 +1,3 @@ +{ + "yarn_offline_cache_hash": "sha256-ofF1TpybxXHuK1lXdiSY2FW4oXFLnME9EwJOMLWPKCw=" +} diff --git a/pkgs/by-name/dr/draupnir/package.json b/pkgs/by-name/dr/draupnir/package.json new file mode 100644 index 000000000000000..52b80ca04b57bb1 --- /dev/null +++ b/pkgs/by-name/dr/draupnir/package.json @@ -0,0 +1,81 @@ +{ + "name": "draupnir", + "version": "2.0.0-beta.4", + "description": "A moderation tool for Matrix", + "main": "lib/index.js", + "repository": "https://github.com/the-draupnir-project/Draupnir.git", + "author": "Gnuxie", + "license": "AFL-3.0", + "private": true, + "scripts": { + "build": "tsc --project test/tsconfig.json && tsc > /dev/null 2>&1", + "postbuild": "yarn describe-version", + "describe-version": "(git describe > version.txt.tmp && mv version.txt.tmp version.txt) || true && rm -f version.txt.tmp", + "remove-tests-from-lib": "rm -rf lib/test/ && cp -r lib/src/* lib/ && rm -rf lib/src/", + "lint": "eslint -c .eslintrc.js src/**/*.ts test/**/*.ts src/**/*.tsx", + "start:dev": "yarn build && node --async-stack-traces lib/index.js", + "test": "ts-mocha --project ./tsconfig.json test/commands/**/*.ts", + "test:integration": "NODE_ENV=harness ts-mocha --async-stack-traces --forbid-only --require test/integration/fixtures.ts --timeout 300000 --project ./tsconfig.json \"test/integration/**/*Test.ts\"", + "test:integration:single": "NODE_ENV=harness npx ts-mocha --require test/integration/fixtures.ts --timeout 300000 --project ./tsconfig.json", + "test:appservice:integration": "NODE_ENV=harness ts-mocha --async-stack-traces --forbid-only --timeout 300000 --project ./tsconfig.json \"test/appservice/integration/**/*Test.ts\"", + "test:appservice:integration:single": "NODE_ENV=harness npx ts-mocha --timeout 300000 --project ./tsconfig.json", + "test:manual": "NODE_ENV=harness ts-node test/integration/manualLaunchScript.ts", + "version": "sed -i '/# version automated/s/[0-9][0-9]*\\.[0-9][0-9]*\\.[0-9][^\"]*/'$npm_package_version'/' synapse_antispam/setup.py && git add synapse_antispam/setup.py && cat synapse_antispam/setup.py" + }, + "devDependencies": { + "@types/better-sqlite3": "^7.6.9", + "@types/config": "^3.3.1", + "@types/crypto-js": "^4.2.2", + "@types/express": "^4.17.21", + "@types/html-to-text": "^8.0.1", + "@types/humanize-duration": "^3.27.1", + "@types/js-yaml": "^4.0.9", + "@types/jsdom": "21.1.6", + "@types/mocha": "^10.0.6", + "@types/nedb": "^1.8.16", + "@types/node": "^20.11.5", + "@types/pg": "^8.6.5", + "@types/request": "^2.48.12", + "@types/shell-quote": "1.7.1", + "@typescript-eslint/eslint-plugin": "^6.19.0", + "@typescript-eslint/parser": "^6.19.0", + "crypto-js": "^4.2.0", + "eslint": "^8.56", + "eslint-plugin-editorconfig": "^4.0.3", + "expect": "^29.7.0", + "mocha": "^10.2.0", + "ts-mocha": "^10.0.0", + "typescript": "^5.3.3", + "typescript-formatter": "^7.2" + }, + "dependencies": { + "@sentry/node": "^7.17.2", + "@sentry/tracing": "^7.17.2", + "@sinclair/typebox": "0.32.29", + "await-lock": "^2.2.2", + "better-sqlite3": "^9.4.3", + "body-parser": "^1.20.2", + "config": "^3.3.9", + "express": "^4.18", + "html-to-text": "^8.0.0", + "humanize-duration": "^3.27.1", + "humanize-duration-ts": "^2.1.1", + "js-yaml": "^4.1.0", + "jsdom": "^24.0.0", + "matrix-appservice-bridge": "^9.0.1", + "matrix-protection-suite": "npm:@gnuxie/matrix-protection-suite@0.22.0", + "matrix-protection-suite-for-matrix-bot-sdk": "npm:@gnuxie/matrix-protection-suite-for-matrix-bot-sdk@0.22.0", + "parse-duration": "^1.0.2", + "pg": "^8.8.0", + "shell-quote": "^1.7.3", + "ulidx": "^2.2.1", + "yaml": "^2.3.2" + }, + "overrides": { + "matrix-bot-sdk": "$@vector-im/matrix-bot-sdk", + "@vector-im/matrix-bot-sdk": "npm:@vector-im/matrix-bot-sdk@^0.6.6-element.1" + }, + "engines": { + "node": ">=18.0.0" + } +} diff --git a/pkgs/by-name/dr/draupnir/package.nix b/pkgs/by-name/dr/draupnir/package.nix new file mode 100644 index 000000000000000..cbc2b29be97b357 --- /dev/null +++ b/pkgs/by-name/dr/draupnir/package.nix @@ -0,0 +1,97 @@ +{ lib +, fetchFromGitHub +, makeWrapper +, nodejs +, matrix-sdk-crypto-nodejs +, mkYarnPackage +, fetchYarnDeps +, nixosTests +}: + +# docs: https://github.com/NixOS/nixpkgs/blob/master/doc/languages-frameworks/javascript.section.md#yarn2nix-javascript-yarn2nix +let + hashesFile = builtins.fromJSON (builtins.readFile ./hashes.json); +in + mkYarnPackage rec { + pname = "draupnir"; + version = "2.0.0-beta.4"; + src = fetchFromGitHub { + owner = "the-draupnir-project"; + repo = "Draupnir"; + rev = "v${version}"; + hash = "sha256-ZbAst3XaTdJxCPsgPc8cAqN0lo6vOvFphqBDjduQ/to="; + }; + + nativeBuildInputs = [ + makeWrapper + ]; + + offlineCache = fetchYarnDeps { + yarnLock = src + "/yarn.lock"; + hash = hashesFile.yarn_offline_cache_hash; + }; + + yarnLock = src + "/yarn.lock"; + packageJSON = ./package.json; + + #prebuild phase + preBuild = '' + # copy built modules to package... + echo "Copying built matrix-sdk-crypto-nodejs modules to package..." + cp -a ${matrix-sdk-crypto-nodejs}/lib/node_modules/* node_modules/ + echo "Adding version.txt..." + mkdir -p deps/draupnir/ + echo "${version}-nix" > deps/draupnir/version.txt + ''; + + buildPhase = '' + echo "Running preBuild" + runHook preBuild + echo "Building..." + yarn --offline --verbose build + echo "Running postBuild..." + runHook postBuild + ''; + + installPhase = '' + runHook preInstall + + mkdir -p $out/share + cp -a . $out/share/draupnir + + makeWrapper ${nodejs}/bin/node $out/bin/draupnir \ + --add-flags $out/share/draupnir/deps/draupnir/lib/index.js + + runHook postInstall + ''; + distPhase = "true"; + + passthru = { + tests = { + inherit (nixosTests) draupnir; + }; + updateScript = ./update.sh; + }; + + meta = with lib; { + description = "A moderation tool for Matrix"; + homepage = "https://github.com/the-draupnir-project/Draupnir"; + longDescription = '' + 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. + + A Synapse module is also available to apply the same rulesets the bot + uses across an entire homeserver. + ''; + license = licenses.afl3; + maintainers = with maintainers; [ RorySys ]; + mainProgram = "draupnir"; + }; + } diff --git a/pkgs/by-name/dr/draupnir/update.sh b/pkgs/by-name/dr/draupnir/update.sh new file mode 100755 index 000000000000000..78842bfcbfc4496 --- /dev/null +++ b/pkgs/by-name/dr/draupnir/update.sh @@ -0,0 +1,39 @@ +#!/usr/bin/env nix-shell +#!nix-shell -i bash -p curl common-updater-scripts coreutils jq prefetch-yarn-deps git + +set -euo pipefail +set -x + +cd "$(git rev-parse --show-toplevel)" + +TMPDIR=$(mktemp -d) + +echo "Getting versions..." +latestVersion="$(curl -sL "https://api.github.com/repos/the-draupnir-project/Draupnir/releases?per_page=1" | jq -r '.[0].tag_name | ltrimstr("v")')" +echo " --> Latest version: ${latestVersion}" +currentVersion=$(nix-instantiate --eval -E "with import ./. {}; draupnir.version or (lib.getVersion draupnir)" | tr -d '"') +echo " --> Current version: ${currentVersion}" +if [[ "$currentVersion" == "$latestVersion" ]]; then + echo "Draupnir is up-to-date: $currentVersion" + exit 0 +else + echo "We are out of date..." +fi + +curl https://raw.githubusercontent.com/the-draupnir-project/Draupnir/v$latestVersion/package.json -o pkgs/by-name/dr/draupnir/package.json + +update-source-version draupnir "$latestVersion" + +# Update yarn offline cache hash +cd $TMPDIR + +curl https://raw.githubusercontent.com/the-draupnir-project/Draupnir/v$latestVersion/yarn.lock -o yarn.lock +TMP_PREFETCH_HASH=`prefetch-yarn-deps yarn.lock` +NEW_YARN_OFFLINE_HASH=`nix hash to-sri --type sha256 $TMP_PREFETCH_HASH` + +cd - +echo "New yarn offline hash: $NEW_YARN_OFFLINE_HASH" + +TMPFILE=$(mktemp) +jq '.yarn_offline_cache_hash = "'$NEW_YARN_OFFLINE_HASH'"' pkgs/by-name/dr/draupnir/hashes.json > $TMPFILE +mv -- "$TMPFILE" pkgs/by-name/dr/draupnir/hashes.json From bbadc5e3f2e99a037c17306dad7e775948bb086c Mon Sep 17 00:00:00 2001 From: Rory& Date: Thu, 25 Apr 2024 12:54:37 +0000 Subject: [PATCH 03/18] nixos/draupnir: init --- nixos/modules/module-list.nix | 1 + nixos/modules/services/matrix/draupnir.md | 80 +++++++ nixos/modules/services/matrix/draupnir.nix | 260 +++++++++++++++++++++ 3 files changed, 341 insertions(+) create mode 100644 nixos/modules/services/matrix/draupnir.md create mode 100644 nixos/modules/services/matrix/draupnir.nix diff --git a/nixos/modules/module-list.nix b/nixos/modules/module-list.nix index 14ff9fd8b68f69f..433a24b95d20e44 100644 --- a/nixos/modules/module-list.nix +++ b/nixos/modules/module-list.nix @@ -682,6 +682,7 @@ ./services/matrix/conduit.nix ./services/matrix/dendrite.nix ./services/matrix/hebbot.nix + ./services/matrix/draupnir.nix ./services/matrix/maubot.nix ./services/matrix/mautrix-facebook.nix ./services/matrix/mautrix-meta.nix diff --git a/nixos/modules/services/matrix/draupnir.md b/nixos/modules/services/matrix/draupnir.md new file mode 100644 index 000000000000000..999787d31246421 --- /dev/null +++ b/nixos/modules/services/matrix/draupnir.md @@ -0,0 +1,80 @@ +# Draupnir (Matrix Moderation Tool) {#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. + +See the [README](https://github.com/the-draupnir-project/draupnir#readme) +page and the [Moderator's guide](https://github.com/the-draupnir-project/Draupnir/blob/main/docs/moderators.md) +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 Room which will be used as a management room for Draupnir. In +this room, Draupnir will log possible errors and debugging information. You'll +need to set this Room-ID in [services.draupnir.settings.managementRoom](#opt-services.draupnir.settings.managementRoom). + +Next, create a new user for Draupnir on your homeserver, if not present already. + +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. + +It is recommended to use [Pantalaimon](https://github.com/matrix-org/pantalaimon), +so your management room can be encrypted. This also applies if you are looking to moderate an encrypted room. + +To enable the Pantalaimon E2E Proxy for draupnir, enable +[services.draupnir.pantalaimon](#opt-services.draupnir.pantalaimon.enable). This will +autoconfigure a new Pantalaimon instance, which will connect to the homeserver +set in [services.draupnir.settings.homeserverUrl](#opt-services.draupnir.settings.homeserverUrl) and Draupnir itself +will be configured to connect to the new Pantalaimon instance. + +``` +{ + services.draupnir = { + enable = true; + pantalaimon = { + enable = true; + username = "draupnir"; + passwordFile = "/run/secrets/draupnir-password"; + options = { + homeserver = "http://localhost:8008"; + ssl = false; + }; + }; + settings = { + managementRoom = "!yyy:domain.tld"; + protectedRooms = [ + "https://matrix.to/#/!xxx:domain.tld" + ]; + }; + }; +} +``` + +### 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. + +## Synapse Antispam Module {#module-services-draupnir-matrix-synapse-antispam} + +Use the Mjolnir Antispam module, Draupnir made no changes here and as such was not packaged. diff --git a/nixos/modules/services/matrix/draupnir.nix b/nixos/modules/services/matrix/draupnir.nix new file mode 100644 index 000000000000000..3367da90eedeadf --- /dev/null +++ b/nixos/modules/services/matrix/draupnir.nix @@ -0,0 +1,260 @@ +{ config, lib, pkgs, utils, ... }: + +let + cfg = config.services.draupnir; + + format = pkgs.formats.yaml {}; + configFile = format.generate "draupnir.yaml" (pkgs.lib.filterAttrsRecursive (name: value: value != null) cfg.settings); +in +{ + #region Options + options.services.draupnir = { + enable = lib.mkEnableOption ("Draupnir, a moderation tool for Matrix"); + + package = lib.mkPackageOption pkgs "draupnir" { }; + + accessTokenFile = lib.mkOption { + type = with lib.types; nullOr path; + default = null; + description = '' + File containing the access token for Draupnir's Matrix account. + Make sure this does not contain newlines if writing manually: `:set noeol nofixeol` for vim or -L for nano. + ''; + }; + + #region Pantalaimon options + pantalaimon = lib.mkOption { + description = '' + `pantalaimon` options (enables E2E Encryption support). + + This will create a `pantalaimon` instance with the name "draupnir". + ''; + default = { }; + type = lib.types.submodule { + options = { + enable = lib.mkEnableOption ('' + pantalaimon, in order to enable E2EE support. + If `true`, accessToken is ignored and the username/password below will be + used instead. The access token of the bot will be stored in /var/lib/draupnir. + ''); + + username = lib.mkOption { + type = lib.types.str; + description = '' + Account name on the Matrix homeserver. + ''; + }; + + passwordFile = lib.mkOption { + type = with lib.types; nullOr path; + default = null; + description = '' + File containing the password for the Matrix account. + Make sure this does not contain newlines if writing manually: `:set noeol nofixeol` for vim or -L for nano. + ''; + }; + + options = lib.mkOption { + type = lib.types.submodule (import ./pantalaimon-options.nix { inherit lib; inherit config; name = "draupnir"; }); + default = { }; + description = '' + Pass through additional options to the `pantalaimon` service. + ''; + }; + }; + }; + }; + #endregion + + #region Draupnir settings + settings = lib.mkOption { + example = lib.literalExpression '' + { + autojoinOnlyIfManager = true; + automaticallyRedactForReasons = [ "spam" "advertising" ]; + } + ''; + description = '' + Draupnir settings (see [Draupnir's default configuration](https://github.com/the-draupnir-project/Draupnir/blob/main/config/default.yaml) for available settings). + These settings will override settings made by the module config. + ''; + default = { }; + type = lib.types.submodule { + freeformType = format.type; + options = { + #region Readonly settings - these settings are not configurable + dataPath = lib.mkOption { + type = lib.types.str; + default = "/var/lib/draupnir"; + readOnly = true; + description = '' + The path where Draupnir stores its data. + + ::: {.note} + If you want to customize where this data is stored, use a bind mount. + ::: + ''; + }; + #endregion + + #region Base settings + homeserverUrl = lib.mkOption { + type = lib.types.str; + + defaultText = '' + URL to the pantalaimon instance, if enabled. Else unset. + ''; + description = '' + Base URL of the Matrix homeserver, that provides the Client-Server API. + If `services.draupnir.pantalaimon.enable` is `true`, this option will become read only. Configure `services.draupnir.pantalaimon.options.homeserver` instead in that case. + The listen address of `pantalaimon` will then become the `homeserverUrl` of `draupnir`. + ''; + }; + + managementRoom = lib.mkOption { + type = lib.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! + + 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. + ''; + }; + + # protectedRooms = lib.mkOption { + # type = lib.types.listOf lib.types.str; + # default = [ ]; + # example = lib.literalExpression '' + # [ + # "https://matrix.to/#/#yourroom:example.org" + # "https://matrix.to/#/#anotherroom:example.org" + # ] + # ''; + # description = '' + # A list of rooms to protect (matrix.to URLs). + # These can also be configured interactively. + + # Note that this option does nothing in Draupnir v2+! + # ''; + # }; + #endregion + }; + }; + }; + #endregion + }; + #endregion + + #region Service configuration + config = lib.mkIf cfg.enable { + assertions = [ + # pantalaimon enabled - use passwordFile instead of accessTokenFile + { + assertion = cfg.pantalaimon.enable -> cfg.pantalaimon.passwordFile != null; + message = "Set services.draupnir.pantailaimon.passwordFile, as it is required in order to use Pantalaimon."; + } + { + assertion = cfg.pantalaimon.enable -> cfg.accessTokenFile == null; + message = "Unset services.draupnir.accessTokenFile, as it has no effect when Pantalaimon is enabled."; + } + + # pantalaimon disabled - use accessTokenFile instead of passwordFile + { + assertion = !cfg.pantalaimon.enable -> cfg.accessTokenFile != null; + message = "Set services.draupnir.accessTokenFile, as it is required in order to use Draupnir witout Pantalaimon."; + } + { + assertion = !cfg.pantalaimon.enable -> cfg.pantalaimon.passwordFile == null; + message = "Unset services.draupnir.pantalaimon.passwordFile, as it has no effect when Pantalaimon is disabled."; + } + + # Removed options for those migrating from the Mjolnir module - mkRemovedOption module does *not* work with submodules. + + # Noop in v2, but should ideally not be used in mjolnir or 1.x either. + { + assertion = (cfg.settings ? protectedRooms) == false; + message = "Unset services.draupnir.settings.protectedRooms, as it is unsupported on Draupnir. Add these rooms via `!draupnir rooms add` instead."; + } + ]; + + warnings = [ ] + # Unsupported but available options + # - Crypto + ++ lib.optionals (cfg.pantalaimon.enable) [ ''Using Draupnir with Pantalaimon is known to break some features, and is thus unsupported. + Encryption support should only be enabled if you require an encrypted management room or use Draupnir in encrypted rooms.'' ] + ++ lib.optionals (cfg.settings ? experimentalRustCrypto && cfg.settings.experimentalRustCrypto) [ ''Using Draupnir with experimental Rust Crypto support is untested and unsupported. + Encryption support should only be enabled if you require an encrypted management room or use Draupnir in encrypted rooms.'' ] + + # - Deprecated options + ++ lib.optionals (cfg.settings ? verboseLogging && cfg.settings.verboseLogging) [ "Verbose logging in Draupnir is deprecated and may be removed in a future version." ] + ; + + services.pantalaimon-headless.instances."draupnir" = lib.mkIf cfg.pantalaimon.enable (cfg.pantalaimon.options); + services.draupnir.settings.homeserverUrl = lib.mkIf cfg.pantalaimon.enable ("http://${config.services.pantalaimon-headless.instances."draupnir".listenAddress}:${toString config.services.pantalaimon-headless.instances."draupnir".listenPort}/"); + services.draupnir.settings.pantalaimon = lib.mkIf cfg.pantalaimon.enable ({ + use = true; + username = cfg.pantalaimon.username; + }); + + systemd.services.draupnir = { + description = "Draupnir - a moderation tool for Matrix"; + requires = lib.optionals (cfg.pantalaimon.enable) [ + "pantalaimon-draupnir.service" + ]; + 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" ]; + + serviceConfig = { + ExecStart = utils.escapeSystemdExecArgs ([ + (lib.getExe cfg.package) + "--draupnir-config" configFile + ] ++ lib.optionals (cfg.pantalaimon.enable && cfg.pantalaimon.passwordFile != null) [ + "--pantalaimon-password-path" + "/run/credentials/draupnir.service/pantalaimon_password" + ] ++ lib.optionals (!cfg.pantalaimon.enable && cfg.accessTokenFile != null) [ + "--access-token-path" + "/run/credentials/draupnir.service/access_token" + ]); + + WorkingDirectory = "/var/lib/draupnir"; + StateDirectory = "draupnir"; + StateDirectoryMode = "0700"; + ProtectSystem = "strict"; + ProtectHome = true; + PrivateTmp = true; + NoNewPrivileges = true; + PrivateDevices = true; + Restart = "on-failure"; + + DynamicUser = true; + LoadCredential = + lib.optionals (cfg.accessTokenFile != null) [ + "access_token:${cfg.accessTokenFile}" + ] + ++ lib.optionals (cfg.pantalaimon.enable && cfg.pantalaimon.passwordFile != null) [ + "pantalaimon_password:${cfg.pantalaimon.passwordFile}" + ]; + }; + }; + }; + #endregion + + meta = { + doc = ./draupnir.md; + maintainers = with lib.maintainers; [ RorySys ]; + }; +} From ee8cbf8fb755b28fbe0c5beed0da462b89775b47 Mon Sep 17 00:00:00 2001 From: Rory& Date: Thu, 25 Apr 2024 12:54:56 +0000 Subject: [PATCH 04/18] draupnir: add tests Co-authored-by: teutat3s <10206665+teutat3s@users.noreply.github.com> --- nixos/tests/all-tests.nix | 1 + nixos/tests/matrix/draupnir.nix | 224 ++++++++++++++++++++++++++++++++ 2 files changed, 225 insertions(+) create mode 100644 nixos/tests/matrix/draupnir.nix diff --git a/nixos/tests/all-tests.nix b/nixos/tests/all-tests.nix index 0852f2350e1dc39..73fdd961047a03b 100644 --- a/nixos/tests/all-tests.nix +++ b/nixos/tests/all-tests.nix @@ -273,6 +273,7 @@ in { domination = handleTest ./domination.nix {}; dovecot = handleTest ./dovecot.nix {}; drawterm = discoverTests (import ./drawterm.nix); + draupnir = handleTest ./matrix/draupnir.nix {}; drbd = handleTest ./drbd.nix {}; dublin-traceroute = handleTest ./dublin-traceroute.nix {}; earlyoom = handleTestOn ["x86_64-linux"] ./earlyoom.nix {}; diff --git a/nixos/tests/matrix/draupnir.nix b/nixos/tests/matrix/draupnir.nix new file mode 100644 index 000000000000000..d3c1fd001b0a1fb --- /dev/null +++ b/nixos/tests/matrix/draupnir.nix @@ -0,0 +1,224 @@ +import ../make-test-python.nix ( + { pkgs, ... }: + let + # Set up SSL certs for Synapse to be happy. + runWithOpenSSL = file: cmd: pkgs.runCommand file + { + buildInputs = [ pkgs.openssl ]; + } + cmd; + + ca_key = runWithOpenSSL "ca-key.pem" "openssl genrsa -out $out 2048"; + ca_pem = runWithOpenSSL "ca.pem" '' + openssl req \ + -x509 -new -nodes -key ${ca_key} \ + -days 10000 -out $out -subj "/CN=snakeoil-ca" + ''; + key = runWithOpenSSL "matrix_key.pem" "openssl genrsa -out $out 2048"; + csr = runWithOpenSSL "matrix.csr" '' + openssl req \ + -new -key ${key} \ + -out $out -subj "/CN=localhost" \ + ''; + cert = runWithOpenSSL "matrix_cert.pem" '' + openssl x509 \ + -req -in ${csr} \ + -CA ${ca_pem} -CAkey ${ca_key} \ + -CAcreateserial -out $out \ + -days 365 + ''; + in + { + name = "draupnir"; + meta = with pkgs.lib; { + maintainers = [ maintainers.RorySys ]; + }; + + nodes = { + homeserver = { pkgs, ... }: { + services.matrix-synapse = { + enable = true; + settings = { + database.name = "sqlite3"; + tls_certificate_path = "${cert}"; + tls_private_key_path = "${key}"; + enable_registration = true; + enable_registration_without_verification = true; + registration_shared_secret = "supersecret-registration"; + + listeners = [ { + # The default but tls=false + bind_addresses = [ + "0.0.0.0" + ]; + port = 8448; + resources = [ { + compress = true; + names = [ "client" ]; + } { + compress = false; + names = [ "federation" ]; + } ]; + tls = false; + type = "http"; + x_forwarded = false; + } ]; + }; + }; + + networking.firewall.allowedTCPPorts = [ 8448 ]; + + environment.systemPackages = [ + (pkgs.writeShellScriptBin "register_draupnir_user" '' + exec ${pkgs.matrix-synapse}/bin/register_new_matrix_user \ + -u draupnir \ + -p draupnir-password \ + --admin \ + --shared-secret supersecret-registration \ + http://localhost:8448 + '' + ) + (pkgs.writeShellScriptBin "register_moderator_user" '' + exec ${pkgs.matrix-synapse}/bin/register_new_matrix_user \ + -u moderator \ + -p moderator-password \ + --no-admin \ + --shared-secret supersecret-registration \ + http://localhost:8448 + '' + ) + ]; + }; + + draupnir = { ... }: { + services.draupnir = { + enable = true; + accessTokenFile = "/tmp/draupnir-access-token"; + settings = { + homeserverUrl = "http://homeserver:8448"; + managementRoom = "#moderators:homeserver"; + }; + }; + environment.systemPackages = [ + (pkgs.writeShellScriptBin "get_draupnir_access_token" '' + exec ${pkgs.curl}/bin/curl \ + -X POST -s \ + -d '{"type":"m.login.password", "user":"draupnir", "password":"draupnir-password"}' \ + http://homeserver:8448/_matrix/client/v3/login \ + | ${pkgs.jq}/bin/jq --join-output '.access_token' \ + > /tmp/draupnir-access-token + '' + ) + ]; + }; + + draupnirpantalaimon = { pkgs, ... }: { + services.draupnir = { + enable = true; + pantalaimon = { + enable = true; + username = "draupnir"; + passwordFile = pkgs.writeText "password.txt" "draupnir-password"; + options = { + # otherwise draupnir tries to connect to ::1, which is not listened by pantalaimon + listenAddress = "127.0.0.1"; + homeserver = "http://homeserver:8448"; + }; + }; + settings = { + managementRoom = "#moderators-encrypted:homeserver"; + }; + }; + }; + + client = { pkgs, ... }: { + environment.systemPackages = [ + (pkgs.writers.writePython3Bin "create_management_rooms_and_invite_draupnir" + { libraries = with pkgs.python3Packages; [ + matrix-nio + ] ++ matrix-nio.optional-dependencies.e2e; + } '' + import asyncio + + from nio import ( + AsyncClient, + EnableEncryptionBuilder + ) + + + async def main() -> None: + client = AsyncClient("http://homeserver:8448", "moderator") + + await client.login("moderator-password") + + room = await client.room_create( + name="Moderators", + alias="moderators", + ) + + encrypted_room = await client.room_create( + name="Moderators-encrypted", + alias="moderators-encrypted", + initial_state=[EnableEncryptionBuilder().as_dict()], + ) + + await client.join(room.room_id) + await client.room_invite(room.room_id, "@draupnir:homeserver") + + await client.join(encrypted_room.room_id) + await client.room_invite(encrypted_room.room_id, "@draupnir:homeserver") + + asyncio.run(main()) + '' + ) + ]; + }; + }; + + testScript = '' + with subtest("start homeserver"): + homeserver.start() + + homeserver.wait_for_unit("matrix-synapse.service") + homeserver.wait_until_succeeds("curl --fail -L http://localhost:8448/") + + with subtest("register users"): + # register draupnir user + homeserver.succeed("register_draupnir_user") + # register moderator user + homeserver.succeed("register_moderator_user") + + with subtest("start draupnir"): + draupnir.start() + + draupnir.wait_until_succeeds("curl --fail -L http://homeserver:8448/") + + draupnir.succeed("get_draupnir_access_token") + + draupnir.wait_for_unit("draupnir.service") + + with subtest("ensure draupnir can be invited to the management rooms"): + client.start() + + client.wait_until_succeeds("curl --fail -L http://homeserver:8448/") + + client.succeed("create_management_rooms_and_invite_draupnir") + + draupnir.wait_for_console_text("Startup complete. Now monitoring rooms") + + with subtest("start draupnirpantalaimon"): + draupnirpantalaimon.start() + + # wait for pantalaimon to be ready + draupnirpantalaimon.wait_for_unit("pantalaimon-draupnir.service") + draupnirpantalaimon.wait_for_unit("draupnir.service") + + draupnirpantalaimon.wait_until_succeeds("curl --fail -L http://localhost:8009/") + + with subtest("ensure draupnir can be invited to the encrypted management room"): + + draupnirpantalaimon.wait_for_console_text("Startup complete. Now monitoring rooms") + ''; + } +) + From 4ac0923953ab0d088f725541a848d1376e2dee76 Mon Sep 17 00:00:00 2001 From: Rory& Date: Mon, 22 Jul 2024 16:12:34 +0000 Subject: [PATCH 05/18] fixup! draupnir: init at 2.0.0-beta.4 - Remove hook call echos --- pkgs/by-name/dr/draupnir/package.nix | 2 -- 1 file changed, 2 deletions(-) diff --git a/pkgs/by-name/dr/draupnir/package.nix b/pkgs/by-name/dr/draupnir/package.nix index cbc2b29be97b357..25c7d47b81db9d5 100644 --- a/pkgs/by-name/dr/draupnir/package.nix +++ b/pkgs/by-name/dr/draupnir/package.nix @@ -45,11 +45,9 @@ in ''; buildPhase = '' - echo "Running preBuild" runHook preBuild echo "Building..." yarn --offline --verbose build - echo "Running postBuild..." runHook postBuild ''; From 4727e58b3d21c75dfad85712088c843abe69c167 Mon Sep 17 00:00:00 2001 From: Rory& Date: Mon, 22 Jul 2024 16:14:10 +0000 Subject: [PATCH 06/18] fixup! draupnir: init at 2.0.0-beta.4 - set fetchYarnDeps name --- pkgs/by-name/dr/draupnir/package.nix | 1 + 1 file changed, 1 insertion(+) diff --git a/pkgs/by-name/dr/draupnir/package.nix b/pkgs/by-name/dr/draupnir/package.nix index 25c7d47b81db9d5..a0161567a90de73 100644 --- a/pkgs/by-name/dr/draupnir/package.nix +++ b/pkgs/by-name/dr/draupnir/package.nix @@ -27,6 +27,7 @@ in ]; offlineCache = fetchYarnDeps { + name = "${pname}-yarn-offline-cache"; yarnLock = src + "/yarn.lock"; hash = hashesFile.yarn_offline_cache_hash; }; From cbdb0279ded7654d323af14034d7967c3382aaf7 Mon Sep 17 00:00:00 2001 From: Rory& Date: Mon, 22 Jul 2024 16:16:08 +0000 Subject: [PATCH 07/18] fixup! nixos/draupnir: init - remove dead code --- nixos/modules/services/matrix/draupnir.nix | 17 ----------------- 1 file changed, 17 deletions(-) diff --git a/nixos/modules/services/matrix/draupnir.nix b/nixos/modules/services/matrix/draupnir.nix index 3367da90eedeadf..fbe27b53ba85688 100644 --- a/nixos/modules/services/matrix/draupnir.nix +++ b/nixos/modules/services/matrix/draupnir.nix @@ -123,23 +123,6 @@ in This prevents an issue where the control room becomes undefined when the alias can't be resolved. ''; }; - - # protectedRooms = lib.mkOption { - # type = lib.types.listOf lib.types.str; - # default = [ ]; - # example = lib.literalExpression '' - # [ - # "https://matrix.to/#/#yourroom:example.org" - # "https://matrix.to/#/#anotherroom:example.org" - # ] - # ''; - # description = '' - # A list of rooms to protect (matrix.to URLs). - # These can also be configured interactively. - - # Note that this option does nothing in Draupnir v2+! - # ''; - # }; #endregion }; }; From 8c6092fbe6a22100747c77aecd39a6b32fc48606 Mon Sep 17 00:00:00 2001 From: Rory& Date: Mon, 22 Jul 2024 16:26:36 +0000 Subject: [PATCH 08/18] fixup! nixos/draupnir: init - Moderation bot, not tool --- nixos/modules/services/matrix/draupnir.nix | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/nixos/modules/services/matrix/draupnir.nix b/nixos/modules/services/matrix/draupnir.nix index fbe27b53ba85688..bd7c8ff9a431ee5 100644 --- a/nixos/modules/services/matrix/draupnir.nix +++ b/nixos/modules/services/matrix/draupnir.nix @@ -9,7 +9,7 @@ in { #region Options options.services.draupnir = { - enable = lib.mkEnableOption ("Draupnir, a moderation tool for Matrix"); + enable = lib.mkEnableOption "Draupnir, a moderation bot for Matrix"; package = lib.mkPackageOption pkgs "draupnir" { }; @@ -183,7 +183,7 @@ in }); systemd.services.draupnir = { - description = "Draupnir - a moderation tool for Matrix"; + description = "Draupnir - a moderation bot for Matrix"; requires = lib.optionals (cfg.pantalaimon.enable) [ "pantalaimon-draupnir.service" ]; From 0ed8bbcbced448a89c997c9b0069173005daca90 Mon Sep 17 00:00:00 2001 From: Rory& Date: Mon, 22 Jul 2024 16:27:38 +0000 Subject: [PATCH 09/18] fixup! nixos/draupnir: init - witout -> without --- nixos/modules/services/matrix/draupnir.nix | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/nixos/modules/services/matrix/draupnir.nix b/nixos/modules/services/matrix/draupnir.nix index bd7c8ff9a431ee5..717cb34b24d47f2 100644 --- a/nixos/modules/services/matrix/draupnir.nix +++ b/nixos/modules/services/matrix/draupnir.nix @@ -147,7 +147,7 @@ in # pantalaimon disabled - use accessTokenFile instead of passwordFile { assertion = !cfg.pantalaimon.enable -> cfg.accessTokenFile != null; - message = "Set services.draupnir.accessTokenFile, as it is required in order to use Draupnir witout Pantalaimon."; + message = "Set services.draupnir.accessTokenFile, as it is required in order to use Draupnir without Pantalaimon."; } { assertion = !cfg.pantalaimon.enable -> cfg.pantalaimon.passwordFile == null; From 65b7effccf117a87616bd0d61784982be11d714b Mon Sep 17 00:00:00 2001 From: Rory& Date: Mon, 22 Jul 2024 16:29:17 +0000 Subject: [PATCH 10/18] fixup! nixos/draupnir: init - clean up null stripping --- nixos/modules/services/matrix/draupnir.nix | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/nixos/modules/services/matrix/draupnir.nix b/nixos/modules/services/matrix/draupnir.nix index 717cb34b24d47f2..60829b4418a0479 100644 --- a/nixos/modules/services/matrix/draupnir.nix +++ b/nixos/modules/services/matrix/draupnir.nix @@ -4,7 +4,7 @@ let cfg = config.services.draupnir; format = pkgs.formats.yaml {}; - configFile = format.generate "draupnir.yaml" (pkgs.lib.filterAttrsRecursive (name: value: value != null) cfg.settings); + configFile = format.generate "draupnir.yaml" (lib.filterAttrsRecursive (_: value: value != null) cfg.settings); in { #region Options From dfc2fb1bbc44140872e242ba7048d1973085ad93 Mon Sep 17 00:00:00 2001 From: Rory& Date: Mon, 22 Jul 2024 19:06:44 +0000 Subject: [PATCH 11/18] fixup! nixos/draupnir: init - move homeserverUrl to global --- nixos/modules/services/matrix/draupnir.nix | 30 +++++++++++----------- 1 file changed, 15 insertions(+), 15 deletions(-) diff --git a/nixos/modules/services/matrix/draupnir.nix b/nixos/modules/services/matrix/draupnir.nix index 60829b4418a0479..12cbe49e379a05d 100644 --- a/nixos/modules/services/matrix/draupnir.nix +++ b/nixos/modules/services/matrix/draupnir.nix @@ -22,6 +22,14 @@ in ''; }; + homeserverUrl = lib.mkOption { + type = lib.types.str; + description = '' + Base URL of the Matrix homeserver, that provides the Client-Server API. + Will be used by either Draupnir directly, or by Pantalaimon, if enabled. + ''; + }; + #region Pantalaimon options pantalaimon = lib.mkOption { description = '' @@ -98,19 +106,6 @@ in #endregion #region Base settings - homeserverUrl = lib.mkOption { - type = lib.types.str; - - defaultText = '' - URL to the pantalaimon instance, if enabled. Else unset. - ''; - description = '' - Base URL of the Matrix homeserver, that provides the Client-Server API. - If `services.draupnir.pantalaimon.enable` is `true`, this option will become read only. Configure `services.draupnir.pantalaimon.options.homeserver` instead in that case. - The listen address of `pantalaimon` will then become the `homeserverUrl` of `draupnir`. - ''; - }; - managementRoom = lib.mkOption { type = lib.types.str; example = "#moderators:example.org"; @@ -153,6 +148,9 @@ in assertion = !cfg.pantalaimon.enable -> cfg.pantalaimon.passwordFile == null; message = "Unset services.draupnir.pantalaimon.passwordFile, as it has no effect when Pantalaimon is disabled."; } + { + assertion = cfg.pantalaimon.enable -> cfg.pantalaimon. + } # Removed options for those migrating from the Mjolnir module - mkRemovedOption module does *not* work with submodules. @@ -175,8 +173,10 @@ in ++ lib.optionals (cfg.settings ? verboseLogging && cfg.settings.verboseLogging) [ "Verbose logging in Draupnir is deprecated and may be removed in a future version." ] ; - services.pantalaimon-headless.instances."draupnir" = lib.mkIf cfg.pantalaimon.enable (cfg.pantalaimon.options); - services.draupnir.settings.homeserverUrl = lib.mkIf cfg.pantalaimon.enable ("http://${config.services.pantalaimon-headless.instances."draupnir".listenAddress}:${toString config.services.pantalaimon-headless.instances."draupnir".listenPort}/"); + services.pantalaimon-headless.instances.draupnir = lib.mkIf cfg.pantalaimon.enable (cfg.pantalaimon.options // { homeserver = cfg.homeserverUrl; }); + services.draupnir.settings.homeserverUrl = if cfg.pantalaimon.enable + then (with config.services.pantalaimon-headless.instances.draupnir; "http://${listenAddress}:${toString listenPort}/") + else cfg.homeserverUrl; services.draupnir.settings.pantalaimon = lib.mkIf cfg.pantalaimon.enable ({ use = true; username = cfg.pantalaimon.username; From e3adb0cb3b193b57bc395d9ef6fed1205e42cda9 Mon Sep 17 00:00:00 2001 From: Rory& Date: Mon, 22 Jul 2024 19:08:09 +0000 Subject: [PATCH 12/18] fixup! nixos/draupnir: init - drop module config reference --- nixos/modules/services/matrix/draupnir.nix | 1 - 1 file changed, 1 deletion(-) diff --git a/nixos/modules/services/matrix/draupnir.nix b/nixos/modules/services/matrix/draupnir.nix index 12cbe49e379a05d..d4df0121c849efd 100644 --- a/nixos/modules/services/matrix/draupnir.nix +++ b/nixos/modules/services/matrix/draupnir.nix @@ -84,7 +84,6 @@ in ''; description = '' Draupnir settings (see [Draupnir's default configuration](https://github.com/the-draupnir-project/Draupnir/blob/main/config/default.yaml) for available settings). - These settings will override settings made by the module config. ''; default = { }; type = lib.types.submodule { From 1fac8d3d339d4cbb0773cecd942e6d6055a85a3a Mon Sep 17 00:00:00 2001 From: Rory& Date: Mon, 22 Jul 2024 19:11:07 +0000 Subject: [PATCH 13/18] fixup! draupnir: add tests - move homeserverUrl --- nixos/tests/matrix/draupnir.nix | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/nixos/tests/matrix/draupnir.nix b/nixos/tests/matrix/draupnir.nix index d3c1fd001b0a1fb..c4d9664da5be4ca 100644 --- a/nixos/tests/matrix/draupnir.nix +++ b/nixos/tests/matrix/draupnir.nix @@ -93,9 +93,9 @@ import ../make-test-python.nix ( draupnir = { ... }: { services.draupnir = { enable = true; + homeserverUrl = "http://homeserver:8448"; accessTokenFile = "/tmp/draupnir-access-token"; settings = { - homeserverUrl = "http://homeserver:8448"; managementRoom = "#moderators:homeserver"; }; }; @@ -115,6 +115,7 @@ import ../make-test-python.nix ( draupnirpantalaimon = { pkgs, ... }: { services.draupnir = { enable = true; + homeserverUrl = "http://homeserver:8448"; pantalaimon = { enable = true; username = "draupnir"; @@ -122,7 +123,6 @@ import ../make-test-python.nix ( options = { # otherwise draupnir tries to connect to ::1, which is not listened by pantalaimon listenAddress = "127.0.0.1"; - homeserver = "http://homeserver:8448"; }; }; settings = { From a13cc66ac9f3522bdfd0bad78552a4b74723fae4 Mon Sep 17 00:00:00 2001 From: Rory& Date: Mon, 22 Jul 2024 19:13:26 +0000 Subject: [PATCH 14/18] fixup! nixos/draupnir: init - remove parial assertion --- nixos/modules/services/matrix/draupnir.nix | 4 ---- 1 file changed, 4 deletions(-) diff --git a/nixos/modules/services/matrix/draupnir.nix b/nixos/modules/services/matrix/draupnir.nix index d4df0121c849efd..6b19a362972b36b 100644 --- a/nixos/modules/services/matrix/draupnir.nix +++ b/nixos/modules/services/matrix/draupnir.nix @@ -147,10 +147,6 @@ in assertion = !cfg.pantalaimon.enable -> cfg.pantalaimon.passwordFile == null; message = "Unset services.draupnir.pantalaimon.passwordFile, as it has no effect when Pantalaimon is disabled."; } - { - assertion = cfg.pantalaimon.enable -> cfg.pantalaimon. - } - # Removed options for those migrating from the Mjolnir module - mkRemovedOption module does *not* work with submodules. # Noop in v2, but should ideally not be used in mjolnir or 1.x either. From 0c8581d42ac159f679a0ce805512ecfdc64e38ed Mon Sep 17 00:00:00 2001 From: Rory& Date: Thu, 8 Aug 2024 02:24:28 +0000 Subject: [PATCH 15/18] fixup! nixos/draupnir: init - Update docs somewhat --- nixos/modules/services/matrix/draupnir.md | 44 +++++++++++++---------- 1 file changed, 25 insertions(+), 19 deletions(-) diff --git a/nixos/modules/services/matrix/draupnir.md b/nixos/modules/services/matrix/draupnir.md index 999787d31246421..e7b42dbe91408c7 100644 --- a/nixos/modules/services/matrix/draupnir.md +++ b/nixos/modules/services/matrix/draupnir.md @@ -1,4 +1,4 @@ -# Draupnir (Matrix Moderation Tool) {#module-services-draupnir} +# 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. @@ -11,10 +11,10 @@ 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. +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://github.com/the-draupnir-project/Draupnir/blob/main/docs/moderators.md) +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) @@ -37,38 +37,42 @@ you'll need to make the Draupnir user a Matrix server admin. Now invite the Draupnir user to the management room. -It is recommended to use [Pantalaimon](https://github.com/matrix-org/pantalaimon), -so your management room can be encrypted. This also applies if you are looking to moderate an encrypted room. +It is not recommended to use End to End Encryption when not needed, +as it is known to break parts of Draupnir. -To enable the Pantalaimon E2E Proxy for draupnir, enable +To enable the Pantalaimon E2EE Proxy for Draupnir, enable [services.draupnir.pantalaimon](#opt-services.draupnir.pantalaimon.enable). This will autoconfigure a new Pantalaimon instance, which will connect to the homeserver -set in [services.draupnir.settings.homeserverUrl](#opt-services.draupnir.settings.homeserverUrl) and Draupnir itself +set in [services.draupnir.homeserverUrl](#opt-services.draupnir.homeserverUrl) and Draupnir itself will be configured to connect to the new Pantalaimon instance. ``` { services.draupnir = { enable = true; - pantalaimon = { - enable = true; - username = "draupnir"; - passwordFile = "/run/secrets/draupnir-password"; - options = { - homeserver = "http://localhost:8008"; - ssl = false; - }; - }; + + # Point this to your reverse proxy, if eg. Synapse's workers are in use! + homeserverUrl = "http://localhost:8008"; + settings = { managementRoom = "!yyy:domain.tld"; - protectedRooms = [ - "https://matrix.to/#/!xxx:domain.tld" - ]; }; }; } ``` +Additional config for Pantalaimon: +``` +pantalaimon = { + enable = true; + username = "draupnir"; + passwordFile = "/run/secrets/draupnir-password"; + options = { + ssl = false; + }; +}; +``` + ### Element Matrix Services (EMS) {#module-services-draupnir-setup-ems} If you are using a managed ["Element Matrix Services (EMS)"](https://ems.element.io/) @@ -78,3 +82,5 @@ log entry with a URL to the consent page will be generated. ## Synapse Antispam Module {#module-services-draupnir-matrix-synapse-antispam} Use the Mjolnir Antispam module, Draupnir made no changes here and as such was not packaged. +It may be possible that the Mjolir Antispam module does *not* work with Draupnir in the future, +nor is the one in the Draupnir repository maintained or tested. From dbf6ae4dd3d87392c4eb691e83962a6a24560e9d Mon Sep 17 00:00:00 2001 From: Rory& Date: Thu, 8 Aug 2024 02:29:55 +0000 Subject: [PATCH 16/18] fixup! draupnir: init at 2.0.0-beta.4 - Add sqlite as native build input --- pkgs/by-name/dr/draupnir/package.nix | 2 ++ 1 file changed, 2 insertions(+) diff --git a/pkgs/by-name/dr/draupnir/package.nix b/pkgs/by-name/dr/draupnir/package.nix index a0161567a90de73..fb2faad56350e9e 100644 --- a/pkgs/by-name/dr/draupnir/package.nix +++ b/pkgs/by-name/dr/draupnir/package.nix @@ -3,6 +3,7 @@ , makeWrapper , nodejs , matrix-sdk-crypto-nodejs +, sqlite , mkYarnPackage , fetchYarnDeps , nixosTests @@ -24,6 +25,7 @@ in nativeBuildInputs = [ makeWrapper + sqlite ]; offlineCache = fetchYarnDeps { From c2a5e05334add4a3b5b0a3a26086339662671d89 Mon Sep 17 00:00:00 2001 From: Rory& Date: Sun, 15 Sep 2024 22:52:35 +0000 Subject: [PATCH 17/18] fixup! draupnir: init at 2.0.0-beta.6 - ugly sed hack to drop corepack Fixes build with corepack upstream introduced by https://github.com/the-draupnir-project/Draupnir/pull/472 Upstream may move to yarn v4, need to investigate options. (https://github.com/the-draupnir-project/Draupnir/issues/475) Looks like the recommended option is to use a fixed-output derivation? Sources: - https://www.reddit.com/r/NixOS/comments/1f8tq94/its_2024_has_anyone_figured_out_how_to_build_a/ - https://github.com/NixOS/nixpkgs/blob/master/pkgs/applications/networking/cluster/tilt/assets.nix --- pkgs/by-name/dr/draupnir/hashes.json | 2 +- pkgs/by-name/dr/draupnir/package.json | 53 +++++++++++++++------------ pkgs/by-name/dr/draupnir/package.nix | 6 ++- 3 files changed, 35 insertions(+), 26 deletions(-) diff --git a/pkgs/by-name/dr/draupnir/hashes.json b/pkgs/by-name/dr/draupnir/hashes.json index f574d7ce11c786a..f8ec73c940a94ee 100644 --- a/pkgs/by-name/dr/draupnir/hashes.json +++ b/pkgs/by-name/dr/draupnir/hashes.json @@ -1,3 +1,3 @@ { - "yarn_offline_cache_hash": "sha256-ofF1TpybxXHuK1lXdiSY2FW4oXFLnME9EwJOMLWPKCw=" + "yarn_offline_cache_hash": "sha256-5h8d8LKE9RIWYckbEITkYBGj5MIfScrFZiVbJXZSf+8=" } diff --git a/pkgs/by-name/dr/draupnir/package.json b/pkgs/by-name/dr/draupnir/package.json index 52b80ca04b57bb1..0c73708386e022d 100644 --- a/pkgs/by-name/dr/draupnir/package.json +++ b/pkgs/by-name/dr/draupnir/package.json @@ -1,6 +1,6 @@ { "name": "draupnir", - "version": "2.0.0-beta.4", + "version": "2.0.0-beta.6", "description": "A moderation tool for Matrix", "main": "lib/index.js", "repository": "https://github.com/the-draupnir-project/Draupnir.git", @@ -9,62 +9,68 @@ "private": true, "scripts": { "build": "tsc --project test/tsconfig.json && tsc > /dev/null 2>&1", - "postbuild": "yarn describe-version", + "postbuild": "corepack yarn describe-version", "describe-version": "(git describe > version.txt.tmp && mv version.txt.tmp version.txt) || true && rm -f version.txt.tmp", "remove-tests-from-lib": "rm -rf lib/test/ && cp -r lib/src/* lib/ && rm -rf lib/src/", - "lint": "eslint -c .eslintrc.js src/**/*.ts test/**/*.ts src/**/*.tsx", - "start:dev": "yarn build && node --async-stack-traces lib/index.js", - "test": "ts-mocha --project ./tsconfig.json test/commands/**/*.ts", - "test:integration": "NODE_ENV=harness ts-mocha --async-stack-traces --forbid-only --require test/integration/fixtures.ts --timeout 300000 --project ./tsconfig.json \"test/integration/**/*Test.ts\"", - "test:integration:single": "NODE_ENV=harness npx ts-mocha --require test/integration/fixtures.ts --timeout 300000 --project ./tsconfig.json", - "test:appservice:integration": "NODE_ENV=harness ts-mocha --async-stack-traces --forbid-only --timeout 300000 --project ./tsconfig.json \"test/appservice/integration/**/*Test.ts\"", - "test:appservice:integration:single": "NODE_ENV=harness npx ts-mocha --timeout 300000 --project ./tsconfig.json", + "lint": "corepack yarn eslint src test && corepack yarn prettier --check src test", + "start:dev": "corepack yarn build && node --async-stack-traces lib/index.js", + "test:unit": "mocha --require './test/tsnode.cjs' --forbid-only 'test/unit/**/*.{ts,tsx}'", + "test:unit:single": "mocha --require test/tsnode.cjs", + "test:integration": "NODE_ENV=harness mocha --require test/tsnode.cjs --async-stack-traces --forbid-only --require test/integration/fixtures.ts --timeout 300000 --project ./tsconfig.json \"test/integration/**/*Test.ts\"", + "test:integration:single": "NODE_ENV=harness corepack yarn mocha --require test/tsnode.cjs --require test/integration/fixtures.ts --timeout 300000 --project ./tsconfig.json", + "test:appservice:integration": "NODE_ENV=harness mocha --require test/tsnode.cjs --async-stack-traces --forbid-only --timeout 300000 --project ./tsconfig.json \"test/appservice/integration/**/*Test.ts\"", + "test:appservice:integration:single": "NODE_ENV=harness corepack yarn mocha --require test/tsnode.cjs --timeout 300000 --project ./tsconfig.json", "test:manual": "NODE_ENV=harness ts-node test/integration/manualLaunchScript.ts", "version": "sed -i '/# version automated/s/[0-9][0-9]*\\.[0-9][0-9]*\\.[0-9][^\"]*/'$npm_package_version'/' synapse_antispam/setup.py && git add synapse_antispam/setup.py && cat synapse_antispam/setup.py" }, "devDependencies": { + "@eslint/js": "^9.7.0", "@types/better-sqlite3": "^7.6.9", "@types/config": "^3.3.1", "@types/crypto-js": "^4.2.2", + "@types/eslint__js": "^8.42.3", "@types/express": "^4.17.21", "@types/html-to-text": "^8.0.1", "@types/humanize-duration": "^3.27.1", "@types/js-yaml": "^4.0.9", "@types/jsdom": "21.1.6", - "@types/mocha": "^10.0.6", + "@types/mocha": "^10.0.7", "@types/nedb": "^1.8.16", - "@types/node": "^20.11.5", + "@types/node": "^20.14.11", "@types/pg": "^8.6.5", "@types/request": "^2.48.12", "@types/shell-quote": "1.7.1", - "@typescript-eslint/eslint-plugin": "^6.19.0", - "@typescript-eslint/parser": "^6.19.0", "crypto-js": "^4.2.0", - "eslint": "^8.56", - "eslint-plugin-editorconfig": "^4.0.3", + "eslint": "^9.7.0", "expect": "^29.7.0", - "mocha": "^10.2.0", - "ts-mocha": "^10.0.0", - "typescript": "^5.3.3", + "mocha": "^10.7.0", + "prettier": "^3.3.3", + "ts-auto-mock": "^3.7.4", + "ts-node": "^10.9.2", + "typescript": "^5.5.3", + "typescript-eslint": "^7.16.1", "typescript-formatter": "^7.2" }, "dependencies": { + "@gnuxie/typescript-result": "^1.0.0", "@sentry/node": "^7.17.2", "@sentry/tracing": "^7.17.2", - "@sinclair/typebox": "0.32.29", + "@sinclair/typebox": "0.32.34", + "@the-draupnir-project/interface-manager": "^2.3.0", + "@the-draupnir-project/matrix-basic-types": "^0.2.0", "await-lock": "^2.2.2", "better-sqlite3": "^9.4.3", "body-parser": "^1.20.2", "config": "^3.3.9", - "express": "^4.18", + "express": "^4.19", "html-to-text": "^8.0.0", "humanize-duration": "^3.27.1", "humanize-duration-ts": "^2.1.1", "js-yaml": "^4.1.0", "jsdom": "^24.0.0", "matrix-appservice-bridge": "^9.0.1", - "matrix-protection-suite": "npm:@gnuxie/matrix-protection-suite@0.22.0", - "matrix-protection-suite-for-matrix-bot-sdk": "npm:@gnuxie/matrix-protection-suite-for-matrix-bot-sdk@0.22.0", + "matrix-protection-suite": "npm:@gnuxie/matrix-protection-suite@1.3.0", + "matrix-protection-suite-for-matrix-bot-sdk": "npm:@gnuxie/matrix-protection-suite-for-matrix-bot-sdk@1.3.0", "parse-duration": "^1.0.2", "pg": "^8.8.0", "shell-quote": "^1.7.3", @@ -77,5 +83,6 @@ }, "engines": { "node": ">=18.0.0" - } + }, + "packageManager": "yarn@1.22.22+sha1.ac34549e6aa8e7ead463a7407e1c7390f61a6610" } diff --git a/pkgs/by-name/dr/draupnir/package.nix b/pkgs/by-name/dr/draupnir/package.nix index fb2faad56350e9e..c2987712bf6f59d 100644 --- a/pkgs/by-name/dr/draupnir/package.nix +++ b/pkgs/by-name/dr/draupnir/package.nix @@ -15,12 +15,12 @@ let in mkYarnPackage rec { pname = "draupnir"; - version = "2.0.0-beta.4"; + version = "2.0.0-beta.6"; src = fetchFromGitHub { owner = "the-draupnir-project"; repo = "Draupnir"; rev = "v${version}"; - hash = "sha256-ZbAst3XaTdJxCPsgPc8cAqN0lo6vOvFphqBDjduQ/to="; + hash = "sha256-s1LWXVwY+7LD7cJtZW7mBLsdpB499zS/nDsJ7qaQDfg="; }; nativeBuildInputs = [ @@ -45,6 +45,8 @@ in echo "Adding version.txt..." mkdir -p deps/draupnir/ echo "${version}-nix" > deps/draupnir/version.txt + + sed -i 's/corepack //g' deps/draupnir/package.json ''; buildPhase = '' From bd7179de2c4192b0d054086e42f2b4c80a82d60b Mon Sep 17 00:00:00 2001 From: TheArcaneBrony Date: Mon, 16 Sep 2024 01:32:46 +0000 Subject: [PATCH 18/18] fixup! draupnir: init at 2.0.0-beta.4 - Switch to pkgConfig for matrix-sdk-crypto-nodejs and better-sqlite3 Co-Authored-By: div72 --- pkgs/by-name/dr/draupnir/package.nix | 29 +++++++++++++++++++++++++--- 1 file changed, 26 insertions(+), 3 deletions(-) diff --git a/pkgs/by-name/dr/draupnir/package.nix b/pkgs/by-name/dr/draupnir/package.nix index c2987712bf6f59d..9ac8c17cd185565 100644 --- a/pkgs/by-name/dr/draupnir/package.nix +++ b/pkgs/by-name/dr/draupnir/package.nix @@ -3,7 +3,10 @@ , makeWrapper , nodejs , matrix-sdk-crypto-nodejs +, python3 , sqlite +, srcOnly +, removeReferencesTo , mkYarnPackage , fetchYarnDeps , nixosTests @@ -12,6 +15,7 @@ # docs: https://github.com/NixOS/nixpkgs/blob/master/doc/languages-frameworks/javascript.section.md#yarn2nix-javascript-yarn2nix let hashesFile = builtins.fromJSON (builtins.readFile ./hashes.json); + nodeSources = srcOnly nodejs; in mkYarnPackage rec { pname = "draupnir"; @@ -37,11 +41,30 @@ in yarnLock = src + "/yarn.lock"; packageJSON = ./package.json; + pkgConfig = { + "@matrix-org/matrix-sdk-crypto-nodejs" = { + postInstall = '' + # replace with the built package + cd .. + rm -r matrix-sdk-crypto-nodejs + ln -s ${matrix-sdk-crypto-nodejs}/lib/node_modules/@matrix-org/* ./ + ''; + }; + + better-sqlite3 = { + nativeBuildInputs = [ python3 ]; + postInstall = '' + # build native sqlite bindings + npm run build-release --offline --nodedir="${nodeSources}" + find build -type f -exec \ + ${removeReferencesTo}/bin/remove-references-to \ + -t "${nodeSources}" {} \; + ''; + }; + }; + #prebuild phase preBuild = '' - # copy built modules to package... - echo "Copying built matrix-sdk-crypto-nodejs modules to package..." - cp -a ${matrix-sdk-crypto-nodejs}/lib/node_modules/* node_modules/ echo "Adding version.txt..." mkdir -p deps/draupnir/ echo "${version}-nix" > deps/draupnir/version.txt