Skip to content

Deploy a Multi-Service Stack with Secrets

Prerequisites:

This guide walks through deploying a three-service monitoring stack (VictoriaMetrics, Telegraf, Grafana) using Docker Compose, with the Grafana admin password injected from a Qbee secret. Hardcoding the password in the compose file exposes it to anyone who can read the configuration. Instead, you define the value once on the Parameters tab, template it into the compose file, and let the agent inject it at converge time. The secret value never appears in the committed configuration or in device logs.

The stack is fully self-contained: the Telegraf configuration is defined inline in the compose file via a Compose configs block, so there are no host files or bind mounts to manage.

The stack consists of:

  • VictoriaMetrics -- time-series database, stores the metrics collected by Telegraf.
  • Telegraf -- metrics collector, writes system metrics to VictoriaMetrics over its InfluxDB-compatible API.
  • Grafana -- visualization, reads from VictoriaMetrics and renders dashboards.

Step 1 — Define the secret

Define the Grafana admin password as a secret. Secrets are redacted from logs and cannot be retrieved once saved.

  1. Navigate to Configure and select the level (or a parent) where the stack will run.
  2. Open the Parameters bundle.
  3. Under Secrets, add:
  4. GRAFANA_ADMIN_PASSWORD with your desired Grafana admin password (for example, my-grafana-password)
  5. Click Save settings.

Expected outcome: The secret appears in the parameters list. Its value is redacted and cannot be retrieved later.

Secret values are write-only

Once a secret is saved, its value is redacted and cannot be retrieved. You can update the secret by setting a new value, which will be used on the next convergence. See Parameters and secrets for details.


Step 2 — Configure the Docker Compose project

The compose file defines all three services. The Grafana service needs its admin password set through environment, so the compose file is a template with the password injected from the secret. The Telegraf configuration is defined inline via a Compose configs block, so no host file or bind mount is needed.

  1. Open the Docker compose bundle and click + to add a project.
  2. Enter the project name monitoring-stack.
  3. Upload the following compose.yml file:
services:
  victoriametrics:
    image: victoriametrics/victoria-metrics:latest
    ports:
      - "8428:8428"
    volumes:
      - vmdata:/vmdata
    command:
      - "--storageDataPath=/vmdata"
      - "--retentionPeriod=1"
    networks:
      - monitoring

  telegraf:
    image: telegraf:1.30
    depends_on:
      - victoriametrics
    networks:
      - monitoring
    configs:
      - source: telegraf-config
        target: /etc/telegraf/telegraf.conf

  grafana:
    image: grafana/grafana-oss:latest
    ports:
      - "3000:3000"
    environment:
      - GF_SECURITY_ADMIN_PASSWORD={{GRAFANA_ADMIN_PASSWORD}}
    volumes:
      - grafana-data:/var/lib/grafana
    depends_on:
      - victoriametrics
    networks:
      - monitoring

volumes:
  vmdata:
  grafana-data:

configs:
  telegraf-config:
    content: |
      [agent]
        interval = "10s"
        flush_interval = "10s"

      [[outputs.influxdb]]
        urls = ["http://victoriametrics:8428"]
        database = "telegraf"
        skip_database_creation = true

      [[inputs.cpu]]
        percpu = true
        totalcpu = true

      [[inputs.mem]]
      [[inputs.disk]]
      [[inputs.diskio]]
      [[inputs.system]]

networks:
  monitoring:
  1. Enable templating on the compose file and add the template parameters:
  2. Key: GRAFANA_ADMIN_PASSWORD
  3. Value: $(GRAFANA_ADMIN_PASSWORD)
  4. Click Save settings.

Expected outcome: The project appears in the Docker Compose form with the compose file attached and the template parameter mapped to the secret.


Step 3 — Commit and verify

Click Commit changes in the top right. Optionally enter a commit message, then click Commit.

Within one polling cycle the agent applies the Docker Compose project -- with the Grafana admin password substituted into the environment -- pulls the images, and starts the three containers.

To verify, open the device in the console and check the device inventory tab. The monitoring-stack-victoriametrics-1, monitoring-stack-telegraf-1, and monitoring-stack-grafana-1 containers should all appear with a status of running.

Alternatively, open a remote console on the device and run:

docker compose ls
docker compose -p monitoring-stack ps

Expected outcome: The monitoring-stack project appears with all three services running.

To confirm Grafana accepted the injected password, open a browser at http://<device-ip>:3000 and sign in as admin with the password you defined as a secret.

A container is not running

If any of the three containers is missing or has exited, open a remote console and check its logs:

docker compose -p monitoring-stack logs <service>

Replace <service> with victoriametrics, telegraf, or grafana. The most common cause is the image failing to pull -- verify the device can reach the registry and that the agent has converged since the commit.


Done

You have deployed a self-contained multi-service monitoring stack. The Grafana admin password exists in exactly one place (the Parameters tab) and is never committed to the configuration or exposed in device logs. Everything else -- including the Telegraf configuration -- lives in the compose file, so there are no host files or bind mounts to maintain.

What Next?

I want to... Go to
Deploy a simpler single-project stack Deploy a Docker Compose Project
Use the same pattern for a single container Deploy a Docker Container
Understand parameters and secrets in depth Parameters and secrets
Access the running containers Remote Access
View container status Inventory