Skip to main content
This guide walks you through setting up a local Grafana instance with MotherDuck-DuckDB integration, allowing you to create powerful visualizations and dashboards from your MotherDuck data.

Prerequisites

Before you begin, ensure you have:
  • Docker installed (Installation guide)
  • A MotherDuck token set as an environment variable: motherduck_token
  • The repository cloned locally

Quick Start

The setup process is automated through a setup script that handles plugin installation, Docker configuration, and Grafana deployment.
1

Set your MotherDuck token

Export your MotherDuck token as an environment variable:
export motherduck_token="your_token_here"
The setup script validates this environment variable and will fail if it’s not set.
2

Run the setup script

Execute the automated setup script:
./setup.sh
The script performs the following actions:
  • Detects your OS (macOS, Linux, or Windows)
  • Downloads the latest MotherDuck-DuckDB Grafana plugin from GitHub
  • Checks for existing Grafana containers on port 3000 and removes them
  • Validates port 3000 availability
  • Starts a new Grafana Docker container with the plugin mounted
3

Access Grafana

Once the script completes, access Grafana at:
http://localhost:3000
The default credentials are admin/admin. You’ll be prompted to change the password on first login.

Setup Script Details

The setup.sh script automates the entire deployment process:
#!/bin/bash

set -e
# Constants
PLUGIN_REPO="https://api.github.com/repos/motherduckdb/grafana-duckdb-datasource/releases/latest"
CURRENT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
PROVISIONING_DIR="$CURRENT_DIR/provisioning"

# Detect OS and set plugin directory
case "$(uname -s)" in
Darwin)
  PLUGIN_DIR="$CURRENT_DIR/plugins/motherduck-duckdb-datasource"
  ;;
Linux)
  PLUGIN_DIR="$CURRENT_DIR/plugins/motherduck-duckdb-datasource"
  ;;
CYGWIN* | MINGW* | MSYS*)
  echo "⚠ Windows detected. Please manually unzip the plugin."
  exit 1
  ;;
esac
#!/bin/bash

set -e
# Constants
PLUGIN_REPO="https://api.github.com/repos/motherduckdb/grafana-duckdb-datasource/releases/latest"
CURRENT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
PROVISIONING_DIR="$CURRENT_DIR/provisioning"

# Detect OS and set plugin directory
case "$(uname -s)" in
Darwin)
  PLUGIN_DIR="$CURRENT_DIR/plugins/motherduck-duckdb-datasource"
  ;;
Linux)
  PLUGIN_DIR="$CURRENT_DIR/plugins/motherduck-duckdb-datasource"
  ;;
CYGWIN* | MINGW* | MSYS*)
  echo "⚠ Windows detected. Please manually unzip the plugin into your Grafana plugin folder."
  exit 1
  ;;
*)
  echo "❌ Unsupported OS. Please set PLUGIN_DIR manually."
  exit 1
  ;;
esac

mkdir -p "$PLUGIN_DIR"

# Fetch latest release info
echo "📡 Fetching latest release info..."
ZIP_URL=$(curl -s $PLUGIN_REPO | grep browser_download_url | grep motherduck-duckdb-datasource | grep ".zip" | cut -d '"' -f4 | head -n 1)

if [ -z "$ZIP_URL" ]; then
  echo "❌ Failed to fetch zip URL."
  exit 1
fi

# Download and extract plugin
ZIP_FILE=$(basename "$ZIP_URL")
echo "⬇ Downloading plugin from $ZIP_URL..."
curl -L -o "$ZIP_FILE" "$ZIP_URL"
unzip -o "$ZIP_FILE" -d "$PLUGIN_DIR"
rm -f "$ZIP_FILE"
echo "✅ Plugin extracted to $PLUGIN_DIR and zip removed"

# Check and stop existing Grafana container
CONTAINER_ID=$(docker ps --filter "publish=3000" --filter "name=grafana" --format "{{.ID}}")

if [ -n "$CONTAINER_ID" ]; then
  echo "🛑 Stopping Grafana Docker container running on port 3000..."
  docker stop "$CONTAINER_ID"
  docker rm "$CONTAINER_ID"
  echo "✅ Stopped and removed Grafana container running on port 3000."
else
  echo "ℹ No Grafana container running on port 3000."
fi

# Validate port 3000 availability
if lsof -Pi :3000 -sTCP:LISTEN -t >/dev/null; then
  echo "❌ Port 3000 is already in use. Please free up the port and try again."
  exit 1
fi

