1 # Discourse {#module-services-discourse}
3 [Discourse](https://www.discourse.org/) is a
4 modern and open source discussion platform.
6 ## Basic usage {#module-services-discourse-basic-usage}
8 A minimal configuration using Let's Encrypt for TLS certificates looks like this:
11 services.discourse = {
13 hostname = "discourse.example.com";
15 email = "admin@example.com";
17 fullName = "Administrator";
18 passwordFile = "/path/to/password_file";
20 secretKeyBaseFile = "/path/to/secret_key_base_file";
22 security.acme.email = "me@example.com";
23 security.acme.acceptTerms = true;
27 Provided a proper DNS setup, you'll be able to connect to the
28 instance at `discourse.example.com` and log in
29 using the credentials provided in
30 `services.discourse.admin`.
32 ## Using a regular TLS certificate {#module-services-discourse-tls}
34 To set up TLS using a regular certificate and key on file, use
35 the [](#opt-services.discourse.sslCertificate)
36 and [](#opt-services.discourse.sslCertificateKey)
41 services.discourse = {
43 hostname = "discourse.example.com";
44 sslCertificate = "/path/to/ssl_certificate";
45 sslCertificateKey = "/path/to/ssl_certificate_key";
47 email = "admin@example.com";
49 fullName = "Administrator";
50 passwordFile = "/path/to/password_file";
52 secretKeyBaseFile = "/path/to/secret_key_base_file";
57 ## Database access {#module-services-discourse-database}
59 Discourse uses PostgreSQL to store most of its
60 data. A database will automatically be enabled and a database
61 and role created unless [](#opt-services.discourse.database.host) is changed from
62 its default of `null` or [](#opt-services.discourse.database.createLocally) is set
65 External database access can also be configured by setting
66 [](#opt-services.discourse.database.host),
67 [](#opt-services.discourse.database.username) and
68 [](#opt-services.discourse.database.passwordFile) as
69 appropriate. Note that you need to manually create a database
70 called `discourse` (or the name you chose in
71 [](#opt-services.discourse.database.name)) and
72 allow the configured database user full access to it.
74 ## Email {#module-services-discourse-mail}
76 In addition to the basic setup, you'll want to configure an SMTP
77 server Discourse can use to send user
78 registration and password reset emails, among others. You can
79 also optionally let Discourse receive
80 email, which enables people to reply to threads and conversations
83 A basic setup which assumes you want to use your configured
84 [hostname](#opt-services.discourse.hostname) as
85 email domain can be done like this:
89 services.discourse = {
91 hostname = "discourse.example.com";
92 sslCertificate = "/path/to/ssl_certificate";
93 sslCertificateKey = "/path/to/ssl_certificate_key";
95 email = "admin@example.com";
97 fullName = "Administrator";
98 passwordFile = "/path/to/password_file";
101 serverAddress = "smtp.emailprovider.com";
103 username = "user@emailprovider.com";
104 passwordFile = "/path/to/smtp_password_file";
106 mail.incoming.enable = true;
107 secretKeyBaseFile = "/path/to/secret_key_base_file";
112 This assumes you have set up an MX record for the address you've
113 set in [hostname](#opt-services.discourse.hostname) and
114 requires proper SPF, DKIM and DMARC configuration to be done for
115 the domain you're sending from, in order for email to be reliably delivered.
117 If you want to use a different domain for your outgoing email
118 (for example `example.com` instead of
119 `discourse.example.com`) you should set
120 [](#opt-services.discourse.mail.notificationEmailAddress) and
121 [](#opt-services.discourse.mail.contactEmailAddress) manually.
124 Setup of TLS for incoming email is currently only configured
125 automatically when a regular TLS certificate is used, i.e. when
126 [](#opt-services.discourse.sslCertificate) and
127 [](#opt-services.discourse.sslCertificateKey) are
131 ## Additional settings {#module-services-discourse-settings}
133 Additional site settings and backend settings, for which no
134 explicit NixOS options are provided,
135 can be set in [](#opt-services.discourse.siteSettings) and
136 [](#opt-services.discourse.backendSettings) respectively.
138 ### Site settings {#module-services-discourse-site-settings}
140 "Site settings" are the settings that can be
141 changed through the Discourse
142 UI. Their *default* values can be set using
143 [](#opt-services.discourse.siteSettings).
145 Settings are expressed as a Nix attribute set which matches the
146 structure of the configuration in
147 [config/site_settings.yml](https://github.com/discourse/discourse/blob/master/config/site_settings.yml).
148 To find a setting's path, you only need to care about the first
149 two levels; i.e. its category (e.g. `login`)
150 and name (e.g. `invite_only`).
152 Settings containing secret data should be set to an attribute
153 set containing the attribute `_secret` - a
154 string pointing to a file containing the value the option
155 should be set to. See the example.
157 ### Backend settings {#module-services-discourse-backend-settings}
159 Settings are expressed as a Nix attribute set which matches the
160 structure of the configuration in
161 [config/discourse.conf](https://github.com/discourse/discourse/blob/stable/config/discourse_defaults.conf).
162 Empty parameters can be defined by setting them to
165 ### Example {#module-services-discourse-settings-example}
167 The following example sets the title and description of the
168 Discourse instance and enables
169 GitHub login in the site settings,
170 and changes a few request limits in the backend settings:
173 services.discourse = {
175 hostname = "discourse.example.com";
176 sslCertificate = "/path/to/ssl_certificate";
177 sslCertificateKey = "/path/to/ssl_certificate_key";
179 email = "admin@example.com";
181 fullName = "Administrator";
182 passwordFile = "/path/to/password_file";
185 serverAddress = "smtp.emailprovider.com";
187 username = "user@emailprovider.com";
188 passwordFile = "/path/to/smtp_password_file";
190 mail.incoming.enable = true;
194 site_description = "Discuss My Cats (and be nice plz)";
197 enable_github_logins = true;
198 github_client_id = "a2f6dfe838cb3206ce20";
199 github_client_secret._secret = /run/keys/discourse_github_client_secret;
203 max_reqs_per_ip_per_minute = 300;
204 max_reqs_per_ip_per_10_seconds = 60;
205 max_asset_reqs_per_ip_per_10_seconds = 250;
206 max_reqs_per_ip_mode = "warn+block";
208 secretKeyBaseFile = "/path/to/secret_key_base_file";
213 In the resulting site settings file, the
214 `login.github_client_secret` key will be set
215 to the contents of the
216 {file}`/run/keys/discourse_github_client_secret`
219 ## Plugins {#module-services-discourse-plugins}
221 You can install Discourse plugins
222 using the [](#opt-services.discourse.plugins)
223 option. Pre-packaged plugins are provided in
224 `<your_discourse_package_here>.plugins`. If
225 you want the full suite of plugins provided through
226 `nixpkgs`, you can also set the [](#opt-services.discourse.package) option to
227 `pkgs.discourseAllPlugins`.
229 Plugins can be built with the
230 `<your_discourse_package_here>.mkDiscoursePlugin`
231 function. Normally, it should suffice to provide a
232 `name` and `src` attribute. If
233 the plugin has Ruby dependencies, however, they need to be
234 packaged in accordance with the [Developing with Ruby](https://nixos.org/manual/nixpkgs/stable/#developing-with-ruby)
235 section of the Nixpkgs manual and the
236 appropriate gem options set in `bundlerEnvArgs`
237 (normally `gemdir` is sufficient). A plugin's
238 Ruby dependencies are listed in its
239 {file}`plugin.rb` file as function calls to
240 `gem`. To construct the corresponding
241 {file}`Gemfile` manually, run {command}`bundle init`, then add the `gem` lines to it
244 Much of the packaging can be done automatically by the
245 {file}`nixpkgs/pkgs/servers/web-apps/discourse/update.py`
246 script - just add the plugin to the `plugins`
247 list in the `update_plugins` function and run
250 ./update.py update-plugins
253 Some plugins provide [site settings](#module-services-discourse-site-settings).
254 Their defaults can be configured using [](#opt-services.discourse.siteSettings), just like
255 regular site settings. To find the names of these settings, look
256 in the `config/settings.yml` file of the plugin
259 For example, to add the [discourse-spoiler-alert](https://github.com/discourse/discourse-spoiler-alert)
260 and [discourse-solved](https://github.com/discourse/discourse-solved)
261 plugins, and disable `discourse-spoiler-alert`
266 services.discourse = {
268 hostname = "discourse.example.com";
269 sslCertificate = "/path/to/ssl_certificate";
270 sslCertificateKey = "/path/to/ssl_certificate_key";
272 email = "admin@example.com";
274 fullName = "Administrator";
275 passwordFile = "/path/to/password_file";
278 serverAddress = "smtp.emailprovider.com";
280 username = "user@emailprovider.com";
281 passwordFile = "/path/to/smtp_password_file";
283 mail.incoming.enable = true;
284 plugins = with config.services.discourse.package.plugins; [
285 discourse-spoiler-alert
290 spoiler_enabled = false;
293 secretKeyBaseFile = "/path/to/secret_key_base_file";