Skip to content

Installation

Deploy Auditty Edge on Kubernetes, Linux VMs, the CLI, or as a network (OTLP) proxy

Kubernetes (Helm)

Deploy Auditty Edge on any Kubernetes cluster via Helm. The core components are:

  • auditty-edge (DaemonSet) — runs on every node to intercept and process container logs. Runs as root with two scoped Linux capabilities (DAC_READ_SEARCH, SYS_PTRACE), not in privileged mode
  • auditty-edge-api (Deployment) — non-privileged cluster-level service with RBAC permissions to query the K8s API
  • auditty-edge-compactor (CronJob) — created automatically when Vault is enabled, runs hourly to optimize archived data for fast retrieval

Resource Sizing

Edge runs as a DaemonSet — resources are allocated per node. The right sizing depends on log throughput, not pod count — a single high-volume workload can produce more logs than dozens of lightweight services.

ProfileCPUMemoryLog throughput
Standard500m512MiUp to ~5K lines/sec per node
High throughput1 CPU1Gi5K–20K lines/sec per node
Extreme2 CPU1.5Gi20K+ lines/sec per node

Prerequisites

  • Helm installed on your system
  • Access to a Kubernetes cluster
  • A namespace to install into — defaults to auditty, but any namespace works via --namespace <name> (add --create-namespace if it does not exist). Edge reads its own namespace at runtime, so self-monitoring is prevented wherever you install it.

Step 1: Prepare values.yaml

Create and configure your values.yaml file. At minimum set hivemind_api_key and cluster_name.

Step 2: Install via Helm

helm upgrade --install auditty-edge oci://ghcr.io/auditty/helm-charts/auditty-edge --version <tag> --namespace auditty --create-namespace --values values.yaml

*Use the version tag provided by your CX contact.

Using ArgoCD?

Set repoURL to the full OCI path including the chart name:

repoURL: ghcr.io/auditty/helm-charts/auditty-edge
targetRevision: "<tag>"

What Happens Next

  • auditty-edge pods deploy as DaemonSet (one per node)
  • auditty-edge-api pod deploys as Deployment (one replica)
  • auditty-edge-compactor CronJob is created automatically when Vault is enabled
  • This typically takes a few seconds
  • If pods fail to start, check their logs for more information
  • Log processing begins as soon as the pods are running

Strict / Proxied Clusters

On clusters that force all egress through a forward proxy or enforce a default-deny NetworkPolicy, set both of the following — otherwise metrics show zero active nodes and Vault backfill links never appear:

  • proxy.httpsProxy / proxy.httpProxy — routes outbound calls (Vault uploads, Auditty) through your proxy. In-cluster traffic (edge → edge-api, the K8s API) is excluded from the proxy automatically.
  • networkPolicy.enabled: true — opens the edge → edge-api hop on port 8080. Without it that internal call is dropped, silently disabling metrics reporting and backfill-URL generation.
  • networkPolicy.restrictEgress stays false unless you have mapped your egress. If you turn it on while using a forward proxy, add the proxy’s CIDR/port to egressHTTPSCIDRs first — proxy traffic uses the proxy port (e.g. 8080), not 443, so the default 443-only rules would block it.

Values.yaml Configuration

Complete values.yaml template with all configurable fields.

Important Configuration

  • hivemind_api_key is mandatory — provide via helm install, values.yaml, or secretRef
  • secretRef — store API key in a Kubernetes Secret instead of ConfigMap
  • cluster_name is required — unique identifier for this cluster in Auditty
  • edgeApi.enabled controls the Edge API component (enabled by default)
  • Configure rules to control which logs are intercepted and processed
# Default values for auditty-edge.

# Image configuration
image:
  repository: public.ecr.aws/o8y0g3i1/space/edge
  tag: ""  # If empty, Chart.appVersion will be used
  pullPolicy: Always

# Labels applied to all resources
commonLabels: {}

# Secret reference for API key
# Create a secret with your API key and reference it here
secretRef:
  enabled: false              # Set to true to use secret instead of configMap
  secretName: ""              # Name of the secret containing the API key
  apiKeyName: "hivemind_api_key" # Key within the secret

# Edge API configuration (cluster-level service)
edgeApi:
  enabled: true           # Set to false to disable Edge API
  replicas: 1
  resources:
    requests:
      memory: "256Mi"
      cpu: "100m"
    limits:
      memory: "512Mi"
      cpu: "200m"