# Validate environment variable
if ! printenv motherduck_token >/dev/null 2>&1; then
  echo "❌ Required environment variable 'motherduck_token' is not set." >&2
  exit 1
fi
MOTHERDUCK_TOKEN_VALUE="$(printenv motherduck_token)"

# Start Grafana container
echo "🚀 Starting Grafana Docker container..."
docker run -d \
  --name=grafana \
  -p 3000:3000 \
  -v "$PLUGIN_DIR:/var/lib/grafana/plugins/motherduck-duckdb-datasource" \
  -v "$PROVISIONING_DIR:/etc/grafana/provisioning" \
  -e "GF_PLUGINS_ALLOW_LOADING_UNSIGNED_PLUGINS=motherduck-duckdb-datasource" \
  -e "motherduck_token=${MOTHERDUCK_TOKEN_VALUE}" \
  grafana/grafana:latest-ubuntu

# Wait for container to start
for i in {1..5}; do
  if docker ps --filter "name=grafana" --filter "status=running" | grep -q grafana; then
    echo "✅ Grafana Docker container is running."
    break
  fi
  echo "⏳ Waiting for Grafana Docker container to start... ($i/5)"
  sleep 1
done

if ! docker ps --filter "name=grafana" --filter "status=running" | grep -q grafana; then
  echo "❌ Grafana Docker container failed to start after 5 seconds."
  exit 1
fi

echo "🔗 Grafana is now running at http://localhost:3000"

Data Source Configuration

The setup script automatically configures the MotherDuck data source through provisioning. Here’s the configuration file:
apiVersion: 1
datasources:
  - name: MotherDuck-Sample-Data
    type: motherduck-duckdb-datasource
    access: proxy
    isDefault: true
    editable: true
    jsonData:
      database: "" # Leave blank for MotherDuck
      initSql: "ATTACH IF NOT EXISTS 'md:sample_data'" # you can have multiple initsql.
    secureJsonData:
      token: $__env{motherduck_token}
The initSql field allows you to automatically attach databases when the data source is initialized. You can add multiple databases by including additional ATTACH statements.

Creating Your First Dashboard

1

Navigate to dashboards

From the Grafana home page, click on the “Dashboards” menu item in the left sidebar.
2

Create new dashboard

Click the “New” button and select “New Dashboard”.
3

Add a visualization

Click “Add visualization” and select MotherDuck-DuckDB as your data source.
4

Configure query settings

Important: Set the format to time series at the top of the query builder before writing your query.
Switch from builder to code mode if you’d like to enter SQL manually.
5

Write your query

Enter your SQL query. For example:
SELECT created_date, COUNT(status)
FROM sample_data.nyc.service_requests
GROUP BY created_date LIMIT 1000
6

Save the dashboard

Configure your visualization settings and click “Apply” to add it to your dashboard.

Example Queries

Here are some example queries you can use with the sample data:
SELECT created_date, COUNT(status)
FROM sample_data.nyc.service_requests
GROUP BY created_date 
LIMIT 1000

Sharing Dashboards

If you’ve created a dashboard you want to share with others:
1

Export the dashboard

Click the “Share” or “Export” button on your dashboard. Alternatively, go to dashboard settings and find the “JSON Model” section.
2

Save the JSON file

Copy the JSON and create a file under provisioning/dashboards/json/:
provisioning/dashboards/json/my-dashboard.json
3

Commit and share

Commit the file to your repository:
git add provisioning/dashboards/json/my-dashboard.json
git commit -m "Add my custom dashboard"
git push
4

Create a pull request

Open a pull request to share your dashboard with the team.

Troubleshooting

The script checks for port availability. If port 3000 is in use:
  1. Stop any existing services on port 3000
  2. Or modify the script to use a different port:
    -p 3001:3000
    
If the plugin doesn’t appear in Grafana:
  1. Check that the plugin was downloaded correctly
  2. Verify the Docker volume mount is correct
  3. Ensure unsigned plugins are allowed in the Docker command:
    -e "GF_PLUGINS_ALLOW_LOADING_UNSIGNED_PLUGINS=motherduck-duckdb-datasource"
    
If Grafana cannot connect to MotherDuck:
  1. Verify your motherduck_token environment variable is set
  2. Check that the token is valid and not expired
  3. Look at the Grafana logs:
    docker logs grafana
    
The pre-provisioned dashboards for NYC services and rideshare data are available in provisioning/dashboards/json/ and will automatically load when Grafana starts.

Build docs developers (and LLMs) love