Skip to main content
The endpoints anyone can reach without signing in, sign-in, sign-up, password reset and one-time codes, are rate limited out of the box. You do not have to configure anything for that to work. This page is for when you want to tighten it, loosen it, or add a captcha.

What is already on

Rate limiting needs no configuration and no secret. Each protected action is counted twice, once per email address and once per IP address, over a rolling window. Whichever ceiling is hit first starts refusing requests. The window is 15 minutes.
The sign-in limits are deliberately loose. They exist to stop credential stuffing and mail bombing, not to punish someone mistyping their password, and a shared office connection should never reach the IP ceiling in normal use.

Where the counters live

If REDIS_URL is set, which it is in every standard install, counters live in Redis and are shared across every backend instance. Without it she falls back to counting inside a single process, which is correct for one instance and wrong the moment you run two. She says which one she chose in the startup log:

Changing the limits

Every number above can be overridden. Times are in milliseconds, counts are per window.
Setting any one of them to 0 disables that dimension. For example GUARD_LOGIN_IP=0 stops counting sign-in attempts per IP while still counting them per email address.
A value that is not a whole number falls back to the default rather than failing, so a typo leaves the original limit in place silently. If you change one, confirm the new behaviour rather than assuming it took.

Adding a captcha

Cloudflare Turnstile can be required before an action goes through. It is off unless you configure it.
1

Create a Turnstile widget

In the Cloudflare dashboard, under Turnstile, add a widget for your domain. You get a site key and a secret key.
2

Set both keys

Both, or neither. The site key alone renders the widget in the browser, but with no secret there is nothing to check the answer against, so it is decorative. Verification only engages when TURNSTILE_SECRET is set.
3

Choose which actions it guards

By default only one-time code requests require a captcha. Change that with a comma separated list:
The names you can use are otp_request, otp_verify, login, register and forgot.

Passwordless sign-in

Instead of a password, she can mail a one-time code:
This one is compared against the literal string true, so any other value leaves it off.
It needs working email. With no provider configured the code is never delivered and nobody can sign in. Set up Email Notifications first.
The one-time code endpoints are the most attractive ones to abuse, which is why they carry the tightest limits above and are the default target for the captcha.

The public API hourly cap

Separate from all of the above, post creation through the public API is capped per hour. It defaults to 90 requests per hour and is set with:
This only applies to the API, not to posting from the web interface. See Public API for what counts against it.

Close sign-ups

DISABLE_REGISTRATION stops new accounts entirely, which beats rate limiting them

Email notifications

Needed for passwordless sign-in and password resets