txw

open source · ejabberd module · 04

mod_signup_keyword

Keyword-gated registration for ejabberd.

A custom ejabberd module that gates XEP-0077 in-band registration behind one reusable shared keyword — the simplest onboarding model for a small or private XMPP server, where you want friends-of-friends to self-register without per-person invite tokens.

01 Built on ejabberd

One shared keyword

Give your friends one word. Anyone who has it registers themselves over in-band registration; everyone else is turned away. Lowest-friction onboarding for a personal server.

Standard IBR, untouched

Sits on XEP-0077 in-band registration and surfaces the keyword as a XEP-0004 data-form field. Clients that render data forms generically — including Mach — need zero changes.

Reuses ejabberd auth

Accounts go straight through ejabberd_auth:try_register/3, so SCRAM hashing and your existing Mnesia or SQL storage stack are reused unchanged. No parallel user database.

Constant-time gate

The keyword is compared in constant time — no timing side-channel — and the keyword itself is never logged. Only the source IP and attempted username are recorded on a failed attempt.

02 What it is

ejabberd ships two registration models, and both are awkward for a personal server. Open in-band registration lets anyone on the internet create accounts — a spam magnet. XEP-0445 invite tokens are single-use, so you must mint one per person. mod_signup_keyword splits the difference: one shared keyword for everyone, rotated when you like.

The keyword is a password gate on in-band registration. The server returns a data form with username, password, and keyword fields; it validates the keyword in constant time and creates the account only on a match. The honest trade-off is that a leaked keyword lets anyone register until you rotate it — strictly weaker than per-person tokens, by design.

03 How it works

  1. 01

    Compile

    Build the .beam against your ejabberd tree with erlc. One expected warning — behaviour gen_mod undefined — resolves at load time once ejabberd is on the code path.

  2. 02

    Configure

    Add mod_signup_keyword to ejabberd.yml with your keyword, a welcome message, reserved usernames, and a per-IP rate limit. Do not load mod_register alongside it — both own the register namespace and will conflict.

  3. 03

    Restart

    Restart ejabberd (systemctl, or stopsrc/startsrc on AIX). The module advertises register and answers the jabber:iq:register IQ handler.

  4. 04

    Verify

    Run the bundled test script against your host to confirm the form advertises the keyword field, then hand the keyword to the people you want on the server.

04 What’s in it

Per-IP rate limiting

A module-level registration_timeout_ms throttle (10 min default) — ejabberd’s top-level registration_timeout does not apply, since this module replaces mod_register.

Reserved usernames

Common admin names — admin, root, support, info — can’t be claimed even with the right keyword. Editable in config.

Welcome message

An optional message body sent to each newly registered user. Empty string to disable.

Standard error mapping

Wrong keyword, taken username, malformed JID, weak password, and rate limiting each return the appropriate XMPP error stanza.

Keyword never logged

Failed attempts log the source IP and attempted username only. The keyword stays on-box and out of source control.

No dependencies

Erlang/OTP and ejabberd, nothing else. A single .beam file dropped into your ebin directory.

05 Get it

mod_signup_keyword is open source, GPL-2.0-or-later (the same licence as ejabberd, since it is a derivative work). The source, configuration reference, and an end-to-end test script live on GitHub.

View on GitHub

Verified with Mach — Mach detects the keyword field and renders it as an invite-code input, no changes required.