at 22.05-pre 17 kB view raw
1<chapter xmlns="http://docbook.org/ns/docbook" 2 xmlns:xlink="http://www.w3.org/1999/xlink" 3 xmlns:xi="http://www.w3.org/2001/XInclude" 4 version="5.0" 5 xml:id="module-services-discourse"> 6 <title>Discourse</title> 7 <para> 8 <link xlink:href="https://www.discourse.org/">Discourse</link> is a 9 modern and open source discussion platform. 10 </para> 11 12 <section xml:id="module-services-discourse-basic-usage"> 13 <title>Basic usage</title> 14 <para> 15 A minimal configuration using Let's Encrypt for TLS certificates looks like this: 16<programlisting> 17services.discourse = { 18 <link linkend="opt-services.discourse.enable">enable</link> = true; 19 <link linkend="opt-services.discourse.hostname">hostname</link> = "discourse.example.com"; 20 admin = { 21 <link linkend="opt-services.discourse.admin.email">email</link> = "admin@example.com"; 22 <link linkend="opt-services.discourse.admin.username">username</link> = "admin"; 23 <link linkend="opt-services.discourse.admin.fullName">fullName</link> = "Administrator"; 24 <link linkend="opt-services.discourse.admin.passwordFile">passwordFile</link> = "/path/to/password_file"; 25 }; 26 <link linkend="opt-services.discourse.secretKeyBaseFile">secretKeyBaseFile</link> = "/path/to/secret_key_base_file"; 27}; 28<link linkend="opt-security.acme.email">security.acme.email</link> = "me@example.com"; 29<link linkend="opt-security.acme.acceptTerms">security.acme.acceptTerms</link> = true; 30</programlisting> 31 </para> 32 33 <para> 34 Provided a proper DNS setup, you'll be able to connect to the 35 instance at <literal>discourse.example.com</literal> and log in 36 using the credentials provided in 37 <literal>services.discourse.admin</literal>. 38 </para> 39 </section> 40 41 <section xml:id="module-services-discourse-tls"> 42 <title>Using a regular TLS certificate</title> 43 <para> 44 To set up TLS using a regular certificate and key on file, use 45 the <xref linkend="opt-services.discourse.sslCertificate" /> 46 and <xref linkend="opt-services.discourse.sslCertificateKey" /> 47 options: 48 49<programlisting> 50services.discourse = { 51 <link linkend="opt-services.discourse.enable">enable</link> = true; 52 <link linkend="opt-services.discourse.hostname">hostname</link> = "discourse.example.com"; 53 <link linkend="opt-services.discourse.sslCertificate">sslCertificate</link> = "/path/to/ssl_certificate"; 54 <link linkend="opt-services.discourse.sslCertificateKey">sslCertificateKey</link> = "/path/to/ssl_certificate_key"; 55 admin = { 56 <link linkend="opt-services.discourse.admin.email">email</link> = "admin@example.com"; 57 <link linkend="opt-services.discourse.admin.username">username</link> = "admin"; 58 <link linkend="opt-services.discourse.admin.fullName">fullName</link> = "Administrator"; 59 <link linkend="opt-services.discourse.admin.passwordFile">passwordFile</link> = "/path/to/password_file"; 60 }; 61 <link linkend="opt-services.discourse.secretKeyBaseFile">secretKeyBaseFile</link> = "/path/to/secret_key_base_file"; 62}; 63</programlisting> 64 65 </para> 66 </section> 67 68 <section xml:id="module-services-discourse-database"> 69 <title>Database access</title> 70 <para> 71 <productname>Discourse</productname> uses 72 <productname>PostgreSQL</productname> to store most of its 73 data. A database will automatically be enabled and a database 74 and role created unless <xref 75 linkend="opt-services.discourse.database.host" /> is changed from 76 its default of <literal>null</literal> or <xref 77 linkend="opt-services.discourse.database.createLocally" /> is set 78 to <literal>false</literal>. 79 </para> 80 81 <para> 82 External database access can also be configured by setting 83 <xref linkend="opt-services.discourse.database.host" />, <xref 84 linkend="opt-services.discourse.database.username" /> and <xref 85 linkend="opt-services.discourse.database.passwordFile" /> as 86 appropriate. Note that you need to manually create a database 87 called <literal>discourse</literal> (or the name you chose in 88 <xref linkend="opt-services.discourse.database.name" />) and 89 allow the configured database user full access to it. 90 </para> 91 </section> 92 93 <section xml:id="module-services-discourse-mail"> 94 <title>Email</title> 95 <para> 96 In addition to the basic setup, you'll want to configure an SMTP 97 server <productname>Discourse</productname> can use to send user 98 registration and password reset emails, among others. You can 99 also optionally let <productname>Discourse</productname> receive 100 email, which enables people to reply to threads and conversations 101 via email. 102 </para> 103 104 <para> 105 A basic setup which assumes you want to use your configured <link 106 linkend="opt-services.discourse.hostname">hostname</link> as 107 email domain can be done like this: 108 109<programlisting> 110services.discourse = { 111 <link linkend="opt-services.discourse.enable">enable</link> = true; 112 <link linkend="opt-services.discourse.hostname">hostname</link> = "discourse.example.com"; 113 <link linkend="opt-services.discourse.sslCertificate">sslCertificate</link> = "/path/to/ssl_certificate"; 114 <link linkend="opt-services.discourse.sslCertificateKey">sslCertificateKey</link> = "/path/to/ssl_certificate_key"; 115 admin = { 116 <link linkend="opt-services.discourse.admin.email">email</link> = "admin@example.com"; 117 <link linkend="opt-services.discourse.admin.username">username</link> = "admin"; 118 <link linkend="opt-services.discourse.admin.fullName">fullName</link> = "Administrator"; 119 <link linkend="opt-services.discourse.admin.passwordFile">passwordFile</link> = "/path/to/password_file"; 120 }; 121 mail.outgoing = { 122 <link linkend="opt-services.discourse.mail.outgoing.serverAddress">serverAddress</link> = "smtp.emailprovider.com"; 123 <link linkend="opt-services.discourse.mail.outgoing.port">port</link> = 587; 124 <link linkend="opt-services.discourse.mail.outgoing.username">username</link> = "user@emailprovider.com"; 125 <link linkend="opt-services.discourse.mail.outgoing.passwordFile">passwordFile</link> = "/path/to/smtp_password_file"; 126 }; 127 <link linkend="opt-services.discourse.mail.incoming.enable">mail.incoming.enable</link> = true; 128 <link linkend="opt-services.discourse.secretKeyBaseFile">secretKeyBaseFile</link> = "/path/to/secret_key_base_file"; 129}; 130</programlisting> 131 132 This assumes you have set up an MX record for the address you've 133 set in <link linkend="opt-services.discourse.hostname">hostname</link> and 134 requires proper SPF, DKIM and DMARC configuration to be done for 135 the domain you're sending from, in order for email to be reliably delivered. 136 </para> 137 138 <para> 139 If you want to use a different domain for your outgoing email 140 (for example <literal>example.com</literal> instead of 141 <literal>discourse.example.com</literal>) you should set 142 <xref linkend="opt-services.discourse.mail.notificationEmailAddress" /> and 143 <xref linkend="opt-services.discourse.mail.contactEmailAddress" /> manually. 144 </para> 145 146 <note> 147 <para> 148 Setup of TLS for incoming email is currently only configured 149 automatically when a regular TLS certificate is used, i.e. when 150 <xref linkend="opt-services.discourse.sslCertificate" /> and 151 <xref linkend="opt-services.discourse.sslCertificateKey" /> are 152 set. 153 </para> 154 </note> 155 156 </section> 157 158 <section xml:id="module-services-discourse-settings"> 159 <title>Additional settings</title> 160 <para> 161 Additional site settings and backend settings, for which no 162 explicit <productname>NixOS</productname> options are provided, 163 can be set in <xref linkend="opt-services.discourse.siteSettings" /> and 164 <xref linkend="opt-services.discourse.backendSettings" /> respectively. 165 </para> 166 167 <section xml:id="module-services-discourse-site-settings"> 168 <title>Site settings</title> 169 <para> 170 <quote>Site settings</quote> are the settings that can be 171 changed through the <productname>Discourse</productname> 172 UI. Their <emphasis>default</emphasis> values can be set using 173 <xref linkend="opt-services.discourse.siteSettings" />. 174 </para> 175 176 <para> 177 Settings are expressed as a Nix attribute set which matches the 178 structure of the configuration in 179 <link xlink:href="https://github.com/discourse/discourse/blob/master/config/site_settings.yml">config/site_settings.yml</link>. 180 To find a setting's path, you only need to care about the first 181 two levels; i.e. its category (e.g. <literal>login</literal>) 182 and name (e.g. <literal>invite_only</literal>). 183 </para> 184 185 <para> 186 Settings containing secret data should be set to an attribute 187 set containing the attribute <literal>_secret</literal> - a 188 string pointing to a file containing the value the option 189 should be set to. See the example. 190 </para> 191 </section> 192 193 <section xml:id="module-services-discourse-backend-settings"> 194 <title>Backend settings</title> 195 <para> 196 Settings are expressed as a Nix attribute set which matches the 197 structure of the configuration in 198 <link xlink:href="https://github.com/discourse/discourse/blob/stable/config/discourse_defaults.conf">config/discourse.conf</link>. 199 Empty parameters can be defined by setting them to 200 <literal>null</literal>. 201 </para> 202 </section> 203 204 <section xml:id="module-services-discourse-settings-example"> 205 <title>Example</title> 206 <para> 207 The following example sets the title and description of the 208 <productname>Discourse</productname> instance and enables 209 <productname>GitHub</productname> login in the site settings, 210 and changes a few request limits in the backend settings: 211<programlisting> 212services.discourse = { 213 <link linkend="opt-services.discourse.enable">enable</link> = true; 214 <link linkend="opt-services.discourse.hostname">hostname</link> = "discourse.example.com"; 215 <link linkend="opt-services.discourse.sslCertificate">sslCertificate</link> = "/path/to/ssl_certificate"; 216 <link linkend="opt-services.discourse.sslCertificateKey">sslCertificateKey</link> = "/path/to/ssl_certificate_key"; 217 admin = { 218 <link linkend="opt-services.discourse.admin.email">email</link> = "admin@example.com"; 219 <link linkend="opt-services.discourse.admin.username">username</link> = "admin"; 220 <link linkend="opt-services.discourse.admin.fullName">fullName</link> = "Administrator"; 221 <link linkend="opt-services.discourse.admin.passwordFile">passwordFile</link> = "/path/to/password_file"; 222 }; 223 mail.outgoing = { 224 <link linkend="opt-services.discourse.mail.outgoing.serverAddress">serverAddress</link> = "smtp.emailprovider.com"; 225 <link linkend="opt-services.discourse.mail.outgoing.port">port</link> = 587; 226 <link linkend="opt-services.discourse.mail.outgoing.username">username</link> = "user@emailprovider.com"; 227 <link linkend="opt-services.discourse.mail.outgoing.passwordFile">passwordFile</link> = "/path/to/smtp_password_file"; 228 }; 229 <link linkend="opt-services.discourse.mail.incoming.enable">mail.incoming.enable</link> = true; 230 <link linkend="opt-services.discourse.siteSettings">siteSettings</link> = { 231 required = { 232 title = "My Cats"; 233 site_description = "Discuss My Cats (and be nice plz)"; 234 }; 235 login = { 236 enable_github_logins = true; 237 github_client_id = "a2f6dfe838cb3206ce20"; 238 github_client_secret._secret = /run/keys/discourse_github_client_secret; 239 }; 240 }; 241 <link linkend="opt-services.discourse.backendSettings">backendSettings</link> = { 242 max_reqs_per_ip_per_minute = 300; 243 max_reqs_per_ip_per_10_seconds = 60; 244 max_asset_reqs_per_ip_per_10_seconds = 250; 245 max_reqs_per_ip_mode = "warn+block"; 246 }; 247 <link linkend="opt-services.discourse.secretKeyBaseFile">secretKeyBaseFile</link> = "/path/to/secret_key_base_file"; 248}; 249</programlisting> 250 </para> 251 <para> 252 In the resulting site settings file, the 253 <literal>login.github_client_secret</literal> key will be set 254 to the contents of the 255 <filename>/run/keys/discourse_github_client_secret</filename> 256 file. 257 </para> 258 </section> 259 </section> 260 <section xml:id="module-services-discourse-plugins"> 261 <title>Plugins</title> 262 <para> 263 You can install <productname>Discourse</productname> plugins 264 using the <xref linkend="opt-services.discourse.plugins" /> 265 option. Pre-packaged plugins are provided in 266 <literal>&lt;your_discourse_package_here&gt;.plugins</literal>. If 267 you want the full suite of plugins provided through 268 <literal>nixpkgs</literal>, you can also set the <xref 269 linkend="opt-services.discourse.package" /> option to 270 <literal>pkgs.discourseAllPlugins</literal>. 271 </para> 272 273 <para> 274 Plugins can be built with the 275 <literal>&lt;your_discourse_package_here&gt;.mkDiscoursePlugin</literal> 276 function. Normally, it should suffice to provide a 277 <literal>name</literal> and <literal>src</literal> attribute. If 278 the plugin has Ruby dependencies, however, they need to be 279 packaged in accordance with the <link 280 xlink:href="https://nixos.org/manual/nixpkgs/stable/#developing-with-ruby">Developing 281 with Ruby</link> section of the Nixpkgs manual and the 282 appropriate gem options set in <literal>bundlerEnvArgs</literal> 283 (normally <literal>gemdir</literal> is sufficient). A plugin's 284 Ruby dependencies are listed in its 285 <filename>plugin.rb</filename> file as function calls to 286 <literal>gem</literal>. To construct the corresponding 287 <filename>Gemfile</filename> manually, run <command>bundle 288 init</command>, then add the <literal>gem</literal> lines to it 289 verbatim. 290 </para> 291 292 <para> 293 Much of the packaging can be done automatically by the 294 <filename>nixpkgs/pkgs/servers/web-apps/discourse/update.py</filename> 295 script - just add the plugin to the <literal>plugins</literal> 296 list in the <function>update_plugins</function> function and run 297 the script: 298 <programlisting language="bash"> 299./update.py update-plugins 300</programlisting>. 301 </para> 302 303 <para> 304 Some plugins provide <link 305 linkend="module-services-discourse-site-settings">site 306 settings</link>. Their defaults can be configured using <xref 307 linkend="opt-services.discourse.siteSettings" />, just like 308 regular site settings. To find the names of these settings, look 309 in the <literal>config/settings.yml</literal> file of the plugin 310 repo. 311 </para> 312 313 <para> 314 For example, to add the <link 315 xlink:href="https://github.com/discourse/discourse-spoiler-alert">discourse-spoiler-alert</link> 316 and <link 317 xlink:href="https://github.com/discourse/discourse-solved">discourse-solved</link> 318 plugins, and disable <literal>discourse-spoiler-alert</literal> 319 by default: 320 321<programlisting> 322services.discourse = { 323 <link linkend="opt-services.discourse.enable">enable</link> = true; 324 <link linkend="opt-services.discourse.hostname">hostname</link> = "discourse.example.com"; 325 <link linkend="opt-services.discourse.sslCertificate">sslCertificate</link> = "/path/to/ssl_certificate"; 326 <link linkend="opt-services.discourse.sslCertificateKey">sslCertificateKey</link> = "/path/to/ssl_certificate_key"; 327 admin = { 328 <link linkend="opt-services.discourse.admin.email">email</link> = "admin@example.com"; 329 <link linkend="opt-services.discourse.admin.username">username</link> = "admin"; 330 <link linkend="opt-services.discourse.admin.fullName">fullName</link> = "Administrator"; 331 <link linkend="opt-services.discourse.admin.passwordFile">passwordFile</link> = "/path/to/password_file"; 332 }; 333 mail.outgoing = { 334 <link linkend="opt-services.discourse.mail.outgoing.serverAddress">serverAddress</link> = "smtp.emailprovider.com"; 335 <link linkend="opt-services.discourse.mail.outgoing.port">port</link> = 587; 336 <link linkend="opt-services.discourse.mail.outgoing.username">username</link> = "user@emailprovider.com"; 337 <link linkend="opt-services.discourse.mail.outgoing.passwordFile">passwordFile</link> = "/path/to/smtp_password_file"; 338 }; 339 <link linkend="opt-services.discourse.mail.incoming.enable">mail.incoming.enable</link> = true; 340 <link linkend="opt-services.discourse.mail.incoming.enable">plugins</link> = with config.services.discourse.package.plugins; [ 341 discourse-spoiler-alert 342 discourse-solved 343 ]; 344 <link linkend="opt-services.discourse.siteSettings">siteSettings</link> = { 345 plugins = { 346 spoiler_enabled = false; 347 }; 348 }; 349 <link linkend="opt-services.discourse.secretKeyBaseFile">secretKeyBaseFile</link> = "/path/to/secret_key_base_file"; 350}; 351</programlisting> 352 353 </para> 354 </section> 355</chapter>