> ## Documentation Index
> Fetch the complete documentation index at: https://lightdash-mintlify-a500dcd2.mintlify.site/llms.txt
> Use this file to discover all available pages before exploring further.

# Self-hosting

> Configure your self-hosted Lightdash instance to run Data apps.

<Info>
  Data apps are an **enterprise** feature. You'll need a valid `LIGHTDASH_LICENSE_KEY` set on your instance before any of the configuration below takes effect.
</Info>

Data apps are AI-generated React code, produced inside an isolated [E2B](https://e2b.dev/) sandbox, built with Vite, and stored in an S3-compatible bucket. To enable the feature on a self-hosted Lightdash instance you need to bring your own E2B and Claude credentials (via Anthropic or AWS Bedrock), and point Lightdash at a bucket it can write to.

## Prerequisites

* **Enterprise license** - `LIGHTDASH_LICENSE_KEY` must be set on your instance.
* **S3-compatible storage** - a bucket Lightdash can write to for app source and built artifacts. If your instance isn't already using S3, [set that up first](/self-host/customize-deployment/configure-lightdash-to-use-external-object-storage).
* **An E2B account** - sign up at [e2b.dev](https://e2b.dev/) and create an API key. E2B is the sandbox provider we use to build the apps.
* **A Claude provider** - either an [Anthropic](https://console.anthropic.com/) API key or an [AWS Bedrock](https://aws.amazon.com/bedrock/) account with Claude Sonnet access enabled. Claude is the model that writes the React code inside the sandbox.

## Configuration

Add the following environment variables to your Lightdash deployment:

| Variable               | Example                        | Purpose                                                                                                                                      |
| ---------------------- | ------------------------------ | -------------------------------------------------------------------------------------------------------------------------------------------- |
| `APPS_RUNTIME_ENABLED` | `true`                         | Main switch for the feature.                                                                                                                 |
| `APPS_S3_BUCKET`       | `lightdash-apps`               | Bucket Lightdash will write app source and built artifacts to. Falls back to `S3_BUCKET` if unset - set this if you want a dedicated bucket. |
| `E2B_API_KEY`          | `<your-e2b-api-key>`           | Your [E2B](https://e2b.dev/) API key. E2B is the sandbox provider where we generate and build the apps.                                      |
| `E2B_TEMPLATE_NAME`    | `lightdash/lightdash-data-app` | Lightdash's public E2B template - pulls our prebuilt sandbox image so you don't have to build one yourself.                                  |

You also need to configure a Claude provider. Pick one of the two options below.

### Option A: Anthropic (default)

| Variable            | Example                    | Purpose                                                                                                                                     |
| ------------------- | -------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------- |
| `ANTHROPIC_API_KEY` | `<your-anthropic-api-key>` | Your [Anthropic](https://console.anthropic.com/) API key. Used when `AI_DEFAULT_PROVIDER` is unset or set to anything other than `bedrock`. |

### Option B: AWS Bedrock

Set `AI_DEFAULT_PROVIDER=bedrock` to route data app generation through AWS Bedrock instead of the Anthropic API. Use a region where Claude Sonnet access is enabled on your AWS account.

| Variable                    | Example                   | Purpose                                                                                         |
| --------------------------- | ------------------------- | ----------------------------------------------------------------------------------------------- |
| `AI_DEFAULT_PROVIDER`       | `bedrock`                 | Switches both AI Analyst and data apps to Bedrock.                                              |
| `BEDROCK_REGION`            | `us-east-1`               | **(Required)** AWS region with Claude Sonnet access enabled.                                    |
| `BEDROCK_API_KEY`           | `<your-bedrock-api-key>`  | Bedrock API key (bearer token). Simplest option - use this *or* the IAM keys below, not both.   |
| `BEDROCK_ACCESS_KEY_ID`     | `<aws-access-key-id>`     | AWS access key ID. Use with `BEDROCK_SECRET_ACCESS_KEY` as an alternative to `BEDROCK_API_KEY`. |
| `BEDROCK_SECRET_ACCESS_KEY` | `<aws-secret-access-key>` | AWS secret access key paired with `BEDROCK_ACCESS_KEY_ID`.                                      |
| `BEDROCK_SESSION_TOKEN`     | `<aws-session-token>`     | Optional. AWS session token for temporary IAM credentials.                                      |

The Bedrock credentials are the same ones used by AI Analyst - see [AWS Bedrock configuration](/self-host/customize-deployment/environment-variables#aws-bedrock-configuration) for the full reference. The sandbox firewall is automatically updated to allow outbound traffic to the Bedrock runtime hosts for your region.

Restart the backend. The "Data apps" entry will appear in the **New** menu for users with the appropriate permission scope.

### Optional configuration

| Variable           | Default                                     | Purpose                                                                                                                                                                                                                                                                                                                                                     |
| ------------------ | ------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `E2B_TEMPLATE_TAG` | Running Lightdash version (e.g. `0.2917.1`) | Pins the sandbox image to a specific tag of the E2B template. Each Lightdash release publishes a matching tag so the backend and sandbox stay in sync. You can override this to roll back to a previous build (e.g. `E2B_TEMPLATE_TAG=0.2916.0`) or set it to an empty string to use the template's `default` tag. Most operators don't need to touch this. |

### Custom dependencies

Data apps can [declare their own npm dependencies](/guides/data-apps#declared-dependencies) alongside the sandbox template's built-in library set. Because installing third-party packages is a supply-chain capability, the feature is gated at three layers — all three must pass for an upload to declare dependencies:

1. **Instance env flag** (this page): `LIGHTDASH_APP_CUSTOM_DEPENDENCIES_ENABLED=true`. Off by default. Also acts as an instance-wide kill-switch — see below.
2. **Per-organization feature flag**: `enable-data-app-custom-dependencies`. Lets Lightdash Cloud enable the feature for specific orgs without instance-wide exposure. On single-org self-hosted instances, add it to `LIGHTDASH_ENABLE_FEATURE_FLAGS` to turn it on globally.
3. **Admin-only scope**: `manage:DataAppDependency` (see [Permissions](#permissions)). Required to add or change custom dependencies specifically; template-only uploads are unaffected.

Template-only uploads always succeed regardless of these settings.

| Variable                                      | Default              | Purpose                                                                                                                                                                                                                                                                                                                                                                                                         |
| --------------------------------------------- | -------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `LIGHTDASH_APP_CUSTOM_DEPENDENCIES_ENABLED`   | `false`              | Master switch for custom dependencies. When `false`, uploads that declare a non-empty dependency set are rejected at the API, and builds or AI iterations of versions that already have stored custom dependencies also refuse to run — flipping the toggle back to `false` is a hard stop that also blocks sandbox restores of previously-approved dependency sets. Template-only uploads are always accepted. |
| `LIGHTDASH_APP_DEPENDENCY_REGISTRY_HOSTS`     | `registry.npmjs.org` | Comma-separated list of npm registry hostnames added to the sandbox egress allowlist when a version has custom dependencies. Use this to point at an internal mirror. Template-only builds never gain these hosts.                                                                                                                                                                                              |
| `LIGHTDASH_APP_DEPENDENCY_INSTALL_TIMEOUT_MS` | `120000` (2 minutes) | Timeout in milliseconds for the `pnpm install` step that runs before the Vite build when a version has custom dependencies. Raise this if your registry is slow, or lower it to fail faster in CI-style setups.                                                                                                                                                                                                 |

Turning `LIGHTDASH_APP_CUSTOM_DEPENDENCIES_ENABLED` back off is a full kill-switch: it stops installs on every path, including new uploads, AI-iterate carry-forward builds, and sandbox restores of versions whose dependency sets were previously approved. Use it if you need to disable third-party installs on the instance without redeploying app source.

### Upload-time dependency checks

Two optional guards run on uploads that pass the gates above. Both apply to the resolved lockfile (direct + transitive), so a malicious transitive dependency is caught even if the top-level package looks fine.

| Variable                                         | Default   | Purpose                                                                                                                                                                                                                                                                                                                                                                                                         |
| ------------------------------------------------ | --------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `LIGHTDASH_APP_DEPENDENCY_MALWARE_CHECK_ENABLED` | `true`    | Screens every resolved package in the lockfile against the [OSV](https://osv.dev/) malicious-packages feed and rejects the upload if any version carries a `MAL-` advisory. Precise (near-zero false positives) and defaults on for that reason. **Fails closed** — if `api.osv.dev` can't be reached the upload is rejected. Set to `false` on air-gapped instances or during an OSV outage to keep uploading. |
| `LIGHTDASH_APP_DEPENDENCY_MIN_RELEASE_AGE_DAYS`  | `0` (off) | Minimum age in days a resolved dependency's version must have since publication on npm. Guards against freshly published, potentially compromised versions before advisory feeds catch up. Off by default because it adds registry round-trips and can block legitimate recent releases; `3` is a sensible starting point if you want it on. Fails closed when a publish date can't be verified.                |

## Costs

Self-hosting Data apps means you pay E2B and your Claude provider directly:

* **E2B** bills per sandbox-second. A typical build runs for 1–15 minutes; sandboxes are paused between iterations and resumed on follow-up prompts.
* **Anthropic or AWS Bedrock** bills per token. Each generation sends the project's dbt catalog and the user's prompt to Claude, plus any attached charts, dashboards, or images.

Both providers expose usage dashboards. We recommend setting spend limits on both before rolling the feature out to your users.

## Permissions

Data apps follow the same space-based permission model as charts and dashboards. The relevant scopes (`view:DataApp`, `create:DataApp`, `manage:DataApp`) are bundled into the default system roles - but on enterprise instances using custom roles, you'll need to grant them explicitly. See [Custom roles](/references/workspace/custom-roles) for details.

Adding [custom npm dependencies](#custom-dependencies) to an app requires an additional scope, `manage:DataAppDependency`, which is granted to admins only in the default role set. This is deliberate — declaring third-party packages is a supply-chain capability distinct from uploading a template-only app. Grant it to a custom role only when you're comfortable with those users choosing which packages your build sandbox pulls from your configured registry.

## Troubleshooting

**The "Data apps" entry doesn't appear in the New menu.**
Check that `APPS_RUNTIME_ENABLED=true`, `LIGHTDASH_LICENSE_KEY` is set, and the signed-in user has the `create:DataApp` scope.

**Builds fail immediately with a sandbox creation error.**
Verify `E2B_API_KEY` is valid and that your E2B account has access to the `lightdash/lightdash-data-app` template. If you've overridden `E2B_TEMPLATE_TAG`, double-check the tag exists.

**Builds fail mid-generation with an Anthropic error.**
Check your Anthropic account usage limits and confirm `ANTHROPIC_API_KEY` is valid. Long-running generations can hit rate limits on lower-tier Anthropic plans.

**Builds fail mid-generation with a Bedrock error.**
Confirm `BEDROCK_REGION` is set to a region where Claude Sonnet access is enabled, and that either `BEDROCK_API_KEY` or the `BEDROCK_ACCESS_KEY_ID` / `BEDROCK_SECRET_ACCESS_KEY` pair is valid. If you use IAM credentials, the principal must have permission to invoke Claude models on Bedrock.
