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

# FAQ

> Common questions about deploying and operating NOFire Edge

## Connectivity & Networking

<AccordionGroup>
  <Accordion title="Does Edge require inbound firewall rules?">
    No. Both Edge and Edge Proxy initiate **outbound** connections only. Edge Proxy dials `my.nofire.ai:443` and maintains a long-lived bidirectional gRPC stream. Edge publishes graph updates to the same backend. No inbound ports need to be opened and no load balancer is required.
  </Accordion>

  <Accordion title="Does it work with an internal HTTP proxy?">
    Edge Proxy communicates over HTTP/2 with a long-lived gRPC stream (connections span 30+ minutes). Standard HTTP/1.1 proxies will not support this. If your outbound traffic passes through an internal proxy:

    * The proxy must support HTTP/2 with long-lived streaming connections
    * If it does not, allowlist `my.nofire.ai:443` directly so Edge Proxy bypasses the proxy for that destination
  </Accordion>

  <Accordion title="What happens if the connection to NOFire drops?">
    Edge Proxy reconnects automatically. It uses exponential backoff starting at 1 second, capped at 60 seconds. All three internal loops (heartbeat, receive, send) monitor the connection — if any exits with an error, the stream is cancelled and reconnection begins immediately.

    You can observe reconnections in the proxy logs:

    ```bash theme={null}
    kubectl logs -l app.kubernetes.io/component=edge-proxy -n nofire-system | grep -E "reconnect|StreamAck|StreamInit"
    ```
  </Accordion>

  <Accordion title="What happens if DNSTap is not configured?">
    Edge still runs and publishes your cluster topology (pods, services, deployments, namespaces, nodes). What you lose is **runtime service dependency discovery** — the edges between services in the dependency graph will not be populated.

    Without DNSTap, NOFire can see your infrastructure but cannot automatically map which services call which. You can still use the platform, but dependency-based production context will be less accurate.

    See [Installation](/edge/installation#dnstap-configuration) for setup steps.
  </Accordion>

  <Accordion title="Why does the quick-start require a reinstall to pin the ClusterIP?">
    CoreDNS is configured to forward DNS tap frames to the Edge service by IP address (not DNS name). If Edge is uninstalled and reinstalled without pinning the ClusterIP, Kubernetes assigns a new IP, and CoreDNS stops sending DNS traffic until manually reconfigured.

    Pinning the ClusterIP at install time prevents this. It is a one-time step — `helm upgrade` preserves the ClusterIP without reinstalling.
  </Accordion>
</AccordionGroup>

***

## Data & Security

<AccordionGroup>
  <Accordion title="Do my credentials leave the cluster?">
    No. Credentials are stored as Kubernetes Secrets and mounted into the Edge Proxy pod at `/var/run/secrets/<secret-name>/`. The proxy resolves credentials locally and injects them into HTTP requests to your data sources. Raw secret values are never included in the gRPC stream sent to NOFire's backend.
  </Accordion>

  <Accordion title="What data does Edge send to NOFire?">
    Two data streams:

    1. **Kubernetes resource graph** — Edge continuously watches your cluster and publishes changes: pods, services, deployments, namespaces, nodes, and service-to-service dependency edges discovered via DNS. No workload data (secrets, configmap values, environment variables) is included.

    2. **Observability query results** — When NOFire AI queries your on-prem data sources (Prometheus, Loki, Grafana etc.), Edge Proxy executes the HTTP request locally and returns the response body over the gRPC stream. PII redaction runs on this data before it leaves the cluster.
  </Accordion>

  <Accordion title="Does Edge write to my Kubernetes cluster?">
    No. Edge operates in read-only mode. It uses the Kubernetes Watch API with `get`, `list`, and `watch` verbs only. It never creates, modifies, or deletes any Kubernetes resources.

    See [RBAC Permissions](/edge/rbac) for the full permission list.
  </Accordion>

  <Accordion title="Is PII redaction on by default?">
    No. Redaction must be explicitly enabled. When enabled, the proxy runs the following passes on every response body before transmission:

    1. Standard patterns — email, SSN, credit card, phone, IPv4 addresses
    2. Custom regex patterns — user-defined rules with configurable replacement strings
    3. JSON path targeting — redact specific fields by dot-notation path

    To enable standard redaction:

    ```yaml theme={null}
    edgeProxy:
      redaction:
        enabled: true
        standardPII: true
    ```

    See [Sensitive Data Redaction](/security/pii-redaction) for custom pattern configuration.
  </Accordion>

  <Accordion title="Can I run Edge as a non-root user?">
    Yes. Add security contexts to your `values.yaml`:

    ```yaml theme={null}
    podSecurityContext:
      runAsNonRoot: true
      runAsUser: 1000
      runAsGroup: 1000
      fsGroup: 1000

    securityContext:
      allowPrivilegeEscalation: false
      capabilities:
        drop:
          - ALL
    ```
  </Accordion>
</AccordionGroup>

***

## Performance & Scaling

<AccordionGroup>
  <Accordion title="What are the resource requirements?">
    Edge Agent and Edge Proxy are deployed as separate pods. The agent keeps an in-memory graph of all Kubernetes resources, so memory scales with cluster size.

    Typical small-to-medium cluster (up to \~1,000 pods):

    | Component  | CPU       | Memory      |
    | ---------- | --------- | ----------- |
    | Edge Agent | 100m–500m | 128Mi–512Mi |
    | Edge Proxy | 50m–200m  | 64Mi–256Mi  |

    For large clusters, increase the memory request for the Edge Agent. Resource limits can be set via `resources` in `values.yaml`.
  </Accordion>

  <Accordion title="What happens if Edge Proxy receives more requests than it can handle?">
    Edge Proxy uses a semaphore to bound concurrent outbound HTTP requests. The default limit is 10 concurrent requests. Requests that arrive while all slots are occupied receive a `503 Too Many Requests` response, which is returned to NOFire Brain.

    To increase the limit:

    ```yaml theme={null}
    edgeProxy:
      stream:
        maxConcurrent: 20
    ```
  </Accordion>

  <Accordion title="Is there a limit on query response size?">
    Yes. Edge Proxy enforces a 50MB maximum response body per request. Responses larger than 1MB are automatically split into chunks before transmission over the gRPC stream. Both limits are configurable:

    ```yaml theme={null}
    edgeProxy:
      http:
        maxResponseBodySize: 52428800  # 50MB default
        chunkSize: 1048576             # 1MB per chunk
    ```
  </Accordion>

  <Accordion title="How frequently does Edge poll the Kubernetes API?">
    Edge uses the Kubernetes Watch API rather than polling. It receives real-time push events when resources are created, updated, or deleted. There is no configurable polling interval — changes are reflected within seconds of occurring in the cluster.
  </Accordion>
</AccordionGroup>

***

## Configuration & GitOps

<AccordionGroup>
  <Accordion title="Can NOFire remotely change my Edge configuration?">
    No. All Edge and Edge Proxy configuration is managed through your `values.yaml` and applied via Helm. NOFire's backend has no ability to modify your connector list, credentials, or any other settings remotely.

    This means configuration changes follow your standard code review and deployment process. The running state always matches what is in version control.
  </Accordion>
</AccordionGroup>

***

## Deployment & Operations

<AccordionGroup>
  <Accordion title="How do I upgrade Edge?">
    Use `helm upgrade`. Your DNSTap configuration and pinned ClusterIP are preserved across upgrades.

    ```bash theme={null}
    helm upgrade nofire-edge nofire/nofire-edge \
      -f values.yaml \
      -n nofire-system
    ```

    To upgrade to a specific chart version:

    ```bash theme={null}
    helm upgrade nofire-edge nofire/nofire-edge \
      --version <chart-version> \
      -f values.yaml \
      -n nofire-system
    ```

    If something goes wrong, roll back to the previous release:

    ```bash theme={null}
    helm rollback nofire-edge -n nofire-system
    ```
  </Accordion>

  <Accordion title="Can I deploy Edge in multiple clusters?">
    Yes. Deploy a separate Helm release in each cluster with a unique `kube.clusterName`. Each cluster appears independently in the NOFire dashboard.

    ```bash theme={null}
    # Cluster 1
    helm install nofire-edge nofire/nofire-edge \
      --set config.publisher.apiKey=YOUR_API_KEY \
      --set config.kube.clusterName=prod-us-east \
      -n nofire-system --create-namespace

    # Cluster 2
    helm install nofire-edge nofire/nofire-edge \
      --set config.publisher.apiKey=YOUR_API_KEY \
      --set config.kube.clusterName=prod-eu-west \
      -n nofire-system --create-namespace
    ```
  </Accordion>

  <Accordion title="How do I verify Edge Proxy is connected after deployment?">
    Check the proxy logs for a successful stream handshake:

    ```bash theme={null}
    kubectl logs -l app.kubernetes.io/component=edge-proxy -n nofire-system | grep "StreamAck"
    ```

    Expected output: a log line containing `StreamAck` with `status: OK`.

    To check the health of all configured connectors:

    ```bash theme={null}
    kubectl exec -n nofire-system deploy/nofire-edge-edge-proxy -- \
      wget -qO- http://localhost:8081/healthz/connectors
    ```

    This returns the health status of each data source connection.
  </Accordion>

  <Accordion title="How do I check if a specific data source connector is reachable?">
    Use the health endpoint with a specific connector key:

    ```bash theme={null}
    kubectl exec -n nofire-system deploy/nofire-edge-edge-proxy -- \
      wget -qO- http://localhost:8081/healthz/connectors/prod-prometheus
    ```

    The response indicates whether the connector's health check endpoint is reachable and responding correctly. Each connector type uses a different health check path (e.g., Prometheus uses `/api/v1/query?query=up`, Loki uses `/loki/api/v1/status/buildinfo`).
  </Accordion>

  <Accordion title="How do I configure HTTPS for a data source with a private CA or mutual TLS?">
    Add certificate configuration to the connector in your `values.yaml`. You can specify the certificate content directly or reference file paths if the certificates are mounted via secrets.

    ```yaml theme={null}
    onPremConnections:
      prod-prometheus:
        type: prometheus
        url: "https://prometheus.internal.company.com"
        secretName: prometheus-creds
        tlsConfig:
          caCert: |
            -----BEGIN CERTIFICATE-----
            ...
          clientCert: |
            -----BEGIN CERTIFICATE-----
            ...
          clientKey: |
            -----BEGIN RSA PRIVATE KEY-----
            ...
    ```
  </Accordion>
</AccordionGroup>
