Team & Accounts

Accounts & multi-tenancy

Every resource you create — endpoints, domains, certificates, firewall rules, dedicated IPs — belongs to an account, not to an individual person. An account can be shared with teammates. The person who created the account is its owner; everyone else joins as a member. Owners and members differ only in permissions; the resources themselves are the account's.

The active account is server-authoritative: it travels in your session, so there is no account id in any URL. Switching accounts re-issues your session against the new account, and from then on every page shows that account's resources.

Plan-gated: Non-owner members require the plan's account_members entitlement, custom roles require account_rbac, and the account audit log requires the account_audit_log entitlement. The owner always has access regardless of plan.

Setting up your own account

Every user has an account of their own, created when the user is: when you sign up with email and password, with Google or GitHub, through an invitation link, or when an admin creates your user. The first time you reach the dashboard, that account opens the setup wizard.

Step 1 is the account itself: its name (it starts as “your name’s account”) and whether it’s Personal or Company, with the company details. The other steps are the same as for a new account: Plan, Billing details, Payment and Review & subscribe (paid plans only), Team and Get started. On the free plan it takes about five clicks.

Until the setup is finished, every page of your account opens the wizard (see Finishing the setup later). If you were on your way somewhere, such as a Deploy to ngris link or a page you opened by its URL, Finish setup takes you there.

Your own account first. You can accept invitations to other accounts once your own account’s setup is finished. The invitation pop-up waits until then, and the wizard’s last step shows how many invitations you have, with a link to review them.

Creating an account

Open the account switcher (your account name at the top of the sidebar) and choose Create account, or pick Create → Account in the top bar. Both open the Create account wizard at /account/new. The account is created when you finish the first step, and you're switched into it right away, so the remaining steps run inside the new account. You become its owner.

The seven steps

  1. Account — the account's name, and who it's for: Personal (your own projects) or Company (a business or organization). For a company, enter its legal name; the website, company size, industry and country of registration are optional. See Company profile. Create account creates the account and switches you into it.
  2. Plan — the same plans as on the Billing page, billed monthly or yearly. Nothing is charged here.
  3. Billing details — who the invoices are made out and sent to: the name on invoices, the billing email, an optional phone number, and the address. A company account can also add tax IDs (VAT / GST) here when tax ID collection is on. The form starts out with the company's legal name and country and your sign-in email. Required for a paid plan; on the free plan you can skip it.
  4. Payment (paid plans) — add a card, or continue with a card the account already has. A card you add here becomes the account's default card, and 3-D Secure is handled in the form. Nothing is charged yet.
  5. Review & subscribe (paid plans) — a summary of the account, plan, invoice recipient and card, with the amount due today and the recurring amount after it. Subscribe and pay charges the card now, the same way a checkout on the Billing page does. If the account is already subscribed to the plan (for example, the page reloaded during the charge), the step offers Continue instead of charging again.
  6. Team (optional) — invite people by email, each with a role, or Skip for now. On a Personal account the invite form stays folded behind Invite teammates. Invitations follow the same rules as on the Members page, including the plan's seat cap and custom roles.
  7. Get started — pick what you'll run on ngris: tunnels to local services, hosted apps, edge functions, or not sure yet. Finish setup completes the wizard and shows a short checklist of first steps for that choice, with an offer to have Iris walk you through them. The answer also puts the matching tasks first in the Getting started card on the account’s dashboard (an edge-functions answer adds Write an edge function); each task disappears once it’s done, and the × on the card hides it in that browser. The answer only changes the tips; every feature stays available.

On the free plan the wizard skips Payment and Review & subscribe.

Limits

  • A new account starts on the free plan. It doesn't inherit the plan of the account you were in; it moves to a paid plan only when you subscribe.
  • You can own up to 10 accounts besides your default account (the one created when you signed up). An account whose setup isn't finished counts too.
  • You can't create a new account while an account you own is suspended.
  • Account names and company legal names are up to 255 characters, using letters, numbers, spaces and . ' - _ ( ) ! ? : , + &. A website must start with https:// or http://.

Finishing the setup later

The wizard saves your progress after every step. What you completed stays saved: the account, its billing details, card, subscription and invitations. Anything you typed into a step without submitting it isn't kept.

