Grafana Datasource Create

This role creates InfluxDB datasources in Grafana using the Grafana HTTP API.

ARA Ansible Bash DNS Grafana HTTPS InfluxDB JSON

Grafana Datasource Create Role

Overview

This role creates InfluxDB datasources in Grafana using the Grafana HTTP API. It authenticates with an API token, configures datasources with InfluxQL query language support, and implements idempotent creation that safely handles existing datasources without errors.

Purpose

  • Automated Datasource Creation: Configure Grafana datasources via code
  • InfluxDB Integration: Connect Grafana to InfluxDB time-series databases
  • API-Based: Uses Grafana HTTP API for reliable automation
  • Idempotent: Safe to run multiple times without errors
  • Secure Authentication: Uses API token (Bearer authentication)
  • Multiple Datasources: Create multiple datasources in one playbook run
  • Credential Protection: Passwords never logged or exposed

Requirements

  • Ansible 2.9 or higher
  • Grafana server running and accessible via HTTPS
  • Grafana API token with datasource creation permissions (stored in Ansible Vault)
  • InfluxDB server(s) accessible from Grafana
  • Network connectivity to Grafana API (port 3000 by default)

What is Grafana Datasource?

A Grafana datasource is a connection configuration that tells Grafana:

  • Where to fetch data (URL)
  • How to authenticate (credentials)
  • What query language to use (InfluxQL, Flux, SQL, etc.)
  • How to proxy requests (direct or proxy mode)

Role Variables

Required Variables

VariableRequiredDescription
vault_grafana_ansibleuser_api_tokenYesGrafana API token for authentication (in vault)
grafana_datasource_create_datasourcesYesList of datasource configurations

Optional Variables

VariableDefaultDescription
grafana_datasource_create_hostAuto-detectedGrafana server host:port
grafana_datasource_create_port3000Grafana HTTP port
grafana_datasource_create_validate_certstrueValidate SSL certificates

Variable Details

vault_grafana_ansibleuser_api_token

Grafana API token with datasource creation permissions. Must be stored in Ansible Vault.

How to create an API token in Grafana:

  1. Log into Grafana web UI
  2. Go to Configuration → API Keys (or Administration → Service Accounts → Tokens in newer versions)
  3. Click “Add API key” or “Add service account token”
  4. Name: ansible-datasource-manager
  5. Role: Editor (minimum permission for datasource creation)
  6. Click “Add”
  7. Copy token (shown only once!)

Example vault variable:

vault_grafana_ansibleuser_api_token: "eyJrIjoiYWJjMTIzZGVmNDU2Z2hpNzg5amtsMDEyM..."

grafana_datasource_create_datasources

List of InfluxDB datasources to create.

Structure:

grafana_datasource_create_datasources:
  - name: datasource_display_name
    uid: unique_identifier
    url: http://influxdb-host:8086
    database: database_name
    user: influxdb_username
    password: influxdb_password
    is_default: true  # Optional: make this the default datasource

Complete example:

grafana_datasource_create_datasources:
  - name: "InfluxDB Homelab"
    uid: "influxdb-homelab"
    url: "http://influxdb:8086"
    database: "homelab"
    user: "grafana"
    password: "{{ vault_influxdb_grafana_password }}"
    is_default: true

  - name: "InfluxDB Monitoring"
    uid: "influxdb-monitoring"
    url: "http://influxdb:8086"
    database: "monitoring"
    user: "grafana"
    password: "{{ vault_influxdb_grafana_password }}"
    is_default: false

Field descriptions:

FieldRequiredDescription
nameYesDisplay name in Grafana UI
uidYesUnique identifier for referencing in dashboards
urlYesInfluxDB HTTP API URL (usually port 8086)
databaseYesInfluxDB database name
userYesInfluxDB username for authentication
passwordYesInfluxDB password (use vault variable)
is_defaultNoMake this the default datasource (default: false)

grafana_datasource_create_host

Grafana server host and port, auto-detected from inventory.

Default:

grafana_datasource_create_host: "{{ hostvars['grafana']['ansible_host'] }}:{{ grafana_datasource_create_port }}"

