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.
| Profile | CPU | Memory | Log throughput |
|---|---|---|---|
| Standard | 500m | 512Mi | Up to ~5K lines/sec per node |
| High throughput | 1 CPU | 1Gi | 5K–20K lines/sec per node |
| Extreme | 2 CPU | 1.5Gi | 20K+ 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-namespaceif 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
egressHTTPSCIDRsfirst — 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/0Linux 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 CollectorStep 1: Install
curl -fsSL https://get.auditty.ai/edge | sudo bashThe 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 filesStep 3: Start & Verify
sudo systemctl restart auditty-edge # restart after config changes
systemctl status auditty-edge
journalctl -u auditty-edge -fPoint 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/*.logCLI (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| Flag | Short | Default | Description |
|---|---|---|---|
--input | -i | (required) | Input directory containing log files |
--output | -o | (required) | Output directory for processed logs |
--config | -c | Config file path | |
--watch | -w | false | Watch for new/modified files continuously |
--recursive | -r | true | Process subdirectories recursively |
--log-level | -l | info | Log level: debug, info, warn, error |
--shadow-mode | -s | false | Metrics only — no suppression applied |
--metrics | -m | true | Write a CSV metrics report to the output dir |
--rules | Custom rules YAML file (overrides config) | ||
--preserve-structure | true | Mirror 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/NDJSON —
POSTto/ingest: a JSON array, NDJSON, or plain text lines. Recognized keys includemessage,namespace,service,timestamp. - Event time — resolved from
timestamp/ts/time, with zero-config fallbacks for@timestamp(Elastic) andEdgeStartTimestamp(Cloudflare Logpush); add vendor-specific keys viaproxy.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 withproxy.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
200means 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: 70The 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.