# ConfigMap configuration
configMap:
  create: true

  # Optional: roll the edge DaemonSet + edge-api Deployment automatically when
  # the ConfigMap changes (stamps a config checksum onto the pod templates).
  # Edge hot-reloads most config at runtime; enable this to also pick up
  # startup-only values (e.g. edge_api.service_url) without a manual restart.
  rollOnConfigChange: false

  # Optional metadata fields for your organization, environment, or cluster
  # org_name: ""           # (Optional) Organization name
  # org_unit: ""           # (Optional) Business unit or team name
  # env_name: ""           # (Optional) Environment name (dev, staging, prod) — powers Hivemind environment filter
  cluster_name: "prod-us-east"  # Required — unique identifier for this cluster

  # Hivemind API key - provide via helm install --set, secretRef, or set directly
  hivemind_api_key: ""

  rules:
    # Example: preserve critical errors from production databases
    - name: "preserve-prod-db-critical-errors"
      action: preserve
      scope:
        namespaceIncludes: "prod"
        workloadIncludes: "database"
      match:
        entryRegex: "CRITICAL|FATAL|PANIC"
      description: "Preserve critical errors for compliance and incident response"

# DaemonSet configuration
daemonSet:
  priorityClassName: ""
  nodeSelector: {}
  annotations: {}

  # Resource requests and limits
  resources:
    requests:
      memory: "512Mi"
      cpu: "500m"
    limits:
      memory: "512Mi"
      cpu: "500m"

  affinity: {}
  tolerations: []

# Prometheus scraping annotations
prometheusScrape:
  enabled: false

# Egress proxy (optional) — for clusters where all outbound traffic must route
# through a forward proxy. Injected into edge, edge-api, and the compactor.
# In-cluster destinations (loopback, metadata IP, RFC1918 ranges, .svc /
# .cluster.local, kubernetes.default) are added to NO_PROXY automatically, so
# internal traffic (edge → edge-api, the K8s API) never goes through the proxy.
proxy:
  httpProxy: ""
  httpsProxy: ""
  noProxy: ""        # extra bypass entries, merged on top of the in-cluster defaults

# NetworkPolicy — REQUIRED on clusters with a default-deny policy. Without it the
# edge → edge-api hop (port 8080) is dropped, silently disabling metrics
# reporting and Vault backfill links.
networkPolicy:
  enabled: false
  # Opt-in egress hardening (default false). When true, egress is scoped to only
  # what Edge needs (DNS, the K8s API server, edge → edge-api on 8080, and HTTPS
  # to Hivemind / cloud storage) instead of allow-all. Left off by default because
  # egress topology is environment-specific — if you run a forward proxy you must
  # add the proxy's CIDR/port below before enabling, or all outbound traffic is
  # blocked (proxy traffic uses the proxy port, not 443).
  restrictEgress: false
  dnsNamespace: kube-system          # namespace where CoreDNS/kube-dns runs
  egressAPIServerCIDRs:              # K8s API server (ports 443/6443)
    - 0.0.0.0/0
  egressHTTPSCIDRs:                  # external HTTPS (Hivemind, cloud storage, proxy)
    - 0.0.0.0/0

Linux VM / Bare Metal (systemd)

auditty-edge-service runs as a systemd daemon on any Linux host (Ubuntu, Debian, RHEL, and compatible). It tails your log files in read-only mode — never touching your application logs — and writes filtered output to a separate directory that your existing log collector reads from.

Your App → /var/log/myapp/app.log → Auditty (tail) → /var/log/auditty/var_log_myapp_app.log → Your Log Collector

Step 1: Install

curl -fsSL https://get.auditty.ai/edge | sudo bash

The installer detects architecture (amd64/arm64), downloads and verifies the binary, installs to /usr/local/bin/auditty-edge, creates /etc/auditty/config.yaml, and starts the systemd service.

Step 2: Configure

# /etc/auditty/config.yaml

hivemind_api_key: "YOUR_API_KEY"
log_level: info

interceptor:
  type: service

service:
  input_dirs:
    - /var/log/myapp
  input_patterns:
    - "*.log"
  input_recursive: true
  output_dir: /var/log/auditty   # where filtered logs are written
  enable_rotation: false          # let logrotate manage output files

Step 3: Start & Verify

sudo systemctl restart auditty-edge   # restart after config changes
systemctl status auditty-edge
journalctl -u auditty-edge -f

Point Your Log Collector at the Output Directory

