Skip to content

Users and registration

Conatus has exactly two instance-level roles: administrator and member. That is separate from project roles, which are per project. See Collaboration.

The first account created on an empty database becomes the instance administrator. There are two ways to create it.

Go to /register on a fresh instance. Because there are no accounts yet, registration is open for exactly one signup. Fill in a username and password and you are the administrator.

Set both values before the first docker compose up:

CONATUS_ADMIN_USERNAME=admin
CONATUS_ADMIN_PASSWORD=replace-with-a-long-random-password

A one-shot job creates a verified administrator, but only if the database is empty. On an instance that already has accounts it does nothing.

Requirements: the username must be 3–32 characters of letters, numbers, dots, underscores or hyphens, and the password at least 8. Both must be set together or the job errors out rather than half-configuring the instance.

After the first login, remove both values from .env and delete the stopped bootstrap container.

Both paths take the same database lock, so two of them racing cannot both decide they are first.

REGISTRATION_MODE controls what happens after that first account.

Value Behaviour
invite-only (default) Signup requires a one-time link from an administrator
open Anyone who can reach /register can create an account

Administrators get a Registration section in Settings.

Generate a link and you get a URL of the form https://tasks.example.com/register?invite=…. Send it to the person by whatever channel you trust. Conatus does not email it.

An invitation is:

  • one-time, consumed by the account it creates;
  • valid for 7 days;
  • optionally locked to a username. Leave the username blank for a shareable link that anyone can use once; fill it in and the link only works for that exact username.

The Settings list shows active invitations only, and lets you revoke one before it is used. A username can hold only one active invitation at a time.

Rejected signups are told why: the link is invalid, expired or already used; it was issued for a different username; or registration requires an invitation.

Generating a link requires the instance to know its own public URL. Behind a proxy, that means AUTH_URL and PUBLIC_BASE_URL must be set, otherwise the request fails rather than producing a link pointing at the wrong host.

The administrator is the account that bootstrapped the instance. It can:

  • generate and revoke registration invitations.

That is the whole of it. There is no user-management screen, no ability to reset another account’s password, no impersonation and no cross-account data access. An administrator has no privileged view of anyone else’s tasks.

One invariant is enforced: an administrator cannot delete their own account while other accounts exist, so an instance cannot be orphaned. The last remaining account may delete itself, which reopens first-user bootstrap.

Rule Value
Username 3–32 characters, lowercase letters, numbers, dots, underscores, hyphens
Username uniqueness Case-insensitive, normalised to lowercase
Password Minimum 8 characters, no other requirement
Email Optional, unique, and only needed for reminder emails and password reset

Usernames cannot be changed after registration.

Password reset and email verification need SMTP configured. Without SMTP_HOST, SMTP_PORT and SMTP_FROM, an account with a forgotten password cannot be recovered from inside the app. Plan for that when running a username-only instance.

Deleting an account cascades everything it owns, including projects shared with other people.

All counted in memory, per app container:

Action Limit
Login and device-token, per username 5 per 5 minutes
Login and device-token, per IP 20 per 5 minutes
Registration, per IP 5 per 15 minutes
Registration, per username 5 per 15 minutes
Password reset request, per IP 10 per 15 minutes
Password reset request, per email 3 per 15 minutes
Verification resend, per IP 10 per 15 minutes
Verification resend, per email 3 per 15 minutes
Client error reports, per IP 30 per 5 minutes

Login and device-token share one budget: both accept a password, so separate budgets would let an attacker double their allowance by switching entry points.

Rate-limited responses are 429 with a Retry-After header.

Client IPs come from X-Forwarded-For or X-Real-IP, so a reverse proxy in front of Conatus must set them, and must strip client-supplied copies, or the limits are easy to bypass. See Reverse proxy.