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.
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.
Name your account
This is your own account on ngris. Name it and tell us who it’s for. You can change both later in Account settings.
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
- 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.
- Plan — the same plans as on the Billing page, billed monthly or yearly. Nothing is charged here.
- 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.
- 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.
- 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.
- 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.
- 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 withhttps://orhttp://.
What will you run on ngris?
We’ll point you at the right first steps. You can use everything either way.
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.
The owner is finishing setting up this account
Acme Robotics opens for you as soon as its owner completes the setup. Meanwhile, switch to another account.
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.
/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/profile | Needs 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/profile | Needs 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/onboarding | Needs 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.
Company profile
Whether this account belongs to a person or a company, and the company's details.
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
- Click Invite member and enter their email and the role to grant.
- They receive an invitation link. Accepting it joins them to the account with that role.
- 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.
| User | Role | Joined | |
|---|---|---|---|
| maria@example.com You | Owner | Mar 3, 2026 | |
| sam@example.com | Admin | Apr 18, 2026 | |
| lee@example.com | Support engineer | Sep 9, 2026 |
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 |
|---|---|
| Endpoints | Tunnels and endpoint settings. |
| Domains | Custom domains and DNS. |
| Certificates / SSL | TLS certificate management. |
| Dedicated IPs | Requesting and attaching dedicated IPs. |
| Firewall | Firewall policies. |
| Rate Limits | Rate-limit rules. |
| Traffic Inspector | The live traffic view and Security Analytics. |
| Members | Inviting / removing teammates. |
| Roles | Creating and editing roles. |
| Account Settings | Account name and tenant-level settings. |
| Billing | Subscription, plan, payment methods, invoices. |
| Databases | Databases: 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 data | The 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.
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.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_domain | The email domain this config applies to (e.g. company.com). One config per domain, per account. |
| provider_type | One 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_id | OAuth/OIDC client ID. |
| client_secret | Provider client secret. Never returned in API responses; leave blank on update to keep the stored value. |
| auth_url / token_url / userinfo_url | Endpoint URLs for custom oidc providers (can be auto-discovered from an issuer URL — see below). Ignored for google/github. |
| issuer / jwks_url | Required 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. |
| scopes | Space-separated OAuth scopes. Defaults to openid profile email. |
| enforced | When on, matching-domain users must sign in via SSO. Turning this on requires the sso entitlement. |
| domain_verified | Read-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:
- 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.
- 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-configurationand fills inauth_url,token_url,userinfo_url,issuer, andjwks_urlfor you. - Enter the
client_id,client_secret, and theemail_domainto route through this provider, then save. Bothissuerandjwks_urlare required foroidc— if Discover couldn't reach your provider, fill them in by hand (the JWKS URL is thejwks_urifrom the discovery document). - 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.
Connect your OIDC provider
Set up an application at your OIDC provider with the redirect URL from the guide, then enter its credentials.
Credentials
Configured providers
1_ngris-sso-verify.example.com = ngris-sso-verify=8d1f2c9a7e3b
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.
Members
People with access to this account. Each member is assigned a role that grants a matrix of permissions. Manage roles →
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.
account_audit_log entitlement on the active plan.| When | Event | Type | User |
|---|---|---|---|
| 10/19/2026, 2:02:11 PM | Invited member: lee@example.com | Team | maria |
| 10/18/2026, 9:47:30 AM | Changed member role | Team | maria |
| 10/17/2026, 4:20:05 PM | Updated account settings | Team | sam |