# Fluentd
<source>
  @type tail
  path /var/log/auditty/*.log
</source>

# Vector
[sources.auditty_logs]
type    = "file"
include = ["/var/log/auditty/*.log"]

# Filebeat
filebeat.inputs:
  - type: log
    paths:
      - /var/log/auditty/*.log

CLI (Local / Batch Processing)

edge-cli runs the full Auditty pipeline against a directory of log files and writes filtered output locally. Useful for one-off processing, backfills, CI pipelines, or testing rules before deploying to production.

Usage

# One-shot: process all logs in /var/logs → /processed/logs
edge-cli -i /var/logs -o /processed/logs

# Watch mode: run continuously like a service
edge-cli -i /var/logs -o /processed/logs -w

# With custom config and debug logging
edge-cli -i /var/logs -o /processed/logs -c edge-config.yaml -l debug

# Validate a config file without processing anything
edge-cli validate-config -c edge-config.yaml
FlagShortDefaultDescription
--input-i(required)Input directory containing log files
--output-o(required)Output directory for processed logs
--config-cConfig file path
--watch-wfalseWatch for new/modified files continuously
--recursive-rtrueProcess subdirectories recursively
--log-level-linfoLog level: debug, info, warn, error
--shadow-mode-sfalseMetrics only — no suppression applied
--metrics-mtrueWrite a CSV metrics report to the output dir
--rulesCustom rules YAML file (overrides config)
--preserve-structuretrueMirror input directory structure in output

Suppression Summaries

When logs are suppressed, edge-cli writes summary files to <output>/suppression_summaries/. Each summary contains the count, time window, and the searchable ids (IPs, trace_id, user_id, etc.) indexed inline — with every original line recoverable from the output/Vault, so nothing is lost.

Edge Proxy (OTLP / Network Ingest)

auditty-edge-proxy brings the same dedup intelligence to sources that aren’t Kubernetes pods on a node Auditty can reach — serverless, CI runners, app SDKs, or any OpenTelemetry pipeline. Instead of intercepting files, it receives logs over the network, runs the exact same pipeline (fingerprint → dedup → rules → rate-limit), forwards survivors to a configured upstream, and archives suppressed originals to the Vault.

sender → edge-proxy → [fingerprint → dedup → rules → rate-limit] → survivors → your upstream (OTLP/HTTP or JSON)
                                                              └→ suppressed → Vault (optional)

How non-K8s sources appear in Auditty

Edge Proxy reports through the same metrics/signals/logs pipeline as the DaemonSet. It uses your configured cluster_name as the cluster label and a stable node identity (proxy.node_id, falling back to NODE_NAME, then hostname) as the node — pin proxy.node_id on scaled Deployments so vault files and backfill links keep matching across redeploys. OTLP resource attributes (service.name, k8s.namespace.name, …) populate the workload/namespace dimensions.

Step 1: Configure

# /etc/auditty/config.yaml

hivemind_api_key: "YOUR_API_KEY"
cluster_name: "edge-proxy-us-east"   # synthetic cluster label in Hivemind

interceptor:
  type: proxy

proxy:
  listen_addr: ":4318"               # OTLP/HTTP default port
  node_id: "cdn-gateway-1"           # stable node identity (pin on scaled Deployments)
  auth_token: "${EDGE_PROXY_TOKEN}"  # require a bearer token on ingress
  enable_otlp: true                  # POST /v1/logs  (OTLP/HTTP)
  enable_http: true                  # POST /ingest   (generic JSON/NDJSON)
  # timestamp_fields: ["timestamp_ms"]  # extra event-time keys; @timestamp and
  #                                     # EdgeStartTimestamp work out of the box
  upstream:
    endpoint: "https://otlp.example.com/v1/logs"
    protocol: otlp                   # otlp (protobuf) | http (JSON)
    compression: gzip
    headers:
      Authorization: "Bearer ${UPSTREAM_TOKEN}"

forwarder:
  vault:
    enabled: true                    # archive suppressed originals (optional)

Step 2: Point senders at the proxy

  • OpenTelemetry — set your OTLP/HTTP logs exporter endpoint to http://<edge-proxy>:4318 (logs path /v1/logs).
  • Generic JSON/NDJSONPOST to /ingest: a JSON array, NDJSON, or plain text lines. Recognized keys include message, namespace, service, timestamp.
  • Event time — resolved from timestamp/ts/time, with zero-config fallbacks for @timestamp (Elastic) and EdgeStartTimestamp (Cloudflare Logpush); add vendor-specific keys via proxy.timestamp_fields. Batch-delivered sources (CDN → S3 → proxy) are archived under the log’s own time, so backfill windows match the source’s clock.
  • Include the bearer token: Authorization: Bearer $EDGE_PROXY_TOKEN.

Step 3: Forward survivors to Datadog (Vector → Auditty → Datadog)

To place Auditty between Vector and Datadog, point your senders at the proxy and forward the surviving (post-suppression) stream on to Datadog. There is no separate “Datadog sink” to configure — survivors egress over OTLP/HTTP to any upstream with custom auth headers. Two supported paths:

your apps → Vector → edge-proxy → [suppress] → survivors → Datadog
                                              └→ suppressed → Vault (optional)

Option A — keep Vector as your Datadog shipper (recommended). Auditty drops in as a suppression hop and your existing datadog_logs sink (tags, pipelines, API key) is reused unchanged.

# edge-proxy: send survivors back to Vector
proxy:
  upstream:
    endpoint: "http://vector:8080"   # a Vector http_server source
    protocol: http                   # JSON array of records

# vector.yaml: receive survivors, ship to Datadog with your existing sink
sources:
  from_auditty:
    type: http_server
    address: 0.0.0.0:8080
    decoding:
      codec: json
sinks:
  datadog:
    type: datadog_logs
    inputs: [from_auditty]
    default_api_key: "${DD_API_KEY}"

Option B — straight to Datadog (one less hop). Point the upstream at Datadog’s HTTP logs intake and pass your API key as a header. The message field maps to the Datadog log message, a sender’s service (OTLP service.name or a generic service field) maps to Datadog’s reserved service facet, and every other attribute (e.g. application and your custom keys) passes through untouched. Use your site’s intake host (e.g. datadoghq.eu).

proxy:
  upstream:
    endpoint: "https://http-intake.logs.datadoghq.com/api/v2/logs"
    protocol: http
    compression: gzip
    headers:
      DD-API-KEY: "${DD_API_KEY}"

Security & overload

  • Secure by default — set auth_token (bearer) and/or mTLS (tls_client_ca_file). With neither, the proxy refuses to start rather than serve an open sink; opt into an unauthenticated sink on a trusted network with proxy.insecure: true.
  • Admission is all-or-nothing per request: under saturation the proxy returns HTTP 503 with Retry-After having accepted nothing, so a retry never duplicates part of a batch. A 200 means every record landed. It never hangs a client or silently drops data.

Scaling

  • Scale up first. A single instance runs the same pipeline as the DaemonSet and handles tens of thousands of records/sec on a few cores — give one instance more CPU/memory before adding replicas.
  • Scale out for capacity & HA. Run multiple replicas behind a Service/load balancer for raw throughput. Survivors and Vault archival are always correct regardless of replica count.
  • Keep dedup tight with source affinity. Each instance dedups only against what it has seen itself, so round-robin balancing softens the global suppression ratio (~linearly with replicas). Use a consistent-hash LB keyed on a stable source attribute (e.g. service.name / host.name) so all logs from one source hit the same replica.

Deploy on Kubernetes (same Helm chart)

The network proxy ships in the same auditty-edge Helm chart as the DaemonSet — enable it alongside (or instead of) the node interceptor with edgeProxy.enabled. It deploys as a horizontally-scalable Deployment + Service, with an optional HPA that scales on CPU/memory.

edgeProxy:
  enabled: true
  listenPort: 4318                # OTLP/HTTP ingress port
  authToken: "${EDGE_PROXY_TOKEN}" # required (or set insecure: true)
  upstream:
    endpoint: "https://otlp.example.com/v1/logs"
  hpa:
    enabled: true                 # autoscaler owns the replica count
    minReplicas: 2
    maxReplicas: 10
    targetCPUUtilization: 70

The DaemonSet, edge-api, and edge-proxy each have independent autoscaling and resource settings, so you can run any combination from one release.

Scaling and suppression: each proxy pod keeps its own suppression state, and pods do not share it. So that a source still suppresses correctly across replicas, the proxy Service defaults to sessionAffinity: ClientIP, pinning each sender to one replica. For diverse senders you still get spread across pods; if many sources share one egress IP they pin to a single replica (correct, just less balanced). Set edgeProxy.service.sessionAffinity: None only if you accept per-replica suppression — summary_min_count then applies per replica and the dedup ratio scales sub-linearly with replica count.