| Crates.io | grafana-sync |
| lib.rs | grafana-sync |
| version | 0.1.0 |
| created_at | 2025-04-25 11:52:02.815727+00 |
| updated_at | 2025-04-25 11:52:02.815727+00 |
| description | Dashboard synchronization tool for grafana |
| homepage | https://github.com/wobcom/grafana-sync |
| repository | https://github.com/wobcom/grafana-sync |
| max_upload_size | |
| id | 1648922 |
| size | 5,747,498 |
A lightweight Rust service that keeps tagged Grafana dashboards perfectly in-step across any number of Grafana instances.
Running several Grafana servers— for multi-region HA, developer sandboxes, on-prem/lab copies, or blue/green upgrades—inevitably leads to diverging dashboards. Grafana Sync solves that by:
How it works (in a nutshell)
+-----------+ +-----------+ +-----------+
| Grafana 1 | <---> | Grafana 2 | <---> | Grafana N |
+-----------+ +-----------+ +-----------+
↑ ↑ ↑
| | |
+------------------------+----------+-------------+---------→
|
+--------------+
| Grafana Sync |
+--------------+
cargo install grafana-sync
Or grab a pre-built binary from the releases.
[!NOTE] An empty, default config file will be created for you the first time you start the program.
config.yaml
sync_tag: "SyncMe" # Only dashboards with this tag are considered
sync_rate_mins: 1 # Polling interval
instances: # Two or more Grafana servers
- url: https://grafana.example.de
api_token: token1 # Needs folder+dashboards RW permissions
- url: http://localhost:3000
api_token: token2
grafana-sync config.yaml
You should see log lines such as:
[2025-04-24T15:03:12Z INFO ] Loaded 2 instance(s):
[2025-04-24T15:03:12Z INFO ] - https://grafana.example.de
[2025-04-24T15:03:12Z INFO ] - http://localhost:3000
[2025-04-24T15:03:12Z INFO ] === sync-cycle #0 (2025-04-24 17:03:12.058072 +02:00) ===
[2025-04-24T15:03:12Z INFO ] https://grafana.example.de: 7 sync dashboards
[2025-04-24T15:03:12Z INFO ] http://localhost:3000: 7 sync dashboards
[2025-04-24T15:03:12Z INFO ]
[2025-04-24T15:03:12Z INFO ] ...
[2025-04-24T15:03:12Z INFO ]
[2025-04-24T15:03:12Z INFO ] === finished sync-cycle #0 in 210.51555ms ===
Leave it running as a systemd service, Docker container or Kubernetes sidecar.
[!NOTE] It's also built with Nix users in mind and packaged accordingly, provided with a ready-to-use dev shell.
[!NOTE] All heavy I/O is async; CPU work is negligible, so a single-CPU VM handles dozens of instances comfortably.
| Key | Type | Default | Description |
|---|---|---|---|
| sync_tag | str | SyncMe | Tag used to select dashboards for replication. |
| instances | list | — | Grafana endpoints with an API token that has Editor rights or higher. |
| sync_rate_mins | int | 1 | How often the full bidirectional sync cycle runs. |
# /etc/systemd/system/grafana-sync.service
[Unit]
Description=Grafana dashboard synchroniser
After=network-online.target
[Service]
ExecStart=/usr/local/bin/grafana-sync /etc/grafana-sync.yaml
Restart=on-failure
User=grafana-sync
[Install]
WantedBy=multi-user.target
Metrics & health: expose Prometheus and /health in a future release.
git clone https://github.com/wobcom/grafana-sync.git
cd grafana-sync
cargo test
cargo run # Of course you need to have a config.yaml or pass one in
Key crates: reqwest, tokio, serde, chrono, tracing, log.
We follow the Rust 2021 edition and cargo clippy --all-targets --all-features -- -D warnings for CI.
Pull requests are welcome! Please open an issue first to discuss major changes. For security disclosures, please e-mail soc@wobcom.de.
Licensed under the MIT license. See LICENSE for details.
Made with ❤️ in Rust