# 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](https://docs.qpoint.io/getting-started/qtap/installation/helm-chart)

***

## 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](https://docs.qpoint.io/getting-started/qplane/configuration/stacks-and-plugins) - Detailed plugin configuration
* [Object Storage Configuration](https://docs.qpoint.io/getting-started/qplane/configuration/object-storage) - S3 setup for captured payloads
* [Alerting](https://docs.qpoint.io/getting-started/qplane/configuration/alerting) - Configure notifications for issues
