Multica Docs

Sign-in and signup configuration

Configure email + verification code sign-in, Google OAuth, and signup allowlists. Avoid the 888888 trap.

Multica supports two sign-in methods: email + verification code (default) and Google OAuth (optional). On successful sign-in, the server issues a JWT cookie with a 30-day lifetime. This page covers how to configure each method, how to restrict who can sign up, and the single biggest trap for self-hosted deployments.

For the list of environment variables referenced below, see Environment variables; for token usage and lifecycle details, see Authentication and tokens.

How email + verification code sign-in works

The user enters an email on the sign-in page → the server sends a 6-digit code → the user enters it → the server verifies it → a JWT cookie is issued. Standard flow. It requires Resend as the email provider:

  1. Create a Resend account and verify your domain

  2. Create an API key

  3. Set the environment variables:

    RESEND_API_KEY=re_xxxxxxxxxxxxxxxx
    RESEND_FROM_EMAIL=noreply@yourdomain.com  # must be a domain verified in Resend
  4. Restart the server

What happens if you don't set RESEND_API_KEY: the server doesn't error, but every email that should have been sent is written to the server's stdout only. Handy for local development (copy the code from the logs); in production it's a black hole.

The 888888 trap

If APP_ENV is not set to production, anyone can sign in to any account with the code 888888.

Multica has a development-only master code, 888888 — a backdoor so local development doesn't depend on Resend. The rule is straightforward: when APP_ENV != "production", any email plus 888888 passes verification.

Production deployments must set APP_ENV=production. If you deploy via make selfhost / docker-compose.selfhost.yml, this value is already set to production by default; but if you deploy from source yourself, write your own Docker config, or redefine environment variables in Kubernetes — you must add APP_ENV=production yourself.

To check whether your deployment has this trap: open the sign-in page, enter any email to request a code, then enter 888888. If you get in, your APP_ENV is not set to production, and the entire instance is wide open.

Google OAuth configuration

Optional. Without it, only email + verification code is available; with it, the sign-in page gets a "Sign in with Google" button.

  1. Create an OAuth 2.0 client in the Google Cloud Console

  2. Set the Authorized redirect URIs to your Multica frontend address plus /auth/callback, for example:

    https://multica.yourdomain.com/auth/callback
  3. Once you have the client ID and client secret, set three environment variables:

    GOOGLE_CLIENT_ID=xxxxx.apps.googleusercontent.com
    GOOGLE_CLIENT_SECRET=GOCSPX-xxxxxxxxxxxxxxx
    GOOGLE_REDIRECT_URI=https://multica.yourdomain.com/auth/callback
  4. Restart the server.

Takes effect at runtime: the frontend reads these settings at runtime via /api/config — after changing them, restart the server and the frontend picks up the new values with no rebuild or redeploy.

The redirect URI must match exactly in both the Google Console and GOOGLE_REDIRECT_URI — including protocol (http vs https), trailing slash, and port. Any mismatch and Google rejects the entire OAuth flow; the error shown to the user is redirect_uri_mismatch.

Restricting who can sign up

Three environment variables combine by priority:

Rendering diagram…

Existing users can always sign in again — the signup allowlist only applies to first-time signup, not returning users.

  • ALLOWED_EMAILS (highest priority) — explicit email allowlist, comma-separated. When non-empty, only listed emails can sign up.
  • ALLOWED_EMAIL_DOMAINS — domain allowlist, comma-separated (for example company.io,partner.com).
  • ALLOW_SIGNUP — master switch, default true. Set false to disable signup entirely.

The three layers are AND semantics, not OR. A common wrong intuition is that ALLOWED_EMAIL_DOMAINS=company.io + ALLOW_SIGNUP=true means "allow company.io plus everyone else." It does not. If any layer has a non-empty value, emails not matching it are rejected outrightALLOW_SIGNUP=true does not override that.

To actually "allow everyone," leave all three variables empty (or keep ALLOW_SIGNUP=true).

Typical configurations:

GoalConfiguration
Internal only, employees of company.ioALLOWED_EMAIL_DOMAINS=company.io
Internal + a few external collaboratorsALLOWED_EMAIL_DOMAINS=company.io + collaborator addresses added to ALLOWED_EMAILS
Disable self-serve signup entirely, invite-onlyALLOW_SIGNUP=false
Open signup (not recommended for production)All three empty

Can you still invite people when signup is disabled?

Only people who already have a Multica account. Accepting an invite doesn't check the signup allowlist — if the invitee has signed up already (for example in another workspace), clicking the invite link and signing in lets them accept.

But people who have never signed up cannot be rescued by an invite. Before accepting, they must sign in, and the first step of sign-in (requesting the verification code) passes through the signup allowlist check. If ALLOW_SIGNUP=false, or their email isn't in ALLOWED_EMAILS / ALLOWED_EMAIL_DOMAINS, they cannot complete signup, and therefore cannot accept the invite.

To invite an external collaborator who hasn't signed up yet: temporarily add their email to ALLOWED_EMAILS, wait for them to sign up and accept the invite, then remove the entry.

For how to create and use invites, see Members and roles.

Next