Install Veirox Connect on self-managed Kubernetes

Applies to: kubeadm, RKE2, k3s, OpenShift, Rancher, VMware Tanzu,
any upstream Kubernetes you run yourself.

This is the most demanding install path because self-managed clusters
have the fewest assumptions baked in: no cloud IAM, possibly no
Internet egress, possibly a TLS-inspecting proxy in the middle, and
Pod Security Admission often strictly enforced.


Preflight checklist

  • [ ] Kubernetes 1.26+ (kubectl version --short).
  • [ ] A NetworkPolicy controller is running (Calico, Cilium, Weave,
    Antrea, or the built-in one on Kind/k3s). If not, --set networkPolicy.enabled=false — but you lose defence-in-depth.
  • [ ] helm 3.9+ with OCI support (it's on by default since 3.8).
  • [ ] Cluster egress to docker.io and ghcr.io on 443/TCP, or a
    private registry mirror with the Veirox image.
  • [ ] Cluster egress to your Veirox backend (usually
    veirox.com) on 443/TCP, or a MITM TLS proxy with
    a CA bundle
    .
  • [ ] Cluster has Pod Security Standard set at least to
    baseline. The chart already satisfies restricted.

Standard install (cluster has Internet)

kubectl create namespace veirox
kubectl -n veirox create secret generic veirox-connector-token \
  --from-literal=token=veirox_enr_...

helm install veirox-connector \
  oci://ghcr.io/msrashed2018/charts/veirox-connector \
  --namespace veirox \
  --set backendUrl=https://www.veirox.com \
  --set rbacPreset=readOnly

No Internet

If the cluster has no egress to the public Internet at all, use the
airgap install path for the systemd agent, not
this Helm chart
— the reverse-WebSocket architecture requires the
agent to reach the Veirox backend at runtime, not just at install.

If the cluster has egress only to a private registry mirror for
images (but can reach Veirox for WebSocket), mirror the Veirox
image first:

1. Mirror the image

# On a workstation with Internet + access to your registry
docker pull docker.io/msrashed/veirox-connector:0.2.0-k8s
docker tag  docker.io/msrashed/veirox-connector:0.2.0-k8s \
            registry.corp.internal/veirox-connector:0.2.0-k8s
docker push registry.corp.internal/veirox-connector:0.2.0-k8s

2. Mirror the chart

helm pull oci://ghcr.io/msrashed2018/charts/veirox-connector --version 0.2.0
# Produces veirox-connector-0.2.0.tgz
helm push veirox-connector-0.2.0.tgz oci://registry.corp.internal/charts

3. Install from your registry

helm install veirox-connector \
  oci://registry.corp.internal/charts/veirox-connector \
  --version 0.2.0 \
  --namespace veirox \
  --set image.repository=registry.corp.internal/veirox-connector \
  --set image.tag=0.2.0-k8s \
  --set backendUrl=https://veirox.customer.com

Shared-SNI reverse proxy (bearer fallback)

If your Veirox backend is fronted by a reverse proxy (Traefik,
nginx, Envoy) that serves multiple routes on the same TLS host
(e.g., /api, /console, /connectors/ws all on veirox.example.com),
you may hit a limitation: only one set of TLS options can apply per
SNI host
. If the WS route's options differ from the others, most
proxies silently fall back to defaults and stop requesting a client
certificate. Agents in release mode then can't authenticate via mTLS.

Symptom: agent logs auth rejected: missing credential; backend
logs connector_ws_empty_credential.

Fix A (recommended): host the Connect WS on a dedicated SNI,
e.g. veirox-connect.example.com with its own TLS cert. One router
per SNI = clean TLS options.

Fix B (workaround): set --set enrollment.preferBearer=true on
the Helm install. The agent will enroll with a bearer credential
instead of an mTLS client cert — less secure, but works transparently
with any reverse proxy:

helm install veirox-connector \
  oci://ghcr.io/msrashed2018/charts/veirox-connector \
  --namespace veirox \
  --set backendUrl=https://veirox.example.com \
  --set enrollment.preferBearer=true

The bearer mode is tracked as a migration-window default in
agent-entities/issues/2026-04-15-traefik-shared-sni-mtls.md. A proper
hostname split is planned for a future release.


TLS-inspecting proxy

If your cluster's egress goes through a proxy that re-signs outbound
TLS (Zscaler, Palo Alto Networks, Bluecoat, etc.), the agent's rustls
stack won't trust the re-issued cert. Mount your corporate CA bundle:

1. Create a Secret with the CA PEM

kubectl -n veirox create secret generic veirox-corp-ca \
  --from-file=ca.pem=/path/to/corp-ca.pem

2. Enable the mount

helm upgrade veirox-connector \
  oci://ghcr.io/msrashed2018/charts/veirox-connector \
  --namespace veirox \
  --set extraCaBundle.enabled=true \
  --set extraCaBundle.secretName=veirox-corp-ca

The chart mounts the Secret at /etc/veirox-connector-corp-ca/ca.pem
and the agent's rustls uses it as an additional trust anchor.

SSL_CERT_FILE does not work for this agent — rustls ignores
it. You must mount via extraCaBundle.


Pod Security Admission (PSA)

If your cluster enforces PSA at the restricted profile (the
strictest standard), the chart meets it. Verify before install:

# Label the namespace to enforce `restricted`
kubectl label namespace veirox \
  pod-security.kubernetes.io/enforce=restricted \
  pod-security.kubernetes.io/warn=restricted

# Dry-run the chart against it
helm template veirox-connector \
  oci://ghcr.io/msrashed2018/charts/veirox-connector \
  --namespace veirox \
  --set backendUrl=https://veirox.customer.com \
  | kubectl apply --dry-run=server -f -

Expected: zero PSA warnings. If you see violates PodSecurity "restricted":..., a mutating webhook upstream is altering the spec —
investigate with kubectl get mutatingwebhookconfigurations.


NetworkPolicy CIDR pinning

The chart's default NetworkPolicy allows 443 egress to
0.0.0.0/0. In a hardened environment, pin to your Veirox
backend's CIDR to reduce lateral movement surface:

# my-values.yaml
networkPolicy:
  enabled: true
  allowedEgressCidrs:
    - 203.0.113.42/32   # veirox.customer.com — resolve once, pin here

Note: if the backend IP changes (e.g., LB failover), the agent
drops offline until you reapply the policy. Pin only in steady-state
networks; use 0.0.0.0/0 on clusters where availability > attack
surface.


OpenShift specifics

OpenShift 4.x has its own Security Context Constraints (SCC). The
chart runs as UID 65532 — grant the restricted-v2 SCC to the SA:

oc adm policy add-scc-to-user restricted-v2 \
  -z veirox-connector -n veirox

If you see unable to validate against any security context constraint, inspect the error and grant accordingly. The chart does
not need the privileged, anyuid, or hostnetwork SCCs.


k3s / Rancher Desktop

k3s uses a built-in NetworkPolicy controller (flannel + wireguard in
newer versions, or disabled on --disable-network-policy clusters).
If your k3s has NP disabled:

helm install ... --set networkPolicy.enabled=false

The agent still works; you just don't get the egress pinning
defence-in-depth.


Verify the install

  1. Pod Ready=true in veirox namespace.
  2. Connector appears in the Veirox UI (online=true).
  3. Run the verification checklist.

Uninstall

helm uninstall veirox-connector -n veirox
kubectl delete namespace veirox
kubectl get clusterrole,clusterrolebinding | grep veirox || echo "clean"

Troubleshooting

Symptom Likely cause
Pod ImagePullBackOff with x509: certificate signed by unknown authority Your container runtime doesn't trust the registry. Either add the registry's CA to the kubelet's trust store, or mirror to your own registry.
Pod starts, logs enrollment failed: error sending request for url Backend URL unreachable from the pod network. Check egress NP, firewall, or MITM proxy (needs extraCaBundle).
Pod starts, logs enrollment failed: invalid peer certificate: UnknownIssuer TLS-inspecting proxy without corporate CA mounted. See TLS-inspecting proxy.
helm install says chart requires kubeVersion: >=1.26.0 which is incompatible Upgrade the cluster or fork the chart's Chart.yaml.