# Duplicati Dashboard

Link: [https://github.com/fabien-github/duplicati\_dashboard?tab=readme-ov-file#demo](https://github.com/fabien-github/duplicati_dashboard?tab=readme-ov-file#demo)   
git clone [https://github.com/fabien-github/duplicati\_dashboard.git](https://github.com/fabien-github/duplicati_dashboard.git)

Duplicati Dashboard is a monitoring solution for [Duplicati](https://www.duplicati.com/).

It allows you to monitor your backups status, collects stats for each reports and alerts you by email when a backup fails. It is intended to be self-hosted and works with [docker-compose](https://docs.docker.com/compose/).

Everything is already pre-configured and ready to be deployed.

- [Duplicati Dashboard](https://github.com/fabien-github/duplicati_dashboard?tab=readme-ov-file#duplicati-dashboard)
- [Demo](https://github.com/fabien-github/duplicati_dashboard?tab=readme-ov-file#demo)
- [Quick Start](https://github.com/fabien-github/duplicati_dashboard?tab=readme-ov-file#quick-start)
    - [Running with docker-compose](https://github.com/fabien-github/duplicati_dashboard?tab=readme-ov-file#running-with-docker-compose)
    - [Setup Duplicati](https://github.com/fabien-github/duplicati_dashboard?tab=readme-ov-file#setup-duplicati)
    - [Connect to your dashboard](https://github.com/fabien-github/duplicati_dashboard?tab=readme-ov-file#connect-to-your-dashboard)
- [Configuration](https://github.com/fabien-github/duplicati_dashboard?tab=readme-ov-file#configuration)
    - [Env file](https://github.com/fabien-github/duplicati_dashboard?tab=readme-ov-file#env-file)
- [Notes](https://github.com/fabien-github/duplicati_dashboard?tab=readme-ov-file#notes)
    - [Grafana configuration locked](https://github.com/fabien-github/duplicati_dashboard?tab=readme-ov-file#grafana-configuration-locked)
    - [Backup over more than 30 days rotation](https://github.com/fabien-github/duplicati_dashboard?tab=readme-ov-file#backup-over-more-than-30-days-rotation)
    - [Alerting graph](https://github.com/fabien-github/duplicati_dashboard?tab=readme-ov-file#alerting-graph)
    - [Deleting removed backup data](https://github.com/fabien-github/duplicati_dashboard?tab=readme-ov-file#deleting-removed-backup-data)
    - [Docker-compose](https://github.com/fabien-github/duplicati_dashboard?tab=readme-ov-file#docker-compose)
- [Other informations](https://github.com/fabien-github/duplicati_dashboard?tab=readme-ov-file#other-informations)
- [License](https://github.com/fabien-github/duplicati_dashboard?tab=readme-ov-file#license)

# Demo

<div class="markdown-heading" dir="auto" id="bkmrk-" style="text-align: justify;">[<svg aria-hidden="true" class="octicon octicon-link" height="16" version="1.1" viewbox="0 0 16 16" width="16"></svg>](https://github.com/fabien-github/duplicati_dashboard?tab=readme-ov-file#demo)</div>[![](https://github.com/fabien-github/duplicati_dashboard/raw/main/docs/img/demo.gif)](https://github.com/fabien-github/duplicati_dashboard/blob/main/docs/img/demo.gif)

> The right side of the video is not integrated in the dashboard. You can't control your backup with it.

# Quick Start

<div class="markdown-heading" dir="auto" id="bkmrk--3" style="text-align: justify;">[<svg aria-hidden="true" class="octicon octicon-link" height="16" version="1.1" viewbox="0 0 16 16" width="16"></svg>](https://github.com/fabien-github/duplicati_dashboard?tab=readme-ov-file#quick-start)</div>### Running with docker-compose

<div class="markdown-heading" dir="auto" id="bkmrk--5" style="text-align: justify;">[<svg aria-hidden="true" class="octicon octicon-link" height="16" version="1.1" viewbox="0 0 16 16" width="16"></svg>](https://github.com/fabien-github/duplicati_dashboard?tab=readme-ov-file#running-with-docker-compose)</div>```
git clone https://github.com/fabien-github/duplicati_dashboard.git
cd duplicati_dashboard
docker-compose up -d
```

<div class="zeroclipboard-container" id="bkmrk--7" style="text-align: justify;">  
</div>### Setup Duplicati

<div class="markdown-heading" dir="auto" id="bkmrk--8" style="text-align: justify;">[<svg aria-hidden="true" class="octicon octicon-link" height="16" version="1.1" viewbox="0 0 16 16" width="16"></svg>](https://github.com/fabien-github/duplicati_dashboard?tab=readme-ov-file#setup-duplicati)</div>Add theses two options for each backup you want to monitor:

- **send-http-result-output-format:** json
- **send-http-url:** [http://localhost:8080](http://localhost:8080)

[![](https://github.com/fabien-github/duplicati_dashboard/raw/main/docs/img/backup_options_report_config.png)](https://github.com/fabien-github/duplicati_dashboard/blob/main/docs/img/backup_options_report_config.png)

> This assumes that your Duplicati instance is on the same host as your Duplicati Dashboard.

### Connect to your dashboard

<div class="markdown-heading" dir="auto" id="bkmrk--11" style="text-align: justify;">[<svg aria-hidden="true" class="octicon octicon-link" height="16" version="1.1" viewbox="0 0 16 16" width="16"></svg>](https://github.com/fabien-github/duplicati_dashboard?tab=readme-ov-file#connect-to-your-dashboard)</div>[http://localhost:3000](http://localhost:3000)

Login: `admin` Password: `password`

> For email alerting, you need to configure a SMTP relay. See [Configuration &gt; Env file](https://github.com/fabien-github/duplicati_dashboard?tab=readme-ov-file#env-file)

# Configuration

<div class="markdown-heading" dir="auto" id="bkmrk--13" style="text-align: justify;">[<svg aria-hidden="true" class="octicon octicon-link" height="16" version="1.1" viewbox="0 0 16 16" width="16"></svg>](https://github.com/fabien-github/duplicati_dashboard?tab=readme-ov-file#configuration)</div>## Env file

<div class="markdown-heading" dir="auto" id="bkmrk--15" style="text-align: justify;">[<svg aria-hidden="true" class="octicon octicon-link" height="16" version="1.1" viewbox="0 0 16 16" width="16"></svg>](https://github.com/fabien-github/duplicati_dashboard?tab=readme-ov-file#env-file)</div>The file [`config.env`](https://github.com/fabien-github/duplicati_dashboard/blob/main/config.env) is used to configure some options. It will be shared between the 3 containers.

Only use this default configuration for testing purposes.

Influxdb variable will create and setup the database only on the first startup.

<table id="bkmrk-variables-default-de" tabindex="0"><thead><tr><th>Variables</th><th>Default</th><th>Description</th></tr></thead><tbody><tr><td>DOCKER\_INFLUXDB\_INIT\_MODE</td><td>setup</td><td>[Automatically bootstrap the system](https://github.com/docker-library/docs/blob/master/influxdb/README.md#automated-setup)</td></tr><tr><td>DOCKER\_INFLUXDB\_INIT\_USERNAME</td><td>telegraf\_user</td><td>Influxdb superadmin user</td></tr><tr><td>DOCKER\_INFLUXDB\_INIT\_PASSWORD</td><td>telegraf\_password</td><td>Influxdb superadmin password</td></tr><tr><td>DOCKER\_INFLUXDB\_INIT\_ORG</td><td>telegraf\_org</td><td>Influxdb Organization (used by influxdb / telegraf / grafana)</td></tr><tr><td>DOCKER\_INFLUXDB\_INIT\_BUCKET</td><td>telegraf</td><td>Influxdb bucket to store reports (used by influxdb / telegraf / grafana)</td></tr><tr><td>DOCKER\_INFLUXDB\_INIT\_ADMIN\_TOKEN</td><td>telegraf\_token</td><td>Influxdb superadmin token (used by influxdb / telegraf / grafana)</td></tr><tr><td>DOCKER\_INFLUXDB\_INIT\_RETENTION</td><td> </td><td>Influxdb data retention, default will retain forever</td></tr><tr><td>INFLUXD\_REPORTING\_DISABLED</td><td>false</td><td>Disable [InfluxData telemetry](https://docs.influxdata.com/influxdb/v2.0/reference/config-options/#reporting-disabled)</td></tr><tr><td>TELEGRAF\_LISTENER\_PORT</td><td>8080</td><td>Port used by [http\_listener\_v2](https://github.com/influxdata/telegraf/tree/master/plugins/inputs/http_listener_v2) input, endpoint for the reports sent by Duplicati</td></tr><tr><td>TELEGRAF\_LISTENER\_PATH</td><td>/</td><td>Path to listen to</td></tr><tr><td>GF\_SECURITY\_ADMIN\_USER</td><td>admin</td><td>Grafana superadmin user</td></tr><tr><td>GF\_SECURITY\_ADMIN\_PASSWORD</td><td>password</td><td>Grafana superadmin password</td></tr><tr><td>GF\_SERVER\_ROOT\_URL</td><td>[http://localhost:3000](http://localhost:3000)</td><td>Grafana URL, used in some templates like email notifications</td></tr><tr><td>GF\_DASHBOARDS\_DEFAULT\_HOME\_DASHBOARD\_PATH</td><td>/etc/grafana/provisioning/dashboards/duplicati\_dashboard.json</td><td>Force Duplicati dashboard by default on home page</td></tr><tr><td>GF\_SMTP\_ENABLED</td><td>false</td><td>[Set to true for email notifications](https://grafana.com/docs/grafana/latest/administration/configuration/#smtp)</td></tr><tr><td>GF\_SMTP\_HOST</td><td>localhost:25</td><td>SMTP relay server. \[host\]:\[port\]</td></tr><tr><td>GF\_SMTP\_FROM\_NAME</td><td>Grafana</td><td>Name of the email sender</td></tr><tr><td>GF\_SMTP\_USER</td><td> </td><td>In case of SMTP auth</td></tr><tr><td>GF\_SMTP\_PASSWORD</td><td> </td><td>In case of SMTP auth</td></tr><tr><td>GF\_SMTP\_FROM\_ADDRESS</td><td><admin@grafana.localhost></td><td>Address used when sending out emails</td></tr><tr><td>GF\_SMTP\_EHLO\_IDENTITY</td><td>${HOSTNAME}</td><td>Name to be used as client identity for EHLO in SMTP dialog (Default will be the container ID)</td></tr><tr><td>GF\_SMTP\_STARTTLS\_POLICY</td><td> </td><td>“OpportunisticStartTLS”, “MandatoryStartTLS”, “NoStartTLS”</td></tr><tr><td>NOTIFIER\_EMAIL\_RECIPIENT</td><td><example@example.com></td><td>Recipients for email notification (separated by a semicolon)</td></tr><tr><td>NOTIFIER\_EMAIL\_REMINDER\_ENABLE</td><td>true</td><td>Re-send an email if alerts are still active</td></tr><tr><td>NOTIFIER\_EMAIL\_REMINDER\_FREQUENCY</td><td>2h</td><td>Delay between email reminders</td></tr></tbody></table>

# Notes

<div class="markdown-heading" dir="auto" id="bkmrk--17" style="text-align: justify;">[<svg aria-hidden="true" class="octicon octicon-link" height="16" version="1.1" viewbox="0 0 16 16" width="16"></svg>](https://github.com/fabien-github/duplicati_dashboard?tab=readme-ov-file#notes)</div>## Grafana configuration locked

<div class="markdown-heading" dir="auto" id="bkmrk--19" style="text-align: justify;">[<svg aria-hidden="true" class="octicon octicon-link" height="16" version="1.1" viewbox="0 0 16 16" width="16"></svg>](https://github.com/fabien-github/duplicati_dashboard?tab=readme-ov-file#grafana-configuration-locked)</div>The dashboard is locked by the Grafana provisioning system. You can't edit the datasource, the dashboard or the alert notifier from the UI. You will need to copy the dashboard or disable the provisioning configuration.

Dashboard path: `./grafana/provisioning/dashboards/duplicati_dashboard.json`

The idea is to keep the stack easy to deploy for everyone without investing time to learn Grafana configuration.

Feel free to fork the project or directly edit files on your own.

More information [here](https://grafana.com/docs/grafana/latest/administration/provisioning/).

## Backup over more than 30 days rotation

<div class="markdown-heading" dir="auto" id="bkmrk--21" style="text-align: justify;">[<svg aria-hidden="true" class="octicon octicon-link" height="16" version="1.1" viewbox="0 0 16 16" width="16"></svg>](https://github.com/fabien-github/duplicati_dashboard?tab=readme-ov-file#backup-over-more-than-30-days-rotation)</div>- Grafana will discover your backups name from the reports but only over the last 90 days. So if your backups are scheduled for more than 90 days, you will need to edit the request of the variable `Backup` in the dashboard configuration:

```
from(bucket: v.defaultBucket)
  |> range(start: -90d)
  |> filter(fn: (r) => true)
  |> toString()
  |> group(columns: ["backup-name"])
  |> distinct(column: "backup-name")
  |> keep(columns: ["_value"])
```

<div class="highlight highlight-source-shell notranslate position-relative overflow-auto" dir="auto" id="bkmrk--23" style="text-align: justify;"><div class="zeroclipboard-container">  
</div></div>- Last reported status / Last reported variations / Alerting graph are based over the past 30 days. You will need to adapt each panel requests if your backups are scheduled over more than 30 days.

```
import "influxdata/influxdb/schema"

from(bucket: v.defaultBucket)
  |> range(start: -30d)
  ...
```

<div class="highlight highlight-source-shell notranslate position-relative overflow-auto" dir="auto" id="bkmrk--24" style="text-align: justify;"><div class="zeroclipboard-container">  
</div></div>- In [v2](https://github.com/fabien-github/duplicati_dashboard/releases/tag/v1.0.0), alerts have their own provisioning file and query range can be edited [here](https://github.com/fabien-github/duplicati_dashboard/blob/3e1d558d54c6b3ecbb7ed67627a812c5dd060f31/grafana/provisioning/alerting/duplicati_alert.yml#L30).

## Alerting graph

<div class="markdown-heading" dir="auto" id="bkmrk--25" style="text-align: justify;">[<svg aria-hidden="true" class="octicon octicon-link" height="16" version="1.1" viewbox="0 0 16 16" width="16"></svg>](https://github.com/fabien-github/duplicati_dashboard?tab=readme-ov-file#alerting-graph)</div>The section "Alerting graph" is only used to trigger an alert when a backup fails. This is due to the lack of grafana alert support on other panel type. [\#6983](https://github.com/grafana/grafana/issues/6983)

Backups status will be checked every minutes. An alert will be triggered after a pending status of 10min. Same delays are used on the recovery.

Warning reports don't trigger an alert.

## Deleting removed backup data

<div class="markdown-heading" dir="auto" id="bkmrk--27" style="text-align: justify;">[<svg aria-hidden="true" class="octicon octicon-link" height="16" version="1.1" viewbox="0 0 16 16" width="16"></svg>](https://github.com/fabien-github/duplicati_dashboard?tab=readme-ov-file#deleting-removed-backup-data)</div>After getting inside the influxdb container:

```
influx delete \
  --org telegraf_org \
  --bucket telegraf \
  --token "telegraf_token" \
  --start 1970-01-01T00:00:00Z \
  --stop $(date +"%Y-%m-%dT%H:%M:%SZ") \
  --predicate '_measurement="duplicati" AND "backup-name"="backup_to_delete"'
```

<div class="highlight highlight-source-shell notranslate position-relative overflow-auto" dir="auto" id="bkmrk--29" style="text-align: justify;"><div class="zeroclipboard-container">  
</div></div>## Docker-compose

<div class="markdown-heading" dir="auto" id="bkmrk--30" style="text-align: justify;">[<svg aria-hidden="true" class="octicon octicon-link" height="16" version="1.1" viewbox="0 0 16 16" width="16"></svg>](https://github.com/fabien-github/duplicati_dashboard?tab=readme-ov-file#docker-compose)</div>- **Telegraf**: Receive JSON reports from Duplicati.
- **Influxdb**: Store reports converted by Telegraf.
- **Grafana**: Requests Influxdb to generate dashboard and alerts.

Telegraf endpoint provides a limited [HTTP autentification](https://github.com/influxdata/telegraf/tree/master/plugins/inputs/http_listener_v2).  
The configuration file is located here : `./telegraf/telegraf.conf`

Feel free to add a proxy like traefik or nginx to protect the stack on an unsecure network. (TLS, IP Restrictions, ...)

# Other informations

<div class="markdown-heading" dir="auto" id="bkmrk--32" style="text-align: justify;">[<svg aria-hidden="true" class="octicon octicon-link" height="16" version="1.1" viewbox="0 0 16 16" width="16"></svg>](https://github.com/fabien-github/duplicati_dashboard?tab=readme-ov-file#other-informations)</div>- Not sure of the scalabilty, requests to the database are not efficients. Timeseries databases are not really adapted for this kind of data. This is mainly due to the nested and uneven json format from the reports and the variation time between reports.
- Features are limited directly by the stack itself. For example, it's nearly impossible to add a managment system for the backups.
- This project has no link with the development of Duplicati and his team.

# License

<div class="markdown-heading" dir="auto" id="bkmrk--34" style="text-align: justify;">[<svg aria-hidden="true" class="octicon octicon-link" height="16" version="1.1" viewbox="0 0 16 16" width="16"></svg>](https://github.com/fabien-github/duplicati_dashboard?tab=readme-ov-file#license)</div>Distributed under the GNU General Public License v3.0 License. See [LICENSE](https://github.com/fabien-github/duplicati_dashboard/blob/main/LICENSE) for more information.