Discourse is a web platform for hosting and moderating online discussion.
The Tor forum is currently hosted free of charge by Discourse.org for the benefit of the Tor community.
Tutorial
Enable new topics by email
Topic creation by email is the ability to create a new forum topic in a category simply by sending an email to a specific address.
This feature is enabled per-category. To enable it for a category, navigate to it, click the "wrench" icon (top right), open the Settings tab and scroll to the Email header.
Enter an email address under Custom incoming email address. The address to
use should be in the format <categoryname>+discourse@forum.torproject.org
.
Per the forum's settings, only users with trust level 2 (member) or higher are allowed to post new topics by email.
Use the app
The official companion app for Discourse is DiscourseHub.
Unfortunately, it doesn't appear to be available from the F-Droid repository at the moment.
Mirror a mailing list
The instructions to set up a forum category that mirrors for a mailing list can be found here.
The address that needs to be subscribed to the mailing list is
discourse@forum.torproject.org
.
How-to
Launch the Discourse Rails console
Log-in to the server's console as root and run:
cd /srv/discourse
./launcher enter app
rails c
Reset a user's two-factor auth settings
In case a user can't log-in anymore due to two-factor authentication parameters, it's possible to reset those using the Rails console.
First, load the user object by email, username or id:
user=User.find_by_email('email')
user=User.find_by_username('username')
user=User.find(id)
Then, simply run these two commands:
user.user_second_factors.destroy_all
user.security_keys.destroy_all
These instructions are copied from this post on the Discourse Meta forum.
Reset a user account password
Usually when there is a need to reset a user's password, the user can self-service through the forgotten password forum.
In case of issues with email, the password can also be reset from the Rails console:
First, load the user object by email, username or id:
user=User.find_by_email('email')
user=User.find_by_username('username')
user=User.find(id)
Then:
user.password='passwordstring'
user.save!
These instructions are copied from this post on the Discourse Meta forum.
Adding or removing plugins
The plugins installed on our Discourse instance are configured using Puppet, in
hiera/role/forum.yaml
.
To add or remove a plugin, simply add/remove the repository URL to the
profile::discourse::plugins
key, run the Puppet agent and rebuild the
container:
./launcher rebuild app
This process can take a few minutes, during which the forum is unavailable.
Discourse has a plugins directory here: https://www.discourse.org/plugins
Un-delete a topic
As an admin user, the list of all deleted topics may be shown by navigating to https://forum.torproject.org/latest?status=deleted
Tu un-delete a topic, open it, click the wrench icon and select
Un-delete topic
.
Permanently destroy a topic
If a topic needs to be purged from Discourse, this can be accomplished using the Rails console as follows, using the numeric topic identifier:
Topic.find(topic_id).destroy
These instructions are copied from this post on the Discourse Meta forum.
Enter the Discourse container
It's possible to enter the Discourse container to look around, make modifications, and restart the Discourse daemon itself.
cd /srv/discourse
./launcher enter app
Any changes made in the container will be lost on upgrades, or when the
container is rebuilt using ./launcher rebuild app
.
Within the container its possible to restart the Discourse daemon using:
sv restart unicorn
Read-only mode
It's possible to enable "read-only" mode on the forum, which will prevent any changes and will block and new topic, replies, messages, settings changes, etc.
To enable it, navigate to the Admin
section, then Backups
and click the
button labeled Enable read-only
.
It's also possible to enable a "partial read-only" mode which is like normal "read-only" except it allows administrators to make changes. Enabling this mode must be done via the rails console:
Discourse.enable_readonly_mode(Discourse::STAFF_WRITES_ONLY_MODE_KEY)
To disable it:
Discourse.disable_readonly_mode(Discourse::STAFF_WRITES_ONLY_MODE_KEY)
The documentation for this feature is found at https://meta.discourse.org/t/partial-read-only-mode/210401/18
Pager playbook
Email issues
If mail is not going out or some recurring background job doesn't work, see the Sidekiq dashboard in:
https://forum.torproject.org/sidekiq/
Email failures, in particular, are retried for a while, you should be able to see those failures in:
https://forum.torproject.org/sidekiq/retries
Upgrade failure
When upgrading using the web interface, it's possible for the process to fail
with a Docker Manager: FAILED TO UPGRADE
message in the logs.
The quickest way to recover from this is to rebuild the container from the command-line:
cd /srv/discourse
git pull
./launcher rebuild app
Disaster recovery
In case the machine is lost, it's possible to restore the forum from backups.
The first step is to install a new machine following the installation steps in
the Installation
section below.
Once a blank installation is done, restore the Discourse backup directory,
/srv/discourse/shared/standalone/backups/default
, from Bacula backups.
The restoration process is then:
cd /srv/discourse
./launcher enter app
discourse enable_restore
discourse restore <backupfilename>.tar.gz
exit
Once that's done, rebuild the Discourse app using:
./launcher rebuild app
Reference
Installation
Our installation is modeled after upstream's recommended procedure for deploying a single-server Docker-based instance of Discourse.
First, a new machine is required, with the following parameters:
- an 80GB SSD-backed volume for container images and user uploads
- a 20GB NVMe-backed volume for the database
Directories and mounts should be configured in the following manner:
- the SSD volume mounted on
/srv
-
/srv/docker
bind mounted onto/var/lib/docker
When this is ready, the role::forum
Puppet class may be deployed onto the
machine. This will install Discourse's Docker manager software to
/srv/discourse
along with the TPO-specific container templates for the main
application (app.yml
) and the mail bridge (mail-receiver.yml
).
Once the catalog is applied, a few more steps are needed:
- Bootstrap and start Discourse with these commands:
cd /srv/discourse
./launcher bootstrap app
./launcher start app
-
Login to https://forum.torproject.org and create a new admin account
-
Create an API key using the instructions below
-
Run the Puppet agent on the machine to deploy the mail-receiver
API key for incoming mail
Our Discourse setup relies on Postfix to transport incoming and outgoing mail,
such as notifications. For incoming mail, Postfix submits it to a
special mail-receiver
container that is used to deliver email into Discourse
via its web API. A key is needed to authenticate the daemon running inside the
container.
To create and configure the API key:
-
Login to Discourse using the administrator account
-
Navigate to https://forum.torproject.org/admin/api/keys
-
Click the
New API Key
button -
In the Description write
Incoming mail
, for User Level selectAll Users
and for Scope selectGranular
-
Locate
email
undertopics
and check the box next toreceive emails
-
Click
Save
-
Copy the generated key, then logon to the Puppet server run this command to enter the API key into the database:
trocla set forum.torproject.org::discourse::mail_apikey plain
Upgrades
When versioned updates are available, an email is sent automatically by
Discourse to torproject-admin@torproject.org
.
These upgrades must be triggered manually. In theory it would be possible to upgrade automatically, but this is discouraged by community members because it can throw up some excitement every now and again depending on what plugins you have.
To trigger an upgrade, simply navigate to the Upgrade page in the Discourse
admin section and hit Upgrade all
, then Start Upgrade
.
Sometimes, this button is greyed out because an upgrade for docker_manager
is available, and it must be installed before the other components are
upgraded. Click the Upgrade
button next to it.
Discourse can also be upgraded via the command-line:
cd /srv/discourse
./launcher rebuild
Onion service
An onion service is configured on the machine using Puppet, listening on ports 80 and 443.
Internally, Discourse has a force_https
setting which determines whether
links are generated using the http
or https
scheme, and affects CSP URLs.
When this is enabled, the forum does not work using the onion service because
CSP URLs in the headers sent by Discourse are generated with the https
scheme. When the parameter is disabled, the main issue is that the links in
notifications all use the http
scheme.
So the most straightforward fix is simply to serve the forum via https
on the
onion service, that way we can leave the force_https
setting enabled, and the
CSP headers don't prevent forum pages from loading.
Another element to take into account is that Discourse forces the hostname as a security feature. This was identified as an issue specifically affecting forums hosted behind .onion services in this meta.discourse.org forum post.
While the solution suggested in that forum discussion involves patching
Discourse, another workaround was added later on in the form of the
DISCOURSE_BACKUP_HOSTNAME
container config environment variable. When set to
the .onion hostname, the forum works under both hostnames without issue.
Directory structure
The purpose of the various directories under /srv/discourse
is described in
the discourse_docker README.
The most important directories are:
-
containers
: contains our Docker container setup configurations -
shared
: contains the logs, files and Postgresql database of the forum
Social login configuration
GitHub
To enable GitHub authentication, you will need the github_client_id
and
github_client_secret
codes. Please refer to the the official Configuring
GitHub login for Discourse documentation
for up to date instructions.
Follow these steps to enable GitHub authentication:
-
Visit
https://github.com/organizations/torproject/settings/applications
. -
Click on "New Org OAuth App" or edit the existing "Tor Forum" app.
-
Follow the official instructions: https://meta.discourse.org/t/13745, or add the following configuration:
Application name: Tor Forum Homepage URL: https://forum.torproject.org/ Authorization callback URL: https://forum.torproject.org/auth/github/callback
-
Copy the
github_client_id
andgithub_client_secret
codes and paste them into the corresponding fields for GitHub client ID and GitHub client secret in https://forum.torproject.org/admin/site_settings/category/login
Design
Docker manager
The Discourse Docker manager is installed under /srv/discourse
and is
responsible for setting up the containers making up the Discourse installation.
The containers themselves are stateless, which means that they can be destroyed
and rebuilt without any data loss. All of the Discourse data is stored under
/srv/discourse/shared
, including the Postgresql database.
Issues
There is no issue tracker specifically for this project, File or search for issues in the team issue tracker.
Maintainer, users, and upstream
Upstream is Discourse.org.
This service is available publicly for the benefit of the entire Tor community.
The forum hosted on TPA infrastructure and administered by the service admins which are lavamind, hiro, gus and duncan.
Monitoring and testing
Only general monitoring is in place on the instance, there is no Discourse-specific monitoring in place.
Logs and metrics
Logs for the main Discourse container (app
) are located under
/srv/discourse/shared/standalone/log
.
The mail-receiver
container logs can be consulted with:
/srv/discourse/launcher logs mail-receiver
Note that this is strictly for incoming mail. Outgoing mail is
delivered normally through the Postfix email server, logging in
/var/log/mail.log*
.
In addition, some logs are accessible via the browser at https://forum.torproject.org/logs (administrators-only).
An overview of all logging is available on this page: Where does Discourse store and show logs?
Backups
Backups containing the database and uploads are generated daily by Discourse
itself in /srv/discourse/shared/standalone/backups
.
All other directories under /srv/discourse/shared/standalone
are excluded from
Bacula backups configured from /etc/bacula/local-exclude
.
It's possible to manually trigger Discourse to create a backup immediately by
entering the container and entering discourse backup
on the command-line.