Skip to main content

Publishing Plugins

This guide covers the process of signing, packaging, and publishing Grafana plugins to make them available to the community or within your organization.

Plugin Signing

Grafana requires plugins to be signed to verify their authenticity and integrity. The signing process creates a MANIFEST.txt file that contains checksums of all plugin files.

Signature Levels

Grafana supports different signature levels:
  • Grafana: Official plugins developed by Grafana Labs
  • Commercial: Commercial plugins from verified partners
  • Community: Community plugins verified by Grafana
  • Private: Private plugins for internal organizational use
  • Private Glob: Private plugins with wildcard matching

Signature Status

When loading plugins, Grafana checks the signature status:
  • internal: Core plugin, no signature required (e.g., built-in data sources)
  • valid: Plugin signature is valid and content matches
  • invalid: Signature verification failed
  • modified: Valid signature but plugin content has been modified
  • unsigned: No signature file present
From pkg/plugins/models.go:
const (
    SignatureStatusInternal SignatureStatus = "internal" // core plugin, no signature
    SignatureStatusValid    SignatureStatus = "valid"    // signed and accurate MANIFEST
    SignatureStatusInvalid  SignatureStatus = "invalid"  // invalid signature
    SignatureStatusModified SignatureStatus = "modified" // valid signature, but content mismatch
    SignatureStatusUnsigned SignatureStatus = "unsigned" // no MANIFEST file
)

Signing Your Plugin

Prerequisites

  1. Create a Grafana Cloud account: Required for plugin signing
  2. Generate an access policy token: From Grafana Cloud portal
  3. Install @grafana/sign-plugin: Plugin signing tool
npm install -g @grafana/sign-plugin

Signing Process

  1. Build your plugin:
yarn build
  1. Sign the plugin:
export GRAFANA_ACCESS_POLICY_TOKEN=<your-token>
npx @grafana/sign-plugin
This creates a MANIFEST.txt file in your plugin directory.
  1. Verify the signature:
cat dist/MANIFEST.txt
The manifest contains:
  • Plugin metadata
  • File checksums (SHA256)
  • Signature information
  • Timestamp

Private Plugins

For internal/private plugins, configure Grafana to allow unsigned plugins:
# grafana.ini
[plugins]
allow_loading_unsigned_plugins = myorg-myplugin-datasource,myorg-anotherplugin-panel
Or use environment variable:
GF_PLUGINS_ALLOW_LOADING_UNSIGNED_PLUGINS=myorg-myplugin-datasource
Security Note: Only allow unsigned plugins from trusted sources.

Plugin Packaging

Directory Structure

A complete plugin package:
myorg-myplugin-datasource/
├── dist/
│   ├── module.js              # Compiled frontend code
│   ├── module.js.map
│   ├── img/
│   │   └── logo.svg
│   └── dashboards/            # Optional: bundled dashboards
│       └── overview.json
├── gpx_myorg_myplugin_linux_amd64   # Backend binary (Linux)
├── gpx_myorg_myplugin_darwin_amd64  # Backend binary (macOS)
├── gpx_myorg_myplugin_windows_amd64.exe  # Backend binary (Windows)
├── plugin.json                # Plugin metadata
├── MANIFEST.txt               # Signature file
├── README.md                  # Documentation
├── CHANGELOG.md               # Version history
└── LICENSE                    # License file

Backend Binaries

For backend plugins, include binaries for all supported platforms:
  • Linux: gpx_<plugin-id>_linux_amd64
  • macOS (Intel): gpx_<plugin-id>_darwin_amd64
  • macOS (ARM): gpx_<plugin-id>_darwin_arm64
  • Windows: gpx_<plugin-id>_windows_amd64.exe
Build using Mage or the plugin SDK:
mage -v buildAll

Creating the Archive

Create a ZIP archive:
cd dist
zip -r myorg-myplugin-datasource-1.0.0.zip myorg-myplugin-datasource/
The archive should:
  • Be named <plugin-id>-<version>.zip
  • Contain a single root directory with the plugin ID
  • Include all necessary files and binaries

Publishing to Grafana Plugin Catalog

Requirements

  1. Open source license: Plugin must be open source (Apache 2.0, MIT, etc.)
  2. Public repository: Code hosted on GitHub, GitLab, or similar
  3. README.md: Comprehensive documentation
  4. CHANGELOG.md: Version history
  5. Valid signature: Plugin must be signed
  6. Working plugin: Thoroughly tested

Submission Process

  1. Create a release on GitHub:
git tag -a v1.0.0 -m "Release version 1.0.0"
git push origin v1.0.0
  1. Attach the signed ZIP archive to the GitHub release
  2. Submit to Grafana:
    • Go to grafana.com/plugins
    • Click “Submit a plugin”
    • Fill out the submission form
    • Provide plugin details and repository URL
  3. Review process:
    • Grafana team reviews the plugin
    • May request changes or improvements
    • Approval typically takes 1-2 weeks
  4. Publication:
    • Once approved, plugin appears in the catalog
    • Available for installation via Grafana UI or CLI

Plugin Metadata

