NEXUS AI documentation

NEXUS AI docs for deploying full-stack apps: CLI, databases, workers, volumes, buckets, backups, restores, secrets, and cloud providers.

Getting started

Create a workspace and ship your first deployment.

Sign up and create a workspace

  1. Go to the Sign up page and create your account.
  2. Add your organization name and confirm your email.
  3. Create your first workspace and project.

Deploy from an AI prompt

Generate code once, review it, then deploy it as a container.

  1. Open a project and expand "Advanced: standalone code generator".
  2. Select a configured AI provider and model, then describe the app, stack, constraints, and acceptance check.
  3. Click Generate Code. Review or edit the returned single file or file set before deploying.
  4. Click Deploy, choose the target and required services or environment settings, then verify build logs and the public URL.

Deploy from your local machine

  1. Choose "Deploy from Local" in your project.
  2. Upload your source folder or drag-and-drop files.
  3. Select build settings and runtime options.
  4. Deploy and open the public URL.

Deploy from a Git repository

  1. Connect GitHub, GitLab, or Bitbucket.
  2. Select a repository and branch.
  3. Set build commands, env vars, and secrets.
  4. Deploy and monitor build logs.

AI App Builder

Chat with an AI to build an app, watch it render live, edit it, and deploy — all in one dashboard flow.

Open the AI App Builder

A persistent chat session with a live local preview, distinct from one-shot "Deploy from Prompt."

  1. Open a project and click "Build with AI" on the project detail page.
  2. Describe the app you want in plain language in the chat panel.
  3. The assistant returns a full set of files; the preview panel renders the app automatically.
  4. Keep chatting to add features, fix issues, or change the design. Each message is a new turn.
  5. Every supported AI provider (Anthropic Claude, OpenAI, Google Gemini, xAI Grok, OpenRouter, and custom OpenAI-compatible endpoints) works as an agent: it lists and reads project files, makes targeted edits, and, when the App preview sandbox is running, installs dependencies and type-checks before it finishes. The chat shows each step as it happens.
  6. If a model cannot call tools reliably, the builder finishes that message as a single response instead of failing, so the conversation continues.
  7. On the Free plan with a platform-provided model, each message runs up to 8 agent steps and 150K tokens. Paid plans and your own API keys allow up to 12 steps and 300K tokens.

How the live preview works

Preview is fully local. No code is sent to a third-party sandbox or CDN.

  1. Generated code is bundled in your browser with esbuild-wasm, using a vendored React runtime, then rendered inside a sandboxed iframe.
  2. The iframe allows scripts only and has no same-origin access, so generated code cannot read your session or localStorage.
  3. v1 preview supports React apps out of the box. Imports beyond React show a friendly unsupported-package message instead of failing silently.
  4. Full-stack Next.js + Prisma apps preview against mock data instead of a real database, since the sandboxed iframe cannot reach one. Deploy to see the app against the real database.

Edit code and manage versions

  1. Open the Code panel to view or edit any generated file directly.
  2. Saving a manual edit creates a new checkpoint, exactly like an AI-generated turn.
  3. Undo and Redo in the editor toolbar (or Cmd/Ctrl+Z and Cmd/Ctrl+Shift+Z) step through your edits to the open file. Each file keeps its own history, including across saves.
  4. Discard changes throws away a file's unsaved edits. Undo brings them back if you change your mind.
  5. After you save, create, or delete a file, the confirmation has an Undo button that restores the project to how it was just before that change.
  6. Every assistant turn stores a complete, restorable snapshot of the app.
  7. Use the version menu to revert to any earlier turn. Reverting creates a new checkpoint rather than deleting history.

Attach design mockups and screenshots

The AI sees attached images and uses them to build or fix the design.

  1. Click the + button in the chat composer or paste an image from the clipboard. Up to 3 images per message (PNG, JPEG, WebP, GIF).
  2. Attached images render as removable thumbnails before you send.
  3. The AI treats images as design references to match (layout, spacing, colors, typography) or bug screenshots to diagnose and fix.
  4. Images from earlier turns stay visible to the AI, so follow-ups like "match the screenshot I sent earlier" work.
  5. Images are downscaled in your browser before upload (max 1568px on the longest edge), so requests stay small.

Upload files: syntax check, preview, and AI fixes

Bring existing source files into a builder project, or start a new project from them. Every file is type-detected and syntax-checked before it is added.

  1. In a project, click Upload in the builder header or drop files anywhere on the builder. To start a new project from files, choose "upload files" on the AI Builder start page.
  2. Limits: up to 20 files per upload, 500 KB per file, and 2 MB per upload. The whole project stays within the builder limit of 200 files and 2 MB. Text source files only; images, fonts, and other binary files are rejected.
  3. The file type is detected from the extension and the content. If a file's content looks like a different type (for example HTML saved as .txt), the dialog offers to check it as that type.
  4. Syntax is checked in your browser for JavaScript, JSX, TypeScript, TSX, CSS, JSON, HTML (including inline scripts and styles, and stray, misnested, or unclosed tags), SVG, XML, and YAML. Other text files, such as Markdown or Python, are added without a check.
  5. Issues are shown with line and column numbers. They never block the upload: choose "Add files" to fix them yourself in the Code tab, where they are marked, or "Add and fix with AI" to have the AI fix only those syntax errors. The files are checked again after the fix.
  6. HTML files have a Preview button in the upload dialog. After upload, a plain HTML site previews instantly in the builder with its local CSS, JavaScript, and SVG files; links between pages work, and a page picker appears for multi-page sites.
  7. Choose a target folder for the upload. If a file already exists, pick Replace it, Keep both (saved as name-1.ext), or Skip. Every upload is a new version you can revert from the version menu.

Click-to-edit: point at the element you want changed

  1. Click "Select element" in the top-right corner of the live preview.
  2. Hover the preview: elements highlight with their tag name. Click the one you want. Press Escape to cancel.
  3. The selection appears as a chip in the chat composer, e.g. Selected: <button> "Get started".
  4. Type the change ("make this bigger", "use the brand blue here") and send. The instruction applies to that exact element.
  5. Combine with image attachments: click the broken element and paste the target design in one message.

Build full-stack apps with a database

The builder can generate Next.js + Prisma apps in addition to React single-page apps.

  1. Ask for a full-stack app, or one that needs to persist data, and the builder scaffolds a Next.js App Router project with Prisma.
  2. Deploying a full-stack build automatically provisions a managed Postgres database and injects the connection string.
  3. The generated data layer has a dual mock/database implementation, so the same code renders in preview (mock data) and in production (real database) without edits.

Add built-in authentication

  1. After the base app exists, ask the builder to add login and signup.
  2. The builder adds a Prisma User model, bcrypt password hashing, and a signed HTTP-only session cookie, plus route guards on protected pages.
  3. Ask for authentication as a follow-up message rather than in the same turn as the initial app. Scaffolding a full app and auth together in one turn can overflow the AI response.

Deploy your app

  1. Click Deploy in the builder header.
  2. Choose a deployment provider and region, the same options available from a standard deployment.
  3. The deploy uses the same pipeline as other deployments, including build logs and status polling.

Self-healing preview and deploy-failure fixes

  1. If a preview build fails, the builder automatically attempts up to two AI-driven fixes before asking you to step in.
  2. After you deploy, the header shows a live status banner (Deploying, Live, or Failed) while polling in the background.
  3. If the deploy fails, click "Fix with AI" to repair the code and redeploy. The fix reuses the existing managed database instead of provisioning a new one.

Push to GitHub

  1. Click "Push to GitHub" in the builder header.
  2. Connect your GitHub App if you have not already, or reuse an existing installation.
  3. Choose a new repository name or an existing repository, then push.
  4. Each push creates a new commit containing the complete current snapshot, including any deleted files.

Vibe-code in Claude chat, preview in the builder

MCP tools bridge chat-based coding and the builder preview, so you can see the app running before any deploy.

  1. Connect the NEXUS AI MCP server in Claude (or any MCP client) and generate an app in chat. Ask it to push the app to the AI Builder; the client calls nexusai_builder_push and returns a preview link.
    "Push this app to my NEXUS AI builder so I can preview it"
    # -> nexusai_builder_push { projectId, files, note }
    # <- https://nexusai.run/projects/<projectId>/builder
  2. Open the link: the app renders in the builder's live preview instantly. No infrastructure is spun up and nothing is billed for previewing.
  3. Iterate wherever you like: keep chatting in the builder (with click-to-edit and image attachments), edit code by hand, or go back to your MCP client.
  4. Bring builder-side edits back into chat with nexusai_builder_pull, which returns the latest snapshot including manual edits.
    "Pull the current files from my builder session"
    # -> nexusai_builder_pull { projectId }
  5. Deploy from either side: the builder's Deploy button or the MCP deploy tools. Every push is a restorable checkpoint in the session history.
  6. Scopes: nexusai_builder_push requires deployments:create; nexusai_builder_pull requires deployments:read. The organization needs an AI provider configured because builder sessions are provider-backed.

AI App Builder FAQ

How is the builder different from "Deploy from Prompt"?

"Deploy from Prompt" generates code once and deploys it in a single pass. The AI App Builder is a persistent session: you iterate conversationally, review a live preview after every turn, edit code directly, revert to earlier versions, and deploy only when you are ready.

Does the builder support frameworks other than React and Next.js?

Not yet in v1. React single-page apps preview live; Next.js + Prisma apps get a mock-data preview plus a real managed database at deploy time. Other frameworks are a planned follow-up.

Can I keep chatting after I deploy?

Yes. Deploying does not end the session. Continue chatting to make changes, then redeploy to update the live app.

Does creating a new repo from the builder require special GitHub permissions?

Creating a brand-new repository requires the GitHub App to have Administration:write, and pushing requires Contents:write on the target repo. Creating a repo under a personal GitHub account is not supported by installation tokens; push to an existing repo, or install the app on an organization.

Does the builder add any branding to generated apps?

On the Free plan, generated Next.js apps include a small "Powered by NEXUS AI" badge linked back to NEXUS AI. Paid plans do not have a badge.

What happens to my managed database if a deploy fails and I use "Fix with AI"?

The database is preserved. "Fix with AI" redeploys with the same managed database attached, so you are not charged for or left with a duplicate database.

Does the AI actually see attached images, or just their file names?

It sees them. Attachments are sent to the model as vision inputs, so it reads layout, colors, spacing, and text from the image itself. That is why "make it look like this" with a pasted mockup works.

Is click-to-edit sending my whole page to the AI?

No. Clicking an element captures a short description (tag, classes, visible text, a trimmed HTML snippet, and ancestor path) that is added to your message. The preview itself stays local in a sandboxed iframe.

Why does nexusai_builder_push say no AI provider is configured?

Builder sessions are backed by an AI provider so you can continue iterating in the builder UI. Add a provider in the dashboard under AI Providers, then retry the push.

Does previewing a pushed app cost anything?

No. The preview runs entirely in the browser of whoever opens the builder link. Nothing deploys and no infrastructure is provisioned until you explicitly deploy.

Can I upload my own files to the AI App Builder?

Yes. Upload up to 20 text source files at a time (500 KB each, 2 MB per upload) into an existing project, or start a new project from them. Each file is type-detected and syntax-checked in your browser before it is added, and an HTML site previews instantly.

Which file types does the upload syntax check support?

JavaScript, JSX, TypeScript, TSX, CSS, JSON, HTML, SVG, XML, and YAML. HTML checks cover inline scripts and styles and stray, misnested, or unclosed tags. Other text files are accepted without a check, and binary files such as images are rejected.

Can the AI fix syntax errors in uploaded files?

Yes. Choose "Add and fix with AI" in the upload dialog. The AI fixes only the reported syntax errors in the uploaded files, then the builder checks those files again and marks anything that remains in the Code tab.

API User Guide

Comprehensive REST API guide for end users, including authentication, deployment flows, and practical examples.

API overview and base URL

Use `/api` as the base path and choose the auth type based on the endpoint family.

  1. Set your API base URL and auth variables once in your shell.
    export NEXUS_API_BASE="https://nexusai.run/api"
    export NEXUS_JWT="YOUR_JWT_FROM_LOGIN"
    export NEXUS_TOKEN="nxk_YOUR_ACCESS_TOKEN"
  2. Most product endpoints require a user JWT in Authorization header.
    curl -s "$NEXUS_API_BASE/projects" \
      -H "Authorization: Bearer $NEXUS_JWT"
  3. Automation endpoints use access tokens (`nxk_...`) with scoped permissions.
    curl -s "$NEXUS_API_BASE/gpt/providers" \
      -H "Authorization: Bearer $NEXUS_TOKEN"
  4. Typical successful API shape:
    {
      "success": true,
      "data": { ... }
    }
  5. OpenAPI spec for GPT automation endpoints:
    curl -s "$NEXUS_API_BASE/openapi.yaml"

Authenticate and get a JWT

Register or login, then reuse the JWT for project, deployment, secrets, GitHub, and database APIs.

  1. Login and capture token from the response data payload.
    curl -s -X POST "$NEXUS_API_BASE/auth/login" \
      -H "Content-Type: application/json" \
      -d '{
        "email": "[email protected]",
        "password": "your-password"
      }'
  2. Verify token validity.
    curl -s "$NEXUS_API_BASE/auth/verify" \
      -H "Authorization: Bearer $NEXUS_JWT"
  3. Use this JavaScript helper for browser or Node fetch calls.
    const api = async (path, options = {}) => {
      const res = await fetch(`${NEXUS_API_BASE}${path}`, {
        ...options,
        headers: {
          'Content-Type': 'application/json',
          Authorization: `Bearer ${NEXUS_JWT}`,
          ...(options.headers || {}),
        },
      });
      return res.json();
    };
    
    const projects = await api('/projects');

Access tokens for automation (nxk_)

Create scoped access tokens for machine workflows such as GPT actions and runtime secret retrieval.

  1. Create a token in the app: Settings -> Access Tokens -> Create Token.
  2. Recommended scopes by use case:
    GPT automation:
      deployments:create, deployments:read, deployments:logs, deployments:delete
    
    Runtime secrets fetch:
      secrets:read (or secrets:read:values if values are required)
  3. Call a GPT endpoint with your access token.
    curl -s "$NEXUS_API_BASE/gpt/deployments" \
      -H "Authorization: Bearer $NEXUS_TOKEN"
  4. Fetch runtime secrets metadata (without values).
    curl -s "$NEXUS_API_BASE/secrets/runtime?includeValues=false" \
      -H "Authorization: Bearer $NEXUS_TOKEN"

ChatGPT App OAuth setup (recommended)

Use OAuth for NexusAI as a ChatGPT App so each user connects with tenant-scoped identity.

  1. Set OAuth endpoints in your ChatGPT App configuration.
    Authorization URL: https://nexusai.run/oauth/authorize
    Token URL: https://nexusai.run/api/oauth/token
    User info URL: https://nexusai.run/api/oauth/me
  2. Configure backend environment variables for your ChatGPT client and callback URL allowlist.
    OAUTH_CLIENT_ID=<chatgpt_client_id>
    OAUTH_CLIENT_SECRET=<chatgpt_client_secret_optional_for_public_client>
    OAUTH_REDIRECT_URIS=<comma-separated-allowed-callback-urls>
    OAUTH_ISSUER=https://nexusai.run
    OAUTH_SIGNING_SECRET=<strong-random-secret>
  3. For public clients, enable PKCE (S256) and include code_challenge/code_verifier in the OAuth flow.
  4. Smoke-test the OAuth token exchange manually (replace placeholders).
    curl -s -X POST "https://nexusai.run/api/oauth/token" \
      -H "Content-Type: application/json" \
      -d '{
        "grant_type":"authorization_code",
        "client_id":"<client_id>",
        "code":"<authorization_code>",
        "redirect_uri":"<redirect_uri>",
        "code_verifier":"<pkce_verifier_if_used>"
      }'
  5. Validate the returned access token against `/api/oauth/me` before enabling deployment tools.
    curl -s "https://nexusai.run/api/oauth/me" \
      -H "Authorization: Bearer <oauth_access_token>"

Projects API quickstart

Create and manage projects, then use the projectId for deployment APIs.

  1. Create a project.
    curl -s -X POST "$NEXUS_API_BASE/projects" \
      -H "Authorization: Bearer $NEXUS_JWT" \
      -H "Content-Type: application/json" \
      -d '{
        "name": "my-api",
        "description": "Customer API",
        "framework": "Express",
        "vaultEnvironment": "Development",
        "repoUrl": "https://github.com/acme/my-api",
        "gitBranch": "main"
      }'
  2. List projects and inspect one by id.
    curl -s "$NEXUS_API_BASE/projects" -H "Authorization: Bearer $NEXUS_JWT"
    curl -s "$NEXUS_API_BASE/projects/<projectId>" -H "Authorization: Bearer $NEXUS_JWT"
  3. Update a project.
    curl -s -X PUT "$NEXUS_API_BASE/projects/<projectId>" \
      -H "Authorization: Bearer $NEXUS_JWT" \
      -H "Content-Type: application/json" \
      -d '{"gitBranch":"main","vaultEnvironment":"Staging"}'

Deployments API (create, monitor, manage, redeploy)

Use simple deploy, full deploy, logs, lifecycle actions, and redeploy templates.

Can I change auto-destroy after a deployment is live?

Yes. Open the deployment details page, use CLI nexus deploy auto-destroy, call REST PATCH /api/deployments/:id/auto-destroy, or use MCP tool nexusai_deploy_auto_destroy. Updating auto-destroy changes the cleanup timestamp only and does not restart, rebuild, or redeploy the app.

Can I reduce auto-destroy time?

Yes. You can extend or reduce the auto-destroy timestamp as long as the new time is at least 5 minutes in the future. To remove the schedule entirely, set autoDestroyAt to null.

Is it safe to stop and start a deployment? Will I lose data?

Yes. Stop performs a soft stop: containers, attached volumes, and network configuration are preserved. Start rehydrates the same configuration without rebuilding the image. The same recovery runs automatically if the host reboots. Delete is the only action that removes volumes and reserved ports.

GitHub integrations API

Connect the GitHub App, list repos, create bindings, and trigger manual deployments.

  1. Start GitHub App installation (JSON mode returns installUrl).
    curl -s "$NEXUS_API_BASE/github/install/start?format=json&redirectPath=/github" \
      -H "Authorization: Bearer $NEXUS_JWT"
  2. List repositories available to the installation.
    curl -s "$NEXUS_API_BASE/github/repos?installationId=<installationId>" \
      -H "Authorization: Bearer $NEXUS_JWT"
  3. Create or update a repo binding.
    curl -s -X POST "$NEXUS_API_BASE/github/bindings" \
      -H "Authorization: Bearer $NEXUS_JWT" \
      -H "Content-Type: application/json" \
      -d '{
        "installationId":"<installationId>",
        "repoId":"123456789",
        "owner":"acme",
        "name":"my-api",
        "fullName":"acme/my-api",
        "defaultBranch":"main",
        "allowedBranches":["main","prod"],
        "autoDeploy":true,
        "runtimeTarget":"cloudrun",
        "servicePort":3000,
        "buildMode":"auto"
      }'
  4. Trigger manual deployment and inspect webhook/deployment history.
    curl -s -X POST "$NEXUS_API_BASE/github/bindings/<bindingId>/deploy" \
      -H "Authorization: Bearer $NEXUS_JWT" \
      -H "Content-Type: application/json" \
      -d '{"branch":"main"}'
    
    curl -s "$NEXUS_API_BASE/github/deployments?page=1&limit=30" -H "Authorization: Bearer $NEXUS_JWT"
    curl -s "$NEXUS_API_BASE/github/webhook-deliveries?page=1&limit=50" -H "Authorization: Bearer $NEXUS_JWT"

Database service API examples

