Loading nixos/modules/services/web-apps/discourse.nix +13 −2 Original line number Diff line number Diff line Loading @@ -17,7 +17,10 @@ let upstreamPostgresqlVersion = lib.getVersion pkgs.postgresql_15; postgresqlPackage = if config.services.postgresql.enable then config.services.postgresql.package else pkgs.postgresql; if config.services.postgresql.enable then config.services.postgresql.finalPackage else pkgs.postgresql; postgresqlVersion = lib.getVersion postgresqlPackage; Loading Loading @@ -540,7 +543,7 @@ in assertions = [ { assertion = (cfg.database.host != null) -> (cfg.database.passwordFile != null); message = "When services.gitlab.database.host is customized, services.discourse.database.passwordFile must be set!"; message = "When services.discourse.database.host is customized, services.discourse.database.passwordFile must be set!"; } { assertion = cfg.hostname != ""; Loading Loading @@ -694,6 +697,9 @@ in services.postgresql = lib.mkIf databaseActuallyCreateLocally { enable = true; extensions = ps: [ ps.pgvector ]; ensureUsers = [ { name = "discourse"; } ]; }; Loading @@ -719,6 +725,7 @@ in psql -tAc "SELECT 1 FROM pg_database WHERE datname = 'discourse'" | grep -q 1 || psql -tAc 'CREATE DATABASE "discourse" OWNER "discourse"' psql '${cfg.database.name}' -tAc "CREATE EXTENSION IF NOT EXISTS pg_trgm" psql '${cfg.database.name}' -tAc "CREATE EXTENSION IF NOT EXISTS hstore" psql '${cfg.database.name}' -tAc "CREATE EXTENSION IF NOT EXISTS vector" ''; serviceConfig = { Loading Loading @@ -805,8 +812,11 @@ in cp -r ${cfg.package}/share/discourse/config.dist/* /run/discourse/config/ cp -r ${cfg.package}/share/discourse/public.dist/* /run/discourse/public/ cp -r ${cfg.package.assets.generated}/* /run/discourse/assets-generated/ ln -sf /var/lib/discourse/uploads /run/discourse/public/uploads ln -sf /var/lib/discourse/backups /run/discourse/public/backups # discourse creates images in this folder, and by default it only has u=rx chmod 750 /run/discourse/public/images ( umask u=rwx,g=,o= Loading Loading @@ -839,6 +849,7 @@ in "assets/javascripts/plugins" "public" "sockets" "assets-generated" ]; RuntimeDirectoryMode = "0750"; StateDirectory = map (p: "discourse/" + p) [ Loading nixos/tests/discourse.nix +1 −1 Original line number Diff line number Diff line Loading @@ -29,7 +29,7 @@ in nodes.discourse = { nodes, ... }: { virtualisation.memorySize = 2048; virtualisation.memorySize = 4096; virtualisation.cores = 4; virtualisation.useNixStoreImage = true; virtualisation.writableStore = false; Loading pkgs/servers/web-apps/discourse/default.nix +139 −50 Original line number Diff line number Diff line Loading @@ -10,6 +10,7 @@ callPackage, nixosTests, defaultGemConfig, ruby_3_3, gzip, gnutar, Loading @@ -34,6 +35,10 @@ procps, rsync, icu, rustPlatform, buildRubyGem, rustc, cargo, pnpm_9, svgo, nodejs, Loading @@ -46,13 +51,13 @@ }: let version = "3.4.7"; version = "3.5.2"; src = fetchFromGitHub { owner = "discourse"; repo = "discourse"; rev = "v${version}"; sha256 = "sha256-vidv5aa2r1YOcnvkqrk7ttuIk1bN5Ct7kMANl8kpEm0="; sha256 = "sha256-8Uzb0cjC3PUrh6Nlu6OJ09GKD+8KZq/IUba2NXLm1JI="; }; ruby = ruby_3_3; Loading Loading @@ -117,9 +122,12 @@ let ); in stdenv.mkDerivation ( removeAttrs args [ "bundlerEnvArgs" ] // { # Allow overriding the plugin name { pluginName = if name != null then name else "${pname}-${version}"; } // removeAttrs args [ "bundlerEnvArgs" ] // { dontConfigure = true; dontBuild = true; installPhase = '' Loading Loading @@ -168,18 +176,15 @@ let name = "discourse-ruby-env-${version}"; inherit version ruby; gemdir = ./rubyEnv; gemset = let gems = import ./rubyEnv/gemset.nix; in gems // { mini_racer = gems.mini_racer // { gemset = import ./rubyEnv/gemset.nix; gemConfig = defaultGemConfig // { mini_racer = attrs: { buildInputs = [ icu ]; dontBuild = false; NIX_LDFLAGS = "-licui18n"; }; libv8-node = attrs: let noopScript = writeShellScript "noop" "exit 0"; linkFiles = writeShellScript "link-files" '' Loading @@ -194,8 +199,7 @@ let echo '--- !ruby/object:Libv8::Node::Location::Vendor {}' >ext/libv8-node/.location.yml ''; in gems.libv8-node // { { dontBuild = false; postPatch = '' cp ${noopScript} libexec/build-libv8 Loading @@ -205,7 +209,7 @@ let cp ${linkFiles} libexec/inject-libv8 ''; }; mini_suffix = gems.mini_suffix // { mini_suffix = attrs: { propagatedBuildInputs = [ libpsl ]; dontBuild = false; # Use our libpsl instead of the vendored one, which isn't Loading @@ -215,6 +219,72 @@ let cp $(readlink -f ${lib.getLib libpsl}/lib/libpsl.so) vendor/libpsl.x86_64.so ''; }; tokenizers = attrs: { cargoDeps = rustPlatform.fetchCargoVendor { inherit (buildRubyGem { inherit (attrs) gemName version source; }) name src unpackPhase nativeBuildInputs ; hash = "sha256-ydSXo3wp13/mPgJv1HbavNurkd2KxuKzuJNHliPpn2I="; }; dontBuild = false; nativeBuildInputs = [ cargo rustc rustPlatform.cargoSetupHook rustPlatform.bindgenHook ]; disallowedReferences = [ rustc.unwrapped ]; preInstall = '' export CARGO_HOME="$PWD/../.cargo/" ''; postInstall = '' find $out -type f -name .rustc_info.json -delete ''; }; tiktoken_ruby = attrs: { cargoDeps = rustPlatform.fetchCargoVendor { inherit (buildRubyGem { inherit (attrs) gemName version source; }) name src unpackPhase nativeBuildInputs ; hash = "sha256-IABOxUymtFkF9sl1kRWAS5hM6GNJI6Y4VFICXdX7zF0="; }; dontBuild = false; nativeBuildInputs = [ cargo rustc rustPlatform.cargoSetupHook rustPlatform.bindgenHook ]; disallowedReferences = [ rustc.unwrapped ]; preInstall = '' export CARGO_HOME="$PWD/../.cargo/" ''; postInstall = '' #ls $GEM_HOME/gems/${attrs.gemName}-${attrs.version}/lib #mv -v $GEM_HOME/gems/${attrs.gemName}-${attrs.version}/lib/{glfm_markdown/glfm_markdown.so,} find $out -type f -name .rustc_info.json -delete ''; }; }; groups = [ Loading @@ -233,11 +303,13 @@ let pname = "discourse-assets"; inherit version src; fetcherVersion = 1; hash = "sha256-WyRBnuKCl5NJLtqy3HK/sJcrpMkh0PjbasGPNDV6+7Y="; hash = "sha256-npRKX5Lr2QrPD8OFBysDl30exP+FTnjMxFeR/Gv0Z0I="; }; nativeBuildInputs = runtimeDeps ++ [ postgresql (postgresql.withPackages (ps: [ ps.pgvector ])) redis uglify-js terser Loading @@ -251,6 +323,7 @@ let "out" "javascripts" "node_modules" "generated" ]; patches = [ Loading @@ -274,6 +347,14 @@ let ]; env.RAILS_ENV = "production"; env.DISCOURSE_DOWNLOAD_PRE_BUILT_ASSETS = "0"; # Allow to use different bundler version than the lockfile has env.BUNDLER_VERSION = pkgs.bundler.version; # requires full git and repository, even a src `leaveDotGit` is not enough. So patch this function to return the version postPatch = '' substituteInPlace script/assemble_ember_build.rb --replace-fail "def core_tree_hash" "def core_tree_hash; return \"v${version}\"" ''; # We have to set up an environment that is close enough to # production ready or the assets:precompile task refuses to Loading @@ -300,6 +381,7 @@ let psql -d postgres -tAc 'CREATE DATABASE "discourse" OWNER "discourse"' psql 'discourse' -tAc "CREATE EXTENSION IF NOT EXISTS pg_trgm" psql 'discourse' -tAc "CREATE EXTENSION IF NOT EXISTS hstore" psql 'discourse' -tAc "CREATE EXTENSION IF NOT EXISTS vector" ${lib.concatMapStringsSep "\n" (p: "ln -sf ${p} plugins/${p.pluginName or ""}") plugins} Loading @@ -310,6 +392,7 @@ let buildPhase = '' runHook preBuild patchShebangs script/ bundle exec rake assets:precompile runHook postBuild Loading @@ -322,9 +405,10 @@ let mv node_modules $node_modules rm -r app/assets/javascripts/plugins rm -rf app/assets/javascripts/plugins mv app/assets/javascripts $javascripts ln -sf /run/discourse/assets/javascripts/plugins $javascripts/plugins mv app/assets/generated $generated runHook postInstall ''; Loading Loading @@ -374,6 +458,10 @@ let # theme-transpiler over and over again. Which at the same time allows the removal # of javascript devDependencies from the runtime environment. ./prebuild-theme-transpiler.patch # Our app/assets/generated folder is a symlink, but the ruby File.mkdir_p doesn't allow # a symlink in the way to the last directory. This patch explicitly resolves the symlink. ./resolve_generated_assets_symlink.patch ]; postPatch = '' Loading Loading @@ -406,6 +494,7 @@ let ln -sf /var/lib/discourse/tmp $out/share/discourse/tmp ln -sf /run/discourse/config $out/share/discourse/config ln -sf /run/discourse/public $out/share/discourse/public ln -sf /run/discourse/assets-generated $out/share/discourse/app/assets/generated ln -sf ${assets.node_modules} $out/share/discourse/node_modules ln -sf ${assets} $out/share/discourse/public.dist/assets rm -r $out/share/discourse/app/assets/javascripts Loading pkgs/servers/web-apps/discourse/plugins/all-plugins.nix +0 −15 Original line number Diff line number Diff line Loading @@ -3,25 +3,10 @@ let callPackage = newScope args; in { discourse-assign = callPackage ./discourse-assign { }; discourse-bbcode-color = callPackage ./discourse-bbcode-color { }; discourse-calendar = callPackage ./discourse-calendar { }; discourse-canned-replies = callPackage ./discourse-canned-replies { }; discourse-chat-integration = callPackage ./discourse-chat-integration { }; discourse-checklist = callPackage ./discourse-checklist { }; discourse-data-explorer = callPackage ./discourse-data-explorer { }; discourse-docs = callPackage ./discourse-docs { }; discourse-github = callPackage ./discourse-github { }; discourse-ldap-auth = callPackage ./discourse-ldap-auth { }; discourse-math = callPackage ./discourse-math { }; discourse-migratepassword = callPackage ./discourse-migratepassword { }; discourse-oauth2-basic = callPackage ./discourse-oauth2-basic { }; discourse-openid-connect = callPackage ./discourse-openid-connect { }; discourse-prometheus = callPackage ./discourse-prometheus { }; discourse-reactions = callPackage ./discourse-reactions { }; discourse-saved-searches = callPackage ./discourse-saved-searches { }; discourse-solved = callPackage ./discourse-solved { }; discourse-spoiler-alert = callPackage ./discourse-spoiler-alert { }; discourse-voting = callPackage ./discourse-voting { }; discourse-yearly-review = callPackage ./discourse-yearly-review { }; } pkgs/servers/web-apps/discourse/plugins/discourse-assign/default.nixdeleted 100644 → 0 +0 −21 Original line number Diff line number Diff line { lib, mkDiscoursePlugin, fetchFromGitHub, }: mkDiscoursePlugin { name = "discourse-assign"; src = fetchFromGitHub { owner = "discourse"; repo = "discourse-assign"; rev = "261a47d119d200a8d922d008ad3d1667df869435"; sha256 = "sha256-0OClWO70btM7EN7Vir1LIhCTeO5+2jtkP4RozoKzp+0="; }; meta = with lib; { homepage = "https://github.com/discourse/discourse-docs"; maintainers = with maintainers; [ dpausp ]; license = licenses.mit; description = "Discourse Plugin for assigning users to a topic"; }; } Loading
nixos/modules/services/web-apps/discourse.nix +13 −2 Original line number Diff line number Diff line Loading @@ -17,7 +17,10 @@ let upstreamPostgresqlVersion = lib.getVersion pkgs.postgresql_15; postgresqlPackage = if config.services.postgresql.enable then config.services.postgresql.package else pkgs.postgresql; if config.services.postgresql.enable then config.services.postgresql.finalPackage else pkgs.postgresql; postgresqlVersion = lib.getVersion postgresqlPackage; Loading Loading @@ -540,7 +543,7 @@ in assertions = [ { assertion = (cfg.database.host != null) -> (cfg.database.passwordFile != null); message = "When services.gitlab.database.host is customized, services.discourse.database.passwordFile must be set!"; message = "When services.discourse.database.host is customized, services.discourse.database.passwordFile must be set!"; } { assertion = cfg.hostname != ""; Loading Loading @@ -694,6 +697,9 @@ in services.postgresql = lib.mkIf databaseActuallyCreateLocally { enable = true; extensions = ps: [ ps.pgvector ]; ensureUsers = [ { name = "discourse"; } ]; }; Loading @@ -719,6 +725,7 @@ in psql -tAc "SELECT 1 FROM pg_database WHERE datname = 'discourse'" | grep -q 1 || psql -tAc 'CREATE DATABASE "discourse" OWNER "discourse"' psql '${cfg.database.name}' -tAc "CREATE EXTENSION IF NOT EXISTS pg_trgm" psql '${cfg.database.name}' -tAc "CREATE EXTENSION IF NOT EXISTS hstore" psql '${cfg.database.name}' -tAc "CREATE EXTENSION IF NOT EXISTS vector" ''; serviceConfig = { Loading Loading @@ -805,8 +812,11 @@ in cp -r ${cfg.package}/share/discourse/config.dist/* /run/discourse/config/ cp -r ${cfg.package}/share/discourse/public.dist/* /run/discourse/public/ cp -r ${cfg.package.assets.generated}/* /run/discourse/assets-generated/ ln -sf /var/lib/discourse/uploads /run/discourse/public/uploads ln -sf /var/lib/discourse/backups /run/discourse/public/backups # discourse creates images in this folder, and by default it only has u=rx chmod 750 /run/discourse/public/images ( umask u=rwx,g=,o= Loading Loading @@ -839,6 +849,7 @@ in "assets/javascripts/plugins" "public" "sockets" "assets-generated" ]; RuntimeDirectoryMode = "0750"; StateDirectory = map (p: "discourse/" + p) [ Loading
nixos/tests/discourse.nix +1 −1 Original line number Diff line number Diff line Loading @@ -29,7 +29,7 @@ in nodes.discourse = { nodes, ... }: { virtualisation.memorySize = 2048; virtualisation.memorySize = 4096; virtualisation.cores = 4; virtualisation.useNixStoreImage = true; virtualisation.writableStore = false; Loading
pkgs/servers/web-apps/discourse/default.nix +139 −50 Original line number Diff line number Diff line Loading @@ -10,6 +10,7 @@ callPackage, nixosTests, defaultGemConfig, ruby_3_3, gzip, gnutar, Loading @@ -34,6 +35,10 @@ procps, rsync, icu, rustPlatform, buildRubyGem, rustc, cargo, pnpm_9, svgo, nodejs, Loading @@ -46,13 +51,13 @@ }: let version = "3.4.7"; version = "3.5.2"; src = fetchFromGitHub { owner = "discourse"; repo = "discourse"; rev = "v${version}"; sha256 = "sha256-vidv5aa2r1YOcnvkqrk7ttuIk1bN5Ct7kMANl8kpEm0="; sha256 = "sha256-8Uzb0cjC3PUrh6Nlu6OJ09GKD+8KZq/IUba2NXLm1JI="; }; ruby = ruby_3_3; Loading Loading @@ -117,9 +122,12 @@ let ); in stdenv.mkDerivation ( removeAttrs args [ "bundlerEnvArgs" ] // { # Allow overriding the plugin name { pluginName = if name != null then name else "${pname}-${version}"; } // removeAttrs args [ "bundlerEnvArgs" ] // { dontConfigure = true; dontBuild = true; installPhase = '' Loading Loading @@ -168,18 +176,15 @@ let name = "discourse-ruby-env-${version}"; inherit version ruby; gemdir = ./rubyEnv; gemset = let gems = import ./rubyEnv/gemset.nix; in gems // { mini_racer = gems.mini_racer // { gemset = import ./rubyEnv/gemset.nix; gemConfig = defaultGemConfig // { mini_racer = attrs: { buildInputs = [ icu ]; dontBuild = false; NIX_LDFLAGS = "-licui18n"; }; libv8-node = attrs: let noopScript = writeShellScript "noop" "exit 0"; linkFiles = writeShellScript "link-files" '' Loading @@ -194,8 +199,7 @@ let echo '--- !ruby/object:Libv8::Node::Location::Vendor {}' >ext/libv8-node/.location.yml ''; in gems.libv8-node // { { dontBuild = false; postPatch = '' cp ${noopScript} libexec/build-libv8 Loading @@ -205,7 +209,7 @@ let cp ${linkFiles} libexec/inject-libv8 ''; }; mini_suffix = gems.mini_suffix // { mini_suffix = attrs: { propagatedBuildInputs = [ libpsl ]; dontBuild = false; # Use our libpsl instead of the vendored one, which isn't Loading @@ -215,6 +219,72 @@ let cp $(readlink -f ${lib.getLib libpsl}/lib/libpsl.so) vendor/libpsl.x86_64.so ''; }; tokenizers = attrs: { cargoDeps = rustPlatform.fetchCargoVendor { inherit (buildRubyGem { inherit (attrs) gemName version source; }) name src unpackPhase nativeBuildInputs ; hash = "sha256-ydSXo3wp13/mPgJv1HbavNurkd2KxuKzuJNHliPpn2I="; }; dontBuild = false; nativeBuildInputs = [ cargo rustc rustPlatform.cargoSetupHook rustPlatform.bindgenHook ]; disallowedReferences = [ rustc.unwrapped ]; preInstall = '' export CARGO_HOME="$PWD/../.cargo/" ''; postInstall = '' find $out -type f -name .rustc_info.json -delete ''; }; tiktoken_ruby = attrs: { cargoDeps = rustPlatform.fetchCargoVendor { inherit (buildRubyGem { inherit (attrs) gemName version source; }) name src unpackPhase nativeBuildInputs ; hash = "sha256-IABOxUymtFkF9sl1kRWAS5hM6GNJI6Y4VFICXdX7zF0="; }; dontBuild = false; nativeBuildInputs = [ cargo rustc rustPlatform.cargoSetupHook rustPlatform.bindgenHook ]; disallowedReferences = [ rustc.unwrapped ]; preInstall = '' export CARGO_HOME="$PWD/../.cargo/" ''; postInstall = '' #ls $GEM_HOME/gems/${attrs.gemName}-${attrs.version}/lib #mv -v $GEM_HOME/gems/${attrs.gemName}-${attrs.version}/lib/{glfm_markdown/glfm_markdown.so,} find $out -type f -name .rustc_info.json -delete ''; }; }; groups = [ Loading @@ -233,11 +303,13 @@ let pname = "discourse-assets"; inherit version src; fetcherVersion = 1; hash = "sha256-WyRBnuKCl5NJLtqy3HK/sJcrpMkh0PjbasGPNDV6+7Y="; hash = "sha256-npRKX5Lr2QrPD8OFBysDl30exP+FTnjMxFeR/Gv0Z0I="; }; nativeBuildInputs = runtimeDeps ++ [ postgresql (postgresql.withPackages (ps: [ ps.pgvector ])) redis uglify-js terser Loading @@ -251,6 +323,7 @@ let "out" "javascripts" "node_modules" "generated" ]; patches = [ Loading @@ -274,6 +347,14 @@ let ]; env.RAILS_ENV = "production"; env.DISCOURSE_DOWNLOAD_PRE_BUILT_ASSETS = "0"; # Allow to use different bundler version than the lockfile has env.BUNDLER_VERSION = pkgs.bundler.version; # requires full git and repository, even a src `leaveDotGit` is not enough. So patch this function to return the version postPatch = '' substituteInPlace script/assemble_ember_build.rb --replace-fail "def core_tree_hash" "def core_tree_hash; return \"v${version}\"" ''; # We have to set up an environment that is close enough to # production ready or the assets:precompile task refuses to Loading @@ -300,6 +381,7 @@ let psql -d postgres -tAc 'CREATE DATABASE "discourse" OWNER "discourse"' psql 'discourse' -tAc "CREATE EXTENSION IF NOT EXISTS pg_trgm" psql 'discourse' -tAc "CREATE EXTENSION IF NOT EXISTS hstore" psql 'discourse' -tAc "CREATE EXTENSION IF NOT EXISTS vector" ${lib.concatMapStringsSep "\n" (p: "ln -sf ${p} plugins/${p.pluginName or ""}") plugins} Loading @@ -310,6 +392,7 @@ let buildPhase = '' runHook preBuild patchShebangs script/ bundle exec rake assets:precompile runHook postBuild Loading @@ -322,9 +405,10 @@ let mv node_modules $node_modules rm -r app/assets/javascripts/plugins rm -rf app/assets/javascripts/plugins mv app/assets/javascripts $javascripts ln -sf /run/discourse/assets/javascripts/plugins $javascripts/plugins mv app/assets/generated $generated runHook postInstall ''; Loading Loading @@ -374,6 +458,10 @@ let # theme-transpiler over and over again. Which at the same time allows the removal # of javascript devDependencies from the runtime environment. ./prebuild-theme-transpiler.patch # Our app/assets/generated folder is a symlink, but the ruby File.mkdir_p doesn't allow # a symlink in the way to the last directory. This patch explicitly resolves the symlink. ./resolve_generated_assets_symlink.patch ]; postPatch = '' Loading Loading @@ -406,6 +494,7 @@ let ln -sf /var/lib/discourse/tmp $out/share/discourse/tmp ln -sf /run/discourse/config $out/share/discourse/config ln -sf /run/discourse/public $out/share/discourse/public ln -sf /run/discourse/assets-generated $out/share/discourse/app/assets/generated ln -sf ${assets.node_modules} $out/share/discourse/node_modules ln -sf ${assets} $out/share/discourse/public.dist/assets rm -r $out/share/discourse/app/assets/javascripts Loading
pkgs/servers/web-apps/discourse/plugins/all-plugins.nix +0 −15 Original line number Diff line number Diff line Loading @@ -3,25 +3,10 @@ let callPackage = newScope args; in { discourse-assign = callPackage ./discourse-assign { }; discourse-bbcode-color = callPackage ./discourse-bbcode-color { }; discourse-calendar = callPackage ./discourse-calendar { }; discourse-canned-replies = callPackage ./discourse-canned-replies { }; discourse-chat-integration = callPackage ./discourse-chat-integration { }; discourse-checklist = callPackage ./discourse-checklist { }; discourse-data-explorer = callPackage ./discourse-data-explorer { }; discourse-docs = callPackage ./discourse-docs { }; discourse-github = callPackage ./discourse-github { }; discourse-ldap-auth = callPackage ./discourse-ldap-auth { }; discourse-math = callPackage ./discourse-math { }; discourse-migratepassword = callPackage ./discourse-migratepassword { }; discourse-oauth2-basic = callPackage ./discourse-oauth2-basic { }; discourse-openid-connect = callPackage ./discourse-openid-connect { }; discourse-prometheus = callPackage ./discourse-prometheus { }; discourse-reactions = callPackage ./discourse-reactions { }; discourse-saved-searches = callPackage ./discourse-saved-searches { }; discourse-solved = callPackage ./discourse-solved { }; discourse-spoiler-alert = callPackage ./discourse-spoiler-alert { }; discourse-voting = callPackage ./discourse-voting { }; discourse-yearly-review = callPackage ./discourse-yearly-review { }; }
pkgs/servers/web-apps/discourse/plugins/discourse-assign/default.nixdeleted 100644 → 0 +0 −21 Original line number Diff line number Diff line { lib, mkDiscoursePlugin, fetchFromGitHub, }: mkDiscoursePlugin { name = "discourse-assign"; src = fetchFromGitHub { owner = "discourse"; repo = "discourse-assign"; rev = "261a47d119d200a8d922d008ad3d1667df869435"; sha256 = "sha256-0OClWO70btM7EN7Vir1LIhCTeO5+2jtkP4RozoKzp+0="; }; meta = with lib; { homepage = "https://github.com/discourse/discourse-docs"; maintainers = with maintainers; [ dpausp ]; license = licenses.mit; description = "Discourse Plugin for assigning users to a topic"; }; }