Custom example:

grafana_datasource_create_host: "grafana.example.com:3000"

grafana_datasource_create_validate_certs

Whether to validate SSL/TLS certificates.

Default: true (validate certificates)

For self-signed certificates:

grafana_datasource_create_validate_certs: false

Dependencies

This role has no dependencies on other Ansible roles, but requires:

  • Grafana server installed and running (see grafana_install role)
  • InfluxDB server accessible from Grafana host
  • API token created in Grafana
  • InfluxDB databases and users already created

Example Playbook

Basic Usage

---
- name: Create Grafana Datasources
  hosts: localhost
  become: false

  vars:
    grafana_datasource_create_datasources:
      - name: "InfluxDB Production"
        uid: "influxdb-prod"
        url: "http://influxdb:8086"
        database: "production"
        user: "grafana"
        password: "{{ vault_influxdb_grafana_password }}"
        is_default: true

  roles:
    - grafana_datasource_create

Multiple Datasources

---
- name: Create Multiple Grafana Datasources
  hosts: localhost
  become: false

  vars:
    grafana_datasource_create_datasources:
      - name: "InfluxDB System Metrics"
        uid: "influxdb-system"
        url: "http://influxdb.local:8086"
        database: "system"
        user: "grafana"
        password: "{{ vault_influxdb_grafana_password }}"
        is_default: true

      - name: "InfluxDB Application Metrics"
        uid: "influxdb-app"
        url: "http://influxdb.local:8086"
        database: "applications"
        user: "grafana"
        password: "{{ vault_influxdb_grafana_password }}"

      - name: "InfluxDB Network Metrics"
        uid: "influxdb-network"
        url: "http://influxdb.local:8086"
        database: "network"
        user: "grafana"
        password: "{{ vault_influxdb_grafana_password }}"

  roles:
    - grafana_datasource_create

With Self-Signed Certificate

---
- name: Create Datasources (Self-Signed Cert)
  hosts: localhost
  become: false

  vars:
    grafana_datasource_create_validate_certs: false
    grafana_datasource_create_datasources:
      - name: "InfluxDB Homelab"
        uid: "influxdb-homelab"
        url: "http://influxdb:8086"
        database: "homelab"
        user: "grafana"
        password: "{{ vault_influxdb_grafana_password }}"

  roles:
    - grafana_datasource_create

What This Role Does

  1. Sends POST request to Grafana API (/api/datasources)
  2. Authenticates with Bearer token (API key)
  3. Configures datasource with parameters:
    • Type: influxdb
    • Access mode: proxy (requests proxied through Grafana backend)
    • URL: InfluxDB server address
    • Database name
    • Authentication credentials
    • Query language: InfluxQL
    • HTTP method: GET
  4. Handles existing datasources gracefully (status 409 = already exists)
  5. Repeats for each datasource in the list

Grafana API Endpoint

Create Datasource

POST /api/datasources
Authorization: Bearer {api_token}
Content-Type: application/json

Request body:

{
  "name": "InfluxDB Homelab",
  "type": "influxdb",
  "access": "proxy",
  "url": "http://influxdb:8086",
  "database": "homelab",
  "user": "grafana",
  "uid": "influxdb-homelab",
  "basicAuth": false,
  "isDefault": true,
  "jsonData": {
    "httpMode": "GET",
    "version": "InfluxQL"
  },
  "secureJsonData": {
    "password": "secret_password"
  }
}

Response:

  • 200 OK: Datasource created successfully
  • 409 Conflict: Datasource already exists (not an error for this role)
  • 401 Unauthorized: Invalid API token
  • 403 Forbidden: Insufficient permissions

Datasource Configuration

Access Modes

ModeDescriptionUse Case
proxyRequests proxied through Grafana serverRecommended (default)
directBrowser connects directly to datasourceNot recommended (security/CORS)

This role uses proxy mode for security and simplicity.

Query Languages

InfluxDB supports two query languages:

