> For the complete documentation index, see [llms.txt](https://docs.qpoint.io/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.qpoint.io/guides/qplane-guides/gitops-configuration-management.md).

# GitOps Configuration Management

Manage Qtap configuration through Git while using Qplane for visualization, search, and dashboards.

***

## Why This Approach

**GitOps benefits:**

* Version-controlled configuration with full audit trail
* Pull request reviews for config changes
* Reproducible deployments across environments
* Rollback capability through git history
* Infrastructure-as-code workflows (ArgoCD, Flux, etc.)

**Qplane benefits:**

* Real-time dashboards and traffic visualization
* Object storage search and retrieval
* Alerting and issue detection
* No infrastructure to manage for the control plane

**The tradeoff:** Configuration lives in git, not Qplane's UI. Changes made in Qplane won't affect your deployed agents.

***

## How It Works

```
┌─────────────────────────────────────────────────────────────────┐
│                        Your Workflow                            │
├─────────────────────────────────────────────────────────────────┤
│                                                                 │
│   1. Configure in Qplane UI                                     │
│              ↓                                                  │
│   2. Export snapshot (YAML)                                     │
│              ↓                                                  │
│   3. Commit to git repository                                   │
│              ↓                                                  │
│   4. Deploy via GitOps (Helm, ArgoCD, etc.)                     │
│              ↓                                                  │
│   5. Qtap runs with static config                               │
│              ↓                                                  │
│   6. Events flow to Qplane for visualization                    │
│                                                                 │
└─────────────────────────────────────────────────────────────────┘
```

Qtap agents run with your git-managed configuration but still send telemetry to Qplane. You get GitOps workflow control with Qplane's visualization capabilities.

***

## Step 1: Configure in Qplane

Start by setting up your configuration in Qplane's UI:

1. Log in to [app.qpoint.io](https://app.qpoint.io/)
2. Configure your stacks, plugins, and capture rules
3. Set up error detection rules
4. Configure PII/sensitive data monitors
5. Define endpoint-specific behaviors
6. Set up tagging for your environment

Use the UI to experiment and validate your configuration before committing to git.

***

## Step 2: Export Your Configuration Snapshot

Once your configuration is ready:

1. Navigate to **Settings → Snapshot**
2. Copy the YAML configuration

The snapshot includes everything:

* Services (event stores, object stores)
* Stacks and plugins configuration
* Tag extraction rules
* Tap settings (direction, filters, endpoints)

**Example snapshot:**

```yaml
version: 2

services:
  event_stores:
    - id: qpoint
      type: pulse
      url: https://api-pulse.qpoint.io
      token:
        type: env
        value: REGISTRATION_TOKEN
  object_stores:
    - id: my_s3_storage
      type: s3
      endpoint: s3.amazonaws.com
      bucket: qtap-objects
      region: us-east-1
      access_url: https://s3.amazonaws.com/{{BUCKET}}/{{DIGEST}}
      insecure: false
      access_key:
        type: env
        value: S3_ACCESS_KEY
      secret_key:
        type: env
        value: S3_SECRET_KEY

stacks:
  default:
    plugins:
      - type: report_usage
      - type: qscan
        config:
          monitors:
            - type: CREDIT_CARD
              record_value: false
            - type: US_SSN
              record_value: false
      - type: detect_errors
        config:
          rules:
            - name: App Error
              trigger_status_codes:
                - '500'
              report_as_issue: true
              record_req_headers: true
              record_res_body: true

tap:
  direction: egress-external
  ignore_loopback: true
  audit_include_dns: false
  http:
    stack: default
  filters:
    groups:
      - qpoint
      - container-runtimes
```

{% hint style="info" %}
The `pulse` event store with your `REGISTRATION_TOKEN` is what connects Qtap to Qplane. Events and metrics flow to Qplane for visualization even though configuration is managed through git.
{% endhint %}

**How object storage works with Qplane:**

When you configure your own S3 object store, the `access_url` tells Qplane how to link to your stored objects. When you investigate a connection in the Qplane UI that was captured by a rule (like `detect_errors`), Qplane renders a direct link to your S3 using this URL template.

For example, with `access_url: http://100.75.117.58:3904/qpoint/{{DIGEST}}`, clicking on a captured request in Qplane opens your object directly from your storage. Your sensitive HTTP payloads stay in your infrastructure while Qplane provides the search and navigation interface.

***

## Step 3: Secure Your Secrets

The snapshot references secrets via environment variables - it doesn't contain the actual values:

```yaml
token:
  type: env
  value: REGISTRATION_TOKEN    # References env var, not the actual token
```

**This means the snapshot is safe to commit to git.** But you need to provision the actual secret values separately using your secret management solution.

### Secrets You'll Need

| Secret               | Purpose                                   | Where to Find                                                  |
| -------------------- | ----------------------------------------- | -------------------------------------------------------------- |
| `REGISTRATION_TOKEN` | Connects Qtap to Qplane for telemetry     | **Settings → Environments → Manage → Copy Registration Token** |
| `S3_ACCESS_KEY`      | Object store authentication (if using S3) | Your S3 provider                                               |
| `S3_SECRET_KEY`      | Object store authentication (if using S3) | Your S3 provider                                               |

### With External Secrets Operator

[External Secrets Operator](https://external-secrets.io/) syncs secrets from your vault to Kubernetes:

```yaml
apiVersion: external-secrets.io/v1beta1
kind: ExternalSecret
metadata:
  name: qtap-secrets
  namespace: qpoint
spec:
  refreshInterval: 1h
  secretStoreRef:
    name: vault-backend      # Your SecretStore
    kind: SecretStore
  target:
    name: qtap-secrets
  data:
    - secretKey: REGISTRATION_TOKEN
      remoteRef:
        key: qpoint/qtap
        property: registration-token
    - secretKey: S3_ACCESS_KEY
      remoteRef:
        key: qpoint/qtap
        property: s3-access-key
    - secretKey: S3_SECRET_KEY
      remoteRef:
        key: qpoint/qtap
        property: s3-secret-key
```

### With Sealed Secrets

[Sealed Secrets](https://github.com/bitnami-labs/sealed-secrets) encrypts secrets for safe git storage:

```bash
# Encrypt your secrets (safe to commit the output)
kubectl create secret generic qtap-secrets \
  --from-literal=REGISTRATION_TOKEN='your-token' \
  --from-literal=S3_ACCESS_KEY='your-key' \
  --from-literal=S3_SECRET_KEY='your-secret' \
  --dry-run=client -o yaml | kubeseal -o yaml > sealed-qtap-secrets.yaml
```

Commit `sealed-qtap-secrets.yaml` to git. The Sealed Secrets controller decrypts it in-cluster.

### With HashiCorp Vault Agent

If using Vault Agent Injector, annotate your Qtap deployment to inject secrets:

```yaml
annotations:
  vault.hashicorp.com/agent-inject: "true"
  vault.hashicorp.com/role: "qtap"
  vault.hashicorp.com/agent-inject-secret-config: "qpoint/qtap"
  vault.hashicorp.com/agent-inject-template-config: |
    {{- with secret "qpoint/qtap" -}}
    export REGISTRATION_TOKEN="{{ .Data.data.registration_token }}"
    export S3_ACCESS_KEY="{{ .Data.data.s3_access_key }}"
    export S3_SECRET_KEY="{{ .Data.data.s3_secret_key }}"
    {{- end -}}
```

### Referencing Secrets in Helm

Once your secrets exist in the cluster, reference them in your Helm deployment:

```yaml
# values.yaml
extraEnv:
  - name: REGISTRATION_TOKEN
    valueFrom:
      secretKeyRef:
        name: qtap-secrets
        key: REGISTRATION_TOKEN
  - name: S3_ACCESS_KEY
    valueFrom:
      secretKeyRef:
        name: qtap-secrets
        key: S3_ACCESS_KEY
  - name: S3_SECRET_KEY
    valueFrom:
      secretKeyRef:
        name: qtap-secrets
        key: S3_SECRET_KEY
```

{% hint style="success" %}
**GitOps-friendly pattern:** Store the encrypted/external secret reference in git alongside your snapshot. The actual secret values live in your vault, never in git.
{% endhint %}

***

## Step 4: Commit Snapshot to Git

Save the exported snapshot directly to your infrastructure repository:

```
infrastructure/
├── qtap/
│   └── qtap-config.yaml      # Your exported snapshot (use as-is)
```

{% hint style="warning" %}
**Don't modify the snapshot.** The snapshot from Qplane is your source of truth. Editing it manually defeats the purpose of using Qplane for configuration and introduces drift between what Qplane shows and what's deployed.
{% endhint %}

**Deploying with Helm:**

The Qtap Helm chart accepts your config file directly via `--set-file`:

```bash
helm install qtap qpoint/qtap \
  -n qpoint \
  --create-namespace \
  --set-file config=./qtap-config.yaml
```

The chart creates the necessary ConfigMap from your file automatically.

For complete Helm installation instructions, see:

* [Qtap Helm Chart](/getting-started/qtap/installation/helm-chart.md)

***

## Step 5: Deploy via GitOps

### With ArgoCD

```yaml
apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
  name: qtap
  namespace: argocd
spec:
  project: default
  source:
    repoURL: https://github.com/your-org/infrastructure
    targetRevision: main
    path: qtap/prod
    helm:
      releaseName: qtap
      fileParameters:
        - name: config
          path: qtap-config.yaml
  destination:
    server: https://kubernetes.default.svc
    namespace: qpoint
  syncPolicy:
    automated:
      prune: true
      selfHeal: true
```

### With Flux

```yaml
apiVersion: helm.toolkit.fluxcd.io/v2beta1
kind: HelmRelease
metadata:
  name: qtap
  namespace: qpoint
spec:
  interval: 5m
  chart:
    spec:
      chart: qtap
      sourceRef:
        kind: HelmRepository
        name: qpoint
        namespace: flux-system
  valuesFrom:
    - kind: ConfigMap
      name: qtap-config
      valuesKey: qtap-config.yaml
```

### Manual Helm

```bash
helm upgrade --install qtap qpoint/qtap \
  -n qpoint \
  --set-file config=./qtap-config.yaml
```

***

## Configuration Drift

{% hint style="warning" %}
**Important:** Once you deploy via GitOps, changes made in Qplane's UI will NOT affect your running agents. Your git repository is the source of truth.
{% endhint %}

**To update configuration:**

1. Make changes in Qplane UI
2. Test and validate in the Qplane interface
3. Export a new snapshot
4. Replace the config in your git repository
5. Submit a pull request for review
6. Merge and let GitOps sync the changes

{% hint style="danger" %}
**Avoid editing the YAML directly in git.** Manual edits create drift between Qplane's view and your deployed configuration. Always make changes in Qplane first, then export.
{% endhint %}

***

## User Permissions

To prevent accidental configuration drift from UI changes:

1. Navigate to **Settings → Team Members**
2. Set most users to **Viewer** role
3. Reserve **Admin** or **Editor** roles for config managers

Viewers can:

* Access all dashboards and visualizations
* Search and view captured objects
* See alerts and issues

Viewers cannot:

* Modify stacks or plugins
* Change capture rules
* Alter endpoint configurations

This ensures the git repository remains the authoritative source while your team still benefits from Qplane's visualization.

***

## What You Get from Qplane

Even with GitOps-managed configuration, Qplane provides:

| Feature                       | Description                                                 |
| ----------------------------- | ----------------------------------------------------------- |
| **Traffic Dashboards**        | Real-time visibility into all captured traffic              |
| **Vendor Inventory**          | Automatic discovery of external APIs                        |
| **Object Search & Retrieval** | Find captured payloads and click through to your S3 storage |
| **Issue Detection**           | Alerts based on your `detect_errors` rules                  |
| **PII Monitoring**            | Results from `qscan` plugin analysis                        |
| **Usage Metrics**             | Performance data from `report_usage` plugin                 |

The `pulse` event store streams all this data to Qplane regardless of how the configuration was deployed.

{% hint style="info" %}
**Why Qplane for object search?** When Qtap captures a request/response to your S3, Qplane indexes the metadata and provides a searchable interface. Click any captured connection to open the full payload directly from your storage via the `access_url` you configured. Without Qplane, you'd need to build your own search and retrieval tooling.
{% endhint %}

***

## Environment-Specific Configuration

If you need different configurations per environment (dev, staging, prod), manage them as separate snapshots in Qplane:

1. Create separate Qplane environments or organizations
2. Configure each environment appropriately in the UI
3. Export a snapshot for each environment
4. Store each snapshot in your git repository under environment-specific paths

```
infrastructure/
├── qtap/
│   ├── dev/
│   │   └── qtap-config.yaml      # Snapshot from dev environment
│   ├── staging/
│   │   └── qtap-config.yaml      # Snapshot from staging environment
│   └── prod/
│       └── qtap-config.yaml      # Snapshot from prod environment
```

This keeps each environment's configuration as a complete, unmodified snapshot from Qplane rather than trying to patch or overlay configurations.

***

## Workflow Summary

| Step | Where           | Action                              |
| ---- | --------------- | ----------------------------------- |
| 1    | Qplane UI       | Configure and experiment            |
| 2    | Qplane Settings | Export snapshot                     |
| 3    | Vault           | Store secrets (token, S3 keys)      |
| 4    | Git             | Commit snapshot + secret references |
| 5    | CI/CD           | Review via pull request             |
| 6    | GitOps          | Deploy to clusters                  |
| 7    | Qplane          | Monitor and visualize               |

***

## What's Next

* [Stacks & Plugins Reference](/getting-started/qplane/configuration/stacks-and-plugins.md) - Detailed plugin configuration
* [Object Storage Configuration](/getting-started/qplane/configuration/object-storage.md) - S3 setup for captured payloads
* [Alerting](/getting-started/qplane/configuration/alerting.md) - Configure notifications for issues


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter, and the optional `goal` query parameter:

```
GET https://docs.qpoint.io/guides/qplane-guides/gitops-configuration-management.md?ask=<question>&goal=<endgoal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is optional and describes the broader end goal you are ultimately trying to accomplish on behalf of the user. GitBook uses it to tailor the answer towards what is most useful for that goal.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