Ensure plugin.json has complete information:
{
  "type": "datasource",
  "name": "My Data Source",
  "id": "myorg-mydatasource-datasource",
  "info": {
    "description": "Connect to MyService for data visualization",
    "author": {
      "name": "My Organization",
      "url": "https://github.com/myorg"
    },
    "keywords": ["datasource", "myservice", "metrics"],
    "logos": {
      "small": "img/logo.svg",
      "large": "img/logo.svg"
    },
    "links": [
      {
        "name": "Website",
        "url": "https://myorg.com"
      },
      {
        "name": "Documentation",
        "url": "https://github.com/myorg/grafana-mydatasource-datasource/blob/main/README.md"
      },
      {
        "name": "GitHub",
        "url": "https://github.com/myorg/grafana-mydatasource-datasource"
      },
      {
        "name": "License",
        "url": "https://github.com/myorg/grafana-mydatasource-datasource/blob/main/LICENSE"
      }
    ],
    "screenshots": [
      {
        "name": "Query Editor",
        "path": "img/screenshot-query-editor.png"
      },
      {
        "name": "Dashboard",
        "path": "img/screenshot-dashboard.png"
      }
    ],
    "version": "1.0.0",
    "updated": "2024-01-01"
  },
  "dependencies": {
    "grafanaVersion": ">=9.0.0",
    "plugins": []
  }
}

Private Plugin Distribution

Internal Plugin Repository

For private/enterprise plugins, set up an internal repository:
  1. Host plugin files on internal server or S3
  2. Configure plugin repository in Grafana:
# grafana.ini
[plugin.admin]
repo_url = https://plugins.internal.company.com
  1. Serve plugin catalog JSON:
{
  "plugins": [
    {
      "id": "myorg-internal-datasource",
      "type": "datasource",
      "name": "Internal Data Source",
      "version": "1.0.0",
      "url": "https://plugins.internal.company.com/myorg-internal-datasource-1.0.0.zip"
    }
  ]
}

Manual Installation

For ad-hoc distribution:
  1. Copy plugin to Grafana plugins directory:
cp -r myorg-myplugin-datasource /var/lib/grafana/plugins/
  1. Restart Grafana:
sudo systemctl restart grafana-server
  1. Verify installation:
grafana-cli plugins ls

Plugin Updates

Version Management

Follow semantic versioning (SemVer):
  • Major (1.0.0 → 2.0.0): Breaking changes
  • Minor (1.0.0 → 1.1.0): New features, backward compatible
  • Patch (1.0.0 → 1.0.1): Bug fixes

Update Process

  1. Update version in package.json and plugin.json
  2. Document changes in CHANGELOG.md
  3. Build and sign the new version
  4. Create GitHub release with new tag
  5. Update plugin catalog (automatic for published plugins)

Migration Handlers

Handle breaking changes with migration code:
// For panel plugins
import { PanelMigrationHandler } from '@grafana/data';

const migrate: PanelMigrationHandler<Options> = (panel) => {
  const version = panel.pluginVersion || '1.0.0';
  
  // Migrate from v1 to v2
  if (semver.lt(version, '2.0.0')) {
    return {
      ...panel.options,
      newOption: convertOldOption(panel.options.oldOption),
    };
  }
  
  return panel.options;
};

Plugin Installation

Users can install plugins via:

Grafana UI

  1. Navigate to ConfigurationPlugins
  2. Search for the plugin
  3. Click Install

Grafana CLI

# Install from catalog
grafana-cli plugins install myorg-myplugin-datasource

# Install specific version
grafana-cli plugins install myorg-myplugin-datasource 1.0.0

# Install from URL
grafana-cli --pluginUrl https://example.com/plugin.zip plugins install myorg-myplugin-datasource

Docker

FROM grafana/grafana:latest

ENV GF_INSTALL_PLUGINS="myorg-myplugin-datasource"

# Or install from URL
RUN grafana-cli --pluginUrl https://example.com/plugin.zip plugins install myorg-myplugin-datasource

Best Practices

Documentation

  1. Comprehensive README: Installation, configuration, usage examples
  2. Screenshots: Show query editor, config, and visualizations
  3. Changelog: Document all changes between versions
  4. License: Include appropriate open source license
  5. Contributing guidelines: If accepting contributions

Quality Assurance

  1. Test thoroughly: All features across Grafana versions
  2. Check compatibility: Test with minimum required Grafana version
  3. Performance: Optimize queries and rendering
  4. Error handling: Graceful degradation and error messages
  5. Security: Sanitize inputs, validate data

Versioning

  1. Follow SemVer: Major.Minor.Patch versioning
  2. Update CHANGELOG: Document all changes
  3. Tag releases: Use git tags for versions
  4. Backward compatibility: Avoid breaking changes when possible
  5. Deprecation warnings: Warn before removing features

Support

  1. Issue tracking: Use GitHub Issues or similar
  2. Community forum: Monitor Grafana community discussions
  3. Response time: Address critical bugs quickly
  4. Documentation updates: Keep docs current

Plugin Catalog Guidelines

Naming Conventions

  • Plugin ID: <org>-<name>-<type> (e.g., acme-weather-datasource)
  • Display name: Clear, descriptive (e.g., “Weather Data Source”)
  • No “Grafana” prefix (automatically implied)

Requirements

  1. Unique ID: No conflicts with existing plugins
  2. Quality code: Well-structured, maintainable
  3. Security: No vulnerabilities
  4. License compatibility: Open source license
  5. Branding: Respect Grafana trademarks

Rejections

Plugins may be rejected for:
  • Security vulnerabilities
  • Malicious code
  • Poor quality or broken functionality
  • Trademark violations
  • Duplicate of existing plugin

Monitoring Plugin Usage

Track plugin adoption:
  1. Download statistics: Available in Grafana plugin catalog
  2. GitHub metrics: Stars, forks, issues
  3. Telemetry (optional): Anonymous usage statistics
  4. User feedback: Issues, discussions, reviews

Resources