Consent Tracking: Blocking Unverified Homeserver Actions

Running an open community communication platform requires clear administrative controls and documented acceptance of community rules. When operating a federated homeserver, administrators need technical mechanisms to present policies, capture user agreement, and restrict participation until that agreement is recorded. Synapse offers dedicated server-side functionality to handle these obligations systematically.
Why should a community homeserver track terms of service agreement?
Managing an online space requires that participants acknowledge community standards before they begin sending messages. As outlined in the Synapse consent tracking documentation, Synapse 0.30 introduced native functionality to track whether users agree to terms and conditions established by the server administrator. When configured, the homeserver actively blocks access to server features until the account holder accepts the posted policy.
While server documentation often references a privacy policy, administrators can use this system for broader community guidelines or acceptable use rules. For operators hosting a server instance alongside traditional boards—such as those covered in our Synapse Matrix homeserver profile—this automated check ensures that members cannot interact in rooms until their verification status is formally logged in the database.
What files and templates are needed to display policy documents?
Synapse collects agreement by serving users a simple web page containing the policy text and an acceptance button. Once the participant clicks to accept, the software logs that decision in the database and displays a confirmation page. To implement this workflow, administrators must supply their own templates on the local filesystem.
The templating system relies on specific conventions:
- Templating Engine: Templates must be written in the Jinja2 templating language. Working samples can be referenced in the
docs/privacy_policy_templatesdirectory. - Language Directory: Files must sit inside a directory named after the language code. Currently, this must always be
enfor English, as internationalisation support is intended for the future. - Versioned Filenames: The policy template file itself must be named according to its version string, such as
1.0.html. When a user accepts, that specific version identifier is committed to the homeserver database. - Python Requirements: The server environment must have Jinja2 installed, typically through commands like
pip install Jinja2orapt-get install python-jinja2.
How is homeserver.yaml configured to handle consent endpoints?
Connecting the template files to the server runtime involves updating homeserver.yaml across several distinct blocks. First, define the directory and policy version under the consent settings:
user_consent:
template_dir: privacy_policy_templates
version: 1.0
Next, generate an arbitrary secret string and assign it to form_secret at the top level of the configuration file. Administrators can run utility commands such as pwgen -y 30 to produce a secure value. In addition, you must enable the consent resource on your network listeners wherever the client resource is active, such as on port 8008:
listeners:
- port: 8008
resources:
- names:
- client
- consent
After saving these adjustments and restarting Synapse, browsing to https://<server>/_matrix/consent will return a "Missing string query parameter 'u'" message. This confirms that the endpoint is active and waiting for valid parameters.
How can administrators build consent links and register new users?
According to the official Synapse consent tracking guide, administrators can construct individual consent addresses to distribute directly to members. The URL combines the base endpoint with two query parameters: u, representing the username localpart or full MXID (such as @user:server.com), and h, a hex-encoded HMAC-SHA256 signature calculated from u using your configured form_secret as the key. This signature can be computed on the command line using tools like OpenSSL.
To integrate this process directly into new member onboarding, add these directives to the configuration:
user_consent:
require_at_registration: true
policy_name: "Privacy Policy"
Within the Jinja2 policy template, administrators can inspect the public_version variable. When an unauthenticated visitor views the document during registration, public_version is true, allowing the template to present the terms while hiding the acceptance submission form. When viewed by an authenticated user with valid signature parameters, the template renders the hidden inputs (containing the user ID, version, and HMAC token) alongside the acceptance button.
How do you block unverified actions and notify users?
Capturing consent is only effective if unverified accounts are restricted from chatting. Administrators can configure Synapse to reject actions across all federated or local channels until the terms are accepted. You can define a customized rejection message that explains why the action was stopped:
user_consent:
block_events_error: >-
You can't send any messages until you consent to the privacy policy at
%(consent_uri)s.
When this block is active, Synapse halts any attempt to join rooms or post messages. However, joining the server notices room is strictly exempted, ensuring that account holders can still receive administrative alerts.
To proactively reach non-compliant members rather than waiting for an error, configure the server notice system by defining server_notice_content under user_consent. The text body can include the %(consent_uri)s placeholder, which Synapse automatically populates with the user's personal acceptance URL. For these dynamic URLs to resolve accurately in both error blocks and server notices, administrators must ensure that public_baseurl is properly configured in homeserver.yaml with the base address clients use to access the server.
Sources
Published October 31, 2026. No affiliate links on this page. Facts come from the sources linked above; check them for updates.