LanguageVersionUsed By
InfluxQLInfluxDB 1.xThis role (default)
FluxInfluxDB 2.xRequires different configuration

This role configures InfluxQL for InfluxDB 1.x compatibility.

HTTP Method

MethodPurpose
GETStandard queries (used by this role)
POSTLarge queries (not needed for most cases)

Idempotency

The role is idempotent - safe to run multiple times:

  • Status 200: Datasource created (didn’t exist)
  • Status 409: Datasource already exists (no error)

Behavior:

  • First run: Creates datasource (200 OK)
  • Subsequent runs: Detects existing datasource (409 Conflict, accepted as success)

Note: The role does not update existing datasources. If configuration changes, you must delete and recreate:

# Delete via Grafana UI or API
curl -X DELETE -H "Authorization: Bearer $TOKEN" \
  https://grafana:3000/api/datasources/uid/influxdb-homelab

# Re-run Ansible role to recreate
ansible-playbook site.yml --tags grafana

Datasource UID

The uid field is a unique identifier used to:

  • Reference datasource in dashboards (instead of name)
  • Enable consistent dashboard imports across environments
  • Prevent name conflicts

Best practices:

  • Use descriptive, lowercase UIDs: influxdb-homelab, influxdb-prod
  • Keep UID consistent across environments
  • Don’t change UID after dashboards reference it

Example dashboard reference:

{
  "datasource": {
    "type": "influxdb",
    "uid": "influxdb-homelab"
  }
}

Default Datasource

Only one datasource should be marked as default:

is_default: true  # Only for one datasource

Purpose: Used when creating new panels without specifying datasource

Recommendation: Set your primary metrics database as default

Security Considerations

  • API Token: Protected with no_log: true to prevent exposure in logs
  • Database Passwords: Sent in secureJsonData (encrypted in Grafana)
  • Vault Storage: All credentials should be in Ansible Vault
  • HTTPS: Role uses HTTPS to Grafana API
  • Bearer Authentication: Modern token-based auth (no username/password)
  • Proxy Mode: Datasource credentials never sent to browser
  • No Logging: Task marked with no_log: true to protect credentials

Tags

This role does not define any tags. Use playbook-level tags if needed:

- hosts: localhost
  roles:
    - grafana_datasource_create
  tags:
    - grafana
    - datasource
    - monitoring
    - influxdb

Notes

  • Role creates datasources for InfluxDB 1.x with InfluxQL only
  • For InfluxDB 2.x with Flux, different configuration needed
  • Datasources are not updated if they already exist (idempotent creation only)
  • API token must have Editor role or higher
  • Role runs on localhost (API calls don’t require target host access)
  • become: false recommended (no root needed for API calls)
  • SSL certificate validation can be disabled for self-signed certs

Troubleshooting

”401 Unauthorized” error

Cause: Invalid or expired API token

Solution:

# Verify token in vault
ansible-vault view group_vars/all/vault.yml

# Test token manually
curl -H "Authorization: Bearer YOUR_TOKEN" \
  https://grafana:3000/api/datasources

# If invalid, create new token in Grafana and update vault

“403 Forbidden” error

Cause: API token has insufficient permissions

Solution: Token needs Editor or Admin role

  1. Log into Grafana
  2. Go to Configuration → API Keys
  3. Find your token
  4. Verify role is “Editor” or “Admin”
  5. If “Viewer”, create new token with higher permissions

”409 Conflict” but datasource not visible

Cause: Datasource exists but may have different name/UID

Solution:

# List existing datasources
curl -H "Authorization: Bearer $TOKEN" \
  https://grafana:3000/api/datasources | jq .

# Check for name/UID conflicts
# Delete conflicting datasource via UI or API

Cannot connect to InfluxDB from Grafana

Cause: URL incorrect or InfluxDB not accessible from Grafana server

Solution:

# Test connectivity from Grafana host
curl -I http://influxdb:8086/ping

# Should return: HTTP/1.1 204 No Content

# Check DNS resolution
nslookup influxdb

# Check firewall
telnet influxdb 8086

“Invalid database credentials”

Cause: InfluxDB username/password incorrect

