Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion _data/shared_chrome.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"$schema": "https://www.metabase.com/shared/chrome.schema.json",
"version": 1,
"generated_at": "2026-07-28T00:38:40+00:00",
"generated_at": "2026-07-28T20:04:12+00:00",
"origin": "https://www.metabase.com",
"stylesheets": [
{
Expand Down
15 changes: 13 additions & 2 deletions _docs/latest/api.json
Original file line number Diff line number Diff line change
Expand Up @@ -22560,7 +22560,7 @@
"get" : {
"operationId" : "get-api-database-id-schema",
"summary" : "GET /api/database/{id}/schema",
"description" : "Return a list of Tables for a Database whose `schema` is `nil` or an empty string.\n\n Optional filters:\n - `can-query=true` - filter to only tables the user can query\n - `can-write-metadata=true` - filter to only tables the user can edit metadata for",
"description" : "Return a list of Tables for a Database whose schema is the `schema` query parameter, or `nil` or an\n empty string when no `schema` is given. Unlike the `/:id/schema/:schema` route, the query parameter\n supports schema names containing slashes, which are rejected at the HTTP layer when percent-encoded in\n the URL path (#77353).\n\n Optional filters:\n - `can-query=true` - filter to only tables the user can query\n - `can-write-metadata=true` - filter to only tables the user can edit metadata for",
"parameters" : [ {
"in" : "path",
"name" : "id",
Expand All @@ -22570,6 +22570,17 @@
"minimum" : 1
},
"description" : "value must be an integer greater than zero."
}, {
"in" : "query",
"name" : "schema",
"required" : false,
"schema" : {
"oneOf" : [ {
"type" : "string"
}, {
"type" : "null"
} ]
}
}, {
"in" : "query",
"name" : "include_hidden",
Expand Down Expand Up @@ -22646,7 +22657,7 @@
"get" : {
"operationId" : "get-api-database-id-schema-schema",
"summary" : "GET /api/database/{id}/schema/{schema}",
"description" : "Returns a list of Tables for the given Database `id` and `schema`.\n\n Optional filters:\n - `can-query=true` - filter to only tables the user can query\n - `can-write-metadata=true` - filter to only tables the user can edit metadata for",
"description" : "Returns a list of Tables for the given Database `id` and `schema`.\n\n Schema names containing slashes, backslashes, or percent signs are rejected at the HTTP layer when\n percent-encoded in the URL path; pass those as the `schema` query parameter of `GET /:id/schema/`\n instead (#77353).\n\n Optional filters:\n - `can-query=true` - filter to only tables the user can query\n - `can-write-metadata=true` - filter to only tables the user can edit metadata for",
"parameters" : [ {
"in" : "path",
"name" : "id",
Expand Down
2 changes: 2 additions & 0 deletions _docs/latest/dashboards/introduction.md
Original file line number Diff line number Diff line change
Expand Up @@ -336,6 +336,8 @@ If your Metabase administrator has enabled [public sharing](../embedding/public-

Public links can be viewed by anyone, even if they don't have access to Metabase. You can also use the public embedding code to embed your question or dashboard in a simple web page or blog post. Check out examples of simple apps with embedded dashboards in our [embedding-reference-apps repository](https://github.com/metabase/embedding-reference-apps). To learn more about [embedding](../embedding/introduction), check out our article on [How to use Metabase to deliver analytics to your customers](/learn/metabase-basics/embedding/overview), as well as an article on how to combine branding, Single Sign-On, full app embedding, and row and column security to deliver [multi-tenant, self-service analytics](/learn/metabase-basics/embedding/multi-tenant-self-service-analytics).

Admins can also [create an account](../people-and-groups/managing#creating-an-account) for someone and point them to a specific dashboard or question. On a dashboard or question, click the **Sharing** icon and select **Invite someone to view this**.

## Exporting results from a dashboard

You can export the entire dashboard as PDF, or export results of individual questions on the dashboard. See [Exporting results](../questions/exporting-results).
Expand Down
4 changes: 3 additions & 1 deletion _docs/latest/data-studio/transforms/addons.md
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ With basic transforms, you can:

- **Metabase Cloud**: Basic transform functionality on Metabase Cloud - Starter, Pro, or Enterprise - comes with an additional small fee per successful transform run, see [Pricing](/pricing).

Only people logged in with an email of a [Metabase Store admin](../../cloud/accounts-and-billing#add-managers) (not just Metabase _instance_ admins) can [enable basic transforms](./transforms-overview#enable-transforms).
Only people logged in with an email of a [Metabase Store admin](../../cloud/accounts-and-billing#add-managers) (not just Metabase _instance_ admins) can [enable basic transforms](./transforms-overview#enable-transforms).

### Cancel basic transforms

Expand Down Expand Up @@ -77,6 +77,8 @@ The Advanced transforms add-on comes with an additional charge per successful tr

To enable Advanced transforms functionality, you need to have [Basic transforms](#basic-transforms) already, see [Enable basic transforms](#enable-basic-transforms).

For the full self-hosted setup see [Set up transforms on a self-hosted Metabase](transforms-overview#set-up-transforms-on-a-self-hosted-metabase).

There are two ways to enable Advanced transforms:

- **From your Metabase instance**: you can navigate to a feature requiring advanced transforms (like Python transforms or transform inspector), and follow the prompts to upgrade.
Expand Down
146 changes: 66 additions & 80 deletions _docs/latest/data-studio/transforms/python-runner.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ To run Python transforms from a self-hosted Metabase, you'll need to configure a

## Prerequisites

- Docker installed and running.
- Docker installed and running, or an infrastructure that can run containers.
- **Self-hosted Metabase Pro or Enterprise license** (Python Runner requires a Pro/Enterprise plan).
- For production: an S3-compatible storage bucket (AWS S3, MinIO, etc.).

Expand Down Expand Up @@ -80,13 +80,13 @@ docker network create metabase-network
docker run -d \
--network metabase-network \
-e AUTH_TOKEN=your-secure-token-here \
--name python-runner metabase/python-runner:latest
--name python-runner --hostname python-runner metabase/python-runner:latest

docker run -d \
--network metabase-network \
-p 3000:3000 \
-e MB_PYTHON_RUNNER_URL=http://python-runner:5000 \
-e MB_PYTHON_RUNNER_API_TOKEN=your-secure-token-here \
-e MB_PYTHON_RUNNER_API_TOKEN=<your-secure-token-here> \
-e MB_PYTHON_STORAGE_S_3_ENDPOINT=https://s3.amazonaws.com \
-e MB_PYTHON_STORAGE_S_3_BUCKET=your-bucket-name \
-e MB_PYTHON_STORAGE_S_3_REGION=us-east-1 \
Expand All @@ -108,24 +108,27 @@ docker run -d \

These settings can also be configured in the Metabase UI at **Admin** > **Settings** > **Python Runner**. Note that environment variables take precedence over UI settings.

| Variable | Description |
| ----------------------------------------- | ---------------------------------------------------------------------------------- |
| `MB_PYTHON_RUNNER_URL` | URL where Metabase can reach the Python Runner (e.g., `http://python-runner:5000`) |
| `MB_PYTHON_RUNNER_API_TOKEN` | Authentication token. Must match `AUTH_TOKEN` in the Python Runner. |
| `MB_PYTHON_STORAGE_S_3_ENDPOINT` | S3 endpoint URL. |
| `MB_PYTHON_STORAGE_S_3_BUCKET` | S3 bucket name for storing Python artifacts |
| `MB_PYTHON_STORAGE_S_3_REGION` | AWS region (e.g., `us-east-1`) |
| `MB_PYTHON_STORAGE_S_3_ACCESS_KEY` | S3 access key |
| `MB_PYTHON_STORAGE_S_3_SECRET_KEY` | S3 secret key |
| `MB_PYTHON_STORAGE_S_3_PATH_STYLE_ACCESS` | (Optional) Set to `true` for S3-compatible services like MinIO or LocalStack |
| Variable | Description |
| ------------------------------------------ | ---------------------------------------------------------------------------------- |
| `MB_PYTHON_RUNNER_URL` | URL where Metabase can reach the Python Runner (e.g., `http://python-runner:5000`) |
| `MB_PYTHON_RUNNER_API_TOKEN` | Authentication token. Must match `AUTH_TOKEN` in the Python Runner. |
| `MB_PYTHON_STORAGE_S_3_ENDPOINT` | S3 endpoint URL. |
| `MB_PYTHON_STORAGE_S_3_CONTAINER_ENDPOINT` | S3 endpoint seen from the runner container, if different from the main endpoint. |
| `MB_PYTHON_STORAGE_S_3_BUCKET` | S3 bucket name for storing Python artifacts |
| `MB_PYTHON_STORAGE_S_3_REGION` | AWS region (e.g., `us-east-1`) |
| `MB_PYTHON_STORAGE_S_3_ACCESS_KEY` | S3 access key |
| `MB_PYTHON_STORAGE_S_3_SECRET_KEY` | S3 secret key |
| `MB_PYTHON_STORAGE_S_3_PATH_STYLE_ACCESS` | (Optional) Set to `true` for S3-compatible services like MinIO or LocalStack |

`MB_PYTHON_STORAGE_S_3_CONTAINER_ENDPOINT` is the host Metabase signs into the presigned URLs the runner uploads to and downloads from. Set it when the runner resolves storage by a different hostname than Metabase does.

## Using Docker Compose

Docker Compose simplifies managing multiple containers. Below are example configurations for different scenarios.
Below are example configurations for different scenarios.

### Simple setup with LocalStack
### Self-hosted storage with MinIO

For simple setup and local testing, you can use LocalStack to simulate S3:
[MinIO](https://min.io/) is an S3-compatible server you can run yourself, which makes it a common pick for self-hosted Metabase. This Compose file runs Metabase, the Python runner, MinIO, and a short-lived container that creates the bucket Metabase will use — neither MinIO nor Metabase creates that bucket for you.

```yml
name: metabase-python-runner
Expand All @@ -136,93 +139,76 @@ services:
- "3000:3000"
environment:
- MB_PYTHON_RUNNER_URL=http://python-runner:5000
- MB_PYTHON_RUNNER_API_TOKEN=your-secure-token-here
- MB_PYTHON_STORAGE_S_3_ENDPOINT=http://localstack:4566
- MB_PYTHON_RUNNER_API_TOKEN=${AUTH_TOKEN}
- MB_PYTHON_STORAGE_S_3_ENDPOINT=http://minio:9000
- MB_PYTHON_STORAGE_S_3_CONTAINER_ENDPOINT=http://minio:9000
- MB_PYTHON_STORAGE_S_3_BUCKET=metabase-python-runner
- MB_PYTHON_STORAGE_S_3_REGION=us-east-1
- MB_PYTHON_STORAGE_S_3_PATH_STYLE_ACCESS=true
- MB_PYTHON_STORAGE_S_3_ACCESS_KEY=test
- MB_PYTHON_STORAGE_S_3_SECRET_KEY=test
- MB_PYTHON_STORAGE_S_3_ACCESS_KEY=${MINIO_ROOT_USER}
- MB_PYTHON_STORAGE_S_3_SECRET_KEY=${MINIO_ROOT_PASSWORD}
depends_on:
localstack-init:
minio-init:
condition: service_completed_successfully
python-runner:
condition: service_started

python-runner:
image: metabase/python-runner:latest
environment:
- AUTH_TOKEN=your-secure-token-here
- AUTH_TOKEN=${AUTH_TOKEN}

localstack:
image: localstack/localstack:latest
minio:
image: quay.io/minio/minio:latest
command: server /data --console-address ":9001"
environment:
- SERVICES=s3
healthcheck:
test: ["CMD", "curl", "-f", "http://localhost:4566/_localstack/health"]
interval: 5s
timeout: 5s
retries: 10

localstack-init:
image: localstack/localstack:latest
entrypoint:
["/bin/sh", "-c", "awslocal s3 mb s3://metabase-python-runner || true"]
environment:
- AWS_ENDPOINT_URL=http://localstack:4566
- MINIO_ROOT_USER=${MINIO_ROOT_USER}
- MINIO_ROOT_PASSWORD=${MINIO_ROOT_PASSWORD}
volumes:
- minio-data:/data

minio-init:
image: quay.io/minio/mc:latest
depends_on:
localstack:
condition: service_healthy
minio:
condition: service_started
entrypoint:
- /bin/sh
- -c
- |
until mc alias set local http://minio:9000 "${MINIO_ROOT_USER}" "${MINIO_ROOT_PASSWORD}" >/dev/null 2>&1; do
echo "waiting for minio..."; sleep 2;
done
mc mb --ignore-existing local/metabase-python-runner

volumes:
minio-data: {}
```

Then run:
Both S3 endpoint variables point at `http://minio:9000` because Metabase and the runner share the Compose network and reach MinIO by the same hostname. `MB_PYTHON_STORAGE_S_3_CONTAINER_ENDPOINT` sets the host Metabase signs into the presigned URLs the runner uploads to and downloads from — if your runner resolves storage by a different hostname than Metabase does, set this to the runner's view of it.

Create a `.env` file:

```bash
docker compose up -d
AUTH_TOKEN=your-secure-token-here
MINIO_ROOT_USER=minioadmin
MINIO_ROOT_PASSWORD=minioadmin
```

### Production setup
Then bring everything up and try a transform:

For production, use an external S3-compatible storage service:
1. Put a strong shared secret in `AUTH_TOKEN` (the runner and Metabase have to agree on it):

```yml
name: metabase-python-runner
services:
metabase:
image: metabase/metabase-enterprise:latest
ports:
- "3000:3000"
environment:
- MB_PYTHON_RUNNER_URL=http://python-runner:5000
- MB_PYTHON_RUNNER_API_TOKEN=${AUTH_TOKEN}
- MB_PYTHON_STORAGE_S_3_ENDPOINT=${S3_ENDPOINT}
- MB_PYTHON_STORAGE_S_3_BUCKET=${S3_BUCKET}
- MB_PYTHON_STORAGE_S_3_REGION=${S3_REGION:-us-east-1}
- MB_PYTHON_STORAGE_S_3_ACCESS_KEY=${S3_ACCESS_KEY}
- MB_PYTHON_STORAGE_S_3_SECRET_KEY=${S3_SECRET_KEY}
depends_on:
python-runner:
condition: service_started

python-runner:
image: metabase/python-runner:latest
environment:
- AUTH_TOKEN=${AUTH_TOKEN}
```
```bash
openssl rand -hex 32
```

Create a `.env` file with your configuration:
2. Start the stack:

```bash
AUTH_TOKEN=your-secure-token-here
S3_ENDPOINT=https://s3.amazonaws.com
S3_BUCKET=metabase-python-runner
S3_REGION=us-east-1
S3_ACCESS_KEY=your-access-key
S3_SECRET_KEY=your-secret-key
```
```bash
docker compose up -d
```

Then run:
3. You'll need a Pro or Enterprise license with the [Advanced transforms add-on](addons). In Metabase, [enable transforms](transforms-overview#enable-transforms), then [create a Python transform](python-transforms#create-a-python-transform) and click **Run**.

```bash
docker compose up -d
```
4. Open **Data Studio > Jobs > Runs** and find your run. If it failed, the run's logs will usually tell you whether Metabase couldn't reach the runner, or the runner couldn't reach MinIO.
10 changes: 10 additions & 0 deletions _docs/latest/data-studio/transforms/transforms-overview.md
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,16 @@ Permission configuration for transform depends on your plan.
- To **see** the list of transforms on your instance, people need to be able to access Data Studio, so they need to be either an Admin or a member of the special [Data Analyst group](../../people-and-groups/managing).
- To **execute** transforms on a database, people need to be either Admins on belong to the special [Data Analyst group](../../people-and-groups/managing). Additionally people need to have the [Transform permissions](../../permissions/data) for that database.

## Set up transforms on a self-hosted Metabase

If you run Metabase yourself, here's the path to working transforms:

1. **Check your plan.** [Basic transforms](addons#basic-transforms) (query-based) are included on self-hosted Metabase. [Advanced transforms](addons#advanced-transforms) — Python transforms, the [transform inspector](transform-inspector), and [writable connections](../../databases/writable-connection) — need a self-hosted Pro or Enterprise plan with the Advanced transforms add-on.
2. **Connect a database that can write.** Transforms create and replace tables in your database, so the database user needs create, drop, and write privileges. See [Database users, roles, and privileges](../../databases/users-roles-privileges). For cleaner isolation, point the transform at a [writable connection](../../databases/writable-connection). Only some databases [support transforms](#databases-that-support-transforms).
3. **For Python transforms, set up a runner.** Query-based transforms need nothing extra — they run inside your database. Python transforms run in a separate execution environment, so you'll point Metabase at a [self-hosted Python runner](python-runner) backed by S3-compatible storage (AWS S3, MinIO, and so on).
4. **[Enable transforms](#enable-transforms)** in Data Studio.
5. **Create and run a transform.** [Create a query-based transform](query-transforms#create-a-query-based-transform) or a [Python transform](python-transforms#create-a-python-transform), run it manually, and check the result under **Runs**. Once it works, [schedule it with jobs](jobs-and-runs).

## Enable transforms

Before you can start writing transforms, you'll need to enable transforms in your Metabase instance.
Expand Down
2 changes: 2 additions & 0 deletions _docs/latest/people-and-groups/managing.md
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,8 @@ Click **Create** to activate an account. An account becomes active once you clic

If you’ve already [configured Metabase to use email](../configuring-metabase/email), Metabase will send the person an email inviting them to log into Metabase. If you haven't yet setup email for your Metabase, Metabase will give you a temporary password that you’ll have to manually send to the person.

Admins can also create an account for someone and point them to a specific dashboard or question. On a dashboard or question, click the **Sharing** icon and select **Invite someone to view this**. Enter the person's email, choose their groups, and click **Send invitation**. Once they sign up, Metabase directs them to that dashboard or question.

To create accounts with SSO, check out [authentication options](./start#authentication).

## Editing an account
Expand Down
Loading