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

# Hardening

> A recommended path to a hardened, zero-trust posture with Nyx — default-deny, egress lockdown, and platform guardrails.

This guide walks through taking a cluster from open to a hardened, zero-trust posture. The steps build on each other, and every one can be staged with [audit mode](/concepts/enforcement-modes) before it blocks anything — so you harden without surprise outages.

## 1. Move to default-deny

The highest-impact change. A new cluster runs `defaultMode: allow`, so every flow no policy matches passes. Hardening means flipping that backstop to deny, in stages.

Start by denying cross-namespace traffic in audit, so you can see what would break before it does:

```yaml theme={null}
apiVersion: nyx.tracenyx.io/v1alpha1
kind: NyxClusterConfig
metadata:
  name: cluster
spec:
  defaultMode: deny-cross-namespace
  enforcement: audit
  excludedNamespaces:
    - kube-system
    - kube-public
    - nyx-system
```

Review the would-deny findings, add explicit allow policies for the cross-namespace traffic that's legitimate, and once the log is clean, set `enforcement: enforce`. When you're ready for full zero-trust, move to `defaultMode: deny` — now even intra-namespace traffic needs an explicit allow.

See [Enforcement Modes](/concepts/enforcement-modes) for the staging detail and [NyxClusterConfig](/reference/nyxclusterconfig) for the fields.

## 2. Lock down egress

Cross-namespace deny handles east-west traffic; egress hardening governs what leaves the cluster. The pattern is default-deny egress, then allowlist only what's needed — by FQDN (`toFqdn.matchName`, which applies to HTTPS on 443) and by IP range (`toIpBlock`).

This policy lets the payments workload reach its provider over HTTPS and denies everything else:

```yaml theme={null}
apiVersion: nyx.tracenyx.io/v1alpha1
kind: NyxNetworkPolicy
metadata:
  name: payments-egress-allowlist
  namespace: cloudmart-payments
spec:
  podSelector:
    matchLabels:
      app: cloudmart-payments
  priority: 100
  enforcement: enforce
  policyTypes:
    - Egress
  egress:
    - decision: Allow
      toFqdn:
        - matchName: api.stripe.com
      ports:
        - protocol: TCP
          port: 443
```

Block plaintext egress as a baseline. FQDN matching relies on the TLS handshake, so plain HTTP can't be matched by name — and production workloads rarely have a good reason to make plaintext outbound calls. Require HTTPS and deny the rest; see [FQDN egress](/reference/nyxnetworkpolicy#fqdn-egress).

## 3. Set platform guardrails

Some rules shouldn't be overridable by any namespace or application team — blocking known-bad destinations, denying public-internet egress for regulated namespaces, and the like. Put these in a `NyxClusterNetworkPolicy` in the `platform-override` band (priority 0–99). Because lower priorities are evaluated first, they win over every namespace and workload policy.

This denies all public-internet egress from production, cluster-wide:

```yaml theme={null}
apiVersion: nyx.tracenyx.io/v1alpha1
kind: NyxClusterNetworkPolicy
metadata:
  name: deny-public-internet
spec:
  tier: platform
  priority: 50
  enforcement: enforce
  namespaceSelector:
    matchLabels:
      environment: production
  policyTypes:
    - Egress
  egress:
    - decision: Deny
      toIpBlock:
        cidr: 0.0.0.0/0
```

See [Priority System](/concepts/priorities) for how the bands resolve.

## 4. Control who can author policy

Hardening the network is only half the picture — control who can change it.

* On **Scout**, policy authorship is tied to your kubectl identity through the [binding step](/quickstart): the admission webhook only accepts policies from a recognised identity.
* On **Sentinel and Aegis**, SSO and RBAC give you team-based control over who can create or modify policies, with every change attributed in the audit log.

See [Tiers](/concepts/tiers).

## 5. Exclude only what you must

`excludedNamespaces` in `NyxClusterConfig` makes a namespace bypass all enforcement, in both directions. Keep the list minimal — typically just the system namespaces that genuinely can't tolerate policy (`kube-system`, `kube-public`, `nyx-system`). Every excluded namespace is a gap in enforcement. Observability still covers excluded namespaces, so you keep visibility even where you don't enforce.
