> ## Documentation Index
> Fetch the complete documentation index at: https://docs.nuon.co/llms.txt
> Use this file to discover all available pages before exploring further.

# Export Runner Audit Logs

> Forward Nuon runner audit events to your own OTLP-compatible logging backend.

Nuon runners can forward audit events directly from your cloud account to an OTLP-compatible logging backend. This
gives your security and operations teams a customer-owned record of deployment, action workflow, and sandbox activity.

Only records marked with `nuon.audit="true"` are forwarded. Application logs, general runner logs, and other
infrastructure logs are not included.

## Supported environments

Runner audit log export supports AWS, Azure, and GCP install runners:

| Provider | Supported install stack                                                                                    | Configuration secret                               |
| -------- | ---------------------------------------------------------------------------------------------------------- | -------------------------------------------------- |
| AWS      | Generated CloudFormation stack or [Nuon Terraform install stack](https://github.com/nuonco/install-stacks) | `nuon/<install-id>/telemetry-export-config`        |
| Azure    | Generated Azure install stack                                                                              | `telemetry-export-config` in the install Key Vault |
| GCP      | [Nuon Terraform install stack](https://github.com/nuonco/install-stacks)                                   | `<install-id>-telemetry-export-config`             |

The AWS and GCP stacks create the configuration secret and grant the runner read access. On Azure, create the install
Key Vault before deploying the stack; the stack grants its runner managed identity read access. In every case, update
the secret after the stack is provisioned. Backend credentials stay in your cloud account and are not stored by the
Nuon control plane or in Terraform state.

## Prerequisites

You will need:

* A current Nuon runner on AWS, Azure, or GCP
* The current install stack, applied to configure runner access to the cloud secret manager
* An OTLP/HTTP logs endpoint available over HTTPS
* Any headers required to authenticate with your logging backend
* Permission to add a secret value in your cloud account

## Create the configuration

Save the following configuration as `telemetry-export-config.yaml`:

```yaml telemetry-export-config.yaml theme={null}
version: v1

telemetry:
  logs:
    audit:
      enabled: true

exporters:
  otlphttp:
    endpoint: https://otlp.example.com
    headers:
      Authorization: Bearer <token>
```

## Configuration reference

| Field                          | Required                       | Description                                                           |
| ------------------------------ | ------------------------------ | --------------------------------------------------------------------- |
| `version`                      | Yes                            | Configuration format version. Set to `v1`.                            |
| `telemetry.logs.audit.enabled` | No                             | Set to `true` to enable runner audit log export. Defaults to `false`. |
| `exporters.otlphttp.endpoint`  | Yes, when telemetry is enabled | HTTPS URL for the OTLP/HTTP backend.                                  |
| `exporters.otlphttp.headers`   | No                             | Headers used to authenticate with the backend.                        |

The endpoint cannot contain credentials, a query string, a fragment, or environment-variable expansion. Omit
`headers` if your backend does not require them.

## Update the configuration secret

Apply or update the install stack first, then use the command for your provider to update the configuration secret.

### AWS

Generated CloudFormation stacks and Nuon Terraform install stacks both create the same secret. Update it after the
stack finishes provisioning:

```sh theme={null}
aws secretsmanager put-secret-value \
  --secret-id "nuon/<install-id>/telemetry-export-config" \
  --secret-string file://telemetry-export-config.yaml \
  --region "<aws-region>"
```

For an existing CloudFormation install, reprovision the install to generate the current template and update the stack
before updating the secret. For a Terraform install, update the install stack module and run `terraform apply` first.

### Azure

The install Key Vault name is the first 24 characters of the install ID. Update the secret after the Azure stack finishes
provisioning:

```sh theme={null}
az keyvault secret set \
  --vault-name "<install-key-vault>" \
  --name "telemetry-export-config" \
  --file "telemetry-export-config.yaml" \
  --encoding utf-8
```

### GCP

The Nuon Terraform install stack creates the secret. Update it after `terraform apply` finishes:

```sh theme={null}
gcloud secrets versions add "<install-id>-telemetry-export-config" \
  --data-file="telemetry-export-config.yaml" \
  --project="<gcp-project-id>"
```

The runner checks for changes every 30 seconds and applies a changed valid configuration without restarting the runner.

## Runner access to the configuration

Nuon-generated Stacks grant the runner the required read access:

| Provider | Runner identity                              | Access                                                              |
| -------- | -------------------------------------------- | ------------------------------------------------------------------- |
| AWS      | Runner instance role                         | `secretsmanager:GetSecretValue` and `secretsmanager:DescribeSecret` |
| Azure    | Runner VMSS system-assigned managed identity | Key Vault Secrets User                                              |
| GCP      | Runner service account                       | Secret Manager Secret Accessor                                      |

## Exported attributes

Every exported record includes attributes that identify it as a Nuon runner audit event:

| Attribute             | Value                               |
| --------------------- | ----------------------------------- |
| `nuon.audit`          | `true`                              |
| `nuon.audit.event`    | The audited operation type          |
| `nuon.audit.outcome`  | `started`, `succeeded`, or `failed` |
| `service.namespace`   | `nuon`                              |
| `service.name`        | `runner`                            |
| `service.version`     | The runner version, when available  |
| `service.instance.id` | The runner ID, when available       |

Records also include relevant identifiers such as `org.id`, `install.id`, `runner_job.group`,
`runner_job.operation`, and entity-specific component, deploy, action workflow, or sandbox identifiers when available.

## Verify export

1. Update the secret with a valid configuration.
2. Check the runner logs for `runner telemetry export collector enabled` with `audit_export.enabled=true`.
3. Trigger a deployment, action workflow, or sandbox operation.
4. Query your logging backend for records where `service.namespace="nuon"` and `nuon.audit="true"`.

Audit events are produced when supported runner operations occur. A newly enabled exporter may remain quiet until one
of these operations runs.

## Update, rotate, or disable export

Edit `telemetry-export-config.yaml` and run the same provider upload command to change the endpoint or rotate
authentication headers. The runner detects the new secret value automatically.

To disable audit export while leaving the telemetry collector available for future telemetry types, set
`telemetry.logs.audit.enabled` to `false` and update the secret. The collector runs without an audit log pipeline. To stop
the telemetry collector entirely, remove or disable the secret value or remove runner access to it. Normal runner
operations and Nuon-managed logging continue unchanged.

## Failure behavior

Audit export does not block runner jobs. A missing, empty, disabled, or inaccessible secret stops the telemetry
collector. An invalid changed value or a transient read or startup failure does not replace a previously active valid
configuration. Once a valid configuration becomes available, the runner detects it automatically.

Delivery is best effort. The collector queues and retries exports, but records may be dropped during a prolonged backend
outage. Runner jobs continue operating normally while the backend is unavailable.

## Troubleshooting

### The configuration secret does not exist

Reprovision the install and apply the latest generated CloudFormation or Terraform stack. On Azure, create the Key
Vault shown in the dashboard before deploying the install stack.

### AWS reports that the secret is scheduled for deletion

If a secret with the same name is already scheduled for deletion, the Stack cannot create it. If the value does not
need to be retained, permanently delete the scheduled secret, wait for deletion to complete, and retry the Stack update:

```sh theme={null}
aws secretsmanager delete-secret \
  --secret-id "nuon/<install-id>/telemetry-export-config" \
  --force-delete-without-recovery \
  --region "<aws-region>"
```

If the value must be retained, restore and copy it before permanently deleting the old secret.

### The runner reports that audit export is disabled

Confirm that the provider-specific secret shown above contains a current value and that the runner identity can read it.
Check the runner logs for `telemetry_export.reason`, which distinguishes a missing, empty, or inaccessible secret.

### The configuration is rejected

Confirm that:

* The secret contains valid YAML matching the configuration example
* The YAML has `version: v1`
* `telemetry.logs.audit.enabled` is a boolean
* The YAML contains `exporters.otlphttp.endpoint` and optional `exporters.otlphttp.headers` when audit export is enabled
* The endpoint uses HTTPS and does not contain credentials, a query string, a fragment, or environment-variable expansion
* Header names are valid HTTP header names and header values do not contain line breaks

### Export is enabled, but no records appear

* Trigger a deployment, action workflow, or sandbox operation to produce an audit event.
* Query for both `service.namespace="nuon"` and `nuon.audit="true"`.
* Confirm that the OTLP endpoint accepts logs over OTLP/HTTP.
* Check the runner logs for TLS, proxy, authentication, or exporter errors.
