grafana-alloy: don't build the frontend twice
[NixPkgs.git] / nixos / modules / services / web-apps / discourse.md
blobd4b9c93c4ead0f5f1b51a56054319c20f4674a2e
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:
9 ```nix
11   services.discourse = {
12     enable = true;
13     hostname = "discourse.example.com";
14     admin = {
15       email = "admin@example.com";
16       username = "admin";
17       fullName = "Administrator";
18       passwordFile = "/path/to/password_file";
19     };
20     secretKeyBaseFile = "/path/to/secret_key_base_file";
21   };
22   security.acme.email = "me@example.com";
23   security.acme.acceptTerms = true;
25 ```
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)
37 options:
39 ```nix
41   services.discourse = {
42     enable = true;
43     hostname = "discourse.example.com";
44     sslCertificate = "/path/to/ssl_certificate";
45     sslCertificateKey = "/path/to/ssl_certificate_key";
46     admin = {
47       email = "admin@example.com";
48       username = "admin";
49       fullName = "Administrator";
50       passwordFile = "/path/to/password_file";
51     };
52     secretKeyBaseFile = "/path/to/secret_key_base_file";
53   };
55 ```
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
63 to `false`.
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
81 via email.
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:
87 ```nix
89   services.discourse = {
90     enable = true;
91     hostname = "discourse.example.com";
92     sslCertificate = "/path/to/ssl_certificate";
93     sslCertificateKey = "/path/to/ssl_certificate_key";
94     admin = {
95       email = "admin@example.com";
96       username = "admin";
97       fullName = "Administrator";
98       passwordFile = "/path/to/password_file";
99     };
100     mail.outgoing = {
101       serverAddress = "smtp.emailprovider.com";
102       port = 587;
103       username = "user@emailprovider.com";
104       passwordFile = "/path/to/smtp_password_file";
105     };
106     mail.incoming.enable = true;
107     secretKeyBaseFile = "/path/to/secret_key_base_file";
108   };
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.
123 ::: {.note}
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
128 set.
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
163 `null`.
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:
171 ```nix
173   services.discourse = {
174     enable = true;
175     hostname = "discourse.example.com";
176     sslCertificate = "/path/to/ssl_certificate";
177     sslCertificateKey = "/path/to/ssl_certificate_key";
178     admin = {
179       email = "admin@example.com";
180       username = "admin";
181       fullName = "Administrator";
182       passwordFile = "/path/to/password_file";
183     };
184     mail.outgoing = {
185       serverAddress = "smtp.emailprovider.com";
186       port = 587;
187       username = "user@emailprovider.com";
188       passwordFile = "/path/to/smtp_password_file";
189     };
190     mail.incoming.enable = true;
191     siteSettings = {
192       required = {
193         title = "My Cats";
194         site_description = "Discuss My Cats (and be nice plz)";
195       };
196       login = {
197         enable_github_logins = true;
198         github_client_id = "a2f6dfe838cb3206ce20";
199         github_client_secret._secret = /run/keys/discourse_github_client_secret;
200       };
201     };
202     backendSettings = {
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";
207     };
208     secretKeyBaseFile = "/path/to/secret_key_base_file";
209   };
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`
217 file.
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
242 verbatim.
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
248 the script:
249 ```bash
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
257 repo.
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`
262 by default:
264 ```nix
266   services.discourse = {
267     enable = true;
268     hostname = "discourse.example.com";
269     sslCertificate = "/path/to/ssl_certificate";
270     sslCertificateKey = "/path/to/ssl_certificate_key";
271     admin = {
272       email = "admin@example.com";
273       username = "admin";
274       fullName = "Administrator";
275       passwordFile = "/path/to/password_file";
276     };
277     mail.outgoing = {
278       serverAddress = "smtp.emailprovider.com";
279       port = 587;
280       username = "user@emailprovider.com";
281       passwordFile = "/path/to/smtp_password_file";
282     };
283     mail.incoming.enable = true;
284     plugins = with config.services.discourse.package.plugins; [
285       discourse-spoiler-alert
286       discourse-solved
287     ];
288     siteSettings = {
289       plugins = {
290         spoiler_enabled = false;
291       };
292     };
293     secretKeyBaseFile = "/path/to/secret_key_base_file";
294   };