Until the setup is finished, every page of that account opens the wizard: after you sign in, when you switch to the account, and when you open a page by its URL. It picks up at the step where you stopped. If you stopped at Billing details, Payment or Review & subscribe, it starts again at Plan so you can confirm the plan; the details and card you saved are still there. Your other accounts aren't affected. The account switcher, your user settings and Log out keep working, so you can leave for another account at any time.

The quickest way to finish is the free plan: choose it, use Skip for now on Billing details and Team, then pick an answer under Get started and click Finish setup. To get rid of an account you no longer want, finish the setup that way, then delete it under Account Settings → Danger zone (see Deleting your account).

Only the dashboard sends you back to the wizard. The API answers as usual for an account whose setup is unfinished.

What members see meanwhile

People can join the account before the setup is finished, for example through the Team step. Only the owner is taken to the wizard, because its billing steps (billing details, card, subscription, tax IDs) are owner-only. Every other member sees The owner is finishing setting up this account, with a button for each of their other accounts to switch to (or links to create an account and to their invitations when they have no other). The account opens for them as soon as the owner finishes. A member whose role can't read account settings isn't redirected.

Company profile

Every account created with the wizard is either Personal or Company. A company account also records the company's legal name, website, size, industry and country of registration. Only the legal name is required.

To see or change it, open Account Settings (/account/settings) and find the Company profile card. The account owner can switch between Personal and Company, edit the fields and Save. Other members who can view account settings see the profile read-only. Switching an account to Personal removes its company details. An account without a profile, such as the one created when you signed up, shows Not set until the owner picks a type.

Invoices use the billing details, not the company profile. The name, email and address on invoices, and the account's tax IDs (VAT / GST), are set under Subscription & Plans → Payment & Billing (/account/billing/payment). Tax IDs can be added there when tax ID collection is on. Only the account owner can change billing details and tax IDs. In the wizard, the billing name and country start out as the company's legal name and country.

API

The profile belongs to the active account:

Call What it does
GET /v1/account/profileNeeds settings:read. Returns {entity_type, company{legal_name, website, size, industry, country}, onboarding{step, use_case, completed_at, pending}, viewer_can_finish}. entity_type is empty on an account that has no profile yet. onboarding.pending is true while the wizard is unfinished. viewer_can_finish is true for the account owner only.
PUT /v1/account/profileNeeds settings:update. Body {entity_type, company{legal_name, website, size, industry, country}}; returns the profile. entity_type is individual or company, and individual clears the company fields. For company, legal_name is required. size is one of 1, 2-10, 11-50, 51-200, 201-1000, 1000+. industry is one of software, saas, ecommerce, media, finance, healthcare, education, government, agency, gaming, telecom, manufacturing, nonprofit, other. country is a two-letter ISO 3166-1 code.
PUT /v1/account/onboardingNeeds settings:update. The wizard's progress: {step?, use_case?, completed?}. step is one of plan, billing, payment, review, team, start; use_case is one of tunnels, apps, edge, unsure; completed: true finishes the setup. Returns the profile. Only an account created with onboarding: true has onboarding to record; any other answers 409.

A field that fails validation is refused with 400 and {error, field}, where field names it (for example company.website). To create an account with a profile, see Create Account. Full reference: Account Profile, Update Account Profile and Update Setup Progress.

Members & invitations

Manage your team from Account → Members (/account/members). The page lists current members with their role and lets you invite, change roles, remove, and transfer ownership.

Inviting a teammate

  1. Click Invite member and enter their email and the role to grant.
  2. They receive an invitation link. Accepting it joins them to the account with that role.
  3. Pending invitations are visible under Account → Invitations (/account/invitations), where the owner can revoke any that haven't been accepted yet.

Roles on a member

  • Owner — full control of the account, including billing, plan changes, and member management. There is exactly one owner; ownership can be transferred to another member. The owner is always exempt from the member gate.
  • Member — access governed by the named role assigned to them (see RBAC below). A member's effective permissions are exactly what their role grants.

Transferring ownership

The owner can hand the account to another active member: on Account → Members, open the member's … menu and choose Make owner. Pick the role you keep after the handover (the built-in Admin role is preselected) and confirm. The new owner gets full control — billing, members, roles and deleting the account — and you stay on as a member with the role you picked. A member paused over the plan's seat limit can't be made owner.

For your security, a transfer signs both of you out everywhere; sign in again to continue.

Leaving an account