Solution:

# Test credentials on InfluxDB
influx -host influxdb -username grafana -password 'password'

# Or via API
curl -G http://influxdb:8086/query \
  --data-urlencode "u=grafana" \
  --data-urlencode "p=password" \
  --data-urlencode "q=SHOW DATABASES"

# If fails, create/update InfluxDB user

“Connection refused” to Grafana API

Cause: Grafana not running or firewall blocking

Solution:

# Check Grafana running
systemctl status grafana-server

# Test from Ansible control node
curl -I https://grafana:3000/api/health

# Check firewall on Grafana host
firewall-cmd --list-ports
# Should include: 3000/tcp

Self-signed certificate errors

Solution: Set grafana_datasource_create_validate_certs: false

Or install CA certificate on Ansible control node:

# Copy CA cert
sudo cp ca.crt /etc/pki/ca-trust/source/anchors/

# Update trust store
sudo update-ca-trust

Testing the Role

Verify Datasource Created

Via Grafana UI:

  1. Log into Grafana
  2. Go to Configuration → Data Sources
  3. Should see your datasource listed
  4. Click to view configuration
  5. Click “Save & Test”
  6. Should show “Data source is working”

Via API:

# List all datasources
curl -H "Authorization: Bearer $TOKEN" \
  https://grafana:3000/api/datasources | jq .

# Get specific datasource by UID
curl -H "Authorization: Bearer $TOKEN" \
  https://grafana:3000/api/datasources/uid/influxdb-homelab | jq .

Test Datasource Connectivity

In Grafana UI:

  1. Go to datasource configuration
  2. Click “Save & Test” button
  3. Should show success message

Via API:

# Test datasource by ID
curl -H "Authorization: Bearer $TOKEN" \
  https://grafana:3000/api/datasources/1/health

# Should return: {"status": "OK"}

Query Data

In Grafana Explore:

  1. Go to Explore (compass icon)
  2. Select your datasource
  3. Write InfluxQL query:
    SELECT mean("value") FROM "cpu_usage" WHERE time > now() - 1h GROUP BY time(1m)
    
  4. Click “Run Query”
  5. Should show data or “No data” (if database empty)

Best Practices

  1. Store API token in vault: Never commit tokens to version control
  2. Use descriptive names: InfluxDB Homelab not DS1
  3. Consistent UIDs: Use same UID across dev/staging/prod
  4. One default datasource: Only mark one as is_default: true
  5. Test connectivity first: Ensure InfluxDB accessible before running role
  6. Document datasources: Comment purpose of each datasource
  7. Rotate API tokens: Periodically regenerate tokens
  8. Least privilege: Use Editor role, not Admin
  9. Separate credentials: Different InfluxDB users per datasource if needed
  10. Version control: Store datasource configs in git (without secrets)

This role is often used with:

  • grafana_install: Install Grafana server
  • grafana_dashboards_backup: Backup Grafana dashboards
  • grafana_alerts_backup: Backup Grafana alert rules
  • influxdb: Install and configure InfluxDB
  • telegraf_agent: Send metrics to InfluxDB for Grafana to visualize

Alternative: Manual Creation

If you prefer manual datasource creation:

Via Grafana UI:

  1. Log into Grafana
  2. Configuration → Data Sources
  3. Click “Add data source”
  4. Select “InfluxDB”
  5. Configure:
    • Name: InfluxDB Homelab
    • URL: http://influxdb:8086
    • Database: homelab
    • User: grafana
    • Password: your_password
    • Query Language: InfluxQL
  6. Click “Save & Test”

Via API (curl):

curl -X POST -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "InfluxDB Homelab",
    "type": "influxdb",
    "access": "proxy",
    "url": "http://influxdb:8086",
    "database": "homelab",
    "user": "grafana",
    "uid": "influxdb-homelab",
    "jsonData": {"httpMode": "GET", "version": "InfluxQL"},
    "secureJsonData": {"password": "your_password"}
  }' \
  https://grafana:3000/api/datasources

License

MIT

Author

Created for homelab infrastructure management.