Query and manage deployment-attached databases from the Databases tab APIs.

  1. List database services and fetch a connection payload.
    curl -s "$NEXUS_API_BASE/deployments/<deploymentId>/databases" \
      -H "Authorization: Bearer $NEXUS_JWT"
    
    curl -s -X POST "$NEXUS_API_BASE/deployments/<deploymentId>/databases/<serviceId>/connection" \
      -H "Authorization: Bearer $NEXUS_JWT" \
      -H "Content-Type: application/json" \
      -d '{"format":"uri"}'
  2. Browse schema and query data.
    curl -s "$NEXUS_API_BASE/deployments/<deploymentId>/databases/<serviceId>/browse/schema" \
      -H "Authorization: Bearer $NEXUS_JWT"
    
    curl -s -X POST "$NEXUS_API_BASE/deployments/<deploymentId>/databases/<serviceId>/browse/query" \
      -H "Authorization: Bearer $NEXUS_JWT" \
      -H "Content-Type: application/json" \
      -d '{
        "query":"SELECT * FROM users ORDER BY created_at DESC LIMIT 10",
        "params":[]
      }'
  3. Service maintenance and metrics.
    curl -s -X POST "$NEXUS_API_BASE/deployments/<deploymentId>/databases/<serviceId>/restart" -H "Authorization: Bearer $NEXUS_JWT"
    curl -s -X POST "$NEXUS_API_BASE/deployments/<deploymentId>/databases/<serviceId>/rotate-credentials" -H "Authorization: Bearer $NEXUS_JWT"
    curl -s "$NEXUS_API_BASE/deployments/<deploymentId>/databases/<serviceId>/metrics" -H "Authorization: Bearer $NEXUS_JWT"

Errors, status codes, and troubleshooting

What do common API status codes mean?

200/201/202: Request succeeded. 400: Invalid input or missing required fields. 401: Missing/invalid token. 403: Permission/scope blocked or account setup required. 404: Resource not found. 409: Duplicate/conflict (for example existing resource). 429: Rate limit reached. 500: Unexpected server error.

How do account setup checks appear in API errors?

Some authenticated endpoints require verified email and payment setup. Example 403 payloads include: - code: EMAIL_NOT_VERIFIED - code: PAYMENT_METHOD_REQUIRED

How should I debug failed requests quickly?

Use this checklist: 1. Confirm base URL includes /api. 2. Confirm token type matches endpoint family (JWT vs nxk access token). 3. Confirm your role or token scopes allow the action. 4. Validate required fields exactly as expected by the endpoint. 5. Retry with curl -v to inspect headers and response body.

curl -v -X POST "$NEXUS_API_BASE/deployments" \
  -H "Authorization: Bearer $NEXUS_JWT" \
  -H "Content-Type: application/json" \
  -d '{"projectId":"...","name":"...","code":"..."}'

NEXUS AI GitHub Deployments

Connect the GitHub App, bind repositories, and monitor automated deployments.

Connect GitHub

Install the NEXUS AI GitHub App and grant repository permissions.

  1. Open GitHub in the sidebar.
  2. Click Connect GitHub to start installation.
  3. On GitHub, select your account or organization and review permissions.
  4. Choose repository access (all repositories or selected repositories only).
  5. Complete installation and return to NEXUS AI.

Select and bind a repository

Create deployment rules for a repository in your tenant.

  1. In GitHub > Repo Bindings, click Load Repositories.
  2. Select a repository and default branch.
  3. Set allowed branches (example: main,prod) and enable Auto Deploy if needed.
  4. Configure build mode, runtime target, service port, and optional subdomain.
  5. Click Create Binding to save the rule.

How auto-deploy works

Push events to allowed branches create deployments automatically.

  1. A push webhook arrives from GitHub and signature verification runs first.
  2. NEXUS AI checks repository binding, branch allowlist, and auto-deploy status.
  3. A deployment record is queued and processed by the build and runtime workers.
  4. Deployment status updates from queued to building to deploying, then healthy or failed.

Add a Deploy to NEXUS AI button to your README

