Environment Variables
Monitored targets are configured exclusively on the UI Data Sources page - MySQL / MongoDB / Redis / Kafka / Elasticsearch / hosts / Flink no longer have corresponding environment variables. Add them on the Data Sources page after startup, or bulk-import a YAML template (each entry is connection-tested during import). Changes take effect immediately, with no container restart.
1.4.x allowed declaring monitored targets in ops.yaml via ENV_MYSQL_* / ENV_REDIS_* and
seeded them into data sources on first startup. That mechanism was removed in 1.5.0 - those
variables are no longer read (setting them has no effect; the startup log lists them explicitly).
Existing data sources are preserved when upgrading from 1.4.x; simply delete those lines from
ops.yaml.
Every other variable on this page (token, subpath, retention, object storage, Alloy, ...) is unaffected and remains authoritative here.
All Ops Platform configuration is passed in through environment variables: written in ops.yaml for Docker Compose, or in a ConfigMap for Kubernetes. The tables below are grouped by purpose. Anything not marked as required is optional and falls back to its default if unset.
General / Gateway
| Environment Variable | Description |
|---|---|
| ENV_OPS_TOKEN | Access authentication key for the Ops Platform; be sure to change it on first deployment |
| ENV_OPS_SUB_PATH | Reverse proxy sub-path. Not needed for direct port access; once set, both the gateway and Grafana automatically adapt GF_SERVER_ROOT_URL and GF_SERVER_SERVE_FROM_SUB_PATH. Example: /mdis |
| ENV_OPS_PORT | Internal listening port of ops-server, default 8081, usually no need to change |
| ENV_OPS_GATEWAY_PORT | External port of the gateway, default 48881 |
Host Monitoring (Node Exporter)
No environment variables. Add a Host data source on the UI Data Sources page, using the
address format IP:59100 (the port is fixed at 59100).
Docker Compose hosts and nodes inside a Kubernetes cluster already run ops-nodeagent (listening on 59100 automatically) - do not add them again and do not install a separate node_exporter. Only additional external hosts need an entry here.
Cluster Monitoring (Kubernetes)
Since Ops Platform 1.3.0, monitoring a Kubernetes cluster (nodes, containers, Pods, cluster object state) is supported. For full configuration, see Kubernetes Cluster Monitoring.
| Environment Variable | Description |
|---|---|
| ENV_K8S_MONITOR_MODE | K8s monitoring mode: off (default, disabled) / incluster (discover targets via the ServiceAccount of the cluster it runs in). K8s-form platform deployments ship with incluster preset; when the platform is outside the cluster, the collector components inside the monitored cluster run with this value. ⚠️ Out-of-cluster pulling (static) was removed in 1.5.3 and now has no effect |
| ENV_K8S_CLUSTER_NAME | Cluster identifier, applied as the origin_prometheus label on that cluster's metrics; the K8s dashboards switch clusters by it. Default default. With multiple clusters give each a distinct name (prod-k8s / test-k8s) — never duplicate, never use an IP |
| ENV_K8S_KSM_NAMESPACE | Namespace where kube-state-metrics runs in incluster mode, default mdis-monitoring. ⚠️ Both K8s manifest sets (the single-file ops.yaml and the PVC 11-configmap.yaml) set it to hap-ops, since they ship their own kube-state-metrics there — no change needed. Only the collector components installed inside a monitored cluster use the mdis-monitoring default |
In incluster mode no data source needs to be registered: ops-prometheus discovers
kubelet / cAdvisor / kube-state-metrics through its own ServiceAccount, and changes take
effect immediately.
Middleware and Monitored Targets
No environment variables. MySQL / MongoDB / Redis / Kafka / Elasticsearch are all added on the UI Data Sources page. Each data source can be tagged with one or more purposes:
- Metrics: included in metric collection and shown on the resource monitoring pages
- Alert: included in alert monitoring
- Diagnose (MongoDB only): used as the slow-query diagnostic target. The account needs
clusterMonitorplusdbAdminon the target databases — the platform runsprofile:1there to enable profiling
Exporter ports are assigned automatically - you do not need to care about them.
Bulk Import
Use Bulk Import at the top right of the Data Sources page (YAML or JSON): download the YAML template, replace the addresses, and upload it. Run Validate only first - it performs format validation and a connection probe per entry without writing anything.
Import is idempotent on (type, name): an entry with an existing name is updated rather than duplicated, so the same file can be imported repeatedly; leaving the password empty on an update keeps the stored one. A failed probe does not block the import, but every failure is listed.
Automated deployments can call the endpoint directly:
curl -X POST "http://YOUR_SERVER_IP:48881/api/alert/sources/import" \
-H "Content-Type: application/yaml" \
--data-binary @datasources.yaml
- For a MySQL cluster, list the real node addresses - not a read/write-splitting entry point such as mysqlrouter, which only exposes whichever backend you get routed to and hides member state
- The Elasticsearch username shipped with Mingdao private deployments is
md, notelastic; getting it wrong looks like a live exporter that returns no metrics at all - For a MongoDB replica set, list all members in the URI, comma-separated
Data Source Service Discovery
agent polls ops-server every 30 seconds for data sources that are enabled and tagged with the
metrics purpose, starting and reclaiming exporters as needed; Prometheus scrape targets are
likewise pushed by the registry and hot-reloaded. This is why data source edits take effect
immediately.
| Variable | Description |
|---|---|
| ENV_OPS_SD_URL | Address ops-prometheus / agent use to reach the registry (ops-server). Default http://gateway:8081. Note: this is ops-server's own port 8081, not the gateway's public 48881 (that is nginx, which has no /api/sd routes). On Kubernetes the Service must expose both ports |
| ENV_OPS_SD_TOKEN | Access token for the registry endpoints; must match across gateway, ops-prometheus and agent. Empty disables the check (only advisable on a Docker internal network) |
| ENV_AGENT_SD_HOST | Hostname of the agent service (used by Prometheus to address exporters). Default agent; rarely needs changing |
Check the agent container log first. Repeated [sd] failed to fetch xxx means it cannot reach
the registry - most often ENV_OPS_SD_URL points at 48881, or the Kubernetes Service exposes only
48881 and not 8081. In that state no exporter starts at all and every middleware dashboard is empty.
Data Retention Periods
| Environment Variable | Description |
|---|---|
| ENV_PROMETHEUS_RETENTION | Prometheus metrics data retention period, default 15d if unset. Example: 30d |
| ENV_LOKI_RETENTION | Loki log data retention period, default 720h (30 days) if unset. Example: 360h |
| ENV_TEMPO_RETENTION | Tempo trace data retention period, default 720h (30 days) if unset. Example: 360h |
Observability Collection (Alloy)
| Environment Variable | Description |
|---|---|
| ENV_TEMPO_GRPC_URL | gRPC address for alloy to forward trace data to Tempo. Example: http://ops-tempo:4317 |
| ENV_PROMETHEUS_REMOTE_WRITE_URL | remote_write target, used in two scenarios: (1) alloy reporting the platform's own metrics, direct in-cluster, e.g. http://ops-prometheus:9090/prometheus/server/api/v1/write; (2) collector components in another K8s cluster pushing metrics back — these must go through the gateway port with a token, e.g. http://<platform>:30881/mdis/prometheus/server/api/v1/write (the platform's ops-prometheus is a ClusterIP and :9090 is unreachable from outside) |
| ENV_PROMETHEUS_REMOTE_WRITE_TOKEN | Bearer token for the gateway route above; use the platform's ENV_OPS_TOKEN. Without it the gateway returns 401, visible only in the collector's log while the UI just shows no data. Not needed when connecting directly to :9090 |
| ENV_LOKI_PUSH_URL | HTTP API address for alloy to push logs to Loki. Example: http://ops-loki:3100/loki/api/v1/push |
| ENV_LOKI_PUSH_TOKEN | Bearer token for log pushes. Only needed when the collector is in another cluster and pushes through the platform gateway (use the platform's ENV_OPS_TOKEN); leave empty when connecting directly to ops-loki in-cluster. Going through the gateway without it returns 401, visible only in the collector's log |
Log Storage Backend (Loki S3/MinIO, Optional)
Uses Loki's local filesystem storage when unset.
| Environment Variable | Description |
|---|---|
| ENV_S3_ENDPOINT | S3-compatible storage endpoint, given as host:port — do not include http://. Example: minio:9000. Tencent COS example: cos.ap-hongkong.myqcloud.com (without bucket prefix). Tempo's minio-go client only accepts host:port; a scheme makes it fail with Endpoint url cannot have fully qualified paths. On the Loki side the protocol is controlled by insecure in its config, so no scheme is needed there either |
| ENV_S3_BUCKET_LOKI | Bucket for logs (Loki). Example: mdis-loki. The bucket must exist before deployment — if it does not, Loki fails with NoSuchBucket and restarts in a loop |
| ENV_S3_BUCKET_TEMPO | Bucket for traces (Tempo). Example: mdis-tempo. Must be a different bucket from Loki's, and must also be created beforehand |
| ENV_S3_BUCKET | Legacy shared bucket name, kept only for backward compatibility (used as a fallback when neither variable above is set). Do not use it for new deployments: it feeds both Loki and Tempo, and sharing one bucket prevents Tempo from starting |
| ENV_S3_ACCESS_KEY | S3 access key |
| ENV_S3_SECRET_KEY | S3 secret key |
| ENV_S3_FORCE_PATH_STYLE | Bucket addressing style. true (default) = path-style, works for MinIO / UCloud US3; Tencent COS / Alibaba OSS only support virtual-host, so set false. Shared by Loki (AWS SDK) and Tempo (minio-go, which maps it to bucket_lookup_type to force DNS) |
Alert Subsystem (Since 1.4.0)
Ops Platform 1.4.0 includes a built-in, self-developed alert subsystem. Alert configuration data (rules/state/history/notification channels/data sources) is stored in a dedicated ops-mongo container, fully decoupled from the business MongoDB being monitored.
| Environment Variable | Description |
|---|---|
| ENV_OPS_MONGODB_URI | MongoDB connection address for the alert subsystem's own storage, pointing to the built-in ops-mongo container by default. Example: mongodb://ops-mongo:27017 |
| ENV_MONGODB_COLLECTION_PREFIX | Common prefix for the alert subsystem's collection names. Example: mdis_ |
| ENV_ALERT_CRYPTO_KEY | AES encryption key for data source credentials (passwords/URIs) before they are persisted. Be sure to change it to a random string on first deployment and keep it safe. After changing the key, previously saved credentials can no longer be decrypted and must be re-entered |
Alert notification channels (Feishu / DingTalk / WeCom / Email / custom Webhook) are configured on the Alert → Notification Channels page in the Ops Platform UI, no longer via environment variables. The SMTP server details for the email channel are also entered on that page.
Slow Query Diagnostics Tuning (optional)
Adjusts how sensitively MongoDB slow queries are captured. The defaults suit production; in a test environment, lowering the first two makes slow queries much easier to reproduce. The four capture conditions are explained in full under Slow Query Analysis.
| Variable | Description |
|---|---|
| ENV_GATEWAY_DOCS_EXAMINED | Minimum documents examined before a query is recorded, default 100000. This is the condition people get stuck on most — a query that is slow but scans little is never recorded |
| ENV_GATEWAY_CAPTURE_INTERVAL_MS | Collection interval in milliseconds, default 600000 (10 minutes). After generating slow queries you must wait for the next cycle |
| ENV_GATEWAY_PROFILE_SLOW_MS | The slowms threshold in milliseconds that the platform sets on the monitored database, default 100 |
| ENV_GATEWAY_LOG_EXPIRE_MS | How long slow query history is kept in the platform's own database, in milliseconds, default 604800000 (7 days) |
Set these on the gateway service. One further condition is fixed and not configurable: the same query
shape must occur at least 50 times within the last 120 minutes.
Connecting Service Logs (easy to confuse — please read)
The Service Logs feature queries the logs that HAP microservices push into Loki. The switch is on the HAP side, not on this platform.
| Where | Variable | Role | Default |
|---|---|---|---|
| HAP private deployment | ENV_LOKI_URL | Write switch: whether HAP's logservice pushes logs to Loki. Without it the installer sets StoreInLoki to false and nothing is ever written | empty (no writes) |
| Ops Platform | ENV_LOKI_URL | Query address: where this platform reads logs from | http://ops-loki:3100, no configuration needed in a standard deployment |
The two share a name but are not the same thing. When the Service Logs page is empty, the one you need to
set is on the HAP side — point it at a reachable address of this platform's Loki (e.g.
http://ops-platform-host-IP:3100) and restart the HAP services.