diff --git a/docs/TROUBLESHOOTING_INFLUXDB.md b/docs/TROUBLESHOOTING_INFLUXDB.md
index 437042b..22b52c6 100644
--- a/docs/TROUBLESHOOTING_INFLUXDB.md
+++ b/docs/TROUBLESHOOTING_INFLUXDB.md
@@ -66,12 +66,319 @@ panic: failed to check influxdb setup status - parse "://:": missing protocol sc
As discussed in [#248](https://github.com/AnalogJ/scrutiny/issues/248) and [#234](https://github.com/AnalogJ/scrutiny/issues/234),
this usually related to either:
-- Upgrading from the LSIO Scrutiny image to the Official Scrutiny image, without removing LSIO specific environmental variables
- - remove the `SCRUTINY_WEB=true` and `SCRUTINY_COLLECTOR=true` environmental variables. They were used by the LSIO image, but are unnecessary and cause issues with the official Scrutiny image.
-- Updated versions of the [LSIO Scrutiny images are broken](https://github.com/linuxserver/docker-scrutiny/issues/22), as they have not installed InfluxDB which is a required dependency of Scrutiny v0.4.x
- - You can revert to an earlier version of the LSIO image (`lscr.io/linuxserver/scrutiny:060ac7b8-ls34`), or just change to the official Scrutiny image (`ghcr.io/analogj/scrutiny:master-omnibus`)
+- Upgrading from the LSIO Scrutiny image to the Official Scrutiny image, without removing LSIO specific environmental
+ variables
+ - remove the `SCRUTINY_WEB=true` and `SCRUTINY_COLLECTOR=true` environmental variables. They were used by the LSIO
+ image, but are unnecessary and cause issues with the official Scrutiny image.
+- Updated versions of the [LSIO Scrutiny images are broken](https://github.com/linuxserver/docker-scrutiny/issues/22),
+ as they have not installed InfluxDB which is a required dependency of Scrutiny v0.4.x
+ - You can revert to an earlier version of the LSIO image (`lscr.io/linuxserver/scrutiny:060ac7b8-ls34`), or just
+ change to the official Scrutiny image (`ghcr.io/analogj/scrutiny:master-omnibus`)
Here's a couple of confirmed working docker-compose files that you may want to look at:
- https://github.com/AnalogJ/scrutiny/blob/master/docker/example.hubspoke.docker-compose.yml
- https://github.com/AnalogJ/scrutiny/blob/master/docker/example.omnibus.docker-compose.yml
+
+## Bring your own InfluxDB
+
+> WARNING: Most users should not follow these steps. This is ONLY for users who have an EXISTING InfluxDB installation which contains data from multiple services.
+> The Scrutiny Docker omnibus image includes an empty InfluxDB instance which it can configure.
+> If you're deploying manually or via Hub/Spoke, you can just follow the installation instructions, Scrutiny knows how
+> to run the first-time setup automatically.
+
+The goal here is to create an InfluxDB API key with minimal permissions for use by Scrutiny.
+
+- Create Scrutiny buckets (`metrics`, `metrics_weekly`, `metrics_monthly`, `metrics_yearly`) with placeholder config
+- Create Downsampling tasks (`tsk-weekly-aggr`, `tsk-monthly-aggr`, `tsk-yearly-aggr`) with placeholder script.
+- Create API token with restricted scope
+- NOTE: Placeholder bucket & task configuration will be replaced automatically by Scrutiny during startup
+
+The placeholder buckets and tasks need to be created before the API token can be created, as the resource ID's need to
+exist for the scope restriction to work.
+
+Scopes:
+
+- `orgs`: read - required for scrutiny to find it's configured org_id
+- `tasks`: scrutiny specific read/write access - Scrutiny only needs access to the downsampling tasks you created above
+- `buckets`: scrutiny specific read/write access - Scrutiny only needs access to the buckets you created above
+
+### Setup Environmental Variables
+
+```bash
+# replace the following values with correct values for your InfluxDB installation
+export INFLUXDB_ADMIN_TOKEN=pCqRq7xxxxxx-FZgNLfstIs0w==
+export INFLUXDB_ORG_ID=b2495xxxxx
+export INFLUXDB_HOSTNAME=http://localhost:8086
+
+# if you want to change the bucket name prefix below, you'll also need to update the setting in the scrutiny.yaml config file.
+export INFLUXDB_SCRUTINY_BUCKET_BASENAME=metrics
+```
+
+### Create placeholder buckets
+
+
+ Click to expand!
+
+```bash
+curl -sS -X POST ${INFLUXDB_HOSTNAME}/api/v2/buckets \
+-H "Content-Type: application/json" \
+-H "Authorization: Token ${INFLUXDB_ADMIN_TOKEN}" \
+--data-binary @- << EOF
+{
+"name": "${INFLUXDB_SCRUTINY_BUCKET_BASENAME}",
+"orgID": "${INFLUXDB_ORG_ID}",
+"retentionRules": []
+}
+EOF
+
+curl -sS -X POST ${INFLUXDB_HOSTNAME}/api/v2/buckets \
+-H "Content-Type: application/json" \
+-H "Authorization: Token ${INFLUXDB_ADMIN_TOKEN}" \
+--data-binary @- << EOF
+{
+"name": "${INFLUXDB_SCRUTINY_BUCKET_BASENAME}_weekly",
+"orgID": "${INFLUXDB_ORG_ID}",
+"retentionRules": []
+}
+EOF
+
+curl -sS -X POST ${INFLUXDB_HOSTNAME}/api/v2/buckets \
+-H "Content-Type: application/json" \
+-H "Authorization: Token ${INFLUXDB_ADMIN_TOKEN}" \
+--data-binary @- << EOF
+{
+"name": "${INFLUXDB_SCRUTINY_BUCKET_BASENAME}_monthly",
+"orgID": "${INFLUXDB_ORG_ID}",
+"retentionRules": []
+}
+EOF
+
+curl -sS -X POST ${INFLUXDB_HOSTNAME}/api/v2/buckets \
+-H "Content-Type: application/json" \
+-H "Authorization: Token ${INFLUXDB_ADMIN_TOKEN}" \
+--data-binary @- << EOF
+{
+"name": "${INFLUXDB_SCRUTINY_BUCKET_BASENAME}_yearly",
+"orgID": "${INFLUXDB_ORG_ID}",
+"retentionRules": []
+}
+EOF
+```
+
+
+
+### Create placeholder tasks
+
+
+ Click to expand!
+
+```bash
+curl -sS -X POST ${INFLUXDB_HOSTNAME}/api/v2/tasks \
+ -H "Content-Type: application/json" \
+ -H "Authorization: Token ${INFLUXDB_ADMIN_TOKEN}" \
+ --data-binary @- << EOF
+{
+ "orgID": "${INFLUXDB_ORG_ID}",
+ "flux": "option task = {name: \"tsk-weekly-aggr\", every: 1y} \nyield now()"
+}
+EOF
+
+curl -sS -X POST ${INFLUXDB_HOSTNAME}/api/v2/tasks \
+ -H "Content-Type: application/json" \
+ -H "Authorization: Token ${INFLUXDB_ADMIN_TOKEN}" \
+ --data-binary @- << EOF
+{
+ "orgID": "${INFLUXDB_ORG_ID}",
+ "flux": "option task = {name: \"tsk-monthly-aggr\", every: 1y} \nyield now()"
+}
+EOF
+
+curl -sS -X POST ${INFLUXDB_HOSTNAME}/api/v2/tasks \
+ -H "Content-Type: application/json" \
+ -H "Authorization: Token ${INFLUXDB_ADMIN_TOKEN}" \
+ --data-binary @- << EOF
+{
+ "orgID": "${INFLUXDB_ORG_ID}",
+ "flux": "option task = {name: \"tsk-yearly-aggr\", every: 1y} \nyield now()"
+}
+EOF
+
+```
+
+
+
+### Create InfluxDB API Token
+
+
+ Click to expand!
+
+```bash
+# replace these values with placeholder bucket and task ids from your InfluxDB installation.
+export INFLUXDB_SCRUTINY_BASE_BUCKET_ID=1e0709xxxx
+export INFLUXDB_SCRUTINY_WEEKLY_BUCKET_ID=1af03dexxxxx
+export INFLUXDB_SCRUTINY_MONTHLY_BUCKET_ID=b3c59c7xxxxx
+export INFLUXDB_SCRUTINY_YEARLY_BUCKET_ID=f381d8cxxxxx
+
+export INFLUXDB_SCRUTINY_WEEKLY_TASK_ID=09a64ecxxxxx
+export INFLUXDB_SCRUTINY_MONTHLY_TASK_ID=09a64xxxxx
+export INFLUXDB_SCRUTINY_YEARLY_TASK_ID=09a64ecxxxxx
+
+
+curl -sS -X POST ${INFLUXDB_HOSTNAME}/api/v2/authorizations \
+ -H "Content-Type: application/json" \
+ -H "Authorization: Token ${INFLUXDB_ADMIN_TOKEN}" \
+ --data-binary @- << EOF
+{
+ "description": "scrutiny - restricted scope token",
+ "orgID": "${INFLUXDB_ORG_ID}",
+ "permissions": [
+ {
+ "action": "read",
+ "resource": {
+ "type": "orgs"
+ }
+ },
+ {
+ "action": "read",
+ "resource": {
+ "type": "tasks"
+ }
+ },
+ {
+ "action": "write",
+ "resource": {
+ "type": "tasks",
+ "id": "${INFLUXDB_SCRUTINY_WEEKLY_TASK_ID}",
+ "orgID": "${INFLUXDB_ORG_ID}"
+ }
+ },
+ {
+ "action": "write",
+ "resource": {
+ "type": "tasks",
+ "id": "${INFLUXDB_SCRUTINY_MONTHLY_TASK_ID}",
+ "orgID": "${INFLUXDB_ORG_ID}"
+ }
+ },
+ {
+ "action": "write",
+ "resource": {
+ "type": "tasks",
+ "id": "${INFLUXDB_SCRUTINY_YEARLY_TASK_ID}",
+ "orgID": "${INFLUXDB_ORG_ID}"
+ }
+ },
+ {
+ "action": "read",
+ "resource": {
+ "type": "buckets",
+ "id": "${INFLUXDB_SCRUTINY_BASE_BUCKET_ID}",
+ "orgID": "${INFLUXDB_ORG_ID}"
+ }
+ },
+ {
+ "action": "write",
+ "resource": {
+ "type": "buckets",
+ "id": "${INFLUXDB_SCRUTINY_BASE_BUCKET_ID}",
+ "orgID": "${INFLUXDB_ORG_ID}"
+ }
+ },
+ {
+ "action": "read",
+ "resource": {
+ "type": "buckets",
+ "id": "${INFLUXDB_SCRUTINY_WEEKLY_BUCKET_ID}",
+ "orgID": "${INFLUXDB_ORG_ID}"
+ }
+ },
+ {
+ "action": "write",
+ "resource": {
+ "type": "buckets",
+ "id": "${INFLUXDB_SCRUTINY_WEEKLY_BUCKET_ID}",
+ "orgID": "${INFLUXDB_ORG_ID}"
+ }
+ },
+ {
+ "action": "read",
+ "resource": {
+ "type": "buckets",
+ "id": "${INFLUXDB_SCRUTINY_MONTHLY_BUCKET_ID}",
+ "orgID": "${INFLUXDB_ORG_ID}"
+ }
+ },
+ {
+ "action": "write",
+ "resource": {
+ "type": "buckets",
+ "id": "${INFLUXDB_SCRUTINY_MONTHLY_BUCKET_ID}",
+ "orgID": "${INFLUXDB_ORG_ID}"
+ }
+ },
+ {
+ "action": "read",
+ "resource": {
+ "type": "buckets",
+ "id": "${INFLUXDB_SCRUTINY_YEARLY_BUCKET_ID}",
+ "orgID": "${INFLUXDB_ORG_ID}"
+ }
+ },
+ {
+ "action": "write",
+ "resource": {
+ "type": "buckets",
+ "id": "${INFLUXDB_SCRUTINY_YEARLY_BUCKET_ID}",
+ "orgID": "${INFLUXDB_ORG_ID}"
+ }
+ }
+ ]
+}
+EOF
+```
+
+
+
+### Save InfluxDB API Token
+
+After running the Curl command above, you'll see a JSON response that looks like the following:
+
+```json
+{
+ "token": "ksVU2t5SkQwYkvIxxxxxxxYt2xUt0uRKSbSF1Po0UQ==",
+ "status": "active",
+ "description": "scrutiny - restricted scope token",
+ "orgID": "b2495586xxxx",
+ "org": "my-org",
+ "user": "admin",
+ "permissions": [
+ {
+ "action": "read",
+ "resource": {
+ "type": "orgs"
+ }
+ },
+ {
+ "action": "read",
+ "resource": {
+ "type": "tasks"
+ }
+ },
+ {
+ "action": "write",
+ "resource": {
+ "type": "tasks",
+ "id": "09a64exxxxx",
+ "orgID": "b24955860xxxxx",
+ "org": "my-org"
+ }
+ },
+ ...
+ ]
+}
+```
+
+You must copy the token field from the JSON response, and save it in your `scrutiny.yaml` config file. After that's
+done, you can start the Scrutiny server
+
diff --git a/webapp/backend/pkg/database/scrutiny_repository.go b/webapp/backend/pkg/database/scrutiny_repository.go
index 28e0e2d..81f2316 100644
--- a/webapp/backend/pkg/database/scrutiny_repository.go
+++ b/webapp/backend/pkg/database/scrutiny_repository.go
@@ -242,21 +242,29 @@ func (sr *scrutinyRepository) EnsureBuckets(ctx context.Context, org *domain.Org
//create buckets (used for downsampling)
weeklyBucket := fmt.Sprintf("%s_weekly", sr.appConfig.GetString("web.influxdb.bucket"))
- if _, foundErr := sr.influxClient.BucketsAPI().FindBucketByName(ctx, weeklyBucket); foundErr != nil {
+ if foundWeeklyBucket, foundErr := sr.influxClient.BucketsAPI().FindBucketByName(ctx, weeklyBucket); foundErr != nil {
// metrics_weekly bucket will have a retention period of 8+1 weeks (since it will be down-sampled once a month)
_, err := sr.influxClient.BucketsAPI().CreateBucketWithName(ctx, org, weeklyBucket, weeklyBucketRetentionRule)
if err != nil {
return err
}
+ } else if sr.appConfig.GetBool("web.influxdb.retention_policy") {
+ //correctly set the retention period for the bucket (may not be able to do it during setup/creation)
+ foundWeeklyBucket.RetentionRules = domain.RetentionRules{weeklyBucketRetentionRule}
+ sr.influxClient.BucketsAPI().UpdateBucket(ctx, foundWeeklyBucket)
}
monthlyBucket := fmt.Sprintf("%s_monthly", sr.appConfig.GetString("web.influxdb.bucket"))
- if _, foundErr := sr.influxClient.BucketsAPI().FindBucketByName(ctx, monthlyBucket); foundErr != nil {
+ if foundMonthlyBucket, foundErr := sr.influxClient.BucketsAPI().FindBucketByName(ctx, monthlyBucket); foundErr != nil {
// metrics_monthly bucket will have a retention period of 24+1 months (since it will be down-sampled once a year)
_, err := sr.influxClient.BucketsAPI().CreateBucketWithName(ctx, org, monthlyBucket, monthlyBucketRetentionRule)
if err != nil {
return err
}
+ } else if sr.appConfig.GetBool("web.influxdb.retention_policy") {
+ //correctly set the retention period for the bucket (may not be able to do it during setup/creation)
+ foundMonthlyBucket.RetentionRules = domain.RetentionRules{monthlyBucketRetentionRule}
+ sr.influxClient.BucketsAPI().UpdateBucket(ctx, foundMonthlyBucket)
}
yearlyBucket := fmt.Sprintf("%s_yearly", sr.appConfig.GetString("web.influxdb.bucket"))