Skip to main content
A single self-hosted deployment can serve one project by default - the one you mount with NAO_DEFAULT_PROJECT_PATH. If you want to host several projects on the same instance and domain (for example one project per team, per warehouse, or per client) and let users switch between them, run the deployment in multi-project mode.

How it works

nao organizes hosting as organization -> projects -> members:
  • One instance owns one organization.
  • The organization owns any number of projects. Each project is the unit that holds its own context folder, data connections, chats, members, and settings.
  • Users switch between the projects they belong to from the workspace switcher in the sidebar. No separate URL or subdomain per project - everything lives under the same domain.
Each project’s context is pushed to the instance with nao deploy. Projects are identified by project_name within the organization: deploying a new name creates a project, deploying an existing name updates it in place.
Multi-project hosting reuses the same organization and project model as nao Cloud. Enabling it on your own infrastructure is a one-line switch, described below - it does not depend on nao’s hosted service.

Single-project vs multi-project

Single-project (default)Multi-project
NAO_MODEself-hostedcloud
Context sourceA mounted folder or git repo (NAO_DEFAULT_PROJECT_PATH)Pushed with nao deploy
Projects per instanceOneMany
Project switcherNot used - always serves the default projectUsers switch between projects they belong to
NAO_DEFAULT_PROJECT_PATH and NAO_MODE=cloud cannot be set at the same time - the container exits on startup if both are present. Multi-project mode replaces the single mounted folder with projects pushed via nao deploy, so remove any NAO_DEFAULT_PROJECT_PATH (and the project volume mount) when you switch.

Step 1: Enable multi-project mode

Set a single environment variable on your deployment:
NAO_MODE=cloud
When NAO_MODE=cloud, the container automatically:
  • switches the context source to api (projects arrive over nao deploy instead of a mounted folder),
  • unsets NAO_DEFAULT_PROJECT_PATH,
  • creates a projects directory (/app/projects by default, configurable with NAO_PROJECTS_DIR) where each deployed project is stored in its own folder.
Everything else from the Deployment Guide stays the same - the PostgreSQL database, BETTER_AUTH_SECRET, LLM keys, and Cloud Run / container configuration are all shared across every project on the instance.
Because projects are pushed over the API rather than baked into the image, you don’t need the COPY step or the NAO_CONTEXT_GIT_URL variables from the single-project guide. Use the stock getnao/nao image and deploy your projects afterward.

Step 2: Create an organization API key

nao deploy authenticates with an organization-level API key, which can write to every project in the organization.
  1. Open the deployed chat UI and sign in as an admin.
  2. Go to Settings -> Organization -> API Keys.
  3. Click Create key, name it, and copy the value - it is shown only once.
See Per-organization API keys for details.

Step 3: Deploy each project

From each project folder (the one containing nao_config.yaml), push it to the instance:
nao deploy https://your-nao-domain.com --api-key nao_sk_...
The project_name in each project’s nao_config.yaml determines its identity in the organization:
  • A new project_name creates a new project on the instance.
  • An existing project_name replaces that project’s context folder in place (every deploy is a full replacement, not a merge).
Repeat for every project you want to host. For example, to host three projects on one domain:
# from ~/projects/sales
nao deploy https://your-nao-domain.com --api-key nao_sk_...     # project_name: sales

# from ~/projects/finance
nao deploy https://your-nao-domain.com --api-key nao_sk_...     # project_name: finance

# from ~/projects/marketing
nao deploy https://your-nao-domain.com --api-key nao_sk_...     # project_name: marketing

nao deploy reference

Full command flags, exclusions, .naoignore, and create-vs-update behavior

Step 4: Switch between projects

Once more than one project exists, the workspace switcher appears in the sidebar. Users pick the active project there, and their chats, context, and data connections are scoped to that project. The selection is remembered per user. Deploying a new project automatically adds every existing organization member to it. To scope who can see each project, manage members per project under Settings -> Project -> Team:

Organizations and projects

Manage organization members, per-project teams, and roles

Keeping projects in sync

Each project is a normal nao context folder, so the usual workflow applies: edit context locally (or in git), run nao sync, then nao deploy to push. To automate this, run nao deploy from CI on each push to the branch that holds a project.

Synchronization

Automate context sync and deploys with GitHub Actions

Notes and limitations

  • One domain, no per-project URLs. Projects are not exposed as subpaths or subdomains. Selection is per user through the switcher, not the URL.
  • Switching requires NAO_MODE=cloud. In default self-hosted mode the server always serves the single default project, even if extra project rows exist - the switcher won’t change what’s served.
  • API keys are organization-scoped. One key can create or overwrite any project in the organization. Treat it as a privileged secret and rotate it from the same API Keys page.