Kubernetes Install
Install the Apoxy controller into a cluster, verify the install, and debug common failure modes.
This guide walks through installing the Apoxy controller into a Kubernetes cluster. Use this path when your source of truth for Gateway API resources lives in Kubernetes.
Install the controller
apoxy k8s install fetches the onboarding manifests from the Apoxy API and applies them to
your target cluster:
apoxy k8s install \
--context <kube-context> \
--namespace apoxy \
--cluster-name <cluster-name> \
--mirror gateway \
--yesAvailable flags
- --kubeconfig
- Explicit kubeconfig path.
- --dry-run
- Print the manifests without applying them.
- --force
- Force overwrite conflicting fields during apply.
- --image
- Override the controller image embedded in the onboarding manifests.
- --yes
- Skip interactive confirmation.
Your first install
Authenticate and install the controller:
apoxy auth login
apoxy k8s install \
--context prod-us-west-2 \
--namespace apoxy \
--cluster-name prod-us-west-2 \
--mirror gatewayDuring installation, the CLI resolves your kubeconfig and context, requests onboarding
manifests from the Apoxy API, and applies resources into the target namespace. On subsequent
runs, if you omit --cluster-name, the CLI recovers it from the namespace annotation
apoxy.dev/cluster-name.
Mirror mode
The --mirror flag controls which resource types the controller mirrors to Apoxy:
| Mode | What it mirrors | When to use |
|---|---|---|
| gateway | Gateway API resources (gateway.networking.k8s.io) | Gateway API is your primary routing configuration. |
| ingress | Ingress resources | You're bridging an existing Ingress workflow into Apoxy. |
| all | Both Gateway API and Ingress | Mixed environments running both resource families. |
Preview with dry-run
Before applying to a cluster, preview the manifests:
apoxy k8s install \
--context dev-cluster \
--namespace apoxy \
--cluster-name dev-cluster \
--mirror gateway \
--dry-runVerify the install
After installing, confirm these basics:
- The kubeconfig path resolves to the cluster you intended.
- The selected context matches the target cluster.
- The namespace is correct.
- The Apoxy CLI is authenticated (
apoxy auth login). - The project selection in your CLI config matches the target environment.
Common errors
failed to load kubeconfig- Bad kubeconfig path or incorrect current context.
failed to get YAML- Authentication issue or API-side onboarding problem.
- Apply conflicts
- Use
--forceonly when you understand the field ownership implications. - Non-interactive runs without
--yes - The CLI requires confirmation by default.
How the controller authenticates to Apoxy
The first time the controller starts in your cluster, it issues itself a per-cluster client certificate from the Apoxy control plane and uses it as its identity for every subsequent request. There is no long-lived API key in the cluster after install completes.
The flow:
apoxy k8s installwrites the onboarding manifests — including a one-time bootstrap secret keyed to the cluster name — into your cluster.- The controller pod starts, exchanges the bootstrap material for a client certificate via the
Apoxy API, and stores it in Secret
apoxy/apiz-cert:tls.crt— the certificate, signed by Apoxy.tls.key— the matching private key (generated in the pod; never leaves the cluster).ca.crt— Apoxy's root, used to verify the upstream.
- The controller and the aggregated API server (
v1alpha.core.apoxy.devand siblings) use this cert as a client certificate when proxying to Apoxy. The control plane authenticates each request by certificate fingerprint and authorizes against the project the cert was issued for.
The cert's subject encodes the service user kube-controller-<cluster-name>, so a cert minted
for one cluster cannot impersonate another even within the same project.
Cert lifetime
Issued certificates are valid for 365 days. The controller auto-renews them when validity drops below 30 days: an hourly tick checks the live cert, and on the first tick below threshold the controller re-issues against Apoxy over mTLS with its current cert and hot-reloads the new material in place (no pod restart). See Auto-rotation for the full lifecycle and how to disable it.
You can also rotate explicitly with apoxy k8s certs rotate (see Rotating the kube-controller
certificate). Manual rotation has two modes:
- Restart mode (default) — the CLI patches the pod template to force a rolling restart; the new pod loads the new cert at startup.
- Hot-reload mode (
--no-restart) — the controller watches its projectedapiz-certSecret mount via fsnotify and atomically swaps the upstream client cert without a pod restart. Same mechanism the auto-renewer uses.
The Apoxy API publishes the cert's fingerprint and expiry; the CLI can inspect both:
apoxy k8s certs list --context <kube-context>Revocation
Revocation is project-scoped and immediate. When you revoke a fingerprint via apoxy k8s certs revoke <fp> --user-jwt <jwt>, the Apoxy ext_authz layer drops the cert from its
allowed-fingerprint set within ~30 seconds, after which any request presenting that cert fails
with 403. Revoke requires a user JWT (your dashboard session token), not an API key — a
leaked API key sitting next to the cert in the cluster cannot revoke the cert it lives next
to.
Updating the install
Re-run apoxy k8s install when you need to:
- Change the mirror mode.
- Switch to a custom controller image.
- Pick up updated onboarding manifests from Apoxy.
Use --cluster-name explicitly in automation so the intended cluster identity is always
clear.