Mirra
Function Client (self-host)

Sign in with Privy

A self-hosted server signs people in with its own email-and-password accounts unless AUTH_PROVIDER names another provider. You can sign them in through Privy instead, with an app of your own.

Pick one before your team signs up. A server has one sign-in provider at a time, and switching later is not a migration. Moving from local accounts to Privy, nobody's account moves: each person gets a new, empty one.

1. Create the Privy app

In the Privy dashboard, create an app, then:

  • Login methods: email only. The clients ask Privy for email and nothing else.
  • Embedded wallets: off, for both Ethereum and Solana. The clients never create one.
  • Allowed origins: every origin a client loads from:
    • your server, https://<FUNCTION_DOMAIN> (the web client the edge serves);
    • any CDN copy of the web client (Getting the client to your team);
    • for client development, a separate Privy app with http://localhost:1430 as its origin. Leave it off the app your team signs in with.

Anyone who can sign in to your Privy app gets an account on your server: the server has no sign-up switch under Privy. Restrict who can sign in in the Privy dashboard (its allowlist of emails or domains) before you give out the address. With billing off, every account spends your Anthropic key.

Note the app's App ID, App secret and Client ID.

2. Give them to the server

In .env.selfhost, add:

AUTH_PROVIDER=privy
PRIVY_APP_ID=<App ID>
PRIVY_APP_SECRET=<App secret>
PRIVY_CLIENT_ID=<Client ID>

Then docker compose --env-file .env.selfhost up -d. The boot log says mirra.auth=privy.

The app secret stays on the server, which uses it to verify each sign-in. The app ID and client ID are public: /api/client-config hands them to the web client, which is how it knows which Privy app to open. You don't rebuild the client to change them.

Without the app ID or the secret, the server stops at boot and names what is missing:

This server cannot start on the selfhost profile until its environment is fixed:
- AUTH_PROVIDER=privy needs PRIVY_APP_ID and PRIVY_APP_SECRET, from your app in the Privy dashboard. Set them, or unset AUTH_PROVIDER for this server's own email-and-password accounts.

Other providers

AUTH_PROVIDER=oidc authenticates API and SDK requests with access tokens from your own OpenID Connect provider (Keycloak, Authentik, Auth0, Entra ID). The web client doesn't offer OIDC sign-in. apps/server/.env.selfhost.example describes its settings.

On this page