Any member other than the owner can leave: Account → Members → Leave account (at the bottom of the page, or Leave account in your own row's menu). You lose access right away, your API keys for that account are revoked, and you're signed out everywhere — your own accounts aren't affected. To come back, an admin of the account has to invite you again. The owner can't leave; transfer ownership first. A member can leave even while the account is suspended.

Named-role RBAC

Permissions are assigned to members through named roles, managed under Account → Roles (/account/roles). A role is a matrix of permissions over the account's resources; assign a role to a member and they inherit exactly those permissions.

The permission matrix

Each role grants permissions per resource. The resources in the matrix are:

Resource Covers
EndpointsTunnels and endpoint settings.
DomainsCustom domains and DNS.
Certificates / SSLTLS certificate management.
Dedicated IPsRequesting and attaching dedicated IPs.
FirewallFirewall policies.
Rate LimitsRate-limit rules.
Traffic InspectorThe live traffic view and Security Analytics.
MembersInviting / removing teammates.
RolesCreating and editing roles.
Account SettingsAccount name and tenant-level settings.
BillingSubscription, plan, payment methods, invoices.
DatabasesDatabases: creating, renaming and deleting them, their users and password resets, connecting them to apps (which also needs Endpoints), and their backups (taking, restoring and deleting them, and the backup schedule).
Database dataThe data inside databases: read lets a member download database backups (from a database's Backups tab, and a database dump from an app's Backups tab). The built-in Admin role has it; custom roles that existed before databases got their own permissions have it off until an admin turns it on.

Create, edit, and delete custom roles to match how your team is organised. There is no “owner” role row — ownership is a property of the membership itself, and the owner implicitly holds every permission.

Plan-gated: every account has a built-in Admin role that works on any plan that allows members. Custom roles require the plan's account_rbac entitlement. Without it you can't create or edit roles, or assign or invite anyone into a custom role. Members who already hold a custom role stay in the account, but they have no permissions until the plan includes custom roles again. Move them to the Admin role or upgrade. You can still delete custom roles.
Authoritative gate: roles and permissions are enforced server-side on every action. The dashboard hides controls you can't use, but the real check happens at the API — a member without a permission gets a 403 even if they reach the endpoint directly.

Single Sign-On (SSO)

SSO is configured per account. Account owners and admins manage it under Account → Single Sign-On (/account/settings/sso). SSO is gated by the sso entitlement and is keyed by email domain — users whose email matches a configured domain sign in through that provider. Providers: Google, GitHub, or any OpenID Connect (OIDC) identity provider. SAML is not supported.

Configuration fields

Field Notes
email_domainThe email domain this config applies to (e.g. company.com). One config per domain, per account.
provider_typeOne of google, github or oidc (custom OpenID Connect). For google/github the endpoint URLs are locked to the provider's canonical values and filled automatically. SAML is not supported: saving a saml config is refused (400 “SAML sign-in is not supported. Use OpenID Connect (oidc), Google or GitHub instead.”). A SAML provider saved earlier shows as Unsupported and never signs anyone in; delete it and add your identity provider again with OIDC (Okta, Microsoft Entra ID, Google Workspace and most others offer it).
client_idOAuth/OIDC client ID.
client_secretProvider client secret. Never returned in API responses; leave blank on update to keep the stored value.
auth_url / token_url / userinfo_urlEndpoint URLs for custom oidc providers (can be auto-discovered from an issuer URL — see below). Ignored for google/github.
issuer / jwks_urlRequired for oidc. The provider's OIDC issuer identifier and its JWKS (signing-key) endpoint. At login ngris verifies the provider's signed id_token against these (see below). Auto-filled by Discover. Cleared for google/github.
scopesSpace-separated OAuth scopes. Defaults to openid profile email.
enforcedWhen on, matching-domain users must sign in via SSO. Turning this on requires the sso entitlement.
domain_verifiedRead-only. Whether the account has proven ownership of email_domain (see below). oidc configs only take effect at login once verified.

Custom OIDC (Okta, Microsoft Entra ID, Auth0, …)

Any OIDC-compliant identity provider works. The fastest setup uses Discover so you only supply one URL:

  1. In your IdP, register an OIDC/OAuth web application using the Authorization Code flow. Set the redirect (callback) URL to the one ngris shows on the SSO page, and note the client ID and client secret.
  2. In ngris under Account → Single Sign-On, choose provider type oidc, paste your provider's issuer URL (e.g. https://acme.okta.com/oauth2/default), and click Discover. ngris reads the provider's .well-known/openid-configuration and fills in auth_url, token_url, userinfo_url, issuer, and jwks_url for you.
  3. Enter the client_id, client_secret, and the email_domain to route through this provider, then save. Both issuer and jwks_url are required for oidc — if Discover couldn't reach your provider, fill them in by hand (the JWKS URL is the jwks_uri from the discovery document).
  4. Complete domain verification (below), then Test the config and turn on enforcement if you want to require SSO.

How identity is verified at login

For custom oidc, ngris does not trust the identity from the user-info body. At login it cryptographically verifies the provider's signed id_token before creating a session: it checks the signature against the keys published at jwks_url, and validates the token's iss (must match issuer), aud (must contain your client_id), and exp, plus the login nonce. Identity is trusted only when your IdP provably asserts it. google and github need no issuer/JWKS — their identity comes from platform-controlled endpoints (GitHub issues no id_token).

Domain verification

Because a custom oidc config points at owner-supplied provider endpoints, an account must prove it controls the email domain before that config can assert users' identities at login. Add the shown DNS TXT record, then run Verify:

  • Host — _ngris-sso-verify.<your-domain>
  • Value — ngris-sso-verify=<token> (the per-config token shown in the dashboard)

google and github are auto-verified — their identity is asserted by Google/GitHub against locked canonical endpoints, so no DNS proof is required. Until an oidc config is verified it is ignored at login (it will neither be offered nor enforced).

Enforcement & MFA

On the login page, enforcement is evaluated against the user's default account: if that account enforces SSO for the user's email domain, password login is blocked with SSO_REQUIRED and the user is sent through SSO. Signing into a different account that enforces SSO triggers an SSO step-up at account-switch time. Accounts without SSO stay on password login, so a user who owns a password account and is only a member of an SSO-enforced account is never forced through SSO just to reach their own account.

SSO does not bypass two-factor authentication: if the user has MFA enabled, they complete the SSO handshake and are then challenged for their MFA code before the session is issued.

You can test a configuration before relying on it; the latest test status and any error are surfaced on the config. A configuration starts in the active status.

Seat cap

The number of members an account may hold is capped by your plan's max members setting. The Members page shows current seat usage (members used / max). Invitations beyond the cap are rejected, and accepting an invite is re-checked against the cap so a burst of simultaneous accepts can't overshoot it.

A plan with the cap set to -1 allows unlimited members (so does an unset cap; a 0 means no members beyond the owner). Downgrading to a plan without the account_members entitlement suspends existing non-owner memberships — they are not deleted, and re-upgrading restores them.

When an account is suspended

A suspended account can't be used by any of its members, whatever the reason for the suspension: its resources, logs, data and backups can't be opened, and nothing can be changed — in the dashboard, the API, the CLI, the MCP server and Iris alike. Its endpoints, tunnels and apps stop serving, and its databases are closed to apps; nothing is deleted.

Members can still sign in, manage their own settings (profile, password, two-factor sign-in, sessions and their personal data export), switch to their other accounts, open Billing to pay or upgrade, and contact support. Every other page of the account shows one page instead: This account is suspended, with the reason and what to do:

  • An invoice is unpaid. The owner or a member with billing access pays it, and the account is active again within a few minutes; then restart the ngris agent on each server to bring tunnels back. Before the suspension, the banner shows its date. Members without billing access see the date and ask the account owner to pay. See Unpaid invoice → suspension.
  • Usage over the plan's limits. It lifts by itself once usage is back under the limit or the plan is upgraded, as long as no invoice is unpaid.
  • Suspended by ngris. Contact support to have it reviewed.

A member other than the owner can still leave a suspended account: Leave this account on the suspended page, or the API (Leave account). The owner can't leave it, close their user, delete the account or create a new one until the suspension is lifted; the owner can still pay and update billing details, and while the account is suspended for an unpaid invoice, stop the subscription from renewing.

Account audit log

Every resource action on the account — endpoint, domain, certificate, firewall, rate-limit, API-key, dedicated-IP, billing, and member/role changes — is recorded in the account-scoped audit log. Each entry records who acted, what they did, how they authenticated, and from which device, so an owner can answer “who changed this and when.”

Personal sign-in events (password, 2FA, sessions) are not here — those live on the per-user security surfaces under your own profile, which stay strictly separate from the tenant-level account view.

Plan-gated: the audit log requires the account_audit_log entitlement on the active plan.
Was this helpful?