Merge pull request #116074 from talyz/discourse
discourse: Add package and NixOS module
This commit is contained in:
commit
5a1bd5ff66
22 changed files with 5269 additions and 25 deletions
|
@ -118,6 +118,16 @@
|
||||||
<xref linkend="opt-services.samba-wsdd.enable" /> Web Services Dynamic Discovery host daemon
|
<xref linkend="opt-services.samba-wsdd.enable" /> Web Services Dynamic Discovery host daemon
|
||||||
</para>
|
</para>
|
||||||
</listitem>
|
</listitem>
|
||||||
|
<listitem>
|
||||||
|
<para>
|
||||||
|
<link xlink:href="https://www.discourse.org/">Discourse</link>, a
|
||||||
|
modern and open source discussion platform.
|
||||||
|
</para>
|
||||||
|
<para>
|
||||||
|
See the <link linkend="module-services-discourse">Discourse
|
||||||
|
section of the NixOS manual</link> for more information.
|
||||||
|
</para>
|
||||||
|
</listitem>
|
||||||
</itemizedlist>
|
</itemizedlist>
|
||||||
|
|
||||||
</section>
|
</section>
|
||||||
|
|
|
@ -897,6 +897,7 @@
|
||||||
./services/web-apps/calibre-web.nix
|
./services/web-apps/calibre-web.nix
|
||||||
./services/web-apps/convos.nix
|
./services/web-apps/convos.nix
|
||||||
./services/web-apps/cryptpad.nix
|
./services/web-apps/cryptpad.nix
|
||||||
|
./services/web-apps/discourse.nix
|
||||||
./services/web-apps/documize.nix
|
./services/web-apps/documize.nix
|
||||||
./services/web-apps/dokuwiki.nix
|
./services/web-apps/dokuwiki.nix
|
||||||
./services/web-apps/engelsystem.nix
|
./services/web-apps/engelsystem.nix
|
||||||
|
|
1035
nixos/modules/services/web-apps/discourse.nix
Normal file
1035
nixos/modules/services/web-apps/discourse.nix
Normal file
File diff suppressed because it is too large
Load diff
323
nixos/modules/services/web-apps/discourse.xml
Normal file
323
nixos/modules/services/web-apps/discourse.xml
Normal file
|
@ -0,0 +1,323 @@
|
||||||
|
<chapter xmlns="http://docbook.org/ns/docbook"
|
||||||
|
xmlns:xlink="http://www.w3.org/1999/xlink"
|
||||||
|
xmlns:xi="http://www.w3.org/2001/XInclude"
|
||||||
|
version="5.0"
|
||||||
|
xml:id="module-services-discourse">
|
||||||
|
<title>Discourse</title>
|
||||||
|
<para>
|
||||||
|
<link xlink:href="https://www.discourse.org/">Discourse</link> is a
|
||||||
|
modern and open source discussion platform.
|
||||||
|
</para>
|
||||||
|
|
||||||
|
<section xml:id="module-services-discourse-basic-usage">
|
||||||
|
<title>Basic usage</title>
|
||||||
|
<para>
|
||||||
|
A minimal configuration using Let's Encrypt for TLS certificates looks like this:
|
||||||
|
<programlisting>
|
||||||
|
services.discourse = {
|
||||||
|
<link linkend="opt-services.discourse.enable">enable</link> = true;
|
||||||
|
<link linkend="opt-services.discourse.hostname">hostname</link> = "discourse.example.com";
|
||||||
|
admin = {
|
||||||
|
<link linkend="opt-services.discourse.admin.email">email</link> = "admin@example.com";
|
||||||
|
<link linkend="opt-services.discourse.admin.username">username</link> = "admin";
|
||||||
|
<link linkend="opt-services.discourse.admin.fullName">fullName</link> = "Administrator";
|
||||||
|
<link linkend="opt-services.discourse.admin.passwordFile">passwordFile</link> = "/path/to/password_file";
|
||||||
|
};
|
||||||
|
<link linkend="opt-services.discourse.secretKeyBaseFile">secretKeyBaseFile</link> = "/path/to/secret_key_base_file";
|
||||||
|
};
|
||||||
|
<link linkend="opt-security.acme.email">security.acme.email</link> = "me@example.com";
|
||||||
|
<link linkend="opt-security.acme.acceptTerms">security.acme.acceptTerms</link> = true;
|
||||||
|
</programlisting>
|
||||||
|
</para>
|
||||||
|
|
||||||
|
<para>
|
||||||
|
Provided a proper DNS setup, you'll be able to connect to the
|
||||||
|
instance at <literal>discourse.example.com</literal> and log in
|
||||||
|
using the credentials provided in
|
||||||
|
<literal>services.discourse.admin</literal>.
|
||||||
|
</para>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
<section xml:id="module-services-discourse-tls">
|
||||||
|
<title>Using a regular TLS certificate</title>
|
||||||
|
<para>
|
||||||
|
To set up TLS using a regular certificate and key on file, use
|
||||||
|
the <xref linkend="opt-services.discourse.sslCertificate" />
|
||||||
|
and <xref linkend="opt-services.discourse.sslCertificateKey" />
|
||||||
|
options:
|
||||||
|
|
||||||
|
<programlisting>
|
||||||
|
services.discourse = {
|
||||||
|
<link linkend="opt-services.discourse.enable">enable</link> = true;
|
||||||
|
<link linkend="opt-services.discourse.hostname">hostname</link> = "discourse.example.com";
|
||||||
|
<link linkend="opt-services.discourse.sslCertificate">sslCertificate</link> = "/path/to/ssl_certificate";
|
||||||
|
<link linkend="opt-services.discourse.sslCertificateKey">sslCertificateKey</link> = "/path/to/ssl_certificate_key";
|
||||||
|
admin = {
|
||||||
|
<link linkend="opt-services.discourse.admin.email">email</link> = "admin@example.com";
|
||||||
|
<link linkend="opt-services.discourse.admin.username">username</link> = "admin";
|
||||||
|
<link linkend="opt-services.discourse.admin.fullName">fullName</link> = "Administrator";
|
||||||
|
<link linkend="opt-services.discourse.admin.passwordFile">passwordFile</link> = "/path/to/password_file";
|
||||||
|
};
|
||||||
|
<link linkend="opt-services.discourse.secretKeyBaseFile">secretKeyBaseFile</link> = "/path/to/secret_key_base_file";
|
||||||
|
};
|
||||||
|
</programlisting>
|
||||||
|
|
||||||
|
</para>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
<section xml:id="module-services-discourse-database">
|
||||||
|
<title>Database access</title>
|
||||||
|
<para>
|
||||||
|
<productname>Discourse</productname> uses
|
||||||
|
<productname>PostgreSQL</productname> to store most of its
|
||||||
|
data. A database will automatically be enabled and a database
|
||||||
|
and role created unless <xref
|
||||||
|
linkend="opt-services.discourse.database.host" /> is changed from
|
||||||
|
its default of <literal>null</literal> or <xref
|
||||||
|
linkend="opt-services.discourse.database.createLocally" /> is set
|
||||||
|
to <literal>false</literal>.
|
||||||
|
</para>
|
||||||
|
|
||||||
|
<para>
|
||||||
|
External database access can also be configured by setting
|
||||||
|
<xref linkend="opt-services.discourse.database.host" />, <xref
|
||||||
|
linkend="opt-services.discourse.database.username" /> and <xref
|
||||||
|
linkend="opt-services.discourse.database.passwordFile" /> as
|
||||||
|
appropriate. Note that you need to manually create a database
|
||||||
|
called <literal>discourse</literal> (or the name you chose in
|
||||||
|
<xref linkend="opt-services.discourse.database.name" />) and
|
||||||
|
allow the configured database user full access to it.
|
||||||
|
</para>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
<section xml:id="module-services-discourse-mail">
|
||||||
|
<title>Email</title>
|
||||||
|
<para>
|
||||||
|
In addition to the basic setup, you'll want to configure an SMTP
|
||||||
|
server <productname>Discourse</productname> can use to send user
|
||||||
|
registration and password reset emails, among others. You can
|
||||||
|
also optionally let <productname>Discourse</productname> receive
|
||||||
|
email, which enables people to reply to threads and conversations
|
||||||
|
via email.
|
||||||
|
</para>
|
||||||
|
|
||||||
|
<para>
|
||||||
|
A basic setup which assumes you want to use your configured <link
|
||||||
|
linkend="opt-services.discourse.hostname">hostname</link> as
|
||||||
|
email domain can be done like this:
|
||||||
|
|
||||||
|
<programlisting>
|
||||||
|
services.discourse = {
|
||||||
|
<link linkend="opt-services.discourse.enable">enable</link> = true;
|
||||||
|
<link linkend="opt-services.discourse.hostname">hostname</link> = "discourse.example.com";
|
||||||
|
<link linkend="opt-services.discourse.sslCertificate">sslCertificate</link> = "/path/to/ssl_certificate";
|
||||||
|
<link linkend="opt-services.discourse.sslCertificateKey">sslCertificateKey</link> = "/path/to/ssl_certificate_key";
|
||||||
|
admin = {
|
||||||
|
<link linkend="opt-services.discourse.admin.email">email</link> = "admin@example.com";
|
||||||
|
<link linkend="opt-services.discourse.admin.username">username</link> = "admin";
|
||||||
|
<link linkend="opt-services.discourse.admin.fullName">fullName</link> = "Administrator";
|
||||||
|
<link linkend="opt-services.discourse.admin.passwordFile">passwordFile</link> = "/path/to/password_file";
|
||||||
|
};
|
||||||
|
mail.outgoing = {
|
||||||
|
<link linkend="opt-services.discourse.mail.outgoing.serverAddress">serverAddress</link> = "smtp.emailprovider.com";
|
||||||
|
<link linkend="opt-services.discourse.mail.outgoing.port">port</link> = 587;
|
||||||
|
<link linkend="opt-services.discourse.mail.outgoing.username">username</link> = "user@emailprovider.com";
|
||||||
|
<link linkend="opt-services.discourse.mail.outgoing.passwordFile">passwordFile</link> = "/path/to/smtp_password_file";
|
||||||
|
};
|
||||||
|
<link linkend="opt-services.discourse.mail.incoming.enable">mail.incoming.enable</link> = true;
|
||||||
|
<link linkend="opt-services.discourse.secretKeyBaseFile">secretKeyBaseFile</link> = "/path/to/secret_key_base_file";
|
||||||
|
};
|
||||||
|
</programlisting>
|
||||||
|
|
||||||
|
This assumes you have set up an MX record for the address you've
|
||||||
|
set in <link linkend="opt-services.discourse.hostname">hostname</link> and
|
||||||
|
requires proper SPF, DKIM and DMARC configuration to be done for
|
||||||
|
the domain you're sending from, in order for email to be reliably delivered.
|
||||||
|
</para>
|
||||||
|
|
||||||
|
<para>
|
||||||
|
If you want to use a different domain for your outgoing email
|
||||||
|
(for example <literal>example.com</literal> instead of
|
||||||
|
<literal>discourse.example.com</literal>) you should set
|
||||||
|
<xref linkend="opt-services.discourse.mail.notificationEmailAddress" /> and
|
||||||
|
<xref linkend="opt-services.discourse.mail.contactEmailAddress" /> manually.
|
||||||
|
</para>
|
||||||
|
|
||||||
|
<note>
|
||||||
|
<para>
|
||||||
|
Setup of TLS for incoming email is currently only configured
|
||||||
|
automatically when a regular TLS certificate is used, i.e. when
|
||||||
|
<xref linkend="opt-services.discourse.sslCertificate" /> and
|
||||||
|
<xref linkend="opt-services.discourse.sslCertificateKey" /> are
|
||||||
|
set.
|
||||||
|
</para>
|
||||||
|
</note>
|
||||||
|
|
||||||
|
</section>
|
||||||
|
|
||||||
|
<section xml:id="module-services-discourse-settings">
|
||||||
|
<title>Additional settings</title>
|
||||||
|
<para>
|
||||||
|
Additional site settings and backend settings, for which no
|
||||||
|
explicit <productname>NixOS</productname> options are provided,
|
||||||
|
can be set in <xref linkend="opt-services.discourse.siteSettings" /> and
|
||||||
|
<xref linkend="opt-services.discourse.backendSettings" /> respectively.
|
||||||
|
</para>
|
||||||
|
|
||||||
|
<section xml:id="module-services-discourse-site-settings">
|
||||||
|
<title>Site settings</title>
|
||||||
|
<para>
|
||||||
|
<quote>Site settings</quote> are the settings that can be
|
||||||
|
changed through the <productname>Discourse</productname>
|
||||||
|
UI. Their <emphasis>default</emphasis> values can be set using
|
||||||
|
<xref linkend="opt-services.discourse.siteSettings" />.
|
||||||
|
</para>
|
||||||
|
|
||||||
|
<para>
|
||||||
|
Settings are expressed as a Nix attribute set which matches the
|
||||||
|
structure of the configuration in
|
||||||
|
<link xlink:href="https://github.com/discourse/discourse/blob/master/config/site_settings.yml">config/site_settings.yml</link>.
|
||||||
|
To find a setting's path, you only need to care about the first
|
||||||
|
two levels; i.e. its category (e.g. <literal>login</literal>)
|
||||||
|
and name (e.g. <literal>invite_only</literal>).
|
||||||
|
</para>
|
||||||
|
|
||||||
|
<para>
|
||||||
|
Settings containing secret data should be set to an attribute
|
||||||
|
set containing the attribute <literal>_secret</literal> - a
|
||||||
|
string pointing to a file containing the value the option
|
||||||
|
should be set to. See the example.
|
||||||
|
</para>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
<section xml:id="module-services-discourse-backend-settings">
|
||||||
|
<title>Backend settings</title>
|
||||||
|
<para>
|
||||||
|
Settings are expressed as a Nix attribute set which matches the
|
||||||
|
structure of the configuration in
|
||||||
|
<link xlink:href="https://github.com/discourse/discourse/blob/stable/config/discourse_defaults.conf">config/discourse.conf</link>.
|
||||||
|
Empty parameters can be defined by setting them to
|
||||||
|
<literal>null</literal>.
|
||||||
|
</para>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
<section xml:id="module-services-discourse-settings-example">
|
||||||
|
<title>Example</title>
|
||||||
|
<para>
|
||||||
|
The following example sets the title and description of the
|
||||||
|
<productname>Discourse</productname> instance and enables
|
||||||
|
<productname>GitHub</productname> login in the site settings,
|
||||||
|
and changes a few request limits in the backend settings:
|
||||||
|
<programlisting>
|
||||||
|
services.discourse = {
|
||||||
|
<link linkend="opt-services.discourse.enable">enable</link> = true;
|
||||||
|
<link linkend="opt-services.discourse.hostname">hostname</link> = "discourse.example.com";
|
||||||
|
<link linkend="opt-services.discourse.sslCertificate">sslCertificate</link> = "/path/to/ssl_certificate";
|
||||||
|
<link linkend="opt-services.discourse.sslCertificateKey">sslCertificateKey</link> = "/path/to/ssl_certificate_key";
|
||||||
|
admin = {
|
||||||
|
<link linkend="opt-services.discourse.admin.email">email</link> = "admin@example.com";
|
||||||
|
<link linkend="opt-services.discourse.admin.username">username</link> = "admin";
|
||||||
|
<link linkend="opt-services.discourse.admin.fullName">fullName</link> = "Administrator";
|
||||||
|
<link linkend="opt-services.discourse.admin.passwordFile">passwordFile</link> = "/path/to/password_file";
|
||||||
|
};
|
||||||
|
mail.outgoing = {
|
||||||
|
<link linkend="opt-services.discourse.mail.outgoing.serverAddress">serverAddress</link> = "smtp.emailprovider.com";
|
||||||
|
<link linkend="opt-services.discourse.mail.outgoing.port">port</link> = 587;
|
||||||
|
<link linkend="opt-services.discourse.mail.outgoing.username">username</link> = "user@emailprovider.com";
|
||||||
|
<link linkend="opt-services.discourse.mail.outgoing.passwordFile">passwordFile</link> = "/path/to/smtp_password_file";
|
||||||
|
};
|
||||||
|
<link linkend="opt-services.discourse.mail.incoming.enable">mail.incoming.enable</link> = true;
|
||||||
|
<link linkend="opt-services.discourse.siteSettings">siteSettings</link> = {
|
||||||
|
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;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
<link linkend="opt-services.discourse.backendSettings">backendSettings</link> = {
|
||||||
|
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";
|
||||||
|
};
|
||||||
|
<link linkend="opt-services.discourse.secretKeyBaseFile">secretKeyBaseFile</link> = "/path/to/secret_key_base_file";
|
||||||
|
};
|
||||||
|
</programlisting>
|
||||||
|
</para>
|
||||||
|
<para>
|
||||||
|
In the resulting site settings file, the
|
||||||
|
<literal>login.github_client_secret</literal> key will be set
|
||||||
|
to the contents of the
|
||||||
|
<filename>/run/keys/discourse_github_client_secret</filename>
|
||||||
|
file.
|
||||||
|
</para>
|
||||||
|
</section>
|
||||||
|
</section>
|
||||||
|
<section xml:id="module-services-discourse-plugins">
|
||||||
|
<title>Plugins</title>
|
||||||
|
<para>
|
||||||
|
You can install <productname>Discourse</productname> plugins
|
||||||
|
using the <xref linkend="opt-services.discourse.plugins" />
|
||||||
|
option. As long as a plugin supports the standard install
|
||||||
|
method, packaging it should only require fetching its source
|
||||||
|
with an appropriate fetcher.
|
||||||
|
</para>
|
||||||
|
|
||||||
|
<para>
|
||||||
|
Some plugins provide <link
|
||||||
|
linkend="module-services-discourse-site-settings">site
|
||||||
|
settings</link>. Their defaults can be configured using <xref
|
||||||
|
linkend="opt-services.discourse.siteSettings" />, just like
|
||||||
|
regular site settings. To find the names of these settings, look
|
||||||
|
in the <literal>config/settings.yml</literal> file of the plugin
|
||||||
|
repo.
|
||||||
|
</para>
|
||||||
|
|
||||||
|
<para>
|
||||||
|
For example, to add the <link
|
||||||
|
xlink:href="https://github.com/discourse/discourse-spoiler-alert">discourse-spoiler-alert</link>
|
||||||
|
plugin and disable it by default:
|
||||||
|
|
||||||
|
<programlisting>
|
||||||
|
services.discourse = {
|
||||||
|
<link linkend="opt-services.discourse.enable">enable</link> = true;
|
||||||
|
<link linkend="opt-services.discourse.hostname">hostname</link> = "discourse.example.com";
|
||||||
|
<link linkend="opt-services.discourse.sslCertificate">sslCertificate</link> = "/path/to/ssl_certificate";
|
||||||
|
<link linkend="opt-services.discourse.sslCertificateKey">sslCertificateKey</link> = "/path/to/ssl_certificate_key";
|
||||||
|
admin = {
|
||||||
|
<link linkend="opt-services.discourse.admin.email">email</link> = "admin@example.com";
|
||||||
|
<link linkend="opt-services.discourse.admin.username">username</link> = "admin";
|
||||||
|
<link linkend="opt-services.discourse.admin.fullName">fullName</link> = "Administrator";
|
||||||
|
<link linkend="opt-services.discourse.admin.passwordFile">passwordFile</link> = "/path/to/password_file";
|
||||||
|
};
|
||||||
|
mail.outgoing = {
|
||||||
|
<link linkend="opt-services.discourse.mail.outgoing.serverAddress">serverAddress</link> = "smtp.emailprovider.com";
|
||||||
|
<link linkend="opt-services.discourse.mail.outgoing.port">port</link> = 587;
|
||||||
|
<link linkend="opt-services.discourse.mail.outgoing.username">username</link> = "user@emailprovider.com";
|
||||||
|
<link linkend="opt-services.discourse.mail.outgoing.passwordFile">passwordFile</link> = "/path/to/smtp_password_file";
|
||||||
|
};
|
||||||
|
<link linkend="opt-services.discourse.mail.incoming.enable">mail.incoming.enable</link> = true;
|
||||||
|
<link linkend="opt-services.discourse.mail.incoming.enable">plugins</link> = [
|
||||||
|
(pkgs.fetchFromGitHub {
|
||||||
|
owner = "discourse";
|
||||||
|
repo = "discourse-spoiler-alert";
|
||||||
|
rev = "e200cfa571d252cab63f3d30d619b370986e4cee";
|
||||||
|
sha256 = "0ya69ix5g77wz4c9x9gmng6l25ghb5xxlx3icr6jam16q14dzc33";
|
||||||
|
})
|
||||||
|
];
|
||||||
|
<link linkend="opt-services.discourse.siteSettings">siteSettings</link> = {
|
||||||
|
plugins = {
|
||||||
|
spoiler_enabled = false;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
<link linkend="opt-services.discourse.secretKeyBaseFile">secretKeyBaseFile</link> = "/path/to/secret_key_base_file";
|
||||||
|
};
|
||||||
|
</programlisting>
|
||||||
|
|
||||||
|
</para>
|
||||||
|
</section>
|
||||||
|
</chapter>
|
|
@ -397,6 +397,9 @@ in
|
||||||
default = pkgs.nginxStable;
|
default = pkgs.nginxStable;
|
||||||
defaultText = "pkgs.nginxStable";
|
defaultText = "pkgs.nginxStable";
|
||||||
type = types.package;
|
type = types.package;
|
||||||
|
apply = p: p.override {
|
||||||
|
modules = p.modules ++ cfg.additionalModules;
|
||||||
|
};
|
||||||
description = "
|
description = "
|
||||||
Nginx package to use. This defaults to the stable version. Note
|
Nginx package to use. This defaults to the stable version. Note
|
||||||
that the nginx team recommends to use the mainline version which
|
that the nginx team recommends to use the mainline version which
|
||||||
|
@ -404,6 +407,17 @@ in
|
||||||
";
|
";
|
||||||
};
|
};
|
||||||
|
|
||||||
|
additionalModules = mkOption {
|
||||||
|
default = [];
|
||||||
|
type = types.listOf (types.attrsOf types.anything);
|
||||||
|
example = literalExample "[ pkgs.nginxModules.brotli ]";
|
||||||
|
description = ''
|
||||||
|
Additional <link xlink:href="https://www.nginx.com/resources/wiki/modules/">third-party nginx modules</link>
|
||||||
|
to install. Packaged modules are available in
|
||||||
|
<literal>pkgs.nginxModules</literal>.
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
|
||||||
logError = mkOption {
|
logError = mkOption {
|
||||||
default = "stderr";
|
default = "stderr";
|
||||||
type = types.str;
|
type = types.str;
|
||||||
|
|
|
@ -88,6 +88,7 @@ in
|
||||||
croc = handleTest ./croc.nix {};
|
croc = handleTest ./croc.nix {};
|
||||||
deluge = handleTest ./deluge.nix {};
|
deluge = handleTest ./deluge.nix {};
|
||||||
dhparams = handleTest ./dhparams.nix {};
|
dhparams = handleTest ./dhparams.nix {};
|
||||||
|
discourse = handleTest ./discourse.nix {};
|
||||||
dnscrypt-proxy2 = handleTestOn ["x86_64-linux"] ./dnscrypt-proxy2.nix {};
|
dnscrypt-proxy2 = handleTestOn ["x86_64-linux"] ./dnscrypt-proxy2.nix {};
|
||||||
dnscrypt-wrapper = handleTestOn ["x86_64-linux"] ./dnscrypt-wrapper {};
|
dnscrypt-wrapper = handleTestOn ["x86_64-linux"] ./dnscrypt-wrapper {};
|
||||||
doas = handleTest ./doas.nix {};
|
doas = handleTest ./doas.nix {};
|
||||||
|
|
197
nixos/tests/discourse.nix
Normal file
197
nixos/tests/discourse.nix
Normal file
|
@ -0,0 +1,197 @@
|
||||||
|
# This tests Discourse by:
|
||||||
|
# 1. logging in as the admin user
|
||||||
|
# 2. sending a private message to the admin user through the API
|
||||||
|
# 3. replying to that message via email.
|
||||||
|
|
||||||
|
import ./make-test-python.nix (
|
||||||
|
{ pkgs, lib, ... }:
|
||||||
|
let
|
||||||
|
certs = import ./common/acme/server/snakeoil-certs.nix;
|
||||||
|
clientDomain = "client.fake.domain";
|
||||||
|
discourseDomain = certs.domain;
|
||||||
|
adminPassword = "eYAX85qmMJ5GZIHLaXGDAoszD7HSZp5d";
|
||||||
|
secretKeyBase = "381f4ac6d8f5e49d804dae72aa9c046431d2f34c656a705c41cd52fed9b4f6f76f51549f0b55db3b8b0dded7a00d6a381ebe9a4367d2d44f5e743af6628b4d42";
|
||||||
|
admin = {
|
||||||
|
email = "alice@${clientDomain}";
|
||||||
|
username = "alice";
|
||||||
|
fullName = "Alice Admin";
|
||||||
|
passwordFile = "${pkgs.writeText "admin-pass" adminPassword}";
|
||||||
|
};
|
||||||
|
in
|
||||||
|
{
|
||||||
|
name = "discourse";
|
||||||
|
meta = with pkgs.lib.maintainers; {
|
||||||
|
maintainers = [ talyz ];
|
||||||
|
};
|
||||||
|
|
||||||
|
nodes.discourse =
|
||||||
|
{ nodes, ... }:
|
||||||
|
{
|
||||||
|
virtualisation.memorySize = 2048;
|
||||||
|
|
||||||
|
imports = [ common/user-account.nix ];
|
||||||
|
|
||||||
|
security.pki.certificateFiles = [
|
||||||
|
certs.ca.cert
|
||||||
|
];
|
||||||
|
|
||||||
|
networking.extraHosts = ''
|
||||||
|
127.0.0.1 ${discourseDomain}
|
||||||
|
${nodes.client.config.networking.primaryIPAddress} ${clientDomain}
|
||||||
|
'';
|
||||||
|
|
||||||
|
services.postfix = {
|
||||||
|
enableSubmission = true;
|
||||||
|
enableSubmissions = true;
|
||||||
|
submissionsOptions = {
|
||||||
|
smtpd_sasl_auth_enable = "yes";
|
||||||
|
smtpd_client_restrictions = "permit";
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
environment.systemPackages = [ pkgs.jq ];
|
||||||
|
|
||||||
|
services.discourse = {
|
||||||
|
enable = true;
|
||||||
|
inherit admin;
|
||||||
|
hostname = discourseDomain;
|
||||||
|
sslCertificate = "${certs.${discourseDomain}.cert}";
|
||||||
|
sslCertificateKey = "${certs.${discourseDomain}.key}";
|
||||||
|
secretKeyBaseFile = "${pkgs.writeText "secret-key-base" secretKeyBase}";
|
||||||
|
enableACME = false;
|
||||||
|
mail.outgoing.serverAddress = clientDomain;
|
||||||
|
mail.incoming.enable = true;
|
||||||
|
siteSettings = {
|
||||||
|
posting = {
|
||||||
|
min_post_length = 5;
|
||||||
|
min_first_post_length = 5;
|
||||||
|
min_personal_message_post_length = 5;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
unicornTimeout = 900;
|
||||||
|
};
|
||||||
|
|
||||||
|
networking.firewall.allowedTCPPorts = [ 25 465 ];
|
||||||
|
};
|
||||||
|
|
||||||
|
nodes.client =
|
||||||
|
{ nodes, ... }:
|
||||||
|
{
|
||||||
|
imports = [ common/user-account.nix ];
|
||||||
|
|
||||||
|
security.pki.certificateFiles = [
|
||||||
|
certs.ca.cert
|
||||||
|
];
|
||||||
|
|
||||||
|
networking.extraHosts = ''
|
||||||
|
127.0.0.1 ${clientDomain}
|
||||||
|
${nodes.discourse.config.networking.primaryIPAddress} ${discourseDomain}
|
||||||
|
'';
|
||||||
|
|
||||||
|
services.dovecot2 = {
|
||||||
|
enable = true;
|
||||||
|
protocols = [ "imap" ];
|
||||||
|
modules = [ pkgs.dovecot_pigeonhole ];
|
||||||
|
};
|
||||||
|
|
||||||
|
services.postfix = {
|
||||||
|
enable = true;
|
||||||
|
origin = clientDomain;
|
||||||
|
relayDomains = [ clientDomain ];
|
||||||
|
config = {
|
||||||
|
compatibility_level = "2";
|
||||||
|
smtpd_banner = "ESMTP server";
|
||||||
|
myhostname = clientDomain;
|
||||||
|
mydestination = clientDomain;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
environment.systemPackages =
|
||||||
|
let
|
||||||
|
replyToEmail = pkgs.writeScriptBin "reply-to-email" ''
|
||||||
|
#!${pkgs.python3.interpreter}
|
||||||
|
import imaplib
|
||||||
|
import smtplib
|
||||||
|
import ssl
|
||||||
|
import email.header
|
||||||
|
from email import message_from_bytes
|
||||||
|
from email.message import EmailMessage
|
||||||
|
|
||||||
|
with imaplib.IMAP4('localhost') as imap:
|
||||||
|
imap.login('alice', 'foobar')
|
||||||
|
imap.select()
|
||||||
|
status, data = imap.search(None, 'ALL')
|
||||||
|
assert status == 'OK'
|
||||||
|
|
||||||
|
nums = data[0].split()
|
||||||
|
assert len(nums) == 1
|
||||||
|
|
||||||
|
status, msg_data = imap.fetch(nums[0], '(RFC822)')
|
||||||
|
assert status == 'OK'
|
||||||
|
|
||||||
|
msg = email.message_from_bytes(msg_data[0][1])
|
||||||
|
subject = str(email.header.make_header(email.header.decode_header(msg['Subject'])))
|
||||||
|
reply_to = email.header.decode_header(msg['Reply-To'])[0][0]
|
||||||
|
message_id = email.header.decode_header(msg['Message-ID'])[0][0]
|
||||||
|
date = email.header.decode_header(msg['Date'])[0][0]
|
||||||
|
|
||||||
|
ctx = ssl.create_default_context()
|
||||||
|
with smtplib.SMTP_SSL(host='${discourseDomain}', context=ctx) as smtp:
|
||||||
|
reply = EmailMessage()
|
||||||
|
reply['Subject'] = 'Re: ' + subject
|
||||||
|
reply['To'] = reply_to
|
||||||
|
reply['From'] = 'alice@${clientDomain}'
|
||||||
|
reply['In-Reply-To'] = message_id
|
||||||
|
reply['References'] = message_id
|
||||||
|
reply['Date'] = date
|
||||||
|
reply.set_content("Test reply.")
|
||||||
|
|
||||||
|
smtp.send_message(reply)
|
||||||
|
smtp.quit()
|
||||||
|
'';
|
||||||
|
in
|
||||||
|
[ replyToEmail ];
|
||||||
|
|
||||||
|
networking.firewall.allowedTCPPorts = [ 25 ];
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
testScript = { nodes }:
|
||||||
|
let
|
||||||
|
request = builtins.toJSON {
|
||||||
|
title = "Private message";
|
||||||
|
raw = "This is a test message.";
|
||||||
|
target_usernames = admin.username;
|
||||||
|
archetype = "private_message";
|
||||||
|
};
|
||||||
|
in ''
|
||||||
|
discourse.start()
|
||||||
|
client.start()
|
||||||
|
|
||||||
|
discourse.wait_for_unit("discourse.service")
|
||||||
|
discourse.wait_for_file("/run/discourse/sockets/unicorn.sock")
|
||||||
|
discourse.wait_until_succeeds("curl -sS -f https://${discourseDomain}")
|
||||||
|
discourse.succeed(
|
||||||
|
"curl -sS -f https://${discourseDomain}/session/csrf -c cookie -b cookie -H 'Accept: application/json' | jq -r '\"X-CSRF-Token: \" + .csrf' > csrf_token",
|
||||||
|
"curl -sS -f https://${discourseDomain}/session -c cookie -b cookie -H @csrf_token -H 'Accept: application/json' -d 'login=${nodes.discourse.config.services.discourse.admin.username}' -d \"password=${adminPassword}\" | jq -e '.user.username == \"${nodes.discourse.config.services.discourse.admin.username}\"'",
|
||||||
|
"curl -sS -f https://${discourseDomain}/login -v -H 'Accept: application/json' -c cookie -b cookie 2>&1 | grep ${nodes.discourse.config.services.discourse.admin.username}",
|
||||||
|
)
|
||||||
|
|
||||||
|
client.wait_for_unit("postfix.service")
|
||||||
|
client.wait_for_unit("dovecot2.service")
|
||||||
|
|
||||||
|
discourse.succeed(
|
||||||
|
"sudo -u discourse discourse-rake api_key:create_master[master] >api_key",
|
||||||
|
'curl -sS -f https://${discourseDomain}/posts -X POST -H "Content-Type: application/json" -H "Api-Key: $(<api_key)" -H "Api-Username: system" -d \'${request}\' ',
|
||||||
|
)
|
||||||
|
|
||||||
|
client.wait_until_succeeds("reply-to-email")
|
||||||
|
|
||||||
|
discourse.wait_until_succeeds(
|
||||||
|
'curl -sS -f https://${discourseDomain}/topics/private-messages/system -H "Accept: application/json" -H "Api-Key: $(<api_key)" -H "Api-Username: system" | jq -e \'if .topic_list.topics[0].id != null then .topic_list.topics[0].id else null end\' >topic_id'
|
||||||
|
)
|
||||||
|
discourse.succeed(
|
||||||
|
'curl -sS -f https://${discourseDomain}/t/$(<topic_id) -H "Accept: application/json" -H "Api-Key: $(<api_key)" -H "Api-Username: system" | jq -e \'if .post_stream.posts[1].cooked == "<p>Test reply.</p>" then true else null end\' '
|
||||||
|
)
|
||||||
|
'';
|
||||||
|
})
|
|
@ -11,23 +11,23 @@ let
|
||||||
deps = {
|
deps = {
|
||||||
"base/trace_event/common" = fetchgit {
|
"base/trace_event/common" = fetchgit {
|
||||||
url = "${git_url}/chromium/src/base/trace_event/common.git";
|
url = "${git_url}/chromium/src/base/trace_event/common.git";
|
||||||
rev = "936ba8a963284a6b3737cf2f0474a7131073abee";
|
rev = "dab187b372fc17e51f5b9fad8201813d0aed5129";
|
||||||
sha256 = "14nr22fqdpxma1kzjflj6a865vr3hfnnm2gs4vcixyq4kmfzfcy2";
|
sha256 = "0dmpj9hj4xv3xb0fl1kb9hm4bhpbs2s5csx3z8cgjd5vwvhdzig4";
|
||||||
};
|
};
|
||||||
build = fetchgit {
|
build = fetchgit {
|
||||||
url = "${git_url}/chromium/src/build.git";
|
url = "${git_url}/chromium/src/build.git";
|
||||||
rev = "325e95d6dae64f35b160b3dc7d73218cee5ec079";
|
rev = "26e9d485d01d6e0eb9dadd21df767a63494c8fea";
|
||||||
sha256 = "0dddyxa76p2xpjhmxif05v63i5ar6h5v684fdl667sg84f5bhhxf";
|
sha256 = "1jjvsgj0cs97d26i3ba531ic1f9gqan8x7z4aya8yl8jx02l342q";
|
||||||
};
|
};
|
||||||
"third_party/googletest/src" = fetchgit {
|
"third_party/googletest/src" = fetchgit {
|
||||||
url = "${git_url}/external/github.com/google/googletest.git";
|
url = "${git_url}/external/github.com/google/googletest.git";
|
||||||
rev = "5ec7f0c4a113e2f18ac2c6cc7df51ad6afc24081";
|
rev = "e3f0319d89f4cbf32993de595d984183b1a9fc57";
|
||||||
sha256 = "0gmr10042c0xybxnn6g7ndj1na1mmd3l9w7449qlcv4s8gmfs7k6";
|
sha256 = "18xz71l2xjrqsc0q317whgw4xi1i5db24zcj7v04f5g6r1hyf1a5";
|
||||||
};
|
};
|
||||||
"third_party/icu" = fetchgit {
|
"third_party/icu" = fetchgit {
|
||||||
url = "${git_url}/chromium/deps/icu.git";
|
url = "${git_url}/chromium/deps/icu.git";
|
||||||
rev = "960f195aa87acaec46e6104ec93a596da7ae0843";
|
rev = "f2223961702f00a8833874b0560d615a2cc42738";
|
||||||
sha256 = "073kh6gpcairgjxf3hlhpqljc13gwl2aj8fz91fv220xibwqs834";
|
sha256 = "0z5p53kbrjfkjn0i12dpk55cp8976j2zk7a4wk88423s2c5w87zl";
|
||||||
};
|
};
|
||||||
"third_party/jinja2" = fetchgit {
|
"third_party/jinja2" = fetchgit {
|
||||||
url = "${git_url}/chromium/src/third_party/jinja2.git";
|
url = "${git_url}/chromium/src/third_party/jinja2.git";
|
||||||
|
@ -39,29 +39,31 @@ let
|
||||||
rev = "8f45f5cfa0009d2a70589bcda0349b8cb2b72783";
|
rev = "8f45f5cfa0009d2a70589bcda0349b8cb2b72783";
|
||||||
sha256 = "168ppjmicfdh4i1l0l25s86mdbrz9fgxmiq1rx33x79mph41scfz";
|
sha256 = "168ppjmicfdh4i1l0l25s86mdbrz9fgxmiq1rx33x79mph41scfz";
|
||||||
};
|
};
|
||||||
|
"third_party/zlib" = fetchgit {
|
||||||
|
url = "${git_url}/chromium/src/third_party/zlib.git";
|
||||||
|
rev = "156be8c52f80cde343088b4a69a80579101b6e67";
|
||||||
|
sha256 = "0hxbkkzmlv714fjq2jlp5dd2jc339xyh6gkjx1sz3srwv33mlk92";
|
||||||
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
in
|
in
|
||||||
|
|
||||||
stdenv.mkDerivation rec {
|
stdenv.mkDerivation rec {
|
||||||
pname = "v8";
|
pname = "v8";
|
||||||
version = "7.4.255";
|
version = "8.4.255";
|
||||||
|
|
||||||
doCheck = true;
|
doCheck = true;
|
||||||
|
|
||||||
patches = [
|
patches = [
|
||||||
(fetchpatch {
|
|
||||||
url = "https://raw.githubusercontent.com/RPi-Distro/chromium-browser/master/debian/patches/revert-Xclang-instcombine-lower-dbg-declare.patch";
|
|
||||||
sha256 = "02hczcg43m36q8j1kv5j3hq9czj9niiil9w13w22vzv2f3c67dvn";
|
|
||||||
})
|
|
||||||
./darwin.patch
|
./darwin.patch
|
||||||
|
./gcc_arm.patch # Fix building zlib with gcc on aarch64, from https://gist.github.com/Adenilson/d973b6fd96c7709d33ddf08cf1dcb149
|
||||||
];
|
];
|
||||||
|
|
||||||
src = fetchFromGitHub {
|
src = fetchFromGitHub {
|
||||||
owner = "v8";
|
owner = "v8";
|
||||||
repo = "v8";
|
repo = "v8";
|
||||||
rev = version;
|
rev = version;
|
||||||
sha256 = "14i0c71hmffzqnq9n73dh9dnabdxhbjhzkhqpk5yv9y90bwrzi2n";
|
sha256 = "07ymw4kqbz7kv311gpk5bs5q90wj73n2q7jkyfhqk4hvhs1q5bw7";
|
||||||
};
|
};
|
||||||
|
|
||||||
postUnpack = ''
|
postUnpack = ''
|
||||||
|
@ -97,9 +99,7 @@ stdenv.mkDerivation rec {
|
||||||
''v8_snapshot_toolchain="//build/toolchain/linux/unbundle:default"''
|
''v8_snapshot_toolchain="//build/toolchain/linux/unbundle:default"''
|
||||||
] ++ lib.optional stdenv.cc.isClang ''clang_base_path="${stdenv.cc}"'';
|
] ++ lib.optional stdenv.cc.isClang ''clang_base_path="${stdenv.cc}"'';
|
||||||
|
|
||||||
# with gcc8, -Wclass-memaccess became part of -Wall and causes logging limit
|
NIX_CFLAGS_COMPILE = "-O2";
|
||||||
# to be exceeded
|
|
||||||
NIX_CFLAGS_COMPILE = lib.optionalString stdenv.cc.isGNU "-Wno-class-memaccess";
|
|
||||||
|
|
||||||
nativeBuildInputs = [ gn ninja pkg-config python ]
|
nativeBuildInputs = [ gn ninja pkg-config python ]
|
||||||
++ lib.optionals stdenv.isDarwin [ xcbuild darwin.DarwinTools ];
|
++ lib.optionals stdenv.isDarwin [ xcbuild darwin.DarwinTools ];
|
||||||
|
|
31
pkgs/development/libraries/v8/gcc_arm.patch
Normal file
31
pkgs/development/libraries/v8/gcc_arm.patch
Normal file
|
@ -0,0 +1,31 @@
|
||||||
|
diff --git a/third_party/zlib/contrib/optimizations/insert_string.h b/third_party/zlib/contrib/optimizations/insert_string.h
|
||||||
|
index 1826601..d123305 100644
|
||||||
|
--- a/third_party/zlib/contrib/optimizations/insert_string.h
|
||||||
|
+++ b/third_party/zlib/contrib/optimizations/insert_string.h
|
||||||
|
@@ -26,15 +26,23 @@
|
||||||
|
#define _cpu_crc32_u32 _mm_crc32_u32
|
||||||
|
|
||||||
|
#elif defined(CRC32_ARMV8_CRC32)
|
||||||
|
- #if defined(__clang__)
|
||||||
|
+ #if defined(__GNUC__) || defined(__clang__)
|
||||||
|
#undef TARGET_CPU_WITH_CRC
|
||||||
|
- #define __crc32cw __builtin_arm_crc32cw
|
||||||
|
+ #if defined(__clang__)
|
||||||
|
+ #define __crc32cw __builtin_arm_crc32cw
|
||||||
|
+ #elif defined(__GNUC__)
|
||||||
|
+ #define __crc32cw __builtin_aarch64_crc32cw
|
||||||
|
+ #endif
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define _cpu_crc32_u32 __crc32cw
|
||||||
|
|
||||||
|
#if defined(__aarch64__)
|
||||||
|
- #define TARGET_CPU_WITH_CRC __attribute__((target("crc")))
|
||||||
|
+ #if defined(__clang__)
|
||||||
|
+ #define TARGET_CPU_WITH_CRC __attribute__((target("crc")))
|
||||||
|
+ #elif defined(__GNUC__)
|
||||||
|
+ #define TARGET_CPU_WITH_CRC __attribute__((target("+crc")))
|
||||||
|
+ #endif
|
||||||
|
#else // !defined(__aarch64__)
|
||||||
|
#define TARGET_CPU_WITH_CRC __attribute__((target("armv8-a,crc")))
|
||||||
|
#endif // defined(__aarch64__)
|
12
pkgs/servers/web-apps/discourse/action_mailer_ca_cert.patch
Normal file
12
pkgs/servers/web-apps/discourse/action_mailer_ca_cert.patch
Normal file
|
@ -0,0 +1,12 @@
|
||||||
|
diff --git a/config/environments/production.rb b/config/environments/production.rb
|
||||||
|
index 75c3a69512..7fc374cd9d 100644
|
||||||
|
--- a/config/environments/production.rb
|
||||||
|
+++ b/config/environments/production.rb
|
||||||
|
@@ -32,6 +32,7 @@ Discourse::Application.configure do
|
||||||
|
user_name: GlobalSetting.smtp_user_name,
|
||||||
|
password: GlobalSetting.smtp_password,
|
||||||
|
authentication: GlobalSetting.smtp_authentication,
|
||||||
|
+ ca_file: "/etc/ssl/certs/ca-certificates.crt",
|
||||||
|
enable_starttls_auto: GlobalSetting.smtp_enable_start_tls
|
||||||
|
}
|
||||||
|
|
48
pkgs/servers/web-apps/discourse/admin_create.patch
Normal file
48
pkgs/servers/web-apps/discourse/admin_create.patch
Normal file
|
@ -0,0 +1,48 @@
|
||||||
|
diff --git a/lib/tasks/admin.rake b/lib/tasks/admin.rake
|
||||||
|
index 80c403616d..cba01202ac 100644
|
||||||
|
--- a/lib/tasks/admin.rake
|
||||||
|
+++ b/lib/tasks/admin.rake
|
||||||
|
@@ -107,3 +107,43 @@ task "admin:create" => :environment do
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
||||||
|
+
|
||||||
|
+desc "Creates a forum administrator noninteractively"
|
||||||
|
+task "admin:create_noninteractively" => :environment do
|
||||||
|
+ email = ENV["ADMIN_EMAIL"]
|
||||||
|
+ existing_user = User.find_by_email(email)
|
||||||
|
+
|
||||||
|
+ # check if user account already exixts
|
||||||
|
+ if existing_user
|
||||||
|
+ admin = existing_user
|
||||||
|
+ else
|
||||||
|
+ # create new user
|
||||||
|
+ admin = User.new
|
||||||
|
+ end
|
||||||
|
+
|
||||||
|
+ admin.email = email
|
||||||
|
+ admin.name = ENV["ADMIN_NAME"]
|
||||||
|
+ admin.username = ENV["ADMIN_USERNAME"]
|
||||||
|
+
|
||||||
|
+ password = ENV["ADMIN_PASSWORD"]
|
||||||
|
+ unless admin.confirm_password?(password)
|
||||||
|
+ admin.password = password
|
||||||
|
+ puts "Admin password set!"
|
||||||
|
+ end
|
||||||
|
+
|
||||||
|
+ admin.active = true
|
||||||
|
+
|
||||||
|
+ # save/update user account
|
||||||
|
+ saved = admin.save
|
||||||
|
+ raise admin.errors.full_messages.join("\n") unless saved
|
||||||
|
+
|
||||||
|
+ puts "Account created successfully with username #{admin.username}" unless existing_user
|
||||||
|
+
|
||||||
|
+ # grant admin privileges
|
||||||
|
+ admin.grant_admin!
|
||||||
|
+ if admin.trust_level < 1
|
||||||
|
+ admin.change_trust_level!(1)
|
||||||
|
+ end
|
||||||
|
+ admin.email_tokens.update_all confirmed: true
|
||||||
|
+ admin.activate
|
||||||
|
+end
|
234
pkgs/servers/web-apps/discourse/default.nix
Normal file
234
pkgs/servers/web-apps/discourse/default.nix
Normal file
|
@ -0,0 +1,234 @@
|
||||||
|
{ stdenv, makeWrapper, runCommandNoCC, lib, nixosTests
|
||||||
|
, fetchFromGitHub, bundlerEnv, ruby, replace, gzip, gnutar, git
|
||||||
|
, util-linux, gawk, imagemagick, optipng, pngquant, libjpeg, jpegoptim
|
||||||
|
, gifsicle, libpsl, redis, postgresql, which, brotli, procps
|
||||||
|
, nodePackages, v8
|
||||||
|
}:
|
||||||
|
|
||||||
|
let
|
||||||
|
version = "2.6.3";
|
||||||
|
|
||||||
|
src = fetchFromGitHub {
|
||||||
|
owner = "discourse";
|
||||||
|
repo = "discourse";
|
||||||
|
rev = "v${version}";
|
||||||
|
sha256 = "sha256-lAIhVxvmjxEiru1KNxbFV+eDMLUGza/Dma3WU0ex0xs=";
|
||||||
|
};
|
||||||
|
|
||||||
|
runtimeDeps = [
|
||||||
|
# For backups, themes and assets
|
||||||
|
rubyEnv.wrappedRuby
|
||||||
|
gzip
|
||||||
|
gnutar
|
||||||
|
git
|
||||||
|
brotli
|
||||||
|
|
||||||
|
# Misc required system utils
|
||||||
|
which
|
||||||
|
procps # For ps and kill
|
||||||
|
util-linux # For renice
|
||||||
|
gawk
|
||||||
|
|
||||||
|
# Image optimization
|
||||||
|
imagemagick
|
||||||
|
optipng
|
||||||
|
pngquant
|
||||||
|
libjpeg
|
||||||
|
jpegoptim
|
||||||
|
gifsicle
|
||||||
|
nodePackages.svgo
|
||||||
|
];
|
||||||
|
|
||||||
|
runtimeEnv = {
|
||||||
|
HOME = "/run/discourse/home";
|
||||||
|
RAILS_ENV = "production";
|
||||||
|
UNICORN_LISTENER = "/run/discourse/sockets/unicorn.sock";
|
||||||
|
};
|
||||||
|
|
||||||
|
rake = runCommandNoCC "discourse-rake" {
|
||||||
|
nativeBuildInputs = [ makeWrapper ];
|
||||||
|
} ''
|
||||||
|
mkdir -p $out/bin
|
||||||
|
makeWrapper ${rubyEnv}/bin/rake $out/bin/discourse-rake \
|
||||||
|
${lib.concatStrings (lib.mapAttrsToList (name: value: "--set ${name} '${value}' ") runtimeEnv)} \
|
||||||
|
--prefix PATH : ${lib.makeBinPath runtimeDeps} \
|
||||||
|
--set RAKEOPT '-f ${discourse}/share/discourse/Rakefile' \
|
||||||
|
--run 'cd ${discourse}/share/discourse'
|
||||||
|
'';
|
||||||
|
|
||||||
|
rubyEnv = bundlerEnv {
|
||||||
|
name = "discourse-ruby-env-${version}";
|
||||||
|
inherit version ruby;
|
||||||
|
gemdir = ./rubyEnv;
|
||||||
|
gemset =
|
||||||
|
let
|
||||||
|
gems = import ./rubyEnv/gemset.nix;
|
||||||
|
in
|
||||||
|
gems // {
|
||||||
|
mini_racer = gems.mini_racer // {
|
||||||
|
buildInputs = [ v8 ];
|
||||||
|
dontBuild = false;
|
||||||
|
# The Ruby extension makefile generator assumes the source
|
||||||
|
# is C, when it's actually C++ ¯\_(ツ)_/¯
|
||||||
|
postPatch = ''
|
||||||
|
substituteInPlace ext/mini_racer_extension/extconf.rb \
|
||||||
|
--replace '" -std=c++0x"' \
|
||||||
|
'" -x c++ -std=c++0x"'
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
mini_suffix = gems.mini_suffix // {
|
||||||
|
propagatedBuildInputs = [ libpsl ];
|
||||||
|
dontBuild = false;
|
||||||
|
# Use our libpsl instead of the vendored one, which isn't
|
||||||
|
# available for aarch64
|
||||||
|
postPatch = ''
|
||||||
|
cp $(readlink -f ${libpsl}/lib/libpsl.so) vendor/libpsl.so
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
groups = [
|
||||||
|
"default" "assets" "development" "test"
|
||||||
|
];
|
||||||
|
};
|
||||||
|
|
||||||
|
assets = stdenv.mkDerivation {
|
||||||
|
pname = "discourse-assets";
|
||||||
|
inherit version src;
|
||||||
|
|
||||||
|
nativeBuildInputs = [
|
||||||
|
rubyEnv.wrappedRuby
|
||||||
|
postgresql
|
||||||
|
redis
|
||||||
|
which
|
||||||
|
brotli
|
||||||
|
procps
|
||||||
|
nodePackages.uglify-js
|
||||||
|
];
|
||||||
|
|
||||||
|
# We have to set up an environment that is close enough to
|
||||||
|
# production ready or the assets:precompile task refuses to
|
||||||
|
# run. This means that Redis and PostgreSQL has to be running and
|
||||||
|
# database migrations performed.
|
||||||
|
preBuild = ''
|
||||||
|
redis-server >/dev/null &
|
||||||
|
|
||||||
|
initdb -A trust $NIX_BUILD_TOP/postgres >/dev/null
|
||||||
|
postgres -D $NIX_BUILD_TOP/postgres -k $NIX_BUILD_TOP >/dev/null &
|
||||||
|
export PGHOST=$NIX_BUILD_TOP
|
||||||
|
|
||||||
|
echo "Waiting for Redis and PostgreSQL to be ready.."
|
||||||
|
while ! redis-cli --scan >/dev/null || ! psql -l >/dev/null; do
|
||||||
|
sleep 0.1
|
||||||
|
done
|
||||||
|
|
||||||
|
psql -d postgres -tAc 'CREATE USER "discourse"'
|
||||||
|
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"
|
||||||
|
|
||||||
|
# Create a temporary home dir to stop bundler from complaining
|
||||||
|
mkdir $NIX_BUILD_TOP/tmp_home
|
||||||
|
export HOME=$NIX_BUILD_TOP/tmp_home
|
||||||
|
|
||||||
|
export RAILS_ENV=production
|
||||||
|
|
||||||
|
bundle exec rake db:migrate >/dev/null
|
||||||
|
rm -r tmp/*
|
||||||
|
'';
|
||||||
|
|
||||||
|
buildPhase = ''
|
||||||
|
runHook preBuild
|
||||||
|
|
||||||
|
bundle exec rake assets:precompile
|
||||||
|
|
||||||
|
runHook postBuild
|
||||||
|
'';
|
||||||
|
|
||||||
|
installPhase = ''
|
||||||
|
runHook preInstall
|
||||||
|
|
||||||
|
mv public/assets $out
|
||||||
|
|
||||||
|
runHook postInstall
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
|
||||||
|
discourse = stdenv.mkDerivation {
|
||||||
|
pname = "discourse";
|
||||||
|
inherit version src;
|
||||||
|
|
||||||
|
buildInputs = [
|
||||||
|
rubyEnv rubyEnv.wrappedRuby rubyEnv.bundler
|
||||||
|
];
|
||||||
|
|
||||||
|
patches = [
|
||||||
|
# Load a separate NixOS site settings file
|
||||||
|
./nixos_defaults.patch
|
||||||
|
|
||||||
|
# Add a noninteractive admin creation task
|
||||||
|
./admin_create.patch
|
||||||
|
|
||||||
|
# Disable jhead, which is currently marked as vulnerable
|
||||||
|
./disable_jhead.patch
|
||||||
|
|
||||||
|
# Add the path to the CA cert bundle to make TLS work
|
||||||
|
./action_mailer_ca_cert.patch
|
||||||
|
|
||||||
|
# Log Unicorn messages to the journal and make request timeout
|
||||||
|
# configurable
|
||||||
|
./unicorn_logging_and_timeout.patch
|
||||||
|
];
|
||||||
|
|
||||||
|
postPatch = ''
|
||||||
|
# Always require lib-files and application.rb through their store
|
||||||
|
# path, not their relative state directory path. This gets rid of
|
||||||
|
# warnings and means we don't have to link back to lib from the
|
||||||
|
# state directory.
|
||||||
|
find config -type f -execdir sed -Ei "s,(\.\./)+(lib|app)/,$out/share/discourse/\2/," {} \;
|
||||||
|
|
||||||
|
${replace}/bin/replace-literal -f -r -e 'File.rename(temp_destination, destination)' "FileUtils.mv(temp_destination, destination)" .
|
||||||
|
'';
|
||||||
|
|
||||||
|
buildPhase = ''
|
||||||
|
runHook preBuild
|
||||||
|
|
||||||
|
mv config config.dist
|
||||||
|
mv public public.dist
|
||||||
|
mv plugins plugins.dist
|
||||||
|
|
||||||
|
runHook postBuild
|
||||||
|
'';
|
||||||
|
|
||||||
|
installPhase = ''
|
||||||
|
runHook preInstall
|
||||||
|
|
||||||
|
mkdir -p $out/share
|
||||||
|
cp -r . $out/share/discourse
|
||||||
|
rm -r $out/share/discourse/log
|
||||||
|
ln -sf /var/log/discourse $out/share/discourse/log
|
||||||
|
ln -sf /run/discourse/tmp $out/share/discourse/tmp
|
||||||
|
ln -sf /run/discourse/config $out/share/discourse/config
|
||||||
|
ln -sf /run/discourse/assets/javascripts/plugins $out/share/discourse/app/assets/javascripts/plugins
|
||||||
|
ln -sf /run/discourse/public $out/share/discourse/public
|
||||||
|
ln -sf /run/discourse/plugins $out/share/discourse/plugins
|
||||||
|
ln -sf ${assets} $out/share/discourse/public.dist/assets
|
||||||
|
|
||||||
|
runHook postInstall
|
||||||
|
'';
|
||||||
|
|
||||||
|
meta = with lib; {
|
||||||
|
homepage = "https://www.discourse.org/";
|
||||||
|
platforms = platforms.linux;
|
||||||
|
maintainers = with maintainers; [ talyz ];
|
||||||
|
license = licenses.gpl2Plus;
|
||||||
|
description = "Discourse is an open source discussion platform";
|
||||||
|
};
|
||||||
|
|
||||||
|
passthru = {
|
||||||
|
inherit rubyEnv runtimeEnv runtimeDeps rake;
|
||||||
|
ruby = rubyEnv.wrappedRuby;
|
||||||
|
tests = nixosTests.discourse;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
in discourse
|
12
pkgs/servers/web-apps/discourse/disable_jhead.patch
Normal file
12
pkgs/servers/web-apps/discourse/disable_jhead.patch
Normal file
|
@ -0,0 +1,12 @@
|
||||||
|
diff --git a/lib/file_helper.rb b/lib/file_helper.rb
|
||||||
|
index 162de9a40b..9ac8807e9d 100644
|
||||||
|
--- a/lib/file_helper.rb
|
||||||
|
+++ b/lib/file_helper.rb
|
||||||
|
@@ -124,6 +124,7 @@ class FileHelper
|
||||||
|
jpegoptim: { strip: strip_image_metadata ? "all" : "none" },
|
||||||
|
jpegtran: false,
|
||||||
|
jpegrecompress: false,
|
||||||
|
+ jhead: false,
|
||||||
|
)
|
||||||
|
end
|
||||||
|
end
|
39
pkgs/servers/web-apps/discourse/mail_receiver/default.nix
Normal file
39
pkgs/servers/web-apps/discourse/mail_receiver/default.nix
Normal file
|
@ -0,0 +1,39 @@
|
||||||
|
{ stdenv, lib, fetchFromGitHub, ruby, makeWrapper, replace }:
|
||||||
|
|
||||||
|
stdenv.mkDerivation rec {
|
||||||
|
pname = "discourse-mail-receiver";
|
||||||
|
version = "4.0.7";
|
||||||
|
|
||||||
|
src = fetchFromGitHub {
|
||||||
|
owner = "discourse";
|
||||||
|
repo = "mail-receiver";
|
||||||
|
rev = "v${version}";
|
||||||
|
sha256 = "0grifm5qyqazq63va3w26xjqnxwmfixhx0fx0zy7kd39378wwa6i";
|
||||||
|
};
|
||||||
|
|
||||||
|
nativeBuildInputs = [ replace ];
|
||||||
|
buildInputs = [ ruby makeWrapper ];
|
||||||
|
|
||||||
|
dontBuild = true;
|
||||||
|
|
||||||
|
installPhase = ''
|
||||||
|
mkdir -p $out/bin
|
||||||
|
|
||||||
|
replace-literal -f -r -e /etc/postfix /run/discourse-mail-receiver .
|
||||||
|
|
||||||
|
cp -r receive-mail discourse-smtp-fast-rejection $out/bin/
|
||||||
|
cp -r lib $out/
|
||||||
|
|
||||||
|
wrapProgram $out/bin/receive-mail --set RUBYLIB $out/lib
|
||||||
|
wrapProgram $out/bin/discourse-smtp-fast-rejection --set RUBYLIB $out/lib
|
||||||
|
'';
|
||||||
|
|
||||||
|
meta = with lib; {
|
||||||
|
homepage = "https://www.discourse.org/";
|
||||||
|
platforms = platforms.linux;
|
||||||
|
maintainers = with maintainers; [ talyz ];
|
||||||
|
license = licenses.mit;
|
||||||
|
description = "A helper program which receives incoming mail for Discourse";
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
13
pkgs/servers/web-apps/discourse/nixos_defaults.patch
Normal file
13
pkgs/servers/web-apps/discourse/nixos_defaults.patch
Normal file
|
@ -0,0 +1,13 @@
|
||||||
|
diff --git a/app/models/site_setting.rb b/app/models/site_setting.rb
|
||||||
|
index 89a5e923fc..b60754f50a 100644
|
||||||
|
--- a/app/models/site_setting.rb
|
||||||
|
+++ b/app/models/site_setting.rb
|
||||||
|
@@ -26,6 +26,8 @@ class SiteSetting < ActiveRecord::Base
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
+ load_settings(File.join(Rails.root, 'config', 'nixos_site_settings.json'))
|
||||||
|
+
|
||||||
|
setup_deprecated_methods
|
||||||
|
client_settings << :available_locales
|
||||||
|
|
248
pkgs/servers/web-apps/discourse/rubyEnv/Gemfile
Normal file
248
pkgs/servers/web-apps/discourse/rubyEnv/Gemfile
Normal file
|
@ -0,0 +1,248 @@
|
||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
|
source 'https://rubygems.org'
|
||||||
|
# if there is a super emergency and rubygems is playing up, try
|
||||||
|
#source 'http://production.cf.rubygems.org'
|
||||||
|
|
||||||
|
gem 'bootsnap', require: false, platform: :mri
|
||||||
|
|
||||||
|
def rails_master?
|
||||||
|
ENV["RAILS_MASTER"] == '1'
|
||||||
|
end
|
||||||
|
|
||||||
|
if rails_master?
|
||||||
|
gem 'arel', git: 'https://github.com/rails/arel.git'
|
||||||
|
gem 'rails', git: 'https://github.com/rails/rails.git'
|
||||||
|
else
|
||||||
|
# NOTE: Until rubygems gives us optional dependencies we are stuck with this needing to be explicit
|
||||||
|
# this allows us to include the bits of rails we use without pieces we do not.
|
||||||
|
#
|
||||||
|
# To issue a rails update bump the version number here
|
||||||
|
gem 'actionmailer', '6.0.3.3'
|
||||||
|
gem 'actionpack', '6.0.3.3'
|
||||||
|
gem 'actionview', '6.0.3.3'
|
||||||
|
gem 'activemodel', '6.0.3.3'
|
||||||
|
gem 'activerecord', '6.0.3.3'
|
||||||
|
gem 'activesupport', '6.0.3.3'
|
||||||
|
gem 'railties', '6.0.3.3'
|
||||||
|
gem 'sprockets-rails'
|
||||||
|
end
|
||||||
|
|
||||||
|
gem 'json'
|
||||||
|
|
||||||
|
# TODO: At the moment Discourse does not work with Sprockets 4, we would need to correct internals
|
||||||
|
# This is a desired upgrade we should get to.
|
||||||
|
gem 'sprockets', '3.7.2'
|
||||||
|
|
||||||
|
# this will eventually be added to rails,
|
||||||
|
# allows us to precompile all our templates in the unicorn master
|
||||||
|
gem 'actionview_precompiler', require: false
|
||||||
|
|
||||||
|
gem 'seed-fu'
|
||||||
|
|
||||||
|
gem 'mail', require: false
|
||||||
|
gem 'mini_mime'
|
||||||
|
gem 'mini_suffix'
|
||||||
|
|
||||||
|
gem 'redis'
|
||||||
|
|
||||||
|
# This is explicitly used by Sidekiq and is an optional dependency.
|
||||||
|
# We tell Sidekiq to use the namespace "sidekiq" which triggers this
|
||||||
|
# gem to be used. There is no explicit dependency in sidekiq cause
|
||||||
|
# redis namespace support is optional
|
||||||
|
# We already namespace stuff in DiscourseRedis, so we should consider
|
||||||
|
# just using a single implementation in core vs having 2 namespace implementations
|
||||||
|
gem 'redis-namespace'
|
||||||
|
|
||||||
|
# NOTE: AM serializer gets a lot slower with recent updates
|
||||||
|
# we used an old branch which is the fastest one out there
|
||||||
|
# are long term goal here is to fork this gem so we have a
|
||||||
|
# better maintained living fork
|
||||||
|
gem 'active_model_serializers', '~> 0.8.3'
|
||||||
|
|
||||||
|
gem 'onebox'
|
||||||
|
|
||||||
|
gem 'http_accept_language', require: false
|
||||||
|
|
||||||
|
# Ember related gems need to be pinned cause they control client side
|
||||||
|
# behavior, we will push these versions up when upgrading ember
|
||||||
|
gem 'discourse-ember-rails', '0.18.6', require: 'ember-rails'
|
||||||
|
gem 'discourse-ember-source', '~> 3.12.2'
|
||||||
|
gem 'ember-handlebars-template', '0.8.0'
|
||||||
|
gem 'discourse-fonts'
|
||||||
|
|
||||||
|
gem 'barber'
|
||||||
|
|
||||||
|
gem 'message_bus'
|
||||||
|
|
||||||
|
gem 'rails_multisite'
|
||||||
|
|
||||||
|
gem 'fast_xs', platform: :ruby
|
||||||
|
|
||||||
|
gem 'xorcist'
|
||||||
|
|
||||||
|
gem 'fastimage'
|
||||||
|
|
||||||
|
gem 'aws-sdk-s3', require: false
|
||||||
|
gem 'aws-sdk-sns', require: false
|
||||||
|
gem 'excon', require: false
|
||||||
|
gem 'unf', require: false
|
||||||
|
|
||||||
|
gem 'email_reply_trimmer'
|
||||||
|
|
||||||
|
# Forked until https://github.com/toy/image_optim/pull/162 is merged
|
||||||
|
# https://github.com/discourse/image_optim
|
||||||
|
gem 'discourse_image_optim', require: 'image_optim'
|
||||||
|
gem 'multi_json'
|
||||||
|
gem 'mustache'
|
||||||
|
gem 'nokogiri'
|
||||||
|
gem 'css_parser', require: false
|
||||||
|
|
||||||
|
gem 'omniauth'
|
||||||
|
gem 'omniauth-facebook'
|
||||||
|
gem 'omniauth-twitter'
|
||||||
|
gem 'omniauth-github'
|
||||||
|
|
||||||
|
gem 'omniauth-oauth2', require: false
|
||||||
|
|
||||||
|
gem 'omniauth-google-oauth2'
|
||||||
|
|
||||||
|
gem 'oj'
|
||||||
|
gem 'pg'
|
||||||
|
gem 'mini_sql'
|
||||||
|
gem 'pry-rails', require: false
|
||||||
|
gem 'pry-byebug', require: false
|
||||||
|
gem 'r2', require: false
|
||||||
|
gem 'rake'
|
||||||
|
|
||||||
|
gem 'thor', require: false
|
||||||
|
gem 'diffy', require: false
|
||||||
|
gem 'rinku'
|
||||||
|
gem 'sidekiq'
|
||||||
|
gem 'mini_scheduler'
|
||||||
|
|
||||||
|
gem 'execjs', require: false
|
||||||
|
gem 'mini_racer'
|
||||||
|
|
||||||
|
gem 'highline', require: false
|
||||||
|
|
||||||
|
gem 'rack'
|
||||||
|
|
||||||
|
gem 'rack-protection' # security
|
||||||
|
gem 'cbor', require: false
|
||||||
|
gem 'cose', require: false
|
||||||
|
gem 'addressable'
|
||||||
|
|
||||||
|
# Gems used only for assets and not required in production environments by default.
|
||||||
|
# Allow everywhere for now cause we are allowing asset debugging in production
|
||||||
|
group :assets do
|
||||||
|
gem 'uglifier'
|
||||||
|
gem 'rtlit', require: false # for css rtling
|
||||||
|
end
|
||||||
|
|
||||||
|
group :test do
|
||||||
|
gem 'webmock', require: false
|
||||||
|
gem 'fakeweb', require: false
|
||||||
|
gem 'minitest', require: false
|
||||||
|
gem 'simplecov', require: false
|
||||||
|
gem "test-prof"
|
||||||
|
end
|
||||||
|
|
||||||
|
group :test, :development do
|
||||||
|
gem 'rspec'
|
||||||
|
gem 'mock_redis'
|
||||||
|
gem 'listen', require: false
|
||||||
|
gem 'certified', require: false
|
||||||
|
gem 'fabrication', require: false
|
||||||
|
gem 'mocha', require: false
|
||||||
|
|
||||||
|
gem 'rb-fsevent', require: RUBY_PLATFORM =~ /darwin/i ? 'rb-fsevent' : false
|
||||||
|
|
||||||
|
gem 'rspec-rails'
|
||||||
|
|
||||||
|
gem 'shoulda-matchers', require: false
|
||||||
|
gem 'rspec-html-matchers'
|
||||||
|
gem 'byebug', require: ENV['RM_INFO'].nil?, platform: :mri
|
||||||
|
gem "rubocop-discourse", require: false
|
||||||
|
gem 'parallel_tests'
|
||||||
|
|
||||||
|
gem 'rswag-specs'
|
||||||
|
end
|
||||||
|
|
||||||
|
group :development do
|
||||||
|
gem 'ruby-prof', require: false, platform: :mri
|
||||||
|
gem 'bullet', require: !!ENV['BULLET']
|
||||||
|
gem 'better_errors', platform: :mri, require: !!ENV['BETTER_ERRORS']
|
||||||
|
gem 'binding_of_caller'
|
||||||
|
gem 'yaml-lint'
|
||||||
|
gem 'annotate'
|
||||||
|
end
|
||||||
|
|
||||||
|
# this is an optional gem, it provides a high performance replacement
|
||||||
|
# to String#blank? a method that is called quite frequently in current
|
||||||
|
# ActiveRecord, this may change in the future
|
||||||
|
gem 'fast_blank', platform: :ruby
|
||||||
|
|
||||||
|
# this provides a very efficient lru cache
|
||||||
|
gem 'lru_redux'
|
||||||
|
|
||||||
|
gem 'htmlentities', require: false
|
||||||
|
|
||||||
|
# IMPORTANT: mini profiler monkey patches, so it better be required last
|
||||||
|
# If you want to amend mini profiler to do the monkey patches in the railties
|
||||||
|
# we are open to it. by deferring require to the initializer we can configure discourse installs without it
|
||||||
|
|
||||||
|
gem 'flamegraph', require: false
|
||||||
|
gem 'rack-mini-profiler', require: ['enable_rails_patches']
|
||||||
|
|
||||||
|
gem 'unicorn', require: false, platform: :ruby
|
||||||
|
gem 'puma', require: false
|
||||||
|
gem 'rbtrace', require: false, platform: :mri
|
||||||
|
gem 'gc_tracer', require: false, platform: :mri
|
||||||
|
|
||||||
|
# required for feed importing and embedding
|
||||||
|
gem 'ruby-readability', require: false
|
||||||
|
|
||||||
|
gem 'stackprof', require: false, platform: :mri
|
||||||
|
gem 'memory_profiler', require: false, platform: :mri
|
||||||
|
|
||||||
|
gem 'cppjieba_rb', require: false
|
||||||
|
|
||||||
|
gem 'lograge', require: false
|
||||||
|
gem 'logstash-event', require: false
|
||||||
|
gem 'logstash-logger', require: false
|
||||||
|
gem 'logster'
|
||||||
|
|
||||||
|
# NOTE: later versions of sassc are causing a segfault, possibly dependent on processer architecture
|
||||||
|
# and until resolved should be locked at 2.0.1
|
||||||
|
gem 'sassc', '2.0.1', require: false
|
||||||
|
gem "sassc-rails"
|
||||||
|
|
||||||
|
gem 'rotp', require: false
|
||||||
|
|
||||||
|
gem 'rqrcode'
|
||||||
|
|
||||||
|
gem 'rubyzip', require: false
|
||||||
|
|
||||||
|
gem 'sshkey', require: false
|
||||||
|
|
||||||
|
gem 'rchardet', require: false
|
||||||
|
gem 'lz4-ruby', require: false, platform: :ruby
|
||||||
|
|
||||||
|
if ENV["IMPORT"] == "1"
|
||||||
|
gem 'mysql2'
|
||||||
|
gem 'redcarpet'
|
||||||
|
|
||||||
|
# NOTE: in import mode the version of sqlite can matter a lot, so we stick it to a specific one
|
||||||
|
gem 'sqlite3', '~> 1.3', '>= 1.3.13'
|
||||||
|
gem 'ruby-bbcode-to-md', git: 'https://github.com/nlalonde/ruby-bbcode-to-md'
|
||||||
|
gem 'reverse_markdown'
|
||||||
|
gem 'tiny_tds'
|
||||||
|
gem 'csv'
|
||||||
|
end
|
||||||
|
|
||||||
|
gem 'webpush', require: false
|
||||||
|
gem 'colored2', require: false
|
||||||
|
gem 'maxminddb'
|
||||||
|
|
||||||
|
gem 'rails_failover', require: false
|
561
pkgs/servers/web-apps/discourse/rubyEnv/Gemfile.lock
Normal file
561
pkgs/servers/web-apps/discourse/rubyEnv/Gemfile.lock
Normal file
|
@ -0,0 +1,561 @@
|
||||||
|
GEM
|
||||||
|
remote: https://rubygems.org/
|
||||||
|
specs:
|
||||||
|
actionmailer (6.0.3.3)
|
||||||
|
actionpack (= 6.0.3.3)
|
||||||
|
actionview (= 6.0.3.3)
|
||||||
|
activejob (= 6.0.3.3)
|
||||||
|
mail (~> 2.5, >= 2.5.4)
|
||||||
|
rails-dom-testing (~> 2.0)
|
||||||
|
actionpack (6.0.3.3)
|
||||||
|
actionview (= 6.0.3.3)
|
||||||
|
activesupport (= 6.0.3.3)
|
||||||
|
rack (~> 2.0, >= 2.0.8)
|
||||||
|
rack-test (>= 0.6.3)
|
||||||
|
rails-dom-testing (~> 2.0)
|
||||||
|
rails-html-sanitizer (~> 1.0, >= 1.2.0)
|
||||||
|
actionview (6.0.3.3)
|
||||||
|
activesupport (= 6.0.3.3)
|
||||||
|
builder (~> 3.1)
|
||||||
|
erubi (~> 1.4)
|
||||||
|
rails-dom-testing (~> 2.0)
|
||||||
|
rails-html-sanitizer (~> 1.1, >= 1.2.0)
|
||||||
|
actionview_precompiler (0.2.3)
|
||||||
|
actionview (>= 6.0.a)
|
||||||
|
active_model_serializers (0.8.4)
|
||||||
|
activemodel (>= 3.0)
|
||||||
|
activejob (6.0.3.3)
|
||||||
|
activesupport (= 6.0.3.3)
|
||||||
|
globalid (>= 0.3.6)
|
||||||
|
activemodel (6.0.3.3)
|
||||||
|
activesupport (= 6.0.3.3)
|
||||||
|
activerecord (6.0.3.3)
|
||||||
|
activemodel (= 6.0.3.3)
|
||||||
|
activesupport (= 6.0.3.3)
|
||||||
|
activesupport (6.0.3.3)
|
||||||
|
concurrent-ruby (~> 1.0, >= 1.0.2)
|
||||||
|
i18n (>= 0.7, < 2)
|
||||||
|
minitest (~> 5.1)
|
||||||
|
tzinfo (~> 1.1)
|
||||||
|
zeitwerk (~> 2.2, >= 2.2.2)
|
||||||
|
addressable (2.7.0)
|
||||||
|
public_suffix (>= 2.0.2, < 5.0)
|
||||||
|
annotate (3.1.1)
|
||||||
|
activerecord (>= 3.2, < 7.0)
|
||||||
|
rake (>= 10.4, < 14.0)
|
||||||
|
ast (2.4.1)
|
||||||
|
aws-eventstream (1.1.0)
|
||||||
|
aws-partitions (1.390.0)
|
||||||
|
aws-sdk-core (3.109.2)
|
||||||
|
aws-eventstream (~> 1, >= 1.0.2)
|
||||||
|
aws-partitions (~> 1, >= 1.239.0)
|
||||||
|
aws-sigv4 (~> 1.1)
|
||||||
|
jmespath (~> 1.0)
|
||||||
|
aws-sdk-kms (1.39.0)
|
||||||
|
aws-sdk-core (~> 3, >= 3.109.0)
|
||||||
|
aws-sigv4 (~> 1.1)
|
||||||
|
aws-sdk-s3 (1.83.2)
|
||||||
|
aws-sdk-core (~> 3, >= 3.109.0)
|
||||||
|
aws-sdk-kms (~> 1)
|
||||||
|
aws-sigv4 (~> 1.1)
|
||||||
|
aws-sdk-sns (1.35.0)
|
||||||
|
aws-sdk-core (~> 3, >= 3.109.0)
|
||||||
|
aws-sigv4 (~> 1.1)
|
||||||
|
aws-sigv4 (1.2.2)
|
||||||
|
aws-eventstream (~> 1, >= 1.0.2)
|
||||||
|
barber (0.12.2)
|
||||||
|
ember-source (>= 1.0, < 3.1)
|
||||||
|
execjs (>= 1.2, < 3)
|
||||||
|
better_errors (2.9.1)
|
||||||
|
coderay (>= 1.0.0)
|
||||||
|
erubi (>= 1.0.0)
|
||||||
|
rack (>= 0.9.0)
|
||||||
|
binding_of_caller (0.8.0)
|
||||||
|
debug_inspector (>= 0.0.1)
|
||||||
|
bootsnap (1.5.1)
|
||||||
|
msgpack (~> 1.0)
|
||||||
|
builder (3.2.4)
|
||||||
|
bullet (6.1.0)
|
||||||
|
activesupport (>= 3.0.0)
|
||||||
|
uniform_notifier (~> 1.11)
|
||||||
|
byebug (11.1.3)
|
||||||
|
cbor (0.5.9.6)
|
||||||
|
certified (1.0.0)
|
||||||
|
chunky_png (1.3.14)
|
||||||
|
coderay (1.1.3)
|
||||||
|
colored2 (3.1.2)
|
||||||
|
concurrent-ruby (1.1.7)
|
||||||
|
connection_pool (2.2.3)
|
||||||
|
cose (1.2.0)
|
||||||
|
cbor (~> 0.5.9)
|
||||||
|
openssl-signature_algorithm (~> 1.0)
|
||||||
|
cppjieba_rb (0.3.3)
|
||||||
|
crack (0.4.4)
|
||||||
|
crass (1.0.6)
|
||||||
|
css_parser (1.7.1)
|
||||||
|
addressable
|
||||||
|
debug_inspector (0.0.3)
|
||||||
|
diff-lcs (1.4.4)
|
||||||
|
diffy (3.4.0)
|
||||||
|
discourse-ember-rails (0.18.6)
|
||||||
|
active_model_serializers
|
||||||
|
ember-data-source (>= 1.0.0.beta.5)
|
||||||
|
ember-handlebars-template (>= 0.1.1, < 1.0)
|
||||||
|
ember-source (>= 1.1.0)
|
||||||
|
jquery-rails (>= 1.0.17)
|
||||||
|
railties (>= 3.1)
|
||||||
|
discourse-ember-source (3.12.2.2)
|
||||||
|
discourse-fonts (0.0.5)
|
||||||
|
discourse_image_optim (0.26.2)
|
||||||
|
exifr (~> 1.2, >= 1.2.2)
|
||||||
|
fspath (~> 3.0)
|
||||||
|
image_size (~> 1.5)
|
||||||
|
in_threads (~> 1.3)
|
||||||
|
progress (~> 3.0, >= 3.0.1)
|
||||||
|
docile (1.3.2)
|
||||||
|
email_reply_trimmer (0.1.13)
|
||||||
|
ember-data-source (3.0.2)
|
||||||
|
ember-source (>= 2, < 3.0)
|
||||||
|
ember-handlebars-template (0.8.0)
|
||||||
|
barber (>= 0.11.0)
|
||||||
|
sprockets (>= 3.3, < 4.1)
|
||||||
|
ember-source (2.18.2)
|
||||||
|
erubi (1.10.0)
|
||||||
|
excon (0.78.0)
|
||||||
|
execjs (2.7.0)
|
||||||
|
exifr (1.3.9)
|
||||||
|
fabrication (2.21.1)
|
||||||
|
fakeweb (1.3.0)
|
||||||
|
faraday (1.1.0)
|
||||||
|
multipart-post (>= 1.2, < 3)
|
||||||
|
ruby2_keywords
|
||||||
|
fast_blank (1.0.0)
|
||||||
|
fast_xs (0.8.0)
|
||||||
|
fastimage (2.2.0)
|
||||||
|
ffi (1.13.1)
|
||||||
|
flamegraph (0.9.5)
|
||||||
|
fspath (3.1.2)
|
||||||
|
gc_tracer (1.5.1)
|
||||||
|
globalid (0.4.2)
|
||||||
|
activesupport (>= 4.2.0)
|
||||||
|
guess_html_encoding (0.0.11)
|
||||||
|
hashdiff (1.0.1)
|
||||||
|
hashie (4.1.0)
|
||||||
|
highline (2.0.3)
|
||||||
|
hkdf (0.3.0)
|
||||||
|
htmlentities (4.3.4)
|
||||||
|
http_accept_language (2.1.1)
|
||||||
|
i18n (1.8.5)
|
||||||
|
concurrent-ruby (~> 1.0)
|
||||||
|
image_size (1.5.0)
|
||||||
|
in_threads (1.5.4)
|
||||||
|
jmespath (1.4.0)
|
||||||
|
jquery-rails (4.4.0)
|
||||||
|
rails-dom-testing (>= 1, < 3)
|
||||||
|
railties (>= 4.2.0)
|
||||||
|
thor (>= 0.14, < 2.0)
|
||||||
|
json (2.3.1)
|
||||||
|
json-schema (2.8.1)
|
||||||
|
addressable (>= 2.4)
|
||||||
|
jwt (2.2.2)
|
||||||
|
kgio (2.11.3)
|
||||||
|
libv8 (8.4.255.0)
|
||||||
|
listen (3.3.1)
|
||||||
|
rb-fsevent (~> 0.10, >= 0.10.3)
|
||||||
|
rb-inotify (~> 0.9, >= 0.9.10)
|
||||||
|
lograge (0.11.2)
|
||||||
|
actionpack (>= 4)
|
||||||
|
activesupport (>= 4)
|
||||||
|
railties (>= 4)
|
||||||
|
request_store (~> 1.0)
|
||||||
|
logstash-event (1.2.02)
|
||||||
|
logstash-logger (0.26.1)
|
||||||
|
logstash-event (~> 1.2)
|
||||||
|
logster (2.9.4)
|
||||||
|
loofah (2.8.0)
|
||||||
|
crass (~> 1.0.2)
|
||||||
|
nokogiri (>= 1.5.9)
|
||||||
|
lru_redux (1.1.0)
|
||||||
|
lz4-ruby (0.3.3)
|
||||||
|
mail (2.7.1)
|
||||||
|
mini_mime (>= 0.1.1)
|
||||||
|
maxminddb (0.1.22)
|
||||||
|
memory_profiler (0.9.14)
|
||||||
|
message_bus (3.3.4)
|
||||||
|
rack (>= 1.1.3)
|
||||||
|
method_source (1.0.0)
|
||||||
|
mini_mime (1.0.2)
|
||||||
|
mini_portile2 (2.4.0)
|
||||||
|
mini_racer (0.3.1)
|
||||||
|
libv8 (~> 8.4.255)
|
||||||
|
mini_scheduler (0.12.3)
|
||||||
|
sidekiq
|
||||||
|
mini_sql (0.3)
|
||||||
|
mini_suffix (0.3.0)
|
||||||
|
ffi (~> 1.9)
|
||||||
|
minitest (5.14.2)
|
||||||
|
mocha (1.11.2)
|
||||||
|
mock_redis (0.26.0)
|
||||||
|
msgpack (1.3.3)
|
||||||
|
multi_json (1.15.0)
|
||||||
|
multi_xml (0.6.0)
|
||||||
|
multipart-post (2.1.1)
|
||||||
|
mustache (1.1.1)
|
||||||
|
nio4r (2.5.4)
|
||||||
|
nokogiri (1.10.10)
|
||||||
|
mini_portile2 (~> 2.4.0)
|
||||||
|
nokogumbo (2.0.2)
|
||||||
|
nokogiri (~> 1.8, >= 1.8.4)
|
||||||
|
oauth (0.5.4)
|
||||||
|
oauth2 (1.4.4)
|
||||||
|
faraday (>= 0.8, < 2.0)
|
||||||
|
jwt (>= 1.0, < 3.0)
|
||||||
|
multi_json (~> 1.3)
|
||||||
|
multi_xml (~> 0.5)
|
||||||
|
rack (>= 1.2, < 3)
|
||||||
|
oj (3.10.16)
|
||||||
|
omniauth (1.9.1)
|
||||||
|
hashie (>= 3.4.6)
|
||||||
|
rack (>= 1.6.2, < 3)
|
||||||
|
omniauth-facebook (8.0.0)
|
||||||
|
omniauth-oauth2 (~> 1.2)
|
||||||
|
omniauth-github (1.4.0)
|
||||||
|
omniauth (~> 1.5)
|
||||||
|
omniauth-oauth2 (>= 1.4.0, < 2.0)
|
||||||
|
omniauth-google-oauth2 (0.8.0)
|
||||||
|
jwt (>= 2.0)
|
||||||
|
omniauth (>= 1.1.1)
|
||||||
|
omniauth-oauth2 (>= 1.6)
|
||||||
|
omniauth-oauth (1.1.0)
|
||||||
|
oauth
|
||||||
|
omniauth (~> 1.0)
|
||||||
|
omniauth-oauth2 (1.7.0)
|
||||||
|
oauth2 (~> 1.4)
|
||||||
|
omniauth (~> 1.9)
|
||||||
|
omniauth-twitter (1.4.0)
|
||||||
|
omniauth-oauth (~> 1.1)
|
||||||
|
rack
|
||||||
|
onebox (2.2.1)
|
||||||
|
addressable (~> 2.7.0)
|
||||||
|
htmlentities (~> 4.3)
|
||||||
|
multi_json (~> 1.11)
|
||||||
|
mustache
|
||||||
|
nokogiri (~> 1.7)
|
||||||
|
sanitize
|
||||||
|
openssl-signature_algorithm (1.0.0)
|
||||||
|
optimist (3.0.1)
|
||||||
|
parallel (1.20.1)
|
||||||
|
parallel_tests (3.4.0)
|
||||||
|
parallel
|
||||||
|
parser (2.7.2.0)
|
||||||
|
ast (~> 2.4.1)
|
||||||
|
pg (1.2.3)
|
||||||
|
progress (3.5.2)
|
||||||
|
pry (0.13.1)
|
||||||
|
coderay (~> 1.1)
|
||||||
|
method_source (~> 1.0)
|
||||||
|
pry-byebug (3.9.0)
|
||||||
|
byebug (~> 11.0)
|
||||||
|
pry (~> 0.13.0)
|
||||||
|
pry-rails (0.3.9)
|
||||||
|
pry (>= 0.10.4)
|
||||||
|
public_suffix (4.0.6)
|
||||||
|
puma (5.0.4)
|
||||||
|
nio4r (~> 2.0)
|
||||||
|
r2 (0.2.7)
|
||||||
|
rack (2.2.3)
|
||||||
|
rack-mini-profiler (2.2.0)
|
||||||
|
rack (>= 1.2.0)
|
||||||
|
rack-protection (2.1.0)
|
||||||
|
rack
|
||||||
|
rack-test (1.1.0)
|
||||||
|
rack (>= 1.0, < 3)
|
||||||
|
rails-dom-testing (2.0.3)
|
||||||
|
activesupport (>= 4.2.0)
|
||||||
|
nokogiri (>= 1.6)
|
||||||
|
rails-html-sanitizer (1.3.0)
|
||||||
|
loofah (~> 2.3)
|
||||||
|
rails_failover (0.6.2)
|
||||||
|
activerecord (~> 6.0)
|
||||||
|
concurrent-ruby
|
||||||
|
railties (~> 6.0)
|
||||||
|
rails_multisite (2.5.0)
|
||||||
|
activerecord (> 5.0, < 7)
|
||||||
|
railties (> 5.0, < 7)
|
||||||
|
railties (6.0.3.3)
|
||||||
|
actionpack (= 6.0.3.3)
|
||||||
|
activesupport (= 6.0.3.3)
|
||||||
|
method_source
|
||||||
|
rake (>= 0.8.7)
|
||||||
|
thor (>= 0.20.3, < 2.0)
|
||||||
|
rainbow (3.0.0)
|
||||||
|
raindrops (0.19.1)
|
||||||
|
rake (13.0.1)
|
||||||
|
rb-fsevent (0.10.4)
|
||||||
|
rb-inotify (0.10.1)
|
||||||
|
ffi (~> 1.0)
|
||||||
|
rbtrace (0.4.14)
|
||||||
|
ffi (>= 1.0.6)
|
||||||
|
msgpack (>= 0.4.3)
|
||||||
|
optimist (>= 3.0.0)
|
||||||
|
rchardet (1.8.0)
|
||||||
|
redis (4.2.5)
|
||||||
|
redis-namespace (1.8.0)
|
||||||
|
redis (>= 3.0.4)
|
||||||
|
regexp_parser (2.0.0)
|
||||||
|
request_store (1.5.0)
|
||||||
|
rack (>= 1.4)
|
||||||
|
rexml (3.2.4)
|
||||||
|
rinku (2.0.6)
|
||||||
|
rotp (6.2.0)
|
||||||
|
rqrcode (1.1.2)
|
||||||
|
chunky_png (~> 1.0)
|
||||||
|
rqrcode_core (~> 0.1)
|
||||||
|
rqrcode_core (0.1.2)
|
||||||
|
rspec (3.10.0)
|
||||||
|
rspec-core (~> 3.10.0)
|
||||||
|
rspec-expectations (~> 3.10.0)
|
||||||
|
rspec-mocks (~> 3.10.0)
|
||||||
|
rspec-core (3.10.0)
|
||||||
|
rspec-support (~> 3.10.0)
|
||||||
|
rspec-expectations (3.10.0)
|
||||||
|
diff-lcs (>= 1.2.0, < 2.0)
|
||||||
|
rspec-support (~> 3.10.0)
|
||||||
|
rspec-html-matchers (0.9.4)
|
||||||
|
nokogiri (~> 1)
|
||||||
|
rspec (>= 3.0.0.a, < 4)
|
||||||
|
rspec-mocks (3.10.0)
|
||||||
|
diff-lcs (>= 1.2.0, < 2.0)
|
||||||
|
rspec-support (~> 3.10.0)
|
||||||
|
rspec-rails (4.0.1)
|
||||||
|
actionpack (>= 4.2)
|
||||||
|
activesupport (>= 4.2)
|
||||||
|
railties (>= 4.2)
|
||||||
|
rspec-core (~> 3.9)
|
||||||
|
rspec-expectations (~> 3.9)
|
||||||
|
rspec-mocks (~> 3.9)
|
||||||
|
rspec-support (~> 3.9)
|
||||||
|
rspec-support (3.10.0)
|
||||||
|
rswag-specs (2.3.1)
|
||||||
|
activesupport (>= 3.1, < 7.0)
|
||||||
|
json-schema (~> 2.2)
|
||||||
|
railties (>= 3.1, < 7.0)
|
||||||
|
rtlit (0.0.5)
|
||||||
|
rubocop (1.4.2)
|
||||||
|
parallel (~> 1.10)
|
||||||
|
parser (>= 2.7.1.5)
|
||||||
|
rainbow (>= 2.2.2, < 4.0)
|
||||||
|
regexp_parser (>= 1.8)
|
||||||
|
rexml
|
||||||
|
rubocop-ast (>= 1.1.1)
|
||||||
|
ruby-progressbar (~> 1.7)
|
||||||
|
unicode-display_width (>= 1.4.0, < 2.0)
|
||||||
|
rubocop-ast (1.2.0)
|
||||||
|
parser (>= 2.7.1.5)
|
||||||
|
rubocop-discourse (2.4.1)
|
||||||
|
rubocop (>= 1.1.0)
|
||||||
|
rubocop-rspec (>= 2.0.0)
|
||||||
|
rubocop-rspec (2.0.0)
|
||||||
|
rubocop (~> 1.0)
|
||||||
|
rubocop-ast (>= 1.1.0)
|
||||||
|
ruby-prof (1.4.2)
|
||||||
|
ruby-progressbar (1.10.1)
|
||||||
|
ruby-readability (0.7.0)
|
||||||
|
guess_html_encoding (>= 0.0.4)
|
||||||
|
nokogiri (>= 1.6.0)
|
||||||
|
ruby2_keywords (0.0.2)
|
||||||
|
rubyzip (2.3.0)
|
||||||
|
sanitize (5.2.1)
|
||||||
|
crass (~> 1.0.2)
|
||||||
|
nokogiri (>= 1.8.0)
|
||||||
|
nokogumbo (~> 2.0)
|
||||||
|
sassc (2.0.1)
|
||||||
|
ffi (~> 1.9)
|
||||||
|
rake
|
||||||
|
sassc-rails (2.1.2)
|
||||||
|
railties (>= 4.0.0)
|
||||||
|
sassc (>= 2.0)
|
||||||
|
sprockets (> 3.0)
|
||||||
|
sprockets-rails
|
||||||
|
tilt
|
||||||
|
seed-fu (2.3.9)
|
||||||
|
activerecord (>= 3.1)
|
||||||
|
activesupport (>= 3.1)
|
||||||
|
shoulda-matchers (4.4.1)
|
||||||
|
activesupport (>= 4.2.0)
|
||||||
|
sidekiq (6.1.2)
|
||||||
|
connection_pool (>= 2.2.2)
|
||||||
|
rack (~> 2.0)
|
||||||
|
redis (>= 4.2.0)
|
||||||
|
simplecov (0.20.0)
|
||||||
|
docile (~> 1.1)
|
||||||
|
simplecov-html (~> 0.11)
|
||||||
|
simplecov_json_formatter (~> 0.1)
|
||||||
|
simplecov-html (0.12.3)
|
||||||
|
simplecov_json_formatter (0.1.2)
|
||||||
|
sprockets (3.7.2)
|
||||||
|
concurrent-ruby (~> 1.0)
|
||||||
|
rack (> 1, < 3)
|
||||||
|
sprockets-rails (3.2.2)
|
||||||
|
actionpack (>= 4.0)
|
||||||
|
activesupport (>= 4.0)
|
||||||
|
sprockets (>= 3.0.0)
|
||||||
|
sshkey (2.0.0)
|
||||||
|
stackprof (0.2.16)
|
||||||
|
test-prof (0.12.2)
|
||||||
|
thor (1.0.1)
|
||||||
|
thread_safe (0.3.6)
|
||||||
|
tilt (2.0.10)
|
||||||
|
tzinfo (1.2.8)
|
||||||
|
thread_safe (~> 0.1)
|
||||||
|
uglifier (4.2.0)
|
||||||
|
execjs (>= 0.3.0, < 3)
|
||||||
|
unf (0.1.4)
|
||||||
|
unf_ext
|
||||||
|
unf_ext (0.0.7.7)
|
||||||
|
unicode-display_width (1.7.0)
|
||||||
|
unicorn (5.7.0)
|
||||||
|
kgio (~> 2.6)
|
||||||
|
raindrops (~> 0.7)
|
||||||
|
uniform_notifier (1.13.0)
|
||||||
|
webmock (3.10.0)
|
||||||
|
addressable (>= 2.3.6)
|
||||||
|
crack (>= 0.3.2)
|
||||||
|
hashdiff (>= 0.4.0, < 2.0.0)
|
||||||
|
webpush (1.1.0)
|
||||||
|
hkdf (~> 0.2)
|
||||||
|
jwt (~> 2.0)
|
||||||
|
xorcist (1.1.2)
|
||||||
|
yaml-lint (0.0.10)
|
||||||
|
zeitwerk (2.4.1)
|
||||||
|
|
||||||
|
PLATFORMS
|
||||||
|
ruby
|
||||||
|
|
||||||
|
DEPENDENCIES
|
||||||
|
actionmailer (= 6.0.3.3)
|
||||||
|
actionpack (= 6.0.3.3)
|
||||||
|
actionview (= 6.0.3.3)
|
||||||
|
actionview_precompiler
|
||||||
|
active_model_serializers (~> 0.8.3)
|
||||||
|
activemodel (= 6.0.3.3)
|
||||||
|
activerecord (= 6.0.3.3)
|
||||||
|
activesupport (= 6.0.3.3)
|
||||||
|
addressable
|
||||||
|
annotate
|
||||||
|
aws-sdk-s3
|
||||||
|
aws-sdk-sns
|
||||||
|
barber
|
||||||
|
better_errors
|
||||||
|
binding_of_caller
|
||||||
|
bootsnap
|
||||||
|
bullet
|
||||||
|
byebug
|
||||||
|
cbor
|
||||||
|
certified
|
||||||
|
colored2
|
||||||
|
cose
|
||||||
|
cppjieba_rb
|
||||||
|
css_parser
|
||||||
|
diffy
|
||||||
|
discourse-ember-rails (= 0.18.6)
|
||||||
|
discourse-ember-source (~> 3.12.2)
|
||||||
|
discourse-fonts
|
||||||
|
discourse_image_optim
|
||||||
|
email_reply_trimmer
|
||||||
|
ember-handlebars-template (= 0.8.0)
|
||||||
|
excon
|
||||||
|
execjs
|
||||||
|
fabrication
|
||||||
|
fakeweb
|
||||||
|
fast_blank
|
||||||
|
fast_xs
|
||||||
|
fastimage
|
||||||
|
flamegraph
|
||||||
|
gc_tracer
|
||||||
|
highline
|
||||||
|
htmlentities
|
||||||
|
http_accept_language
|
||||||
|
json
|
||||||
|
listen
|
||||||
|
lograge
|
||||||
|
logstash-event
|
||||||
|
logstash-logger
|
||||||
|
logster
|
||||||
|
lru_redux
|
||||||
|
lz4-ruby
|
||||||
|
mail
|
||||||
|
maxminddb
|
||||||
|
memory_profiler
|
||||||
|
message_bus
|
||||||
|
mini_mime
|
||||||
|
mini_racer
|
||||||
|
mini_scheduler
|
||||||
|
mini_sql
|
||||||
|
mini_suffix
|
||||||
|
minitest
|
||||||
|
mocha
|
||||||
|
mock_redis
|
||||||
|
multi_json
|
||||||
|
mustache
|
||||||
|
nokogiri
|
||||||
|
oj
|
||||||
|
omniauth
|
||||||
|
omniauth-facebook
|
||||||
|
omniauth-github
|
||||||
|
omniauth-google-oauth2
|
||||||
|
omniauth-oauth2
|
||||||
|
omniauth-twitter
|
||||||
|
onebox
|
||||||
|
parallel_tests
|
||||||
|
pg
|
||||||
|
pry-byebug
|
||||||
|
pry-rails
|
||||||
|
puma
|
||||||
|
r2
|
||||||
|
rack
|
||||||
|
rack-mini-profiler
|
||||||
|
rack-protection
|
||||||
|
rails_failover
|
||||||
|
rails_multisite
|
||||||
|
railties (= 6.0.3.3)
|
||||||
|
rake
|
||||||
|
rb-fsevent
|
||||||
|
rbtrace
|
||||||
|
rchardet
|
||||||
|
redis
|
||||||
|
redis-namespace
|
||||||
|
rinku
|
||||||
|
rotp
|
||||||
|
rqrcode
|
||||||
|
rspec
|
||||||
|
rspec-html-matchers
|
||||||
|
rspec-rails
|
||||||
|
rswag-specs
|
||||||
|
rtlit
|
||||||
|
rubocop-discourse
|
||||||
|
ruby-prof
|
||||||
|
ruby-readability
|
||||||
|
rubyzip
|
||||||
|
sassc (= 2.0.1)
|
||||||
|
sassc-rails
|
||||||
|
seed-fu
|
||||||
|
shoulda-matchers
|
||||||
|
sidekiq
|
||||||
|
simplecov
|
||||||
|
sprockets (= 3.7.2)
|
||||||
|
sprockets-rails
|
||||||
|
sshkey
|
||||||
|
stackprof
|
||||||
|
test-prof
|
||||||
|
thor
|
||||||
|
uglifier
|
||||||
|
unf
|
||||||
|
unicorn
|
||||||
|
webmock
|
||||||
|
webpush
|
||||||
|
xorcist
|
||||||
|
yaml-lint
|
||||||
|
|
||||||
|
BUNDLED WITH
|
||||||
|
2.1.4
|
2272
pkgs/servers/web-apps/discourse/rubyEnv/gemset.nix
Normal file
2272
pkgs/servers/web-apps/discourse/rubyEnv/gemset.nix
Normal file
File diff suppressed because it is too large
Load diff
|
@ -0,0 +1,25 @@
|
||||||
|
diff --git a/config/unicorn.conf.rb b/config/unicorn.conf.rb
|
||||||
|
index 373e235b3f..57d4d7a55b 100644
|
||||||
|
--- a/config/unicorn.conf.rb
|
||||||
|
+++ b/config/unicorn.conf.rb
|
||||||
|
@@ -27,18 +27,10 @@ pid (ENV["UNICORN_PID_PATH"] || "#{discourse_path}/tmp/pids/unicorn.pid")
|
||||||
|
|
||||||
|
if ENV["RAILS_ENV"] == "development" || !ENV["RAILS_ENV"]
|
||||||
|
logger Logger.new($stdout)
|
||||||
|
- # we want a longer timeout in dev cause first request can be really slow
|
||||||
|
- timeout (ENV["UNICORN_TIMEOUT"] && ENV["UNICORN_TIMEOUT"].to_i || 60)
|
||||||
|
-else
|
||||||
|
- # By default, the Unicorn logger will write to stderr.
|
||||||
|
- # Additionally, some applications/frameworks log to stderr or stdout,
|
||||||
|
- # so prevent them from going to /dev/null when daemonized here:
|
||||||
|
- stderr_path "#{discourse_path}/log/unicorn.stderr.log"
|
||||||
|
- stdout_path "#{discourse_path}/log/unicorn.stdout.log"
|
||||||
|
- # nuke workers after 30 seconds instead of 60 seconds (the default)
|
||||||
|
- timeout 30
|
||||||
|
end
|
||||||
|
|
||||||
|
+timeout (ENV["UNICORN_TIMEOUT"] && ENV["UNICORN_TIMEOUT"].to_i || 60)
|
||||||
|
+
|
||||||
|
# important for Ruby 2.0
|
||||||
|
preload_app true
|
||||||
|
|
164
pkgs/servers/web-apps/discourse/update.py
Executable file
164
pkgs/servers/web-apps/discourse/update.py
Executable file
|
@ -0,0 +1,164 @@
|
||||||
|
#!/usr/bin/env nix-shell
|
||||||
|
#! nix-shell -i python3 -p bundix bundler nix-update python3 python3Packages.requests python3Packages.click python3Packages.click-log
|
||||||
|
|
||||||
|
import click
|
||||||
|
import click_log
|
||||||
|
import shutil
|
||||||
|
import tempfile
|
||||||
|
import re
|
||||||
|
import logging
|
||||||
|
import subprocess
|
||||||
|
import pathlib
|
||||||
|
from distutils.version import LooseVersion
|
||||||
|
from typing import Iterable
|
||||||
|
|
||||||
|
import requests
|
||||||
|
|
||||||
|
logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
|
||||||
|
class DiscourseRepo:
|
||||||
|
version_regex = re.compile(r'^v\d+\.\d+\.\d+$')
|
||||||
|
def __init__(self, owner: str = 'discourse', repo: str = 'discourse'):
|
||||||
|
self.owner = owner
|
||||||
|
self.repo = repo
|
||||||
|
|
||||||
|
@property
|
||||||
|
def tags(self) -> Iterable[str]:
|
||||||
|
r = requests.get(f'https://api.github.com/repos/{self.owner}/{self.repo}/git/refs/tags').json()
|
||||||
|
tags = [x['ref'].replace('refs/tags/', '') for x in r]
|
||||||
|
|
||||||
|
# filter out versions not matching version_regex
|
||||||
|
versions = list(filter(self.version_regex.match, tags))
|
||||||
|
|
||||||
|
# sort, but ignore v for sorting comparisons
|
||||||
|
versions.sort(key=lambda x: LooseVersion(x.replace('v', '')), reverse=True)
|
||||||
|
return versions
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def rev2version(tag: str) -> str:
|
||||||
|
"""
|
||||||
|
normalize a tag to a version number.
|
||||||
|
This obviously isn't very smart if we don't pass something that looks like a tag
|
||||||
|
:param tag: the tag to normalize
|
||||||
|
:return: a normalized version number
|
||||||
|
"""
|
||||||
|
# strip v prefix
|
||||||
|
return re.sub(r'^v', '', tag)
|
||||||
|
|
||||||
|
def get_file(self, filepath, rev):
|
||||||
|
"""returns file contents at a given rev :param filepath: the path to
|
||||||
|
the file, relative to the repo root :param rev: the rev to
|
||||||
|
fetch at :return:
|
||||||
|
|
||||||
|
"""
|
||||||
|
return requests.get(f'https://raw.githubusercontent.com/{self.owner}/{self.repo}/{rev}/{filepath}').text
|
||||||
|
|
||||||
|
|
||||||
|
def _call_nix_update(pkg, version):
|
||||||
|
"""calls nix-update from nixpkgs root dir"""
|
||||||
|
nixpkgs_path = pathlib.Path(__file__).parent / '../../../../'
|
||||||
|
return subprocess.check_output(['nix-update', pkg, '--version', version], cwd=nixpkgs_path)
|
||||||
|
|
||||||
|
|
||||||
|
def _get_current_package_version(pkg: str):
|
||||||
|
nixpkgs_path = pathlib.Path(__file__).parent / '../../../../'
|
||||||
|
return subprocess.check_output(['nix', 'eval', '--raw', f'nixpkgs.{pkg}.version'], text=True)
|
||||||
|
|
||||||
|
|
||||||
|
def _diff_file(filepath: str, old_version: str, new_version: str):
|
||||||
|
repo = DiscourseRepo()
|
||||||
|
|
||||||
|
current_dir = pathlib.Path(__file__).parent
|
||||||
|
|
||||||
|
old = repo.get_file(filepath, 'v' + old_version)
|
||||||
|
new = repo.get_file(filepath, 'v' + new_version)
|
||||||
|
|
||||||
|
if old == new:
|
||||||
|
click.secho(f'{filepath} is unchanged', fg='green')
|
||||||
|
return
|
||||||
|
|
||||||
|
with tempfile.NamedTemporaryFile(mode='w') as o, tempfile.NamedTemporaryFile(mode='w') as n:
|
||||||
|
o.write(old), n.write(new)
|
||||||
|
width = shutil.get_terminal_size((80, 20)).columns
|
||||||
|
diff_proc = subprocess.run(
|
||||||
|
['diff', '--color=always', f'--width={width}', '-y', o.name, n.name],
|
||||||
|
stdout=subprocess.PIPE,
|
||||||
|
cwd=current_dir,
|
||||||
|
text=True
|
||||||
|
)
|
||||||
|
|
||||||
|
click.secho(f'Diff for {filepath} ({old_version} -> {new_version}):', fg='bright_blue', bold=True)
|
||||||
|
click.echo(diff_proc.stdout + '\n')
|
||||||
|
return
|
||||||
|
|
||||||
|
|
||||||
|
@click_log.simple_verbosity_option(logger)
|
||||||
|
|
||||||
|
|
||||||
|
@click.group()
|
||||||
|
def cli():
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
@cli.command()
|
||||||
|
@click.argument('rev', default='latest')
|
||||||
|
@click.option('--reverse/--no-reverse', default=False, help='Print diffs from REV to current.')
|
||||||
|
def print_diffs(rev, reverse):
|
||||||
|
"""Print out diffs for files used as templates for the NixOS module.
|
||||||
|
|
||||||
|
The current package version found in the nixpkgs worktree the
|
||||||
|
script is run from will be used to download the "from" file and
|
||||||
|
REV used to download the "to" file for the diff, unless the
|
||||||
|
'--reverse' flag is specified.
|
||||||
|
|
||||||
|
REV should be the git rev to find changes in ('vX.Y.Z') or
|
||||||
|
'latest'; defaults to 'latest'.
|
||||||
|
|
||||||
|
"""
|
||||||
|
if rev == 'latest':
|
||||||
|
repo = DiscourseRepo()
|
||||||
|
rev = repo.tags[0]
|
||||||
|
|
||||||
|
old_version = _get_current_package_version('discourse')
|
||||||
|
new_version = DiscourseRepo.rev2version(rev)
|
||||||
|
|
||||||
|
if reverse:
|
||||||
|
old_version, new_version = new_version, old_version
|
||||||
|
|
||||||
|
for f in ['config/nginx.sample.conf', 'config/discourse_defaults.conf']:
|
||||||
|
_diff_file(f, old_version, new_version)
|
||||||
|
|
||||||
|
|
||||||
|
@cli.command()
|
||||||
|
@click.argument('rev', default='latest')
|
||||||
|
def update(rev):
|
||||||
|
"""Update gem files and version.
|
||||||
|
|
||||||
|
REV should be the git rev to update to ('vX.Y.Z') or 'latest';
|
||||||
|
defaults to 'latest'.
|
||||||
|
|
||||||
|
"""
|
||||||
|
repo = DiscourseRepo()
|
||||||
|
|
||||||
|
if rev == 'latest':
|
||||||
|
rev = repo.tags[0]
|
||||||
|
logger.debug(f"Using rev {rev}")
|
||||||
|
|
||||||
|
version = repo.rev2version(rev)
|
||||||
|
logger.debug(f"Using version {version}")
|
||||||
|
|
||||||
|
rubyenv_dir = pathlib.Path(__file__).parent / "rubyEnv"
|
||||||
|
|
||||||
|
for fn in ['Gemfile.lock', 'Gemfile']:
|
||||||
|
with open(rubyenv_dir / fn, 'w') as f:
|
||||||
|
f.write(repo.get_file(fn, rev))
|
||||||
|
|
||||||
|
subprocess.check_output(['bundle', 'lock'], cwd=rubyenv_dir)
|
||||||
|
subprocess.check_output(['bundix'], cwd=rubyenv_dir)
|
||||||
|
|
||||||
|
_call_nix_update('discourse', repo.rev2version(rev))
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
cli()
|
|
@ -2252,6 +2252,14 @@ in
|
||||||
|
|
||||||
discount = callPackage ../tools/text/discount { };
|
discount = callPackage ../tools/text/discount { };
|
||||||
|
|
||||||
|
discourse = callPackage ../servers/web-apps/discourse {
|
||||||
|
ruby = ruby_2_7;
|
||||||
|
};
|
||||||
|
|
||||||
|
discourse-mail-receiver = callPackage ../servers/web-apps/discourse/mail_receiver {
|
||||||
|
ruby = ruby_2_7;
|
||||||
|
};
|
||||||
|
|
||||||
discocss = callPackage ../tools/misc/discocss { };
|
discocss = callPackage ../tools/misc/discocss { };
|
||||||
|
|
||||||
disfetch = callPackage ../tools/misc/disfetch { };
|
disfetch = callPackage ../tools/misc/disfetch { };
|
||||||
|
@ -17625,12 +17633,8 @@ in
|
||||||
stdenv = gcc6Stdenv;
|
stdenv = gcc6Stdenv;
|
||||||
});
|
});
|
||||||
|
|
||||||
v8_6_x = v8;
|
|
||||||
v8 = callPackage ../development/libraries/v8 {
|
v8 = callPackage ../development/libraries/v8 {
|
||||||
inherit (python2Packages) python;
|
inherit (python2Packages) python;
|
||||||
} // lib.optionalAttrs stdenv.isLinux {
|
|
||||||
# doesn't build with gcc7
|
|
||||||
stdenv = gcc6Stdenv;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
vaapiIntel = callPackage ../development/libraries/vaapi-intel { };
|
vaapiIntel = callPackage ../development/libraries/vaapi-intel { };
|
||||||
|
|
|
@ -146,8 +146,8 @@ lib.makeScope pkgs.newScope (self: with self; {
|
||||||
|
|
||||||
sha256 = "103nys7zkpi1hifqp9miyl0m1mn07xqshw3sapyz365nb35g5q71";
|
sha256 = "103nys7zkpi1hifqp9miyl0m1mn07xqshw3sapyz365nb35g5q71";
|
||||||
|
|
||||||
buildInputs = [ pkgs.v8_6_x ];
|
buildInputs = [ pkgs.v8 ];
|
||||||
configureFlags = [ "--with-v8=${pkgs.v8_6_x}" ];
|
configureFlags = [ "--with-v8=${pkgs.v8}" ];
|
||||||
|
|
||||||
meta.maintainers = lib.teams.php.members;
|
meta.maintainers = lib.teams.php.members;
|
||||||
meta.broken = true;
|
meta.broken = true;
|
||||||
|
@ -159,8 +159,8 @@ lib.makeScope pkgs.newScope (self: with self; {
|
||||||
|
|
||||||
sha256 = "0g63dyhhicngbgqg34wl91nm3556vzdgkq19gy52gvmqj47rj6rg";
|
sha256 = "0g63dyhhicngbgqg34wl91nm3556vzdgkq19gy52gvmqj47rj6rg";
|
||||||
|
|
||||||
buildInputs = [ pkgs.v8_6_x ];
|
buildInputs = [ pkgs.v8 ];
|
||||||
configureFlags = [ "--with-v8js=${pkgs.v8_6_x}" ];
|
configureFlags = [ "--with-v8js=${pkgs.v8}" ];
|
||||||
|
|
||||||
meta.maintainers = lib.teams.php.members;
|
meta.maintainers = lib.teams.php.members;
|
||||||
meta.broken = true;
|
meta.broken = true;
|
||||||
|
|
Loading…
Reference in a new issue