Let anyone deploy your public GitHub repository to their own NEXUS AI account in one click, with the databases, worker, and settings it needs.

  1. Add the button to README.md. Replace owner/repo with your repository; branch and root-dir are optional query parameters.
    [![Deploy to NEXUS AI](https://nexusai.run/deploy-button.svg)](https://nexusai.run/deploy?repo=https://github.com/owner/repo)
  2. Optionally add a nexus.json at the repository root to describe what the app needs. Every field is optional; without the file, the framework is detected automatically.
    {
      "name": "Shop",
      "description": "Next.js store with Postgres",
      "services": ["postgres", "redis"],
      "worker": { "command": "node worker.js" },
      "rootDir": "backend",
      "startCommand": "npm start",
      "env": {
        "SESSION_SECRET": { "generator": "secret" },
        "STRIPE_SECRET_KEY": { "description": "Your Stripe secret key", "required": true },
        "NODE_ENV": { "value": "production" }
      }
    }
  3. services accepts postgres, mysql, mongodb, and redis. Redis, MongoDB, and a worker run on the NEXUS AI runtime; on Google Cloud Run, AWS App Runner, and Azure Container Apps, postgres and mysql become managed databases.
  4. env entries: value sets a fixed value, generator "secret" creates a random secret at deploy time, and required asks the person deploying for a value. Values are never put in the button URL.
  5. rootDir, buildCommand, startCommand, and installCommand work like the matching nexus deploy source flags.
  6. dockerfile points at a Dockerfile that is not at the repository root (for example docker/Dockerfile), and port sets the port the app listens on when the Dockerfile has no EXPOSE. Both also work as link parameters (dockerfile= and port=), so you can deploy a repository you do not own. A link can also set variables with env=KEY=value (repeatable); the deploy page shows them for review, and names that change how a process starts (NODE_OPTIONS, LD_PRELOAD, PATH, proxy variables) are refused. Example: ?repo=https://github.com/Mintplex-Labs/anything-llm&dockerfile=docker/Dockerfile&port=3001&env=STORAGE_DIR=/app/server/storage. Secrets never go in a link: require=NAME asks for the value on the deploy page, generate=NAME creates a random one at deploy time, and {url} in an env value becomes the deployment URL.
  7. Clicking the button opens a page that shows the repository and what will be created. Visitors sign up or sign in, choose a name and target, fill in required values, and deploy. The deployment follows their plan limits, including automatic expiry of test deployments.
  8. The button works with public GitHub repositories. For a private repository, connect GitHub in NEXUS AI and import it instead.
  9. Step by step setup, the full nexus.json reference, examples, and troubleshooting: https://nexusai.run/kb/deploy-button

Monitor deployments and webhooks

  1. Use the Deployments tab to track commit, branch, actor, status, and runtime URL.
  2. Use Webhook Deliveries to inspect GitHub delivery IDs and processing outcomes.
  3. Use Repo Bindings to review or delete repository-to-tenant bindings.

Troubleshooting

Why do I get "GitHub App slug is not configured"?

The backend is missing GitHub App slug configuration. Fix: set GITHUB_APP_SLUG in backend environment variables (or set GITHUB_APP_NAME so the slug can be derived), then restart the backend.

Why does the GitHub install URL return 404?

This usually means the app slug or account access is wrong. Fix: verify the app exists at https://github.com/apps/<your-app-slug> and confirm you are signed into a GitHub account allowed to install that app.

I selected repositories but did not return to NEXUS AI. What should I check?

Your GitHub App setup callback URL may be incorrect. Fix: set the GitHub App Setup URL to your backend callback endpoint, for example https://nexusai.run/api/github/install/callback. Do not use the OAuth login callback for app installation flow.

Push events are received but deployments do not start. Why?

Most often, one of these conditions failed: repository not bound, branch not allowlisted, or auto-deploy disabled. Fix: review the Repo Binding and Webhook Deliveries tabs to confirm the exact ignore reason.

Role permissions for GitHub deployments

Who can connect GitHub and manage bindings?

Tenant Owner and Admin roles can install the GitHub App, create bindings, and change deployment rules.

What can Developer members do?

Developers can view deployment status and logs for bound repositories, and can trigger manual redeploy if enabled by your organization policy.

Database service deployments

Deploy MySQL, PostgreSQL, MongoDB, and Redis alongside your app and manage them from Deployment Details.

Deploy with additional database services

  1. Open your project and start a deployment (local, prompt, or Git flow).
  2. In the deployment form, go to Additional Services (Optional).
  3. Select one or more services: MySQL, PostgreSQL, MongoDB, or Redis.
  4. Optionally set a custom display name for each selected service.
  5. Deploy your app. NEXUS AI creates the selected services with auto-configured connection details.

Supported service types and default internal ports

  1. Use these default internal ports for service-to-service connections:
    mysql:3306
    postgresql:5432
    mongodb:27017
    redis:6379
  2. Typical in-network hostnames match the service names:
    MYSQL_HOST=mysql
    POSTGRES_HOST=postgresql
    MONGO_HOST=mongodb
    REDIS_HOST=redis

Database service environment variables

NEXUS AI injects these variables into the app container, and into worker sidecars deployed with the same app.

  1. Use the internal hostnames and internal ports from your application code. Do not use published host ports for app-to-database traffic inside the deployment network.
    App container -> PostgreSQL: postgresql:5432
    App container -> MySQL:      mysql:3306
    App container -> MongoDB:    mongodb:27017
    App container -> Redis:      redis:6379
  2. PostgreSQL service variables:
    POSTGRES_HOST=postgresql
    POSTGRES_PORT=5432
    POSTGRES_DB=appdb
    POSTGRES_USER=appuser
    POSTGRES_PASSWORD=<auto-generated>
    DATABASE_URL=postgresql://appuser:<auto-generated>@postgresql:5432/appdb
  3. MySQL service variables:
    MYSQL_HOST=mysql
    MYSQL_PORT=3306
    MYSQL_DATABASE=appdb
    MYSQL_USER=appuser
    MYSQL_PASSWORD=<auto-generated>
    MYSQL_ROOT_PASSWORD=<auto-generated>_root
    DATABASE_URL=mysql://appuser:<auto-generated>@mysql:3306/appdb
  4. MongoDB service variables:
    MONGO_HOST=mongodb
    MONGO_PORT=27017
    MONGO_DATABASE=appdb
    MONGO_USERNAME=root
    MONGO_PASSWORD=<auto-generated>
    MONGO_URI=mongodb://root:<auto-generated>@mongodb:27017/appdb?authSource=admin
  5. Redis service variables:
    REDIS_HOST=redis
    REDIS_PORT=6379
    REDIS_URL=redis://redis:6379/0
  6. When connecting from outside Docker, use the connection details shown in the Databases tab. Host port variables such as POSTGRES_HOST_PORT or REDIS_HOST_PORT are platform wiring values and are not needed inside your application container.

Managed provider limitation

  1. Cloud Run, AWS App Runner, and Azure Container Apps deployments do not support Additional Services in the deployment form.
  2. For those providers, use a managed external database and inject credentials using Secrets Vault.
  3. If you need built-in compose-based database services, deploy on Local Docker provider.

Manage services from Deployment Details

  1. Open a running deployment and switch to the Databases tab.
  2. Review service status and metadata for each database service.
  3. Use refresh to update live service state.
  4. Use service actions to restart services, rotate credentials, and retrieve connection strings.
  5. Use metrics and browser/query tools (if enabled) to inspect schema and run queries.

Database permissions

  1. Viewing database services requires database.read permission.
  2. Restarting services or rotating credentials requires database.manage permission.
  3. Running write queries requires database.write permission.

Database deployment troubleshooting

Why does the Databases tab show "No Database Services"?

This deployment was created without Additional Services enabled. Fix: create a new deployment and select MySQL, PostgreSQL, MongoDB, or Redis before deploying.

Why are Additional Services disabled in the deployment form?

Additional Services are disabled for Cloud Run, App Runner, and Container Apps providers. Fix: use a managed external database for those providers, or use Local Docker provider for compose-based sidecar services.

My app cannot connect to the database service. What should I check first?

Most connection issues are host/port mismatches or service startup timing. Fix: use the internal service hostname (for example mysql/postgresql/mongodb/redis) and default internal port, then confirm the deployment status is RUNNING.

What happens when I rotate credentials?

NEXUS AI rotates credentials and recreates the service container with the new values. Fix: update your application credentials immediately and redeploy if your app caches old values.

Storage volumes and buckets

Persistent filesystem mounts and S3-compatible buckets attached to your deployments. No data lock-in.

Two storage primitives

NEXUS AI offers two distinct storage types. Pick based on how your app reads and writes data.

  1. Volumes are persistent filesystem mounts. Your app writes to a path (default /data) and the data persists across redeploys, restarts, and container destruction. Backed by Docker named volumes. Use for SQLite databases, user uploads written through the filesystem, persistent caches, log archives.
  2. Buckets are S3-compatible object storage. Your app uses an AWS SDK or boto3 against an S3 endpoint. Backed by a shared MinIO instance (Docker-only v1). Use for media uploads, generated reports, public assets, anything addressed by key rather than file path.
  3. Both are org-scoped. Both survive deployment deletion (you must explicitly delete the volume or bucket to destroy the data).

Manage storage from the dashboard

  1. Use the Volumes page for persistent filesystem mounts. Create a volume, attach it to a deployment at a mount path, then redeploy the deployment so Docker starts a new container with the mount.
  2. Use the Buckets page for S3-compatible object storage. Create a bucket, attach it to one or more deployments, then redeploy each deployment so S3_* environment variables are injected.
  3. The dashboard shows attachment status, usage, object count, and available actions. Refresh usage when you need current volume size or bucket object totals.
  4. Deleting a volume or bucket is destructive. Volumes must be detached first. Buckets must be detached from all deployments first.

CLI quick reference

Use these commands for terminal-first storage management.

  1. Volume commands:
    nexus volume list
    nexus volume create app-data --display-name "App data"
    nexus volume attach <volume-id> <deployment-id> --mount /data
    nexus deploy redeploy <deployment-id> --wait
    nexus volume refresh-usage <volume-id>
    nexus volume detach <volume-id>
    nexus volume delete <volume-id> --yes
  2. Bucket commands:
    nexus bucket list
    nexus bucket create user-uploads --display-name "User uploads"
    nexus bucket attach <bucket-id> <deployment-id>
    nexus deploy redeploy <deployment-id> --wait
    nexus bucket files <bucket-id> --prefix uploads/
    nexus bucket upload <bucket-id> ./report.pdf --key reports/report.pdf
    nexus bucket download <bucket-id> reports/report.pdf --out ./report.pdf
    nexus bucket download <bucket-id> reports/report.pdf --share --ttl 900
    nexus bucket credentials <bucket-id>
    nexus bucket rotate-credentials <bucket-id> --yes
    nexus bucket rm <bucket-id> reports/report.pdf --yes
    nexus bucket detach <bucket-id> <deployment-id>
    nexus bucket delete <bucket-id> --yes

Volume workflow: create, attach, deploy

There are two correct sequences. Picking the wrong order is the #1 source of "/data: No such file or directory" errors.

  1. Sequence A (recommended for new deployments). Create the volume, then deploy the app and attach the volume in the same flow:
    # 1. Create the volume
    nexus volume create app-data --display-name "User uploads"
    
    # 2. Deploy the app (or use an existing one), then attach the volume:
    nexus deploy source --repo https://github.com/you/your-app.git --name myapp --provider docker --wait
    nexus volume attach <volume-id> <deployment-id> --mount /data
    
    # 3. Redeploy so the new compose file includes the mount:
    nexus deploy redeploy <deployment-id> --wait
    
    # 4. Verify the mount inside the container:
    docker exec <container-id> ls -la /data
  2. Sequence B (attach to a running deployment). Same idea, different starting point. The redeploy is the load-bearing step. Without it, the running container has no mount, even though the volume row says "attached".
    nexus deploy list                                 # find the deployment id
    nexus volume create app-data
    nexus volume attach <volume-id> <deployment-id> --mount /data
    nexus deploy redeploy <deployment-id> --wait     # required
    docker exec <new-container-id> ls -la /data
  3. Why redeploy is required. Docker bakes container mounts at creation time. You cannot add or remove a mount on a running container. The "redeploy" step destroys the old container and starts a new one with the updated mount list. NEXUS AI calls this out as an explicit action so you know your container is being recreated. Future versions may add an --auto-redeploy flag on attach.

How volumes behave when you scale up and down

Volumes are shared across replicas. This is a Docker constraint and changes how you should design the app.

  1. Scale up (nexus deploy scale <id> 3): every new replica mounts the SAME named volume at the same path. All three replicas read and write the same files on the host filesystem. There is no fan-out, no per-replica copy, no isolation.
    nexus deploy scale <deployment-id> 3
    # All three containers now mount nexus-vol-<volumeId>:/data
    # A file written by replica 1 is visible to replicas 2 and 3 immediately.
  2. Scale down (nexus deploy scale <id> 1): the removed replicas detach. The volume is untouched. Data persists. The remaining replica continues using the same files.
  3. When this is safe. Read-mostly workloads (configs, static assets, model weights). Apps with built-in coordination (POSIX file locking, lease files, distributed mutex via Redis). Workers consuming a shared inbox where each item is processed at most once.
  4. When this is dangerous. Two replicas appending to the same log file produce interleaved garbage. Two replicas writing the same SQLite database with default journaling corrupt it. Counter files, session caches, anything that assumes single-writer semantics. If your app needs per-replica state, give each replica its own deployment, or use the Buckets primitive instead and let the SDK handle concurrency.
  5. How to think about it. Treat a volume the same way you would treat an NFS mount or a shared network drive. Anything safe on NFS is safe on a NEXUS AI volume. Anything that requires single-machine guarantees is not.

Volume lifecycle and detachment

  1. Volumes are single-attach. A volume can be attached to at most one deployment at a time. Trying to attach it to a second deployment returns 409 Conflict.
  2. To move a volume between deployments. Detach from the current deployment, then attach to the new one. Each step requires a redeploy of the affected deployment for the mount to take effect.
    nexus volume detach <volume-id>
    nexus deploy redeploy <old-deployment-id> --wait     # mount removed
    nexus volume attach <volume-id> <new-deployment-id> --mount /data
    nexus deploy redeploy <new-deployment-id> --wait     # mount added
  3. Detaching does not delete data. The volume is now "available" and reattachable.
  4. Deleting a volume is permanent. nexus volume delete <id> destroys the underlying Docker named volume. The volume must be detached first or the request returns 409.
  5. Deleting a deployment does not delete attached volumes. The volume becomes available for reattachment. This is intentional and prevents accidental data loss.

Bucket workflow: create, attach, redeploy, talk S3

Buckets work over the S3 API, so they avoid most of the volume scaling caveats.

  1. Create a bucket and attach it to a deployment.
    nexus bucket create user-uploads
    nexus bucket attach <bucket-id> <deployment-id>
    nexus deploy redeploy <deployment-id> --wait
  2. NEXUS AI injects the following env vars into the deployment on next redeploy. Your app uses these with any AWS SDK pointed at S3_ENDPOINT.
    S3_ENDPOINT=http://host.docker.internal:9000
    S3_REGION=us-east-1
    S3_BUCKET=org-<orgIdShort>-<bucketName>
    S3_ACCESS_KEY=<scoped to this bucket only>
    S3_SECRET_KEY=<scoped to this bucket only>
    
    # Plus per-bucket aliases when multiple buckets are attached:
    S3_BUCKET_USER_UPLOADS=org-...-user-uploads
    S3_BUCKET_USER_UPLOADS_ACCESS_KEY=...
    S3_BUCKET_USER_UPLOADS_SECRET_KEY=...
  3. Example app code (Python boto3).
    import os, boto3
    s3 = boto3.client(
        "s3",
        endpoint_url=os.environ["S3_ENDPOINT"],
        aws_access_key_id=os.environ["S3_ACCESS_KEY"],
        aws_secret_access_key=os.environ["S3_SECRET_KEY"],
        region_name=os.environ["S3_REGION"],
    )
    s3.put_object(Bucket=os.environ["S3_BUCKET"], Key="hello.txt", Body=b"hi")
  4. Buckets are multi-attach. The same bucket can be exposed to many deployments concurrently. The S3 API itself handles concurrent writes safely (last-writer-wins on object PUT, no torn writes).

How buckets behave when you scale

  1. Scale up: every replica gets the same S3_* env vars. Each replica makes independent API calls to MinIO. The S3 API is built for concurrent multi-writer access.
  2. Concurrent writes to the same key: the last PUT wins. No partial writes, no corruption. Use distinct keys per replica if you need per-replica isolation.
  3. Scale down: nothing to detach. The replica process exits and stops making S3 calls. The bucket is unaffected.

Browsing, uploading, and downloading bucket files

  1. CLI file operations.
    nexus bucket files <bucket-id>                       # list
    nexus bucket files <bucket-id> --prefix uploads/     # filter by prefix
    nexus bucket upload <bucket-id> ./report.pdf
    nexus bucket download <bucket-id> report.pdf --out /tmp/report.pdf
    nexus bucket download <bucket-id> report.pdf --share --ttl 600   # signed URL valid 10min
    nexus bucket rm <bucket-id> report.pdf
  2. Web dashboard. The Buckets page has a file browser with upload, download, and delete actions. Downloads are streamed through an authenticated endpoint, audit-logged on every download. Files over 200MB show a memory warning before downloading via the browser; use the CLI for large files.
  3. Sharing files outside NEXUS AI. nexus bucket download --share generates a short-lived signed URL (default 5 minutes, max 1 hour). Anyone with the URL can download. For permanent public access, configure your app to set a public read policy on specific objects (the platform does not expose this directly in v1).

Credentials and rotation

  1. Each bucket gets a per-bucket service account in MinIO with an IAM policy scoped to exactly that bucket. A compromised app cannot read or write any other bucket on the platform.
  2. Reveal the credentials (audit-logged) for use with external clients like AWS CLI: nexus bucket credentials <bucket-id>
  3. Rotate credentials when keys may have leaked, or to migrate legacy buckets that still hold platform-wide credentials:
    nexus bucket rotate-credentials <bucket-id>
    nexus deploy redeploy <deployment-id> --wait     # required for new S3_* env vars to take effect
  4. There is no auth gap during rotation. The new service account is registered before the old one is deleted, and the swap on the deployment row is atomic.

REST API reference

Use a logged-in user JWT and the /api base path for dashboard-grade storage operations.

  1. Volume endpoints:
    GET    /api/volumes
    POST   /api/volumes
    POST   /api/volumes/:id/attach
    POST   /api/volumes/:id/detach
    POST   /api/volumes/:id/refresh-usage
    DELETE /api/volumes/:id
  2. Bucket endpoints:
    GET    /api/buckets
    POST   /api/buckets
    POST   /api/buckets/:id/attach
    POST   /api/buckets/:id/detach
    POST   /api/buckets/:id/refresh-usage
    POST   /api/buckets/:id/rotate-credentials
    GET    /api/buckets/:id/credentials
    GET    /api/buckets/:id/files
    PUT    /api/buckets/:id/files/:key
    GET    /api/buckets/:id/files/:key/download
    POST   /api/buckets/:id/files/:key/download-url
    DELETE /api/buckets/:id/files/:key
    GET    /api/bucket-downloads/:token
  3. Example volume attach request:
    curl -s -X POST "$NEXUS_API_BASE/volumes/<volume-id>/attach" \
      -H "Authorization: Bearer $NEXUS_JWT" \
      -H "Content-Type: application/json" \
      -d '{"deploymentId":"<deployment-id>","mountPath":"/data"}'
  4. Example bucket attach request:
    curl -s -X POST "$NEXUS_API_BASE/buckets/<bucket-id>/attach" \
      -H "Authorization: Bearer $NEXUS_JWT" \
      -H "Content-Type: application/json" \
      -d '{"deploymentId":"<deployment-id>"}'

MCP tools and permissions

AI clients can manage storage through scoped MCP tools.

  1. Volume MCP tools:
    nexusai_volume_list      # deployments:read
    nexusai_volume_create    # deployments:create
    nexusai_volume_attach    # deployments:create
    nexusai_volume_detach    # deployments:create
    nexusai_volume_delete    # deployments:delete
  2. Bucket MCP tools:
    nexusai_bucket_list               # deployments:read
    nexusai_bucket_create             # deployments:create
    nexusai_bucket_attach             # deployments:create
    nexusai_bucket_detach             # deployments:create
    nexusai_bucket_rotate_credentials # deployments:create
    nexusai_bucket_files_list         # deployments:read
    nexusai_bucket_file_download      # deployments:read
    nexusai_bucket_file_delete        # deployments:delete
    nexusai_bucket_delete             # deployments:delete
  3. Dashboard and REST permissions are org-scoped: volumes.read, volumes.manage, buckets.read, and buckets.manage.

Storage FAQ

I attached a volume but /data is empty inside my container. What happened?

The container was created before the volume was attached. Docker bakes mounts at container creation; you cannot add a mount to a running container. Fix: redeploy the deployment after attach. nexus deploy redeploy <deployment-id> --wait. The new container will have the mount.

Can multiple deployments share the same volume?

No. Volumes are single-attach. To share data between deployments, use a Bucket instead. Buckets are multi-attach and the S3 API handles concurrent access safely.

What happens to volume data if I delete the deployment?

Nothing. Deleting a deployment does not delete attached volumes. The volume becomes "available" status and can be attached to a new deployment. To destroy the data: nexus volume detach <id> && nexus volume delete <id>

I scaled my app to 3 replicas. Do I have 3 separate volumes now?

No. All 3 replicas mount the SAME named volume at the same path. They share the underlying filesystem. This is a Docker constraint. If your app cannot tolerate concurrent writes from multiple replicas, either: (1) keep the deployment at 1 replica, (2) split state into separate deployments each with their own volume, or (3) move state into a Bucket where the S3 API handles concurrency.

What happens to volume data if I scale my app down to 0?

Volume data persists. Scaling down (or stopping) only removes container processes; the named volume on the host filesystem is untouched. Scale up later and the new container sees the same files.

Can I attach a bucket to multiple deployments at once?

Yes. Buckets are multi-attach. Every deployment with the bucket attached gets the same S3_* env vars. Each deployment makes independent calls to MinIO using the shared per-bucket service account.

Why did "nexus deploy redeploy" fail with a 409 about container name conflict?

The previous container is still alive and the new one is trying to claim the same name. Fix: nexus deploy stop <deployment-id>; if that leaves a container around, docker rm -f <container-id>; then re-run the redeploy. This is a known issue in the redeploy flow on Local Docker provider, separate from the storage feature itself.

My bucket upload from the web UI failed at 500MB. Why?

The web upload buffers each file in browser memory before sending. Browsers struggle with multi-hundred-megabyte buffers. Fix: use the CLI for large uploads: nexus bucket upload <bucket-id> ./big-file.zip. The CLI streams directly from disk to MinIO with no full-file buffering. There is no fixed size cap on the CLI path.

How do I move data from one volume to another?

The platform has no built-in copy command. Use docker cp or rsync inside the container that has the source volume mounted, then copy to a path the destination volume will mount. Worked example: docker exec <src-container> tar czf - /data | docker exec -i <dst-container> tar xzf - -C /destination

Are storage volumes available on Cloud Run, App Runner, or Container Apps?

Not in v1. Storage volumes are Local Docker only because they are backed by Docker named volumes. Each managed cloud provider has its own filesystem mounting model (Cloud Run + Cloud Storage FUSE, App Runner has no persistent filesystem, Container Apps + Azure Files). Cross-provider volumes are on the roadmap. For cloud providers today: use Buckets (which work everywhere via the S3 API), or use a managed external database connected via Secrets Vault.

Standalone databases

Run a database independently of any app: on NEXUS AI (PostgreSQL or Redis) or as a native cloud instance (AWS RDS, GCP Cloud SQL, Azure Database). Attach them to deployments, deploy an app and database in one command, and back them up with snapshots.

Managed databases vs service databases

Two different ways to run a database on NEXUS AI.

  1. A standalone database runs on its own and is owned by your organization, not by an app. Redeploying, stopping, or deleting a deployment never touches it. It can run on NEXUS AI itself (PostgreSQL or Redis) or as a native cloud instance (AWS RDS, GCP Cloud SQL, or Azure Database, for PostgreSQL or MySQL).
  2. A service database (Additional Service) is a container database that runs alongside a deployment. It is simpler but tied to that deployment’s lifecycle, so its data goes away with the app.
  3. Use a standalone database when the data should outlive the app, be shared across deployments, or be snapshotted and restored on its own. Choose NEXUS AI for the quickest path (ready in seconds, no cloud account needed) and a cloud provider when you want a managed instance in AWS, Google Cloud, or Azure.
  4. Managed databases are organization-scoped: only members of the owning organization can list, attach, snapshot, restore, or delete them. Availability depends on your plan tier.

Supported database services

Which database engines run as managed cloud databases vs container sidecars.

  1. Standalone databases on NEXUS AI support PostgreSQL (17, 16, 15) and Redis (7). Managed cloud databases support PostgreSQL and MySQL only, on all three providers: GCP Cloud SQL, AWS RDS, and Azure Database for Flexible Server. On a cloud provider, --create-db / --services accept "postgres" or "mysql"; anything else is not provisioned as a managed service.
  2. MongoDB is available only as a container sidecar on the Docker provider (nexus deploy ... --provider docker --services mongodb), which is tied to the deployment lifecycle. Redis can run either as a sidecar or, to keep its data independent of the app, as a standalone database on NEXUS AI.
  3. Need Redis or MongoDB alongside a cloud deployment? Point your app at an external managed Redis/Mongo using env vars (--env-file). NEXUS AI does not provision those as managed cloud services.

Choosing a provider (AWS RDS, GCP Cloud SQL, or Azure Database)

Pick the cloud provider when creating the database; the rest of the workflow is identical.

  1. NEXUS AI (local) runs the database as its own container on the NEXUS AI host, with its own storage. It is ready within seconds, needs no cloud account, and is the right choice for apps deployed on NEXUS AI. Pick it in the dashboard, or pass --local from the CLI.
  2. AWS RDS uses the platform AWS account. GCP Cloud SQL reuses your organization’s existing Google Cloud (Cloud Run) credentials — if you have not added a Google Cloud provider to the org yet, GCP managed-database creation returns a configuration error. Azure Database (Flexible Server) uses the platform Azure credentials and is always created private (VNet-only).
  3. Engine versions differ by provider/region: AWS expects full versions (e.g. PostgreSQL 17.10, MySQL 8.0.46); GCP and Azure expect the major family (e.g. PostgreSQL 17, MySQL 8.0). The create form prefills sensible defaults per provider.
  4. Instance sizes differ: AWS uses classes like db.t3.micro; GCP uses tiers like db-custom-1-3840; Azure uses tiers like Standard_B1ms/Standard_B2s. Azure also requires a minimum 32 GiB of storage.
  5. Regions differ (e.g. us-east-1 on AWS, us-central1 on GCP). For Azure, your subscription must be entitled to provision Flexible Server in the chosen region — some regions are offer-restricted; pick an allowed region (e.g. canadacentral) with --region or request a quota increase.
  6. Backups, attach, and restore behave the same across providers. On GCP/Azure, restore creates a new instance internally but appears as a single non-destructive “restore to a new database” action, exactly like AWS.
  7. From the CLI, pass --provider (GCP_CLOUD_SQL, AWS_RDS, or AZURE_DATABASE):
    nexus managed-db create prod-db --provider GCP_CLOUD_SQL --engine POSTGRES --engine-version 17

How deployed apps connect

Connectivity depends on where the app runs.

  1. A database hosted on NEXUS AI listens on the host's internal Docker bridge address, never on a public interface, and apps deployed on NEXUS AI reach it there. Because of that, it can only be attached to apps running on NEXUS AI (local Docker) on the primary host; cloud deployments should use a managed cloud database instead.
  2. NEXUS (Docker) deployments connect to the managed cloud database over its public endpoint. Set MANAGED_DB_ALLOWED_CIDR to the platform host’s public IP so the database firewall admits it. The injected DATABASE_URL points at the public endpoint (PostgreSQL adds sslmode=require).
  3. GCP Cloud Run deployments connect through the native Cloud SQL connector: attaching a Cloud SQL database to the deployment wires the instance into the Cloud Run service and injects a unix-socket DATABASE_URL (host=/cloudsql/PROJECT:REGION:INSTANCE). No public IP or CIDR is needed. The Cloud Run service account must have the Cloud SQL Client role (roles/cloudsql.client).
  4. AWS App Runner deployments connect to a private (vpc-mode) RDS over an App Runner VPC connector: create the RDS with network mode "vpc", attach it, and redeploy. The RDS has no public IP and its firewall admits only the App Runner connector — so the app can reach it and the internet cannot. Public-mode RDS instead uses a public endpoint + CIDR allowlist (for Docker/external use).
  5. Azure Container Apps deployments connect to an Azure Database (Flexible Server) privately: the server has public access disabled and lives in a platform VNet; when you attach it, the Container Apps environment is VNet-injected so the app reaches it over private networking, and nothing outside Azure can.
  6. Running SQL from NEXUS (query API / CLI `nexus managed-db query`): public databases are queried directly over TLS; private (vpc) databases are queried through an in-VPC/VNet proxy that NEXUS authenticates with a short-lived signed token — the database is never exposed publicly. Reads need managed_databases.read; writes/DDL need managed_databases.manage, and all SQL is safety-checked. Deploy the db-proxy (services/db-proxy) and set DB_PROXY_SECRET + DB_PROXY_URL for private-database queries.
  7. In all cases the connection env vars are applied at deploy time, so redeploy after attaching.

Create a managed database

Provisioning is asynchronous and takes a few minutes.

  1. Open Storage → Managed DBs and choose Create database. Pick a name and a location: NEXUS AI (local) for PostgreSQL or Redis, or a cloud provider for PostgreSQL or MySQL with an instance class, storage size, and region.
  2. For a database on NEXUS AI you can set the initial database name, the username, and the password, or leave them blank for defaults (appdb / nexusadmin) and a generated password that is shown to you once. Names use lowercase letters, digits, and underscores; passwords are 12 to 128 characters with no whitespace, quotes, or backslashes. Redis takes an optional ACL username alongside its password.
  3. Local databases are usually AVAILABLE within seconds. Cloud databases appear as PROVISIONING and flip to AVAILABLE once the cloud endpoint is ready, which takes a few minutes.
  4. From the CLI. Use --password-stdin to keep a password out of your shell history:
    nexus managed-db create shop --local --engine postgres --db-name shop_db --username shop_user
    nexus managed-db create cache --local --engine redis
    nexus managed-db create prod-db --engine POSTGRES --engine-version 17.10
    nexus managed-db list
  5. Read the connection details later with `nexus managed-db connection <name>`, or the Connection button in the dashboard. Those reads are audit-logged.
  6. You cannot attach a database until it is AVAILABLE. Standalone databases are available on paid plans.

Query a managed database from the CLI

Run SQL against PostgreSQL or MySQL databases without leaving the terminal.

  1. Pass the database name (or id) and one SQL statement. Always wrap the SQL in quotes, otherwise the shell splits it into separate arguments.
    nexus managed-db query shop "SELECT id, email FROM users LIMIT 10"
    nexus managed-db query shop "SELECT count(*) FROM orders WHERE status = 'paid'"
  2. Create and change tables, and write data:
    nexus managed-db query shop "CREATE TABLE notes (id serial PRIMARY KEY, body text NOT NULL)"
    nexus managed-db query shop "INSERT INTO notes (body) VALUES ('hello')"
    nexus managed-db query shop "UPDATE notes SET body = 'hi' WHERE id = 1"
  3. Use --json for scripting, or load multi-line SQL from a file:
    nexus managed-db query shop "SELECT * FROM users LIMIT 5" --json | jq '.rows[].email'
    nexus managed-db query shop "$(cat migration.sql)"
  4. Reads need managed_databases.read, and writes and DDL need managed_databases.manage. Each call runs one statement, UPDATE and DELETE need a WHERE clause, and Redis is not supported.
  5. CREATE DATABASE, DROP DATABASE, GRANT, REVOKE, CREATE ROLE, and CREATE EXTENSION are blocked and fail with "Query blocked: Statement type not permitted". To get another database, run `nexus managed-db create`. For unrestricted access, use `nexus managed-db connection <name>` and connect with psql or mysql.

Attach a database to a deployment

Attaching injects connection details as environment variables — a redeploy is required.

  1. On an AVAILABLE database, choose Attach and select the target deployment. Optionally set an env prefix: the default is DATABASE, or REDIS for a Redis database, so apps get REDIS_URL.
  2. On the next deploy, NEXUS AI injects DATABASE_URL plus DATABASE_HOST, DATABASE_PORT, DATABASE_USER, DATABASE_PASSWORD, and DATABASE_NAME (using your prefix). A custom prefix produces e.g. ANALYTICS_URL, ANALYTICS_HOST, and so on.
  3. Redeploy is required because container environment variables are baked at container creation — the same rule as volumes and buckets. Attaching does not change a running container.
  4. From the CLI. Both accept names as well as ids:
    nexus managed-db attach shop --deployment my-api
    nexus deploy redeploy my-api
  5. Detaching stops the injection on the next deploy and leaves the data alone. Deleting a database destroys its data, and requires --force (or confirming the warning in the dashboard) while apps are still attached.

Full-stack in one command (--create-db / --services)

Provision the database and deploy the app together — the first deploy comes up already connected.

  1. On a cloud provider you can provision a managed database and attach it in the same deploy. Provisioning runs alongside the build, and the build waits for the database to be AVAILABLE before wiring the service — so the first deploy is DB-connected (no crash-then-redeploy).
    nexus deploy source \
      --repo https://github.com/you/app.git \
      --name myapp --provider gcp_cloud_run \
      --env-file ./.env.prod \
      --create-db postgres
  2. --create-db provisions a database paired with the deploy provider: gcp_cloud_run → Cloud SQL, aws_ecs_fargate (App Runner) → RDS, azure_container_apps → Azure Database. Use "postgres" or "mysql".
  3. For consistency with Docker, a database in --services behaves the same: on a cloud provider "--services postgres" provisions a managed database; on Docker it runs a sidecar container.
  4. Attach an existing managed database at deploy time with --managed-db <dbId> instead of creating a new one. In the web deploy form, the Managed Database dropdown offers both “Create new” and “Attach existing”.
  5. The injected DATABASE_URL overrides any DATABASE_URL in your env file so the app uses the provisioned database. Choose the deploy region with --region; for Azure the database is co-located in the deploy region automatically (required for private VNet connectivity). Your app must read DATABASE_URL (not a hardcoded host).

Redeploy in place (keeps the URL, env, and database)

Rebuild the same deployment without losing its database or configuration.

  1. Redeploy rebuilds the SAME deployment: same id, same public URL, with attached managed databases, volumes, secrets, and environment variables all preserved. The app reconnects to the existing data — nothing is wiped.
  2. In the dashboard, use the Redeploy button on a deployment. From the CLI:
    nexus deploy redeploy <deploymentId> --wait
  3. On Docker full-stack deployments, only the app container is rebuilt; the sidecar database container and its volume (your data) keep running and are reattached.
  4. Changing the name or provider creates a new deployment instead — an in-place rebuild cannot rename or move providers.

Snapshots and restore

Backups use native cloud snapshots; restore is non-destructive.

DATABASE_URL is not set in my app after attaching

Environment variables are injected at deploy time, not at attach time. Redeploy the deployment after attaching. Also confirm the database status is AVAILABLE — a PROVISIONING database is skipped during injection.

Did restoring overwrite my data?

No. Restore is non-destructive: it provisions a new managed database from the snapshot and leaves the source database untouched. You then choose whether to attach the restored database.

Is my managed database publicly accessible?

v1 RDS instances are created publicly accessible behind a dedicated security group. The allowed inbound range is controlled by the RDS_ALLOWED_CIDR setting; provisioning is refused if no CIDR (or explicit public opt-in) is configured. Restrict this to your deploy network for production.

Why can’t I create a managed database?

Managed databases are gated by plan tier (the Free tier has none). If you are at your plan limit or on a plan without managed databases, upgrade to enable them.

Database backups, downloads, and restores

Create portable backups for deployment database services, download them securely, and restore data when needed.

What database backups cover

Backups are available for database services provisioned with a deployment.

  1. Supported services are PostgreSQL, MySQL, MongoDB, and Redis database services created as Additional Services.
  2. Backups are created from a single database service. They can be restored back into the same service or into a compatible database service in another deployment owned by the same organization.
  3. Application code, container images, deployment settings, environment variables, and Secrets Vault entries are not included in database backups.
  4. Backup access is organization-scoped. A user can only create, list, download, delete, or restore backups for services owned by their organization.
  5. Backup file formats are portable and match the database engine:
    PostgreSQL: backup-<timestamp>.dump   # pg_dump custom format
    MySQL:      backup-<timestamp>.sql    # mysqldump SQL file
    MongoDB:    backup-<timestamp>.archive # compressed mongodump archive
    Redis:      backup-<timestamp>.rdb    # Redis RDB snapshot

Before you create a backup

  1. Open the deployment and confirm the database service is running in the Databases tab.
  2. Confirm the service was created by NEXUS AI as an Additional Service. External managed databases must be backed up through their cloud provider or database vendor.
  3. Make sure the database container is healthy and has a container ID. Backup creation requires access to the running service container.
  4. For busy production databases, schedule the backup during a low-write period or briefly pause write-heavy jobs to reduce restore-time surprises.
  5. If the database stores sensitive or regulated data, download the backup only to an approved encrypted workstation or storage location.

Create a backup in the dashboard

  1. Open the project that owns the deployment.
  2. Open the deployment details page.
  3. Go to the Databases tab and locate the database service.
  4. Open the backup controls for that service and choose Create Backup.
  5. Wait for the backup to complete. Large databases can take longer because NEXUS AI runs the database-native dump command and stores the resulting file.
  6. Refresh the backups list and confirm the new record shows completed status, file name, file size, and creation time.

Create and list backups with the REST API

Use your logged-in JWT for dashboard-grade backup operations.

  1. Set the API base URL and JWT once.
    export NEXUS_API_BASE="https://nexusai.run/api"
    export NEXUS_JWT="YOUR_JWT_FROM_LOGIN"
  2. List database services, optionally filtered by deployment ID. Copy the service id you want to back up.
    curl -s "$NEXUS_API_BASE/deployment-services?deployment=<deploymentId>" \
      -H "Authorization: Bearer $NEXUS_JWT"
  3. Create an on-demand backup for the service.
    curl -s -X POST "$NEXUS_API_BASE/deployment-services/<serviceId>/backup" \
      -H "Authorization: Bearer $NEXUS_JWT"
  4. List backups for the service and copy the backup id you need for download or restore.
    curl -s "$NEXUS_API_BASE/deployment-services/<serviceId>/backups" \
      -H "Authorization: Bearer $NEXUS_JWT"

Create, download, and restore backups from the CLI

Use `nexus db` commands when you want terminal-first backup operations.

  1. Log in to the CLI first so requests include your NEXUS AI session token.
    nexus auth login
  2. List database services and copy the service id. You can pass a deployment name or id to filter the list.
    nexus db services
    nexus db services <deployment-name-or-id>
  3. Create a backup for the service.
    nexus db backup <service-id>
  4. List backups for the service and copy the backup id.
    nexus db backups <service-id>
    nexus db backups <service-id> --json
  5. Download the backup to your local machine. By default the CLI uses the original backup file name.
    nexus db backup-download <service-id> <backup-id>
    nexus db backup-download <service-id> <backup-id> --out ./backups/prod-postgres.dump
  6. Generate a short-lived signed URL instead of downloading directly. Use this for browser downloads or another machine that should not receive your CLI token.
    nexus db backup-download <service-id> <backup-id> --share
    nexus db backup-download <service-id> <backup-id> --share --ttl 900
  7. Restore a backup. The CLI asks for confirmation because restore can overwrite current data.
    nexus db restore <service-id> <backup-id>
    nexus db restore <service-id> <backup-id> --yes
  8. Restore a backup into a different database service in another deployment under the same organization.
    nexus db restore-to <target-service-id> <backup-id>
    nexus db restore-to <target-service-id> <backup-id> --yes
    nexus db restore-to <target-service-id> <backup-id> --json
  9. Enable or disable daily automatic backups from the CLI.
    nexus db backup-schedule <service-id> --enable
    nexus db backup-schedule <service-id> --disable
  10. Delete a backup when you no longer need it.
    nexus db backup-delete <service-id> <backup-id>
    nexus db backup-delete <service-id> <backup-id> --yes

Download a backup file

Download directly with your JWT or create a short-lived signed URL for browser and curl use.

  1. Direct authenticated download streams the backup file immediately.
    curl -L -o backup.dump \
      "$NEXUS_API_BASE/deployment-services/<serviceId>/backups/<backupId>/download" \
      -H "Authorization: Bearer $NEXUS_JWT"
  2. For browser downloads or scripts that should not receive your JWT, create a signed URL. The default lifetime is 5 minutes.
    curl -s -X POST "$NEXUS_API_BASE/deployment-services/<serviceId>/backups/<backupId>/download-url" \
      -H "Authorization: Bearer $NEXUS_JWT" \
      -H "Content-Type: application/json" \
      -d '{"ttlSeconds":300}'
  3. Download from the signed URL returned by the API. Signed URLs are capped at 1 hour.
    curl -L -o "<fileName-from-response>" "<signedDownloadUrl>"
  4. Store downloaded backups in encrypted storage, restrict access, and delete local copies when they are no longer needed.

Restore from a backup

Restore writes backup data into the selected running service. You can restore in place or restore to another compatible service in the same organization.

  1. Confirm you selected the correct backup and target service. Restores should only be performed against the matching database engine.
  2. Create a fresh backup before restoring if the current data might need to be recovered later.
  3. Plan a maintenance window. PostgreSQL and MongoDB restores can drop or clean existing objects. Redis restore stops and starts the Redis container.
  4. Run an in-place restore through the API. This keeps the existing behavior and restores the backup into the service path you call.
    curl -s -X POST "$NEXUS_API_BASE/deployment-services/<serviceId>/restore" \
      -H "Authorization: Bearer $NEXUS_JWT" \
      -H "Content-Type: application/json" \
      -d '{"backupId":"<backupId>"}'
  5. Restore into another deployment service in the same organization by calling the target service path.
    curl -s -X POST "$NEXUS_API_BASE/deployment-services/<targetServiceId>/restore-from/<backupId>" \
      -H "Authorization: Bearer $NEXUS_JWT"
  6. Backend integrations can use backupService.restoreBackup(backupId, { targetServiceId }). The targetServiceId option is optional, so existing in-place calls continue to work.
  7. After restore completes, restart or redeploy application containers if they cache connections, schema metadata, or data in memory.
  8. Validate application behavior, critical tables or collections, and authentication flows before sending normal traffic back to the deployment.

Enable or disable scheduled backups

Scheduled backups run daily for services with backup scheduling enabled.

  1. Enable daily backups for a service.
    curl -s -X PATCH "$NEXUS_API_BASE/deployment-services/<serviceId>/backup/schedule" \
      -H "Authorization: Bearer $NEXUS_JWT" \
      -H "Content-Type: application/json" \
      -d '{"enabled":true}'
  2. Disable scheduled backups if the service no longer needs them.
    curl -s -X PATCH "$NEXUS_API_BASE/deployment-services/<serviceId>/backup/schedule" \
      -H "Authorization: Bearer $NEXUS_JWT" \
      -H "Content-Type: application/json" \
      -d '{"enabled":false}'
  3. Use the backups list to confirm recent scheduled backups and last backup time for each service.

Use backups from MCP clients

ChatGPT, Claude, and custom MCP clients can create, list, download, restore, and schedule database backups.

  1. Discover database services first. The service id is required for all backup tools.
    nexusai_db_services_list
  2. Use these MCP tools for the backup lifecycle:
    nexusai_db_backup          # create a backup for serviceId
    nexusai_db_backup_list     # list backups for serviceId
    nexusai_db_backup_download # generate signed download URL
    nexusai_db_restore         # restore serviceId from backupId
    nexusai_db_restore_to      # restore backupId into targetServiceId
    nexusai_db_backup_schedule # enable or disable daily backups
  3. For restore requests through an AI client, include the backup id and the target service id, then ask the client to confirm the destructive action before it calls the restore tool. Cross-service restore uses the nexusai_db_restore_to tool and requires deployments:create scope.

Backup, download, and restore FAQ

Can I restore a backup into a different database service?

Yes, if the target database service belongs to the same organization and is compatible with the backup engine. Use REST POST /api/deployment-services/:targetServiceId/restore-from/:backupId, CLI nexus db restore-to <target-service-id> <backup-id>, or MCP tool nexusai_db_restore_to. Cross-tenant restore is not allowed.

Does restore overwrite existing data?

Yes, restore can overwrite, clean, drop, or replace existing data depending on the engine. PostgreSQL uses pg_restore with clean/if-exists behavior, MySQL imports the SQL dump, MongoDB restores with drop behavior, and Redis replaces the RDB snapshot after stopping and restarting the container.

How long do signed download URLs last?

The default signed download URL lifetime is 5 minutes. You can request ttlSeconds, with a minimum of 30 seconds and a maximum of 3600 seconds.

Why did backup creation fail with "Service has no running container"?

The backup service needs a live database container so it can run pg_dump, mysqldump, mongodump, redis-cli, or copy files from the container. Start or redeploy the database service, wait for it to be running, then retry.

Can I manage backups from the CLI?

Yes. Use nexus db services to find a service id, nexus db backup to create a backup, nexus db backups to list backups, nexus db backup-download to download or generate a signed URL, nexus db restore for in-place restore, nexus db restore-to to restore into another service in the same organization, nexus db backup-schedule to manage daily backups, and nexus db backup-delete to remove old backups.

Are backup files encrypted?

Secrets are encrypted in NEXUS AI, but downloaded database backup files should be treated as sensitive data. Store them only in approved encrypted storage and restrict access according to your organization policy.

Secrets and AI

Securely store API keys and connect cloud AI providers.

Manage secrets and environment variables

  1. Open the Secrets Vault in your project.
  2. Add API keys, tokens, and runtime variables.
  3. Scope secrets by environment (dev, staging, prod).
  4. Rotate keys and audit usage when needed.

Connect cloud AI providers

Connect Anthropic (Claude), OpenAI (GPT), Google (Gemini), Cohere, xAI (Grok), or OpenRouter. Grok and OpenRouter require a paid plan.

  1. Create a Vault secret for your provider API key (recommended).
  2. Go to AI Providers and click "Add Provider".
  3. Choose a provider and select your Vault secret (or paste the API key directly).
  4. Pick a model, set max tokens and temperature, then enable and save.
  5. In a project, select the provider when generating code from a prompt.

Supported AI providers

Provider availability differs between AI Builder and project code generation. Select an enabled provider and a model available to your workspace.

  1. Anthropic (Claude), OpenAI (GPT), and Google (Gemini): supported in AI Builder and project code generation. Add your own API key or use a platform-managed configuration when available on your plan.
  2. Cohere: supported in project code generation. Cohere is not currently supported in AI Builder.
  3. OpenRouter: bring your own API key on a paid plan. Supported in AI Builder and project code generation. Builder requests use your OpenRouter balance without consuming NEXUS AI monthly token or request allowances.
  4. xAI (Grok): supported in AI Builder and project code generation on paid plans, including when you bring your own API key.
  5. NEXUS AI (Managed): a platform-configured provider for AI Builder. No personal API key is needed. Availability depends on platform configuration and your plan.

Keep building with your OpenRouter key

Paid customers can use their own OpenRouter account in AI Builder after reaching their NEXUS AI monthly allowance.

  1. Open AI Providers, click Add Provider, and choose OpenRouter. Add your API key or select a Vault secret.
  2. Leave Base URL blank for https://openrouter.ai/api/v1, or enter your public HTTPS OpenAI-compatible proxy or gateway base URL, including its API path (such as /v1), without /chat/completions. Your API key and requests are sent to this endpoint.
  3. Enter a chat model ID supported by your chosen endpoint (from the OpenRouter catalog when using OpenRouter), set its output limit, then enable and save.
  4. Return to Builder and select OpenRouter in the provider menu. Your configured model is used for new turns; existing project files stay in place.
  5. OpenRouter Builder turns do not consume NEXUS AI monthly request or managed-token allowances. Your selected provider or gateway bills your account directly; its balance, model availability, context limits, and rate limits still apply. Normal platform rate limits and project limits remain in place.
  6. OpenRouter requires a paid plan. After a downgrade to Free, upgrade or select another available provider to continue.

Use xAI (Grok)

Grok requires Starter, Pro, Enterprise, Healthcare Starter, or Healthcare Pro. Free workspaces cannot configure or use Grok, even with a personal xAI API key.

  1. On a paid plan, open AI Providers, choose Add Provider, and select xAI (Grok). Add your xAI API key directly or reference a Vault secret. If Grok is already configured, edit that configuration.
  2. Available models: Grok 4.7, Grok 4.6, Grok 4.5, Grok 4.3, Grok Build 0.1, Grok 4.20 Reasoning, and Grok 4.20 Non-Reasoning. Grok 4.6 is the default.
  3. Enable and save the provider, then select Grok and your preferred model in AI Builder or project code generation.
  4. After a downgrade to Free, existing Grok configurations and Builder sessions cannot be used for generation. Upgrade or switch to an available provider to continue.
  5. Retired model aliases and Grok 4.20 Multi-Agent are not offered. Multi-Agent requires a separate API integration.

Use NEXUS AI (Managed)

Build with the AI provider configured by the platform, without adding a personal API key.

  1. When available, NEXUS AI (Managed) appears in AI Providers. Enable it, then choose NEXUS AI in the AI Builder provider menu.
  2. Use the Default model option. The platform controls the endpoint, API key, and model; personal API keys and custom endpoints cannot be configured for this provider.
  3. Free plans can use this provider when configured, subject to their managed AI token budget. Paid plans use their own plan limits.
  4. You can enable or disable this managed configuration, but cannot delete it. It is currently supported in AI Builder, not project code generation.

GPT Store

Deploy and manage containers from ChatGPT using NEXUS AI.

What the GPT can do

  1. Deploy containers from Docker images.
  2. List deployments and check status.
  3. Fetch logs and destroy deployments with confirmation.
  4. Extend, reduce, or disable deployment auto-destroy schedules without restarting the running app.
  5. Auto-select providers based on your plan via /providers.

Generate an access token

Which scopes are required?

Use deployments:create, deployments:read, deployments:logs, deployments:delete for full GPT actions.

Configure GPT actions

  1. Set the action schema URL to https://nexusai.run/openapi.yaml.
  2. Use Bearer auth with your NEXUS AI access token (nxk_...).
  3. Call /providers first to learn which providers are allowed for the plan.
  4. Confirm before deleting deployments.

Example prompts

  1. Try these in ChatGPT:
    Deploy nginx:latest on port 80 and name it my-nginx.
    Upload this zip and deploy it as zip-app.
    Deploy https://github.com/org/repo.git on main using secret github-token.
    List my deployments and show the status of the most recent one.
    Show the last 50 log lines for my latest deployment.
    Destroy the deployment named my-nginx (confirm before deleting).

Source deployments (Git + Zip)

What do I pass for private Git repos?

Use repoSecretName with the Secrets Vault name that stores your repo token.

How do zip uploads work?

Upload a zip archive, then deploy with sourceType=zip and the uploadId returned by the upload call.

Troubleshooting

Why do I get "Invalid token"?

Use an access token that starts with nxk_. Ensure it was created in the same environment (local vs production).

Why do I get "Insufficient scope"?

Add deployments:read (and other GPT scopes) to the access token and try again.

MCP (Model Context Protocol)

Comprehensive MCP documentation for ChatGPT, Claude, and custom clients using OAuth-protected JSON-RPC on NEXUS AI.

MCP endpoint, transport, and discovery

NEXUS AI exposes MCP as an OAuth-protected HTTP JSON-RPC endpoint.

  1. NEXUS AI is listed on the official MCP Registry. Install in any MCP client via the registry URL or by searching "NEXUS AI" in the client's MCP marketplace.
    Registry listing:
    https://registry.modelcontextprotocol.io/v0.1/servers?search=io.github.nexusrun/nexus-ai
  2. Use POST requests to the MCP endpoint with JSON-RPC 2.0 payloads and an OAuth Bearer access token.
    MCP endpoint: https://mcp.nexusai.run/mcp
    Transport: HTTP JSON-RPC 2.0
    Methods: ping, initialize, tools/list, tools/call
    Notifications: notifications/initialized, notifications/cancelled
    Protocol version: 2026-01-16
  3. Use OAuth/OIDC discovery metadata endpoints during client setup. Metadata is served from mcp.nexusai.run (not the apex nexusai.run, which returns 403 on .well-known/*).
    https://mcp.nexusai.run/.well-known/oauth-authorization-server
    https://mcp.nexusai.run/.well-known/oauth-protected-resource/mcp
    https://mcp.nexusai.run/.well-known/openid-configuration
  4. GET and DELETE on /mcp are intentionally rejected. Use POST only.
    curl -i -X GET "https://mcp.nexusai.run/mcp"
    curl -i -X DELETE "https://mcp.nexusai.run/mcp"

Connect NEXUS AI MCP in ChatGPT

Use this for no-code setup inside ChatGPT.

  1. Open ChatGPT and go to connected apps or MCP servers.
  2. Add server URL:
    https://mcp.nexusai.run/mcp
  3. Complete OAuth sign-in and approve requested scopes.
  4. After connection succeeds, run a verification prompt in ChatGPT.
  5. Example verification prompt:
    List my NEXUS AI deployments and show their status.

Connect NEXUS AI MCP in Claude Desktop, Claude Code, Cursor, and Codex

Each client runs the OAuth sign-in on first connect. A pre-minted OAuth token in a header is the headless fallback.

  1. Claude Desktop. Edit ~/Library/Application Support/Claude/claude_desktop_config.json on macOS, or %APPDATA%\Claude\claude_desktop_config.json on Windows, then restart. Claude Desktop opens the OAuth sign-in on first connect; the headers block is only needed for a pre-minted token.
    {
      "mcpServers": {
        "nexus-ai": {
          "url": "https://mcp.nexusai.run/mcp"
        }
      }
    }
  2. Claude Code. Add the server with one command. Omit --header to have Claude Code run the OAuth sign-in for you on first connect; pass it only for headless use with a pre-minted OAuth token.
    claude mcp add --transport http nexus-ai https://mcp.nexusai.run/mcp \
      --header "Authorization: Bearer <your-nexus-oauth-token>"
  3. Cursor. Cursor Settings, MCP, Add server, with the URL below (or commit .cursor/mcp.json with just the url). Cursor runs the OAuth sign-in on first connect.
    URL: https://mcp.nexusai.run/mcp
  4. Codex CLI. Add the server, then run the OAuth login (writes a [mcp_servers.nexus-ai] block to ~/.codex/config.toml; the token is kept in Codex's credential store, not the file).
    codex mcp add nexus-ai --url https://mcp.nexusai.run/mcp
    codex mcp login nexus-ai
  5. Headless or CI clients that cannot open a browser: mint an OAuth access token with the PKCE auth-code flow described above (Connect NEXUS AI MCP via OAuth), or use the OAuth bridge endpoint to mint a code from a signed-in JWT session, then send it as Authorization: Bearer <token>.
  6. Verification prompt that works across all four clients:
    Call nexusai_whoami and tell me which tenant I am connected to.

Common MCP workflows the agent can run end to end

Canonical task chains your agent can execute. Each step calls one or more MCP tools.

  1. Vibe-code in chat, preview in the AI Builder, then deploy:
    1. nexusai_projects_list           # find the target project
    2. <agent generates the app files in chat>
    3. nexusai_builder_push            # push files, get a live-preview URL for the user
    4. <user reviews the running app, optionally edits in the builder>
    5. nexusai_builder_pull            # bring builder-side edits back into chat (optional)
    6. nexusai_deploy_source / deploy  # ship it when the user approves
  2. Deploy a full-stack app from a prompt:
    1. nexusai_projects_list           # find the target project
    2. nexusai_deploy_source           # build from repo with services=[postgresql, redis]
    3. nexusai_bucket_create           # provision a bucket for uploads
    4. nexusai_bucket_attach           # wire bucket env vars into the deploy
    5. nexusai_deploy_redeploy         # apply the bucket attachment
    6. nexusai_deploy_status           # confirm RUNNING
  3. Snapshot, migrate, validate, recover (the right pattern for risky schema changes):
    1. nexusai_db_services_list        # discover postgres service id
    2. nexusai_db_backup               # snapshot first
    3. <agent runs the migration>
    4. nexusai_deploy_logs             # check for errors
    5a. (success) nexusai_db_backup_list      # confirm backup on retention list
    5b. (failure) nexusai_db_restore          # restore from the snapshot
                  nexusai_deploy_rollback     # revert to previous release
  4. Migrate a legacy bucket to scoped IAM (for buckets created before per-bucket service accounts):
    1. nexusai_bucket_rotate_credentials   # generate fresh scoped svcacct creds
    2. nexusai_deploy_redeploy             # for each attached deployment
    3. nexusai_deploy_status               # confirm RUNNING with new S3_* vars
  5. Seed a staging environment from production:
    1. nexusai_db_services_list        # find prod postgres serviceId
    2. nexusai_db_backup               # take a fresh snapshot
    3. nexusai_db_services_list        # find staging postgres serviceId
    4. nexusai_db_restore_to           # restore prod backup INTO staging
  6. Diagnose and fix a failing deploy:
    1. nexusai_deploy_status                              # state, health, restart count
    2. nexusai_deploy_logs                                # last 200 lines runtime logs
    3a. nexusai_secrets_create / nexusai_secrets_update   # if missing env var
    3b. nexusai_db_propose_fix → nexusai_db_apply_fix     # if schema gap
    3c. <agent edits code, pushes, triggers nexusai_deploy_redeploy>
    4. nexusai_deploy_logs                                # confirm fix
  7. Keep a preview environment alive longer, shorten it, or remove the cleanup timer:
    1. nexusai_deploy_status                 # inspect current autoDestroyAt
    2. nexusai_deploy_auto_destroy           # pass autoDestroyHours to extend/reduce
    3. nexusai_deploy_auto_destroy           # pass autoDestroyAt:null to disable
    4. nexusai_deploy_status                 # confirm the updated schedule

Safety model and confirmation gates

Tools the agent must never call without explicit user confirmation in the same conversation turn.

  1. Destructive or irreversible. The agent should surface the resource ID and wait for an explicit "yes, delete X" / "yes, restore X" before calling:
    nexusai_deploy_delete                # permanent; tears down containers, networks, volumes
    nexusai_db_restore                   # overwrites existing data
    nexusai_db_restore_to                # overwrites target deployment data
    nexusai_bucket_delete                # deletes all bucket contents
    nexusai_volume_delete                # destroys all volume data
    nexusai_bucket_rotate_credentials    # invalidates current S3 credentials
  2. Confirmation-flag gated by the API itself (the call will fail without the flag):
    nexusai_db_query_execute        # DML/DDL requires confirmed=true
    nexusai_db_apply_fix            # requires the proposal ID from nexusai_db_propose_fix
  3. Suggested agent system-prompt rule (paste into your client's system instructions):
    Never call delete/restore/rotate tools without an explicit
    "yes, <verb> <resource>" from the user in the same message.
    For DML/DDL, always call nexusai_db_query_preview first and
    show the SQL before setting confirmed=true on nexusai_db_query_execute.
  4. Every tool call is logged in the AuditLog table with actor identity (user + token name), tool name, parameters (sensitive values redacted), result, timestamp, IP, and user agent. Search by token name to attribute changes to a specific agent.

OAuth flow for MCP clients (PKCE + auth code)

Use standard authorization code flow with PKCE for public clients.

  1. Register an OAuth client (dynamic registration) or use a pre-configured client.
    curl -s -X POST "https://nexusai.run/register" \
      -H "Content-Type: application/json" \
      -d '{
        "client_name":"my-mcp-client",
        "redirect_uris":["https://example.com/callback"],
        "token_endpoint_auth_method":"none",
        "grant_types":["authorization_code","refresh_token"],
        "response_types":["code"],
        "scope":"deployments:read deployments:create deployments:logs deployments:delete"
      }'
  2. Create an authorization code via /oauth/authorize in browser flow, then exchange it at /oauth/token with code_verifier.
    curl -s -X POST "https://nexusai.run/oauth/token" \
      -H "Content-Type: application/json" \
      -d '{
        "grant_type":"authorization_code",
        "client_id":"<client_id>",
        "code":"<authorization_code>",
        "redirect_uri":"https://example.com/callback",
        "code_verifier":"<pkce_code_verifier>"
      }'
  3. Validate your token and granted scopes before MCP calls.
    curl -s "https://nexusai.run/oauth/me" \
      -H "Authorization: Bearer <oauth_access_token>"
  4. Use the OAuth access token in Authorization header for all /mcp requests.
    Authorization: Bearer <oauth_access_token>

OAuth bridge endpoint (first-party authenticated flows)

NEXUS AI also supports creating auth codes from a logged-in user session.

  1. If you already have a NEXUS AI JWT session, call /oauth/authorize/code to mint an authorization code directly.
    curl -s -X POST "https://nexusai.run/oauth/authorize/code" \
      -H "Authorization: Bearer <nexus_jwt>" \
      -H "Content-Type: application/json" \
      -d '{
        "response_type":"code",
        "client_id":"<client_id>",
        "redirect_uri":"https://example.com/callback",
        "scope":"deployments:read deployments:logs",
        "code_challenge":"<pkce_code_challenge>",
        "code_challenge_method":"S256",
        "state":"state-123"
      }'
  2. Use the returned code in the normal /oauth/token exchange.

Dynamic client registration details

DCR endpoint validates redirect URIs and client metadata.

Which endpoint is used for dynamic registration?

Use POST /register (or POST /api/oauth/register).

https://nexusai.run/register
https://nexusai.run/api/oauth/register
What redirect URI rules are enforced?

Rules: 1. At least one redirect URI is required. 2. Maximum 10 redirect URIs. 3. Each URI must be <= 2000 chars. 4. URI fragments (#...) are not allowed. 5. Must use https, except localhost/127.0.0.1 can use http for development.

Which token endpoint auth methods are supported?

Supported values are none, client_secret_post, and client_secret_basic. Public MCP clients should usually use none + PKCE.

What scopes can a client request?

Supported scopes are deployments:read, deployments:create, deployments:logs, deployments:delete.

MCP JSON-RPC request examples

Use these examples to test connectivity and tool execution.

  1. Initialize MCP session.
    curl -s -X POST "https://mcp.nexusai.run/mcp" \
      -H "Authorization: Bearer <oauth_access_token>" \
      -H "Content-Type: application/json" \
      -d '{
        "jsonrpc":"2.0",
        "id":1,
        "method":"initialize",
        "params":{"protocolVersion":"2025-06-18"}
      }'
  2. List available tools.
    curl -s -X POST "https://mcp.nexusai.run/mcp" \
      -H "Authorization: Bearer <oauth_access_token>" \
      -H "Content-Type: application/json" \
      -d '{"jsonrpc":"2.0","id":2,"method":"tools/list"}'
  3. Call a tool (example: current user context).
    curl -s -X POST "https://mcp.nexusai.run/mcp" \
      -H "Authorization: Bearer <oauth_access_token>" \
      -H "Content-Type: application/json" \
      -d '{
        "jsonrpc":"2.0",
        "id":3,
        "method":"tools/call",
        "params":{"name":"nexusai_whoami","arguments":{}}
      }'
  4. Tool results are returned in result.content text. NEXUS AI includes structured data as JSON text inside that content for compatibility with MCP clients.

Complete MCP tool catalog

NEXUS AI exposes 74 tools across 11 categories. Tool names are underscore-based and case-sensitive.

  1. Identity and discovery (4 tools):
    nexusai_whoami
    nexusai_projects_list
    nexusai_providers_list
    nexusai_usage_stats
  2. AI Builder handoff (2 tools). Push a generated app into the AI Builder to give the user a live preview link before deploying; pull the current files back (including edits made in the builder UI) to keep iterating in chat:
    nexusai_builder_push
    nexusai_builder_pull
  3. Deployments (15 tools), including turnkey OpenClaw and Flixty deploys:
    nexusai_deploy_list
    nexusai_deploy_status
    nexusai_deploy_health
    nexusai_deploy_logs
    nexusai_deploy_create
    nexusai_deploy_source
    nexusai_deploy_openclaw
    nexusai_deploy_flixty
    nexusai_deploy_redeploy
    nexusai_deploy_rollback
    nexusai_deploy_start
    nexusai_deploy_stop
    nexusai_deploy_scale
    nexusai_deploy_auto_destroy
    nexusai_deploy_delete
  4. Secrets (4 tools), values encrypted with AES-256-GCM at rest and never returned over the API:
    nexusai_secrets_list
    nexusai_secrets_create
    nexusai_secrets_update
    nexusai_secrets_delete
  5. Custom domains (4 tools), automatic Let's Encrypt certificates after DNS verification:
    nexusai_domains_list
    nexusai_domains_add
    nexusai_domains_verify
    nexusai_domains_remove
  6. External database sources and DB intelligence (8 tools), for querying external databases connected by the user:
    nexusai_db_source_list
    nexusai_db_source_connect
    nexusai_db_source_delete
    nexusai_db_inspect_schema
    nexusai_db_query_preview
    nexusai_db_query_execute
    nexusai_db_propose_fix
    nexusai_db_apply_fix
  7. Deployment-managed database backups (7 tools), for the Postgres/MySQL/Mongo/Redis services provisioned alongside a deployment:
    nexusai_db_services_list
    nexusai_db_backup
    nexusai_db_backup_list
    nexusai_db_backup_download
    nexusai_db_restore
    nexusai_db_restore_to
    nexusai_db_backup_schedule
  8. Persistent storage volumes (5 tools), single-attach, survive redeploys, attached at a mount path:
    nexusai_volume_list
    nexusai_volume_create
    nexusai_volume_attach
    nexusai_volume_detach
    nexusai_volume_delete
  9. S3-compatible buckets (10 tools), multi-attach with scoped per-bucket IAM service accounts:
    nexusai_bucket_list
    nexusai_bucket_create
    nexusai_bucket_attach
    nexusai_bucket_detach
    nexusai_bucket_rotate_credentials
    nexusai_bucket_files_list
    nexusai_bucket_file_upload
    nexusai_bucket_file_download
    nexusai_bucket_file_delete
    nexusai_bucket_delete
  10. Standalone managed databases (11 tools), created independently of any deployment on NEXUS AI or a cloud provider, then attached to apps. Paid plans only:
    nexusai_managed_db_list
    nexusai_managed_db_create
    nexusai_managed_db_connection
    nexusai_managed_db_attach
    nexusai_managed_db_detach
    nexusai_managed_db_query
    nexusai_managed_db_execute
    nexusai_managed_db_snapshot_create
    nexusai_managed_db_snapshot_list
    nexusai_managed_db_restore
    nexusai_managed_db_delete
  11. Support (4 tools), for opening and threading support tickets from the agent:
    nexusai_support_ticket_create
    nexusai_support_ticket_list
    nexusai_support_ticket_get
    nexusai_support_ticket_reply

Scope requirements by tool

The backend enforces 25 OAuth scopes: 4 legacy broad scopes (kept for backward compat) plus 21 fine-grained per-category scopes. Use the narrowest scope set your workflow needs.

  1. No scope required:
    nexusai_whoami
  2. deployments:read (list / status / read-only inspection):
    nexusai_projects_list, nexusai_providers_list, nexusai_usage_stats,
    nexusai_deploy_list, nexusai_deploy_status, nexusai_deploy_health,
    nexusai_builder_pull
  3. deployments:logs (log streaming only):
    nexusai_deploy_logs
  4. deployments:create (deploy / scale / restart / redeploy / rollback / auto-destroy updates):
    nexusai_deploy_create, nexusai_deploy_source, nexusai_deploy_openclaw,
    nexusai_deploy_flixty, nexusai_deploy_redeploy, nexusai_deploy_rollback,
    nexusai_deploy_stop, nexusai_deploy_start, nexusai_deploy_scale,
    nexusai_deploy_auto_destroy, nexusai_builder_push
  5. deployments:delete:
    nexusai_deploy_delete
  6. secrets:read / secrets:manage / secrets:delete:
    secrets:read:    nexusai_secrets_list
    secrets:manage:  nexusai_secrets_create, nexusai_secrets_update
    secrets:delete:  nexusai_secrets_delete
  7. domains:read / domains:manage / domains:delete:
    domains:read:    nexusai_domains_list
    domains:manage:  nexusai_domains_add, nexusai_domains_verify
    domains:delete:  nexusai_domains_remove
  8. db:read / db:query / db:admin / db:source:delete (external databases):
    db:read:           nexusai_db_source_list, nexusai_db_inspect_schema,
                       nexusai_db_query_preview, nexusai_db_services_list,
                       nexusai_db_backup_list, nexusai_db_backup_download
    db:query:          nexusai_db_query_execute (SELECT)
    db:admin:          nexusai_db_source_connect, nexusai_db_propose_fix,
                       nexusai_db_apply_fix, nexusai_db_backup,
                       nexusai_db_restore, nexusai_db_restore_to,
                       nexusai_db_backup_schedule
    db:source:delete:  nexusai_db_source_delete
  9. volumes:read / volumes:manage / volumes:delete:
    volumes:read:    nexusai_volume_list
    volumes:manage:  nexusai_volume_create, nexusai_volume_attach, nexusai_volume_detach
    volumes:delete:  nexusai_volume_delete
  10. buckets:read / buckets:manage / buckets:delete (S3-compatible):
    buckets:read:    nexusai_bucket_list, nexusai_bucket_files_list,
                     nexusai_bucket_file_download
    buckets:manage:  nexusai_bucket_create, nexusai_bucket_attach,
                     nexusai_bucket_detach, nexusai_bucket_rotate_credentials
    buckets:delete:  nexusai_bucket_delete, nexusai_bucket_file_delete
  11. managed_db:read / managed_db:manage / managed_db:delete (standalone databases):
    managed_db:read:    nexusai_managed_db_list, nexusai_managed_db_snapshot_list,
                        nexusai_managed_db_query
    managed_db:manage:  nexusai_managed_db_create, nexusai_managed_db_connection,
                        nexusai_managed_db_attach, nexusai_managed_db_detach,
                        nexusai_managed_db_snapshot_create, nexusai_managed_db_execute,
                        nexusai_managed_db_restore
    managed_db:delete:  nexusai_managed_db_delete
  12. support:read / support:write:
    support:read:   nexusai_support_ticket_list, nexusai_support_ticket_get
    support:write:  nexusai_support_ticket_create, nexusai_support_ticket_reply
  13. Backward compatibility: tokens issued before 2026-05-18 only had the four broad scopes (deployments:{read,logs,create,delete}). The backend's SCOPE_SUPERSETS rule treats those as supersets that still satisfy any fine-grained check. New tokens should request the narrowest scope set the workflow needs.

High-value tool arguments (quick reference)

Most frequent arguments used in production MCP flows.

  1. nexusai_deploy_create arguments:
    required: image, port
    optional: name, environment (DEVELOPMENT|STAGING|PRODUCTION),
    envVars, provider, region, autoDestroyHours, requestId
  2. nexusai_deploy_source arguments:
    required: repoUrl
    optional: name, environment, repoBranch, repoSecretName, envVars,
    provider, region, autoDestroyHours, requestId, framework, dockerfile,
    buildCommand, startCommand, installCommand, outputDir
  3. nexusai_deploy_redeploy arguments:
    required: deploymentId
    optional: overrides {
      name, displayName, provider, region, envVars, code, dockerfile, framework,
      autoDestroyHours, healthCheckEnabled, healthCheckType, healthCheckUrl
    }
  4. Other common required IDs:
    deploy status/logs/start/stop/delete/health: deploymentId
    deploy scale: deploymentId + replicas (1-10)
    secret update/delete: secretId
    domains add: deploymentId + domain
    domains verify/remove: deploymentId + domainId

Self-hosted MCP/OAuth configuration

Set these environment variables for reliable external client integration.

  1. Core OAuth/MCP variables:
    MCP_ORIGIN=https://api.example.com
    OAUTH_ISSUER=https://api.example.com
    OAUTH_SIGNING_SECRET=<strong-random-secret>
    
    OAUTH_CLIENT_ID=<optional-static-client-id>
    OAUTH_CLIENT_SECRET=<optional-static-client-secret>
    OAUTH_REDIRECT_URIS=https://chat.openai.com/aip/callback,https://claude.ai/api/mcp/auth_callback
  2. Important behavior:
    If client secret is not configured, PKCE is required.
    redirect_uri must exactly match allowed client redirect URIs.
    issuer/discovery/token signing must stay consistent across all backend nodes.

MCP troubleshooting playbook

I receive 401 from /mcp with "Unauthorized: Missing or invalid OAuth access token."

Use an OAuth access token from /oauth/token, not a regular app JWT or nxk token. Confirm the request uses Authorization: Bearer <oauth_access_token>.

I get invalid_client or client_secret mismatch during token exchange.

Check token_endpoint_auth_method for your registered client. If token_endpoint_auth_method is none, do not send client_secret and use PKCE.

Token exchange fails with redirect_uri is not allowed.

The redirect_uri must exactly match one of the registered redirect_uris for that client.

Token exchange fails with code_verifier errors.

Use the exact code_verifier pair that generated the code_challenge for that authorization request.

tools/call returns missing scope errors.

Request the required scopes during authorization and re-run the OAuth flow so the new token includes them.

Tool call returns Unknown tool.

Use exact tool names from tools/list. NEXUS AI tool names use underscores (for example nexusai_whoami), not dotted names.

Connection works once, then fails in some clients.

Verify discovery issuer and JWT issuer are consistent. In self-hosted setups, align MCP_ORIGIN, OAUTH_ISSUER, and external domain/proxy configuration.

Access Control (RBAC)

Role-based access control for projects, environments, and deployment providers.

Understanding roles and permissions

NEXUS AI uses role-based access control (RBAC) to manage what users can do within an organization.

What roles are available in NEXUS AI?

NEXUS AI provides six user roles with different permission levels: • Owner - Full control over the organization, projects, and all settings • Admin - Similar to Owner, can manage users and most settings • Deployment Manager - Can manage deployments across all environments • Member (Developer) - Can create projects and deploy to Development/Staging • Auditor - Read-only access for compliance and monitoring • Billing Manager - Manages billing and views usage data

What is the difference between organization roles and project roles?

Organization roles define what a user can do across the entire organization. Project-level permissions can further restrict or grant access to specific projects. For example, a Member can be granted access to deploy to Production for a specific project through the Team Management page.

Environment permissions by role

Control which environments users can create projects in and deploy to.

Which environments can each role access by default?

Default environment permissions by role: • Owner / Admin / Super Admin Development, Staging, Production (full access) • Deployment Manager Development, Staging, Production (full access) • Member (Developer) Development, Staging only • Auditor Read-only (cannot create projects or deploy) • Billing Manager Read-only (cannot create projects or deploy) Members (Developers) cannot create projects in or deploy to Production by default. This protects production environments from unauthorized changes.

How do I grant a Member access to Production?

To grant Production access to a specific user: 1. Go to Team Management in the sidebar 2. Find the user and click the actions menu (three dots) 3. Select "Manage Permissions" 4. Check "Production" in the Allowed Environments section 5. Click "Save Permissions" This grants Production access only for projects the user is assigned to.

Why can't I create a project in Production as a Member?

By default, Members can only create projects in Development and Staging environments. This is a security feature to prevent accidental production deployments. If you need Production access, ask your organization Owner or Admin to grant you permission via Team Management.

Deployment provider permissions

Control which cloud providers users can deploy to.

Which deployment providers can each role access by default?

Default provider permissions by role: • Owner / Admin / Super Admin Local Docker, GCP Cloud Run, AWS App Runner, Azure Container Apps (all providers) • Deployment Manager Local Docker only (can be expanded via Team Management) • Member (Developer) Local Docker only • Auditor Read-only (cannot deploy) • Billing Manager Read-only (cannot deploy) Cloud providers (GCP Cloud Run, AWS App Runner, Azure Container Apps) require explicit permission for non-admin users.

How do I grant a user access to cloud providers?

To grant cloud provider access to a specific user: 1. Go to Team Management in the sidebar 2. Find the user and click the actions menu (three dots) 3. Select "Manage Permissions" 4. Check the desired providers (GCP Cloud Run, AWS App Runner, Azure Container Apps) 5. Click "Save Permissions" Note: Cloud provider access also depends on your organization's plan tier.

Full permissions matrix

Complete overview of all permissions by role.

Organization-level permissions

View Organization Owner: ✓ Admin: ✓ Deploy Mgr: ✓ Member: ✓ Auditor: ✓ Billing Mgr: ✓ Manage Organization Owner: ✓ Admin: ✓ Deploy Mgr: ✗ Member: ✗ Auditor: ✗ Billing Mgr: ✗ Manage Users Owner: ✓ Admin: ✓ Deploy Mgr: ✗ Member: ✗ Auditor: ✗ Billing Mgr: ✗ View Billing Owner: ✓ Admin: ✓ Deploy Mgr: ✗ Member: ✗ Auditor: ✗ Billing Mgr: ✓ Manage Billing Owner: ✓ Admin: ✗ Deploy Mgr: ✗ Member: ✗ Auditor: ✗ Billing Mgr: ✓ View Audit Logs Owner: ✓ Admin: ✓ Deploy Mgr: ✗ Member: ✗ Auditor: ✓ Billing Mgr: ✗ View Usage Owner: ✓ Admin: ✓ Deploy Mgr: ✗ Member: ✗ Auditor: ✓ Billing Mgr: ✓ Manage Secrets Owner: ✓ Admin: ✓ Deploy Mgr: ✓ Member: ✓ Auditor: ✗ Billing Mgr: ✗ Manage AI Providers Owner: ✓ Admin: ✓ Deploy Mgr: ✗ Member: ✗ Auditor: ✗ Billing Mgr: ✗ Manage Custom Domains Owner: ✓ Admin: ✓ Deploy Mgr: ✓ Member: ✗ Auditor: ✗ Billing Mgr: ✗

Project-level permissions

Create Projects Owner: ✓ Admin: ✓ Deploy Mgr: ✗ Member: ✓ Auditor: ✗ Billing Mgr: ✗ View Projects Owner: All Admin: All Deploy Mgr: Assigned Member: Assigned Auditor: All Billing Mgr: All Update Projects Owner: ✓ Admin: ✓ Deploy Mgr: ✗ Member: ✓ Auditor: ✗ Billing Mgr: ✗ Delete Projects Owner: ✓ Admin: ✓ Deploy Mgr: ✗ Member: ✗ Auditor: ✗ Billing Mgr: ✗ Manage Project Members Owner: ✓ Admin: ✓ Deploy Mgr: ✗ Member: ✗ Auditor: ✗ Billing Mgr: ✗ View Deployments Owner: ✓ Admin: ✓ Deploy Mgr: ✓ Member: ✓ Auditor: ✓ Billing Mgr: ✗ Create Deployments Owner: ✓ Admin: ✓ Deploy Mgr: ✓ Member: ✓ Auditor: ✗ Billing Mgr: ✗ Manage Deployments Owner: ✓ Admin: ✓ Deploy Mgr: ✓ Member: ✓ Auditor: ✗ Billing Mgr: ✗ View Deployment Logs Owner: ✓ Admin: ✓ Deploy Mgr: ✓ Member: ✓ Auditor: ✓ Billing Mgr: ✗ Legend: • "All" = Access to all projects in the organization • "Assigned" = Only projects where the user is explicitly added as a member

How do project scopes work?

Project scope determines which projects a user can access: • All Projects: Owner, Admin, Auditor, and Billing Manager can see all projects in the organization. • Assigned Projects Only: Members and Deployment Managers can only see projects they have been explicitly added to. To add a user to a project, go to the project settings and add them as a project member.

Custom domains

Bring your own domain to production deployments.

Add custom domains

  1. Open the Deployment Details page (deployment must be RUNNING).
  2. Scroll to Custom Domains and click "Add Domain".
  3. Enter your domain (example: app.example.com or example.com).
  4. Follow the DNS configuration instructions shown in the UI.
  5. For subdomains: add a CNAME record pointing to your deployment subdomain.
  6. For apex domains: add both an A record (server IP) and TXT record (verification token).
  7. Wait for DNS propagation (often minutes, sometimes longer).
  8. Click "Verify DNS" to confirm the domain is configured correctly.
  9. SSL certificates are issued automatically after verification.

Cloud deployment providers

Enable Cloud Run, App Runner, or Container Apps as deployment targets for your NEXUS AI.

Enable GCP Cloud Run deployments

Cloud Build builds images, Artifact Registry stores them, and Cloud Run runs them.

  1. Enable required APIs.
    gcloud services enable \
      run.googleapis.com \
      cloudbuild.googleapis.com \
      artifactregistry.googleapis.com \
      storage.googleapis.com \
      logging.googleapis.com
  2. Create an Artifact Registry Docker repository.
    gcloud artifacts repositories create nexusai-deployments \
      --repository-format=docker \
      --location=us-central1
  3. Create a Cloud Storage bucket for build source archives.
    gsutil mb -l us-central1 gs://YOUR_UNIQUE_BUILD_BUCKET_NAME
  4. Grant required IAM roles.
    # Replace: PROJECT_ID, BACKEND_SA, PROJECT_NUMBER, BUCKET
    gcloud projects add-iam-policy-binding PROJECT_ID \
      --member=serviceAccount:BACKEND_SA \
      --role=roles/run.admin
    gcloud projects add-iam-policy-binding PROJECT_ID \
      --member=serviceAccount:BACKEND_SA \
      --role=roles/cloudbuild.builds.editor
    gcloud projects add-iam-policy-binding PROJECT_ID \
      --member=serviceAccount:BACKEND_SA \
      --role=roles/logging.viewer
    gsutil iam ch serviceAccount:BACKEND_SA:objectAdmin gs://BUCKET
    
    gcloud projects add-iam-policy-binding PROJECT_ID \
      --member=serviceAccount:[email protected] \
      --role=roles/artifactregistry.writer
    gsutil iam ch serviceAccount:[email protected]:objectViewer gs://BUCKET
  5. Deploy from a project and confirm build and runtime logs appear in the deployment logs view.

Enable AWS App Runner deployments

CodeBuild builds and pushes to ECR, and App Runner runs the service.

  1. Create an ECR repository for deployment images.
    aws ecr create-repository --repository-name nexusai-apps --region us-east-1
  2. Create an S3 bucket for CodeBuild source archives.
    aws s3api create-bucket --bucket YOUR_UNIQUE_BUCKET_NAME --region us-east-1 --create-bucket-configuration LocationConstraint=us-east-1
  3. Create an IAM user/role for the backend and grant permissions for App Runner, CodeBuild, ECR, S3, and CloudWatch Logs (and IAM role creation if you want NEXUS AI to auto-create CodeBuild/App Runner roles).
  4. Deploy from a project and confirm build logs and runtime logs appear in the deployment logs view.
  5. Custom domains are supported for App Runner deployments via the in-app Custom Domains UI.

Enable Azure Container Apps deployments

ACR Tasks builds and pushes images, and Container Apps runs the service.

  1. Login, select a subscription, and register required providers (one-time).
    az login
    az account set --subscription "YOUR_SUBSCRIPTION_ID"
    
    az provider register --namespace Microsoft.App
    az provider register --namespace Microsoft.ContainerRegistry
    az provider register --namespace Microsoft.OperationalInsights
    az provider register --namespace Microsoft.Storage
  2. Create a resource group and service principal with Contributor role.
    RG_NAME="nexusai-core"
    RG_LOCATION="eastus"
    az group create --name "$RG_NAME" --location "$RG_LOCATION"
    
    SUB_ID=$(az account show --query id -o tsv)
    az ad sp create-for-rbac \
      --name "nexusai-backend" \
      --role Contributor \
      --scopes "/subscriptions/$SUB_ID/resourceGroups/$RG_NAME" \
      --query "{AZURE_CLIENT_ID:appId,AZURE_CLIENT_SECRET:password,AZURE_TENANT_ID:tenant}" \
      -o table
    
    echo "AZURE_SUBSCRIPTION_ID=$SUB_ID"
  3. Set Azure environment variables in the backend (.env).
    AZURE_TENANT_ID=...
    AZURE_CLIENT_ID=...
    AZURE_CLIENT_SECRET=...
    AZURE_SUBSCRIPTION_ID=...
    AZURE_DEFAULT_REGION=eastus
    AZURE_RESOURCE_GROUP_PREFIX=nexusai
    AZURE_ACR_NAME_PREFIX=nexusai
    AZURE_ACR_REPO=nexusai-apps
    AZURE_CONTAINERAPPS_ENV_PREFIX=nexusai
    AZURE_LOG_ANALYTICS_WORKSPACE_PREFIX=nexusai
    AZURE_STORAGE_ACCOUNT_PREFIX=nexusai
    AZURE_STORAGE_CONTAINER=build-sources
  4. If you want a single shared resource group, set AZURE_RESOURCE_GROUP=RG_NAME. For per-project resource groups, scope the service principal at the subscription level.
  5. Option 2 (per-project RGs): grant Contributor at subscription scope so the backend can create new resource groups.
    SUB_ID=YOUR_SUBSCRIPTION_ID
    SP_APP_ID=YOUR_SERVICE_PRINCIPAL_APP_ID
    az role assignment create --assignee "$SP_APP_ID" --role Contributor \
      --scope "/subscriptions/$SUB_ID"
  6. The backend will auto-create: Resource Group, ACR, Container Apps Environment, Log Analytics workspace, and Storage account.
  7. Custom domains are supported for Container Apps deployments via the in-app Custom Domains UI.

Azure required permissions (AuthorizationFailed fix)

Use this when deployments fail with `Microsoft.Resources/subscriptions/resourcegroups/write`.

  1. Set variables for your subscription, resource group, and service principal.
    SUB_ID="YOUR_SUBSCRIPTION_ID"
    RG_NAME="nexusai-shared"
    SP_APP_ID="YOUR_AZURE_CLIENT_ID"
  2. Ensure the resource group exists before assigning RBAC at RG scope.
    RG_LOCATION="eastus"
    az group show --name "$RG_NAME" --subscription "$SUB_ID" >/dev/null 2>&1 || \
      az group create --name "$RG_NAME" --location "$RG_LOCATION" --subscription "$SUB_ID"
  3. Grant Contributor at resource-group scope (recommended for a shared group).
    az role assignment create \
      --assignee "$SP_APP_ID" \
      --role Contributor \
      --scope "/subscriptions/$SUB_ID/resourceGroups/$RG_NAME"
  4. Verify the role assignment exists.
    az role assignment list \
      --assignee "$SP_APP_ID" \
      --scope "/subscriptions/$SUB_ID/resourceGroups/$RG_NAME" \
      --include-inherited -o table
  5. If you use per-project resource groups, grant Contributor at subscription scope instead.
    az role assignment create \
      --assignee "$SP_APP_ID" \
      --role Contributor \
      --scope "/subscriptions/$SUB_ID"
  6. After changing IAM, wait 5 to 10 minutes for propagation, then retry deployment. If your worker process has long-lived tokens, restart backend workers before retry.

Billing

Pricing and billing

  1. Review plan limits on the Pricing page.
  2. Upgrade when you need more deployments or usage.
  3. Track spend and alerts in Billing settings.
  4. Download invoices and manage payment methods.

FAQ and troubleshooting

Common deployment validation errors, cloud permissions, and how to unblock yourself fast.

Deployment validation FAQ

Dockerfile validation is enforced to keep deployments secure and predictable.

Why did my deployment fail with "Dockerfile validation failed"?

This means your Dockerfile violates a security policy (base image allowlist, blocked ports, or dangerous build patterns). Fix: check your base image prefix, EXPOSE ports, and avoid restricted patterns like piping remote scripts into a shell.

Why did my deployment fail with "Exposing privileged port 25 is not allowed"?

Issue: Your Dockerfile contains an `EXPOSE 25` instruction. In hardened environments, ports below 1024 are privileged and blocked by NEXUS AI deployments. Solution: Move the service to a non-privileged port (for example `2525` or `587`) and update your app configuration and Dockerfile accordingly.

# Example (Postfix or SMTP-like service)
# Use a non-privileged port and update your service config accordingly.
ENV PORT=2525
EXPOSE 2525
Why did my deployment fail with "Exposing privileged port <port> is not allowed"?

Ports below 1024 are considered privileged. NEXUS AI blocks privileged ports by default (common exceptions are 80 and 443). Fix: move your app to a non-privileged port like 3000 or 8080 and update your Dockerfile and app to listen on that port.

Why did my deployment fail with "Exposing port 22 is not allowed"?

Ports associated with remote access protocols (SSH/Telnet/RDP/VNC) are blocked for safety. Fix: do not expose these ports. If you need admin access, use logs/metrics and application-level endpoints instead.

Why is the `postfix:latest` base image being rejected?

Issue: NEXUS AI enforces a base-image allowlist so builds start from trusted, maintained sources. The `postfix:` prefix is not on the approved list. Solution: Rebuild using an approved base image prefix and install the needed mail utilities through the package manager. Approved prefixes: node:, python:, nginx:, alpine:, ubuntu:, debian:, postgres:, redis:, mongo:, mysql:, httpd:, php:, ruby:, golang:, openjdk:, rust:, gcc:.

# Example approach: start from Debian and install packages
FROM debian:bookworm-slim
RUN apt-get update && apt-get install -y --no-install-recommends postfix && rm -rf /var/lib/apt/lists/*
# Configure Postfix to listen on a non-privileged port (e.g., 2525) in your main.cf
EXPOSE 2525
Why is my base image being rejected with "Base image ... is not allowed"?

NEXUS AI only allows builds that start from approved base image prefixes. Fix: switch your Dockerfile `FROM` to an approved prefix such as `debian:`, `ubuntu:`, `alpine:`, `node:`, or `python:` and install what you need via the package manager.

Why is "curl | sh" / "wget | sh" blocked?

Piping a remote script directly into a shell is a common supply-chain attack vector and is blocked. Fix: install packages using the OS package manager, pin versions where possible, and avoid remote script execution in Docker builds.

Why are privileged container options blocked (`--privileged`, `--cap-add`, host network, Docker socket)?

These options can allow container escape or host compromise and are blocked by policy. Fix: remove privileged flags and redesign the service to run without elevated host access.

Why did my deployment fail with "Dockerfile is too large" or "too many instructions"?

Very large Dockerfiles or extremely high instruction counts can be used for resource exhaustion and are blocked. Fix: reduce layers, remove repeated RUN steps, and prefer package manager installs in fewer commands.

Why is access to `/var/run/docker.sock` blocked?

Mounting the Docker socket into a container can allow full host control and is treated as a container escape risk. Fix: remove Docker socket usage. If you need to build/run containers, use the platform's deployment workflow instead.

Why did my deployment fail with "Dockerfile appears to contain hardcoded secrets"?

The validator detects secret-like values in Dockerfiles to prevent accidental credential leaks. Fix: remove secrets from Dockerfile and provide them at runtime using Secrets Vault and environment variables.

Troubleshooting guide for deployment failures

If you receive `DEPLOYMENT_FAILED` after a validation error, use this checklist:

Error Message                         | Meaning                               | Action Item
------------------------------------- | ------------------------------------- | -------------------------------------------
Dockerfile validation failed          | Configuration violates security policy | Check port numbers and base image prefixes
Base image ... is not allowed         | Image source is untrusted              | Switch to an approved prefix (ubuntu/alpine)
Exposing privileged port              | Port is < 1024                         | Move app to a port like 8080/3000/2525
How do I request a new base image or port exception?

If your project strictly requires a base image or port that is not allowed by default, open a security review ticket with a clear business justification. Email: [email protected]

Ports and service readiness

Most "service won't start" issues come down to the container port and startup behavior.

Cloud Run says my revision is not ready. What should my app listen on?

Your container must listen on the same port that Cloud Run routes traffic to. In NEXUS AI, the port is typically derived from your Dockerfile `EXPOSE` instruction (or defaults based on the generated Dockerfile). Fix: ensure your app listens on the exposed port and does not bind to localhost-only. Use 0.0.0.0 where applicable.

Why doesn't setting `ENV PORT=...` always fix Cloud Run?

Cloud Run provides its own `PORT` environment variable and expects your app to bind to it. NEXUS AI also filters out user-provided `PORT` to avoid conflicts. Fix: update your app to read the `PORT` variable at runtime OR explicitly `EXPOSE` the correct port and configure your server to bind to that port.

Custom domains FAQ

DNS and SSL are the most common sources of custom domain issues.

DNS looks correct, but verification still fails. What should I check?

Common causes: DNS propagation delay, wrong record name (host), or a conflicting existing record. Fix: confirm the exact record name/value from the UI and verify it from multiple resolvers.

# Example checks
dig CNAME app.example.com +short
dig TXT example.com +short
dig A example.com +short
Why does Cloudflare proxy (orange cloud) break verification/SSL?

When Cloudflare proxy is enabled, DNS responses and TLS termination can differ from what NEXUS AI expects for verification and certificate issuance. Fix: disable proxy (set the record to DNS-only) during verification and certificate issuance.

Verification succeeded but SSL is still pending. Why?

Certificate issuance can lag behind DNS verification, especially right after a DNS change. Fix: wait a few minutes and re-check. If it persists, verify there are no restrictive CAA records blocking Let's Encrypt.

How do I check if CAA records are blocking Let's Encrypt?

CAA records can restrict which certificate authorities are allowed to issue certificates for your domain. Fix: ensure your CAA records allow Let's Encrypt (or remove restrictive CAA records).

dig CAA example.com +short
Why does my apex domain fail when my DNS provider doesn't support CNAME at root?

Many DNS providers do not allow CNAME records at the root/apex (`example.com`). Fix: use the platform's apex-domain flow (A + TXT) or use a provider feature like ALIAS/ANAME if supported.

I added the records, but my browser still goes to the old site. Why?

DNS and browser caches can keep old values temporarily. Fix: verify with `dig` from your terminal, wait for TTL expiry, and try an incognito window or flush DNS cache.

GCP Cloud Run troubleshooting

Most Cloud Run issues are IAM permissions or service accessibility.

I see: Permission "iam.serviceAccounts.get" denied

This means the service account running NEXUS AI does not have enough IAM permissions in your GCP project (or the service account does not exist). Fix: grant the required roles to the backend service account. Replace `PROJECT_ID` and `BACKEND_SA`.

PROJECT_ID="your-project-id"
BACKEND_SA="[email protected]"

gcloud projects add-iam-policy-binding "$PROJECT_ID" \
  --member="serviceAccount:$BACKEND_SA" \
  --role="roles/cloudbuild.builds.editor"
gcloud projects add-iam-policy-binding "$PROJECT_ID" \
  --member="serviceAccount:$BACKEND_SA" \
  --role="roles/run.admin"
gcloud projects add-iam-policy-binding "$PROJECT_ID" \
  --member="serviceAccount:$BACKEND_SA" \
  --role="roles/storage.admin"
gcloud projects add-iam-policy-binding "$PROJECT_ID" \
  --member="serviceAccount:$BACKEND_SA" \
  --role="roles/iam.serviceAccountUser"
gcloud projects add-iam-policy-binding "$PROJECT_ID" \
  --member="serviceAccount:$BACKEND_SA" \
  --role="roles/artifactregistry.writer"
How do I view Cloud Build logs for a deployment?

Use the build ID shown in the deployment logs and fetch logs from Cloud Build.

gcloud builds log BUILD_ID --project=PROJECT_ID
How do I find my GCP project number (for the Cloud Build service account)?

The default Cloud Build service account uses the project number: `[email protected]`

gcloud projects describe PROJECT_ID --format="value(projectNumber)"
Cloud Build can't push to Artifact Registry. What should I check?

Most commonly, the Cloud Build service account is missing Artifact Registry write permission. Fix: grant `roles/artifactregistry.writer` to `[email protected]` in the same project/region as your repo.

I get "repository not found" or image push errors. What's a common misconfiguration?

A frequent cause is a mismatch between: - Artifact Registry repo name/region - `GCP_ARTIFACT_REGISTRY_HOST` (should be `REGION-docker.pkg.dev`, no `https://`) Fix: confirm the repo exists and the host matches its region.

Cloud Build fails with "PERMISSION_DENIED". Which identity needs access?

There are two identities involved: - The backend runtime service account (creates builds, reads logs, uploads source archives). - The Cloud Build service account (executes the build and pushes images). Fix: grant roles to the correct identity. A common miss is Artifact Registry write access for the Cloud Build service account and bucket read access for the build source archive.

I can't reach the public Cloud Run service URL

Check that your service has a ready revision and that it is publicly invokable (or that you have authentication configured correctly).

gcloud run services describe SERVICE_NAME \
  --region=us-central1 \
  --project=PROJECT_ID \
  --format="value(status.latestReadyRevisionName,status.latestCreatedRevisionName)"

# Check if the service is public (allUsers has roles/run.invoker)
gcloud run services get-iam-policy SERVICE_NAME \
  --region=us-central1 \
  --project=PROJECT_ID
How do I confirm Artifact Registry is set up correctly?

List repositories in Artifact Registry for your project and confirm the repo/region match your backend configuration.

gcloud artifacts repositories list --project=PROJECT_ID
How do I add a custom domain to a Cloud Run deployment?

NEXUS AI does not support Cloud Run custom domains in-app yet, but you can configure it directly using Cloud Run domain mapping. 1) Create the mapping 2) Add the DNS records returned by the mapping status 3) Wait for the certificate to become ready

gcloud config set project PROJECT_ID

gcloud run domain-mappings create \
  --service SERVICE_NAME \
  --domain app.example.com \
  --region us-central1

gcloud run domain-mappings describe app.example.com \
  --region us-central1 \
  --format="yaml(status.resourceRecords)"

AWS App Runner troubleshooting

Most App Runner issues are ECR/CodeBuild/IAM configuration or container startup behavior.

My App Runner deployment fails during build. What should I check first?

Check that: - CodeBuild can read the S3 source archive bucket. - CodeBuild can authenticate to ECR and push images. - App Runner can pull from ECR (service role permissions).

I see `AccessDeniedException` / `iam:PassRole` errors. What do they mean?

When AWS needs to attach a role to CodeBuild or App Runner, the caller must have permission to pass that role. Fix: ensure the IAM identity used by the backend has `iam:PassRole` for the specific role ARNs you are using.

How do I verify ECR exists and is accessible?

List repositories and verify the expected repo is present in the region you configured.

aws ecr describe-repositories --region us-east-1
Where do I look for AWS build and runtime logs?

Build logs are typically in CodeBuild (CloudWatch Logs). Runtime logs are in App Runner (CloudWatch Logs). Fix: open the related CodeBuild project and App Runner service in AWS Console and inspect CloudWatch logs.

S3 bucket creation fails in us-east-1 with a LocationConstraint error. Why?

In `us-east-1`, S3 bucket creation differs slightly from other regions and LocationConstraint can cause errors depending on the command used. Fix: for us-east-1, create the bucket without the LocationConstraint field.

aws s3api create-bucket --bucket YOUR_UNIQUE_BUCKET_NAME --region us-east-1

Azure Container Apps / ACR troubleshooting

Most Azure deployment issues are permissions, ACR builds (Tasks), or Log Analytics setup.

ACR Tasks requests are not permitted for my registry

Error (rewritten): Azure is blocking ACR Tasks for your Container Registry, so the platform cannot run the registry-side build step (ACR Tasks). This is not a Dockerfile validation issue—your Azure subscription/tenant/registry configuration is rejecting task requests. Fix options: 1) Check the registry SKU and upgrade if needed (Standard/Premium recommended). 2) Check for Azure Policy restrictions blocking ACR Tasks in your subscription. 3) If required, open an Azure Support request to allow ACR Tasks for the registry: http://aka.ms/azuresupport

# Check ACR SKU
az acr show -n REGISTRY_NAME --query sku.name -o tsv

# Upgrade SKU (example: Standard)
az acr update -n REGISTRY_NAME --sku Standard
ACR build fails with authorization errors. What should I check?

Ensure the backend service principal has Contributor on the Resource Group. Confirm `AZURE_TENANT_ID`, `AZURE_CLIENT_ID`, `AZURE_CLIENT_SECRET`, and `AZURE_SUBSCRIPTION_ID` are correct.

Deployment failed with `Microsoft.Resources/subscriptions/resourcegroups/write`. What does this mean?

The Azure service principal used by NEXUS AI does not have enough RBAC permissions on the target resource group (or subscription). Fix: grant Contributor on the target resource group for shared-RG mode, or Contributor on the subscription for per-project RG mode. Then wait for IAM propagation and retry deployment.

SUB_ID="YOUR_SUBSCRIPTION_ID"
RG_NAME="nexusai-shared"
SP_APP_ID="YOUR_AZURE_CLIENT_ID"
RG_LOCATION="eastus"
az group show --name "$RG_NAME" --subscription "$SUB_ID" >/dev/null 2>&1 || \
  az group create --name "$RG_NAME" --location "$RG_LOCATION" --subscription "$SUB_ID"

az role assignment create \
  --assignee "$SP_APP_ID" \
  --role Contributor \
  --scope "/subscriptions/$SUB_ID/resourceGroups/$RG_NAME"

az role assignment list \
  --assignee "$SP_APP_ID" \
  --scope "/subscriptions/$SUB_ID/resourceGroups/$RG_NAME" \
  --include-inherited -o table
No runtime logs appear in the UI. Why?

Container Apps logs are streamed via Log Analytics. Fix: verify the Log Analytics workspace exists and is attached to the Container Apps environment.

I see image pull errors in Container Apps.

Confirm the ACR registry exists and the image tag was pushed by the ACR Task. Check that the Container App registry settings reference the correct login server.

Secrets and encryption FAQ (self-hosted)

Keys are encrypted at rest. Keep your encryption key stable.

I changed `ENCRYPTION_KEY` and now AI providers/secrets fail. What happened?

Provider API keys stored by NEXUS AI are encrypted using `ENCRYPTION_KEY`. If you change it, previously stored encrypted values can't be decrypted anymore. Fix: restore the original `ENCRYPTION_KEY` OR re-save your provider credentials and secrets after changing it.

Quotas and limits FAQ

Plan limits affect AI requests and deployments.

How many AI requests does the Free plan include each day?

The Free plan includes 5 AI requests per day across AI Builder and standard AI generation. The daily allowance resets at 00:00 UTC. Monthly request and managed-token limits also apply.

How many AI requests does the Starter plan include each day?

The Starter plan includes 10 AI requests per day across AI Builder and standard AI generation. The daily allowance resets at 00:00 UTC. The Starter monthly request and managed-token limits also apply.

How many AI requests does the Pro plan include each day?

The Pro plan includes 30 AI requests per day across AI Builder and standard AI generation. The daily allowance resets at 00:00 UTC. The Pro monthly request and managed-token limits also apply.

Why do I see "AI request quota exceeded for this month"?

Your organization hit its monthly AI request limit for the current plan tier. Fix: upgrade your plan or wait for the monthly quota reset.

Why can't I deploy more containers?

Your organization may have reached the concurrent deployment limit (running/building deployments). Fix: stop unused deployments or upgrade your plan limits.

Why did my deployment stop automatically?

Deployments can auto-stop due to plan max runtime (or an auto-destroy setting) to control cost and resource usage. Fix: increase allowed runtime on your plan (if available) or redeploy when needed.

What's the difference between AI request quota and token usage?

Request quota limits the number of generation calls you can make. Token usage measures the size of prompts and outputs (and impacts cost). Fix: if you hit request quota, upgrade or wait for reset. If costs are high, reduce max tokens and use smaller models.

External Database Connections

Connect your own Postgres, Supabase, or any external database. Run safe SQL, inspect schema, and let AI fix deployment errors automatically.

How external DB connections work

  1. NEXUS AI lets you register any external PostgreSQL database (Supabase, Neon, RDS, self-hosted, etc.) as a DB Source.
  2. Your password is encrypted with AES-256-GCM and stored in the Secrets Vault — the raw credential is never persisted in plain text.
  3. Every query opens a fresh short-lived connection, runs inside a transaction with session-level timeouts, and disconnects immediately.
  4. A SQL safety layer blocks dangerous operations (DROP DATABASE, pg_exec, DELETE without WHERE, multi-statement SQL) before any query reaches your database.
  5. All executions are logged to the audit trail with a SHA-256 hash of the SQL — no plain-text query is stored.

Connect a Supabase database

Supabase runs on PostgreSQL. Use the Session Pooler for best compatibility with NEXUS AI short-lived connections.

  1. Step 1 — Find your connection details in Supabase: 1. Go to supabase.com and open your project. 2. In the left sidebar, click "Project Settings" (gear icon at the bottom). 3. Click "Database" from the settings menu. 4. Scroll down to the "Connection string" section. 5. Above the URI / PSQL / Golang tabs, find the "Connection pooler" dropdown — switch it from "Direct connection" to "Session pooler". 6. Copy the Host and Port shown — these differ from the direct connection values. Your Session Pooler details will look like:
    Host:     aws-0-us-east-1.pooler.supabase.com
    Port:     5432
    Database: postgres
    Username: postgres.<your-project-ref>
    Password: <your-database-password>
    SSL mode: require
  2. Step 2 — Register the DB Source in NEXUS AI:
    POST /api/db-sources
    Authorization: Bearer <token>
    
    {
      "name": "my-supabase",
      "host": "aws-0-us-east-1.pooler.supabase.com",
      "port": 5432,
      "dbName": "postgres",
      "username": "postgres.abcdefghijklmnop",
      "password": "<db-password>",
      "sslMode": "require",
      "engine": "POSTGRESQL"
    }
  3. Or use the MCP tool from Claude: nexusai_db_source_connect with the same fields.
  4. Test the connection: POST /api/db-sources/<id>/test — returns latency in ms on success.

Supabase connection modes explained

  1. Supabase provides three connection modes. Choose based on your use case:
    Direct connection       port 5432  — long-lived, migrations, admin tasks
    Session pooler          port 5432  — recommended for NEXUS AI
    Transaction pooler      port 6543  — ultra-short-lived (pgBouncer, limited SET support)
  2. NEXUS AI recommends the Session Pooler (port 5432). It is compatible with all SQL features including SET commands, while still efficiently managing connections.
  3. Important: the Session Pooler username format is postgres.<project-ref> — for example: postgres.abcdefghijklmnop. You can copy this directly from the Supabase connection string shown after switching the pooler dropdown.
  4. Avoid the Transaction Pooler (port 6543) unless you have a specific reason — it uses pgBouncer in transaction mode which blocks certain PostgreSQL features.

Run a query against your external DB

  1. Preview mode runs EXPLAIN and safety analysis without committing any changes:
    POST /api/db-sources/<id>/query
    
    {
      "sql": "SELECT id, email FROM users LIMIT 10",
      "mode": "preview"
    }
  2. Execute mode runs the query for real. DML (INSERT/UPDATE/DELETE) and DDL require confirmed: true:
    POST /api/db-sources/<id>/query
    
    {
      "sql": "UPDATE users SET status = 'active' WHERE id = 'abc'",
      "mode": "execute",
      "confirmed": true
    }
  3. Results are capped at 1000 rows by default. Pass limits.maxRows to override (max 10000).
  4. SELECT queries run inside a READ ONLY transaction — they cannot mutate data even if the SQL tries to.

Inspect database schema

  1. Fetch the full schema graph (tables, columns, indexes, constraints):
    GET /api/db-sources/<id>/schema
  2. Results are cached in Redis for 5 minutes. Pass ?refresh=true to bust the cache and re-fetch live.
  3. Via MCP: use nexusai_db_inspect_schema — Claude will see your full table structure and can write accurate SQL against it.

AI log-to-fix: auto-repair database errors

Paste a deployment log containing database errors. NEXUS AI extracts the error, inspects the live schema, and proposes a DDL fix.

  1. Send the log snippet to the propose-fix endpoint:
    POST /api/db-sources/<id>/propose-fix
    
    {
      "logSnippet": "ERROR: relation \"profiles\" does not exist\nLINE 1: SELECT * FROM profiles WHERE user_id = $1",
      "deploymentId": "<optional-deployment-id>"
    }
  2. NEXUS AI returns a DDL proposal with a risk level (LOW / MEDIUM / HIGH):
    {
      "proposedSql": "CREATE TABLE profiles (id UUID PRIMARY KEY, user_id UUID NOT NULL, ...);",
      "explanation": "The profiles table is missing. This creates it with a user_id foreign key.",
      "riskLevel": "LOW"
    }
  3. Review and apply the fix:
    POST /api/db-fix-proposals/<proposalId>/apply
    
    { "dbSourceId": "<id>" }
  4. Via MCP: nexusai_db_propose_fix → review → nexusai_db_apply_fix.

MCP tools for Claude and ChatGPT

  1. Eight MCP tools are available once you connect NEXUS AI to Claude or ChatGPT:
    nexusai_db_source_list      — list all registered DB sources
    nexusai_db_source_connect   — register a new external DB
    nexusai_db_source_delete    — remove a DB source
    nexusai_db_inspect_schema   — get full schema graph
    nexusai_db_query_preview    — dry-run a SQL query
    nexusai_db_query_execute    — run SQL (confirmed=true for writes)
    nexusai_db_propose_fix      — analyze logs → propose DDL
    nexusai_db_apply_fix        — apply a reviewed fix proposal
  2. Claude will automatically inspect your schema before writing SQL, so queries match your actual table and column names.

SQL safety rules

  1. The following operations are always blocked regardless of confirmed flag:
    DROP DATABASE
    ALTER ROLE / CREATE ROLE
    CREATE EXTENSION
    COPY ... PROGRAM
    pg_read_file, pg_ls_dir, pg_exec
    Multi-statement SQL (more than one statement per request)
    DELETE or UPDATE without a WHERE clause
  2. SELECT queries are auto-allowed and run in a READ ONLY transaction.
  3. DML (INSERT/UPDATE/DELETE) and DDL (CREATE TABLE, ALTER TABLE, etc.) are allowed but require confirmed: true.
  4. DDL that drops or modifies columns is flagged HIGH risk and surfaced in the proposal before apply.

Troubleshooting external DB connections

Connection to Supabase times out or is refused.

Most likely cause: wrong port or username format. Fix: In Supabase Project Settings → Database → Connection string, set the "Connection pooler" dropdown to "Session pooler". Use the Host and Port shown there (port 5432) with username format postgres.<project-ref>.

Queries fail on Supabase with "unsupported startup parameter".

PgBouncer in transaction mode blocks certain SET commands outside a transaction. Fix: NEXUS AI uses SET LOCAL inside the transaction, which pgBouncer allows. If you see this error on a custom query, avoid session-level SET commands in your SQL.

My query was blocked by the SQL safety layer.

The safety service rejected the statement before it reached the database. Fix: check the reasons field in the response. Common causes are: DELETE/UPDATE without WHERE, blocked keywords (DROP DATABASE, pg_exec), or multiple statements separated by semicolons.

Schema introspection shows no tables.

The connected user may not have access to the public schema, or your tables are in a different schema. Fix: grant SELECT on information_schema to the connecting user, or ensure tables are in the public schema. Supabase users should use the postgres superuser or a role with schema access.

The log-to-fix proposal generated invalid SQL.

The AI proposal is validated through the SQL safety layer before being stored. If it fails, the endpoint returns an error instead of a bad proposal. Fix: provide more context in the logSnippet (include the full stack trace and error line). You can also manually write the DDL and execute it via /query with confirmed: true.

NEXUS AI CLI

Deploy, manage, and automate everything from your terminal using the nexus command-line interface.

Installation

Install the NEXUS AI CLI on Linux or macOS with a single command. Node.js 18 or later is required — the installer will set it up for you if it's missing.

  1. Requirements: Node.js v18+ and npm. Check your version:
    node --version   # must be v18.0.0 or higher
    npm --version
  2. Quick install on Linux — auto-detects your distro (Ubuntu, Debian, RHEL, Alpine, Arch) and installs Node.js if needed:
    curl -fsSL https://nexusai.run/install.sh | bash
  3. Quick install on macOS — installs Homebrew and Node.js automatically if not present, supports both Intel and Apple Silicon:
    curl -fsSL https://nexusai.run/install-mac.sh | bash
  4. Install manually via npm (if you already have Node.js 18+):
    npm install -g nexusapp-cli
  5. Or run a one-off command without a global install:
    npx nexusapp-cli auth login
  6. Verify the installation — you should see the version number:
    nexus --version
    nexus --help

Linux installer options

The Linux installer script supports additional flags for custom setups and self-hosted instances.

  1. Install and point to a self-hosted NEXUS AI instance:
    curl -fsSL https://nexusai.run/install.sh | bash -s -- --api-url https://nexus.yourcompany.com
  2. Skip automatic Node.js installation if you manage Node yourself (e.g. via nvm or asdf):
    curl -fsSL https://nexusai.run/install.sh | bash -s -- --skip-node
  3. Download the script first and inspect it before running:
    curl -fsSL https://nexusai.run/install.sh -o install.sh
    cat install.sh          # review the script
    bash install.sh
  4. Uninstall the CLI and optionally remove config:
    bash install.sh --uninstall
  5. Supported distributions: Ubuntu · Debian · Fedora · RHEL · CentOS · Rocky Linux · AlmaLinux · Alpine · Arch · openSUSE. Any other distro falls back to nvm.

macOS installer options

The macOS installer uses Homebrew for Node.js and supports both Intel Macs and Apple Silicon (M1/M2/M3).

  1. Install on macOS — works on both Intel and Apple Silicon:
    curl -fsSL https://nexusai.run/install-mac.sh | bash
  2. Install and point to a self-hosted instance:
    curl -fsSL https://nexusai.run/install-mac.sh | bash -s -- --api-url https://nexus.yourcompany.com
  3. Install via Homebrew tap (once the formula is published):
    brew tap nexusai/tap
    brew install nexus
  4. Skip Node.js installation if you already have v18+ (e.g. managed by nvm or Volta):
    curl -fsSL https://nexusai.run/install-mac.sh | bash -s -- --skip-node
  5. Uninstall the CLI and optionally remove config:
    bash install-mac.sh --uninstall
  6. If you see a "command not found: nexus" error after install, reload your shell:
    source ~/.zshrc    # zsh (default on macOS Catalina+)
    source ~/.bash_profile  # bash

Configuration & environment

The CLI stores credentials in ~/.nexusai/config.json. You can override any setting with environment variables — useful for CI/CD pipelines.

  1. View the current CLI configuration:
    cat ~/.nexusai/config.json
    # Output:
    # {
    #   "apiUrl": "https://nexusai.run",
    #   "token": "nxk_...",
    #   "tokenId": "tok_..."
    # }
  2. Override settings with environment variables (takes precedence over config file):
    export NEXUSAI_API_URL=https://nexus.yourcompany.com
    export NEXUSAI_TOKEN=nxk_your_token_here
  3. In CI/CD pipelines (GitHub Actions, GitLab CI, etc.) set the token as a secret:
    # GitHub Actions example:
    - name: Deploy with NEXUS AI CLI
      env:
        NEXUSAI_TOKEN: ${{ secrets.NEXUSAI_TOKEN }}
      run: |
        nexus deploy redeploy my-app --wait
  4. Reset config by logging out (this revokes the token and removes the config file):
    nexus auth logout
  5. Manually delete config to start fresh (without revoking the token):
    rm -rf ~/.nexusai

Installation troubleshooting

command not found: nexus after install

The npm global bin directory is not in your PATH. Find the directory with "npm bin -g", add it to your shell profile, then reload.

npm bin -g            # e.g. /usr/local/bin or /home/user/.local/bin
export PATH="$(npm bin -g):$PATH"
source ~/.bashrc      # or ~/.zshrc on macOS
Node.js version is too old (< v18)

The CLI requires Node.js 18 or later. Use nvm to switch versions without affecting your system Node.

# Install nvm
curl -fsSL https://raw.githubusercontent.com/nvm-sh/nvm/v0.39.7/install.sh | bash
source ~/.bashrc
# Install and use Node 20 LTS
nvm install 20
nvm use 20
nvm alias default 20
# Then reinstall
npm install -g nexusapp-cli
EACCES: permission denied when running npm install -g

Your global npm prefix is owned by root. Fix this by changing the npm prefix to a user-writable directory instead of using sudo.

# Option 1 — change npm prefix (recommended)
mkdir -p ~/.npm-global
npm config set prefix ~/.npm-global
export PATH="$HOME/.npm-global/bin:$PATH"
npm install -g nexusapp-cli

# Option 2 — use sudo (not recommended)
sudo npm install -g nexusapp-cli
SSL certificate error on corporate networks

Your network uses a custom CA certificate. Configure npm to trust it, or set the NODE_EXTRA_CA_CERTS environment variable.

export NODE_EXTRA_CA_CERTS=/path/to/corporate-ca.crt
npm install -g nexusapp-cli
How do I update the CLI to a newer version?

Run the installer script again — it will upgrade to the latest release. Or update directly via npm.

# Re-run the installer (Linux)
curl -fsSL https://nexusai.run/install.sh | bash

# Or via npm
npm update -g nexusapp-cli

# Check current version
nexus --version
How do I install a specific version?

Pass the version tag to npm install.

npm install -g [email protected]

Authentication

The CLI uses browser-based login (like GitHub CLI) to obtain a persistent access token.

  1. Log in interactively — opens your browser to complete authentication:
    nexus auth login
  2. Point to a self-hosted instance:
    nexus auth login --api-url http://localhost:3001 --web-url http://localhost:3002
  3. Use a pre-existing nxk_* token directly (useful for CI/CD bootstrap):
    nexus auth login --token nxk_abc123...
  4. Check who you are logged in as:
    nexus auth whoami
  5. Log out and revoke the token:
    nexus auth logout
  6. For CI/CD pipelines, skip interactive login entirely with environment variables:
    export NEXUSAI_TOKEN=nxk_your_token_here
    export NEXUSAI_API_URL=https://nexusai.run
    nexus deploy list

CLI App Builder

Build apps with AI from the terminal. The CLI Builder shares projects, files, and checkpoints with the browser AI App Builder.

  1. Start a new app. Your first prompt creates the project; keep the project ID it prints to resume later.
    nexus builder chat
    # or in one step:
    nexus builder new "Build an issue tracker with filters and a detail view"
  2. Resume an app, and choose the AI provider and model (inside chat, /provider and /model show numbered choices):
    nexus builder chat --project <project-id>
    nexus builder providers
  3. Use your own editor as the IDE: dev keeps a local folder in live two-way sync with the Builder. Saved edits become checkpoints, AI changes appear in the folder, and prompts typed at dev> run on your latest code.
    nexus builder dev --project <project-id> --dir ./my-app --open
  4. Edits on both sides are merged. Lines you and the AI both changed get git-style <<<<<<< local / >>>>>>> nexus markers; a file with markers is never uploaded and syncs once you resolve it. For one sync pass (scripts, occasional use):
    nexus builder sync --project <project-id> --dir ./my-app
  5. Check syntax and local imports, and let the AI fix what it finds:
    nexus builder check --project <project-id>
    nexus builder fix --project <project-id> --attempts 2
  6. List and restore checkpoints, and open the browser preview:
    nexus builder versions --project <project-id>
    nexus builder revert <message-id> --project <project-id>
    nexus builder open --project <project-id>
  7. Deploy the current snapshot when you are ready. Nothing deploys automatically.
    nexus builder deploy --project <project-id> --name my-app --provider docker
  8. Explicit one-way copies and single-file changes are still available: pull, push, put, and rm. .git, node_modules, build output, and .env files never sync. Limits: 200 files and 2 MB of text.
    nexus builder pull --project <project-id> --out ./my-app
    nexus builder push --project <project-id> --from ./my-app
  9. Step by step walkthrough with a full example app: https://nexusai.run/kb/cli-app-builder. Complete command reference: https://github.com/nexusrun/nexusai/wiki/CLI

Deploy from a container image

Use nexus deploy create to deploy any pre-built container image.

  1. Deploy nginx:latest on Docker:
    nexus deploy create --image nginx:latest --port 80 --name my-site --provider docker
  2. Deploy to Google Cloud Run and wait for it to go live:
    nexus deploy create \
      --image node:20-alpine \
      --port 3000 \
      --name api-prod \
      --provider gcp_cloud_run \
      --env NODE_ENV=production \
      --env PORT=3000 \
      --wait
  3. Available providers: docker, gcp_cloud_run, aws_ecs_fargate, azure_container_apps.
  4. Images must include a tag and use an allowed base (node:, nginx:, python:, alpine:, ubuntu:, debian:, postgres:, redis:, mongo:, mysql:, httpd:, php:, ruby:, golang:, rust:, gcc:).

Deploy from a Git repository

Use nexus deploy source to build and deploy directly from a repo — no Dockerfile required.

  1. Deploy a public GitHub repo:
    nexus deploy source --repo https://github.com/you/app --name my-app --wait
  2. Specify branch, framework, and build commands:
    nexus deploy source \
      --repo https://github.com/you/api \
      --branch main \
      --framework node \
      --install-command "npm ci" \
      --build-command "npm run build" \
      --start-command "node dist/index.js" \
      --environment PRODUCTION \
      --wait
  3. Deploy a private repo using a stored secret token:
    # First store the token as a secret
    nexus secret create --name GITHUB_TOKEN --environment production
    
    # Then deploy referencing that secret
    nexus deploy source \
      --repo https://github.com/you/private-app \
      --repo-secret GITHUB_TOKEN \
      --wait
  4. Auto-destroy a staging environment after 4 hours:
    nexus deploy source \
      --repo https://github.com/you/app \
      --branch feature/new-ui \
      --environment STAGING \
      --auto-destroy 4 \
      --wait
  5. Deploy one app from a repo that holds several, such as separate frontend/ and backend/ folders. --root-dir names the folder to build; deploy each folder as its own deployment. In the dashboard, set Root Directory in the deploy form.
    nexus deploy source \
      --repo https://github.com/you/shop \
      --root-dir backend \
      --name shop-api \
      --services postgres \
      --wait
    
    nexus deploy source \
      --repo https://github.com/you/shop \
      --root-dir frontend \
      --name shop-web \
      --env VITE_API_URL=https://shop-api.nexusai.run \
      --wait

Manage deployments

All commands accept a deployment name or UUID interchangeably.

  1. List all deployments (shows name and ID):
    nexus deploy list
    nexus deploy list --status RUNNING
    nexus deploy list --project <project-id>
  2. Get full details for a deployment:
    nexus deploy get my-app
  3. Watch live status updates every 3 seconds:
    nexus deploy status my-app --watch
  4. Stream logs in real time:
    nexus deploy logs my-app --follow
    nexus deploy logs my-app --type build --lines 200
  5. Stop, start, or delete. Stop is a soft stop that preserves containers, attached volumes, and network config; start rehydrates the same configuration without rebuilding. Delete is the only one that removes volumes and reserved ports.
    nexus deploy stop my-app
    nexus deploy start my-app
    nexus deploy delete my-app --yes
  6. Scale replicas up or down (1–10):
    nexus deploy scale my-app 3
  7. Extend, reduce, or disable auto-destroy without restarting the deployment:
    nexus deploy auto-destroy my-app --in 4h
    nexus deploy auto-destroy my-app --at 2026-05-19T04:00:00Z
    nexus deploy auto-destroy my-app --off
  8. Redeploy with the same config (triggers a fresh build for source deployments):
    nexus deploy redeploy my-app --wait
  9. Roll back to the previous version:
    nexus deploy rollback my-app
    # Roll back to a specific prior deployment:
    nexus deploy rollback my-app --target <old-deployment-id>

Copy files into a running deployment and execute commands

Use nexus cp and nexus exec for LOCAL_DOCKER deployments when you need to inspect a running container, patch a single file, verify runtime state, or send a reload signal without rebuilding the image.

Which deployment providers support nexus cp and nexus exec?

These commands intentionally support LOCAL_DOCKER deployments only. Google Cloud Run, AWS App Runner, and Azure Container Apps do not expose a normal container shell or Docker copy target through NEXUS AI.

Can I copy a whole directory with nexus cp?

Not directly. nexus cp is single-file copy by design. For directory trees, tar the directory and extract it with nexus exec, or copy a tarball and unpack it inside the container.

tar -czf assets.tar.gz ./assets
nexus cp ./assets.tar.gz my-app:/tmp/assets.tar.gz
nexus exec my-app tar -xzf /tmp/assets.tar.gz -C /app/public
Is nexus exec interactive?

No. nexus exec is batch execution: it runs a command, captures stdout and stderr, and returns the result. There is no interactive TTY yet. Long-running commands should use --timeout.

nexus exec my-app --timeout 120000 sh -c "python manage.py migrate"
How much output can nexus exec return?

Each call has a 2MB stdout and stderr cap. For large output, redirect or pipe to a file inside the container and read the portion you need.

nexus exec my-app sh -c "my-command 2>&1 | tee /tmp/command.log"
nexus exec my-app sh -c "tail -n 200 /tmp/command.log"
Will copied files survive a redeploy or rollback?

No. Files copied into a running container are runtime changes. They can be lost when the container is recreated, scaled, redeployed, rolled back, or replaced. Always commit durable changes to the app source or image.

Secrets management

  1. List all secrets (values are never shown):
    nexus secret list
    nexus secret list --environment production
  2. Create a secret (prompted securely if --value is omitted):
    nexus secret create --name DATABASE_URL --environment production
    # or inline (not recommended — stays in shell history):
    nexus secret create --name API_KEY --environment staging --value "sk-abc123"
  3. Update a secret value:
    nexus secret update <secret-id>
  4. Delete a secret:
    nexus secret delete <secret-id> --yes

Project management

  1. List projects:
    nexus project list
  2. Create a project:
    nexus project create --name "Backend API"
  3. Delete a project:
    nexus project delete <project-id> --yes

Custom domains

  1. Add a custom domain to a deployment:
    nexus domain add my-app api.example.com
  2. The CLI prints the DNS TXT record you need to add for ownership verification. After adding it to your DNS provider, trigger verification:
    # List domains to get the domain ID
    nexus domain list my-app
    
    # Verify (DNS changes can take up to 48h)
    nexus domain verify my-app <domain-id>
  3. Remove a domain:
    nexus domain remove my-app <domain-id>

CI/CD integration (GitHub Actions)

Use NEXUSAI_TOKEN and NEXUSAI_API_URL environment variables for non-interactive pipeline use.

  1. Store your token as a GitHub Actions secret (NEXUSAI_TOKEN), then add a deploy step:
    name: Deploy to NEXUS AI
    on:
      push:
        branches: [main]
    
    jobs:
      deploy:
        runs-on: ubuntu-latest
        steps:
          - uses: actions/checkout@v4
    
          - name: Install NEXUS AI CLI
            run: npm install -g nexusapp-cli
    
          - name: Deploy
            env:
              NEXUSAI_TOKEN: ${{ secrets.NEXUSAI_TOKEN }}
              NEXUSAI_API_URL: https://nexusai.run
            run: |
              nexus deploy source \
                --repo ${{ github.repositoryUrl }} \
                --branch ${{ github.ref_name }} \
                --name my-app \
                --environment PRODUCTION \
                --wait
  2. Deploy a Docker image built in the same pipeline:
          - name: Build and push image
            run: |
              docker build -t myregistry/app:${{ github.sha }} .
              docker push myregistry/app:${{ github.sha }}
    
          - name: Deploy to NEXUS AI
            env:
              NEXUSAI_TOKEN: ${{ secrets.NEXUSAI_TOKEN }}
            run: |
              nexus deploy create \
                --image myregistry/app:${{ github.sha }} \
                --port 8080 \
                --name api-prod \
                --provider gcp_cloud_run \
                --wait

Configuration reference

Where is the config file stored?

After login, credentials are saved to ~/.nexusai/config.json with mode 0600 (owner read/write only). The file contains apiUrl, token, and tokenId.

cat ~/.nexusai/config.json
Which environment variables does the CLI respect?

NEXUSAI_TOKEN overrides the saved token (useful in CI/CD). NEXUSAI_API_URL overrides the saved API base URL. NEXUSAI_WEB_URL overrides the frontend URL used during browser login.

NEXUSAI_TOKEN=nxk_... NEXUSAI_API_URL=https://nexusai.run nexus deploy list
How do I use --json for scripting?

Every read command supports --json to output raw API data, making it easy to pipe into jq or other tools.

nexus deploy list --json | jq '.[] | {name, status, url}'
How do I skip confirmation prompts in scripts?

Pass --yes to any destructive command (stop, delete, rollback, redeploy, domain remove) to skip the interactive confirmation.

nexus deploy delete old-app --yes
nexus deploy stop my-app --yes

Troubleshooting

Cannot reach NEXUS AI API

The CLI cannot connect to the API. Check the API URL in your config or set NEXUSAI_API_URL to the correct address.

cat ~/.nexusai/config.json
# Fix:
nexus auth login --api-url http://localhost:3001 --web-url http://localhost:3002
Session expired. Run 'nexus auth login'

Your access token was revoked or expired. Log in again to get a fresh token.

nexus auth logout
nexus auth login
Insufficient scope error

The token was created with the wrong scopes. Log out and back in — the browser auth page now creates tokens with all required scopes automatically.

nexus auth logout
nexus auth login
Deployment not found: "my-app"

The name does not match any deployment in your organization. Run nexus deploy list to see all deployment names and IDs.

nexus deploy list
Security validation failed: Base image not allowed

Images must include a tag (e.g. nginx:latest, not nginx). Allowed base images: node:, python:, nginx:, alpine:, ubuntu:, debian:, postgres:, redis:, mongo:, mysql:, httpd:, php:, ruby:, golang:, rust:, gcc:.

# Wrong:
nexus deploy create --image nginx --port 80
# Correct:
nexus deploy create --image nginx:latest --port 80

Troubleshooting

Fix common build and deployment failures.

npm install failed (exit code 1)

The most common build failure — dependency installation exits with a non-zero code.

How do I see the full npm error output?

Pull the build logs from the dashboard or CLI. The logs stream the complete Docker build output including every line npm printed before it failed.

nexus deploy logs <deployment-name> --build
package-lock.json is out of sync with package.json

Both npm ci and npm ci --legacy-peer-deps fail when the lockfile was generated in a different state than the current package.json. Regenerate the lockfile locally and commit it.

rm package-lock.json
npm install
git add package-lock.json
git commit -m "regenerate package-lock.json"
nexus deploy redeploy <deployment-name>
Peer dependency conflict beyond --legacy-peer-deps

Two or more packages declare incompatible peer dependencies. Identify the conflict from the npm output (look for ERESOLVE lines), then use overrides in package.json to force a compatible version.

// package.json
{
  "overrides": {
    "conflicting-package": "^3.0.0"
  }
}
Private npm package returning 404 or 403

Your project depends on a private registry package and the build environment has no credentials. Store your npm token as a NEXUS AI secret and add an .npmrc at the project root.

# Step 1 — store token
nexus secret set NPM_TOKEN "your-npm-token" --environment production

# Step 2 — .npmrc at project root
//registry.npmjs.org/:_authToken=${NPM_TOKEN}

# For GitHub Packages:
//npm.pkg.github.com/:_authToken=${NPM_TOKEN}
@your-org:registry=https://npm.pkg.github.com
Transient npm registry timeout or 503

The npm registry was temporarily unavailable. Retry the deployment — these failures resolve on their own.

nexus deploy redeploy <deployment-name>

Next.js: build command resolves to none / next dev in production

NEXUS AI detected Next.js but could not resolve a build script, so it fell back to the development server.

Why does it say "build: none, start: next dev"?

NEXUS AI reads scripts.build and scripts.start from your package.json to resolve build and start commands. If scripts.build is missing, it cannot run next build and skips the build step entirely, falling back to next dev at runtime.

How do I fix it?

Add build and start scripts to package.json, commit the change, and redeploy.

// package.json
{
  "scripts": {
    "dev": "next dev",
    "build": "next build",
    "start": "next start -H 0.0.0.0 -p 3000"
  }
}
Why is next dev a problem in production?

next dev is the development server — it compiles pages on every request, exposes source maps, and uses significantly more memory. Running it in production leads to slow responses, high memory usage, and source code exposure in the browser.

My Next.js build runs out of memory

Large apps can exhaust the default Node.js heap during next build. Increase the memory limit and optionally enable standalone output mode to reduce the final image size.

// package.json
{
  "scripts": {
    "build": "NODE_OPTIONS='--max-old-space-size=4096' next build"
  }
}

// next.config.js — standalone output
module.exports = { output: 'standalone' };

Docker build timeout or OOM kill (exit code 137)

The build process was killed before it completed — usually an out-of-memory kill or oversized build context.

What does exit code 137 mean?

Exit code 137 means the process was killed by the OS — typically an out-of-memory (OOM) event during the Docker build. Large dependency installs or native module compilation are the most common triggers.

How do I reduce build context size?

Add a .dockerignore file to exclude large directories from being sent to the build. This significantly reduces build time and memory usage.

# .dockerignore
node_modules
.next
dist
build
.git
*.log
coverage
.env*
.env.local
Native module compilation fails (canvas, sharp, bcrypt)

Native modules require system build tools (python3, make, g++). NEXUS AI automatically detects and installs build dependencies for known native modules. If your module is not detected, open a support ticket with your deployment ID and the full build log.

About NEXUS AI

NEXUS AI is an agentic AI app builder and full-stack deployment platform. Explore the AI App Builder, learn more on the About page, read the documentation, or contact the team through nexusai.run/contact.

Start for free · Read the documentation · About NEXUS AI · Contact