Note: This guide covers deploying Radar as a pod in your cluster. If you’re running Radar locally but need to understand cluster connection behavior (e.g., using KUBECONFIG to override in-cluster detection), see the Configuration Guide.
Choose the path that matches what you are trying to do:
- New installation: follow Quick Start, then configure how your team will reach and authenticate to Radar.
- Existing installation: start with Upgrading. The correct workflow depends on whether Helm, Argo CD, Flux, or another system owns the deployment.
Quick Start
Upgrading
Upgrade Radar through the same source that manages the current installation. If Argo CD or Flux owns Radar, change the version in Git and let the controller reconcile it. Runninghelm upgrade directly against a GitOps-managed release
creates drift and the controller may revert it.
Before upgrading, review the release notes
between your current and target versions, especially for a major-version update.
The Radar version shown on the Home page matches the published Helm chart
version.
Helm
If Radar links you to a Helm release, use that release name and namespace. You can also find likely releases with:radar with the release name and namespace used by your installation.
--reset-then-reuse-values requires Helm 3.14 or newer. It starts from the
target chart’s defaults, then reapplies the release’s existing values, so keys
introduced by the new chart are not omitted. With an older Helm client, upgrade
Helm or use the installation’s maintained values file; plain --reuse-values
is not equivalent and can omit new defaults.
If the deployment is managed from a values file, use that same file with
-f values.yaml instead of --reset-then-reuse-values so Git remains the
reproducible source of configuration. The command installs the latest published
chart; add --version X.Y.Z to pin the exact version shown in Radar (without
the leading v).
Argo CD or Flux
Do not upgrade the live Helm release or Deployment directly. Update the version in the repository that owns the installation, then reconcile its controller:- Argo CD Application: if the Application directly references the Radar
chart, update its Helm chart
targetRevision. Otherwise update the chart or image version in the Git source referenced by the Application, then sync it. - Flux HelmRelease: update the Radar chart version in the HelmRelease source,
usually
spec.chart.spec.version, then reconcile the HelmRelease. - Flux Kustomization: update the Radar chart or image version in the Git source referenced by the Kustomization, then reconcile it.
If the manager could not be identified
Inspect the Radar Deployment before choosing an upgrade method:meta.helm.sh/release-nameandmeta.helm.sh/release-namespaceidentify the underlying Helm release.argocd.argoproj.io/tracking-idorargocd.argoproj.io/instancepoints to Argo CD ownership.helm.toolkit.fluxcd.io/*andkustomize.toolkit.fluxcd.io/*point to Flux ownership.
Verify or roll back
Wait for the Radar Deployment to finish rolling out, then refresh Radar and confirm the new version on the Home page:helm history and use helm rollback if the rollout
fails. For a GitOps-managed installation, revert the version change in Git and
reconcile the owning object.
Exposing with Gateway API
If your cluster uses Gateway API, the chart can create anHTTPRoute:
rules, the chart routes / to Radar. httpRoute and ingress are mutually exclusive, and at least one parentRefs entry is required. See the chart reference for custom rules and timeouts.
Exposing with Ingress
Ingress without authentication
Warning: Only use this behind a trusted private network boundary. Anyone who can reach Radar can use the permissions granted to its ServiceAccount. For shared or externally reachable installations, configure authentication before exposing the ingress.
Subpath Ingress (No Strip-Prefix)
If your ingress forwards/radar/... to the Radar service as /radar/..., set basePath to the same prefix:
https://tools.your-domain.com/radar/. Do not set basePath when your ingress already rewrites /radar to /.
Path segments accept letters, digits, -, _, . and ~. Radar serves the app
only under the prefix - requests to unprefixed paths get a 404, so update any
external health checks or scrapers that hit /api/health or /metrics directly
(the chart’s own probes follow basePath automatically). basePath is not
supported together with Radar Cloud (--cloud-url), which owns the URL path
itself.
Every URL you hand to an external system must include the prefix. With OIDC
that means the values you register with your identity provider:
{basePath}/auth/callback, so a redirect URL
without the prefix sends the IdP to a path the ingress doesn’t route to Radar and
login ends in a 404.
Give each instance its own hostname. Two Radars behind subpaths on one
hostname (/radar-a, /radar-b) are the same browser origin, so they share
browser state: the session cookie is set at Path=/, and localStorage - which
holds the theme, log-viewer preferences and similar per-instance settings - is
scoped per origin with no path-scoped equivalent in the platform at all. Logging
into one can end the other’s session, and preferences set in one show up in the
other. A hostname each keeps them properly separate.
Separately from that: a Radar per cluster gives you a view per cluster. Each
watches only its own cluster and carries its own upgrades, ingress and auth
config, with no cross-cluster search or combined issue list across them. If you
want several clusters in one view, that is what
Radar Cloud is for, and its agent dials out so there is no
per-cluster ingress to wire up.
With ingress basic authentication
-
Create the auth secret:
-
Configure ingress:
-
Deploy:
With TLS (HTTPS)
Requires cert-manager installed in your cluster.DNS Setup
-
Get your ingress IP:
- Create a DNS A record pointing your domain to the ingress IP.
radar.prod-us-east1.example.com
RBAC
Radar uses its ServiceAccount to access the Kubernetes API. The Helm chart creates a ClusterRole with read-only access to common resources by default:- Pods, Services, ConfigMaps, Events, Namespaces, Nodes, ServiceAccounts, Endpoints
- Deployments, DaemonSets, StatefulSets, ReplicaSets
- Ingresses, NetworkPolicies, Jobs, CronJobs, HPAs, PVCs
- Kubernetes 1.37 Workloads, PodGroups, CompositePodGroups, PodCertificateRequests, and ClusterTrustBundles when the API server advertises them; the scheduling APIs are feature-gated
- Pod logs (enabled by default)
Opt-in Permissions
Some features require additional permissions. Most are disabled by default for security:Node management (cordon, uncordon, drain) is available via the MCP server and API. These operations requireEnable features as needed:patchon nodes,liston pods, andcreateonpods/eviction, which are not included in the default ClusterRole. Add them viarbac.additionalRulesor use per-user authentication so each user’s own RBAC governs node operations.
busybox:latest by default. If the built-in restricted Pod Security Standard rejects the default pod debug container, Radar retries with a restricted-compatible Linux security context using the target/pod non-root UID, or UID 65532 by default, so custom images used in restricted namespaces must work as a non-root user. In air-gapped or private-registry clusters where the default image can’t be pulled, point it at a reachable mirror:
default namespace’s ServiceAccount / node registry config - so the image must be pullable without Radar supplying credentials.
CRD Permissions
Radar reads CRDs from many popular tools. Each CRD group can be toggled individually:get, list, and watch) for both API groups and is enabled by default. Set rbac.crdGroups.calico=false to disable it. If chart-managed Calico access is disabled, grant only the resources you need through rbac.additionalRules; both groups may be required while a cluster exposes modern and legacy Calico APIs.
Graceful RBAC Degradation
You see what you have access to - Radar doesn’t require cluster-admin. Whatever your ServiceAccount (or the impersonated user, when auth is enabled) can list, Radar shows. Resource types you can’t list show an actionable denied-state instead of a misleading “0 / None found”: for a core cluster-scoped kind (Node, PV, StorageClass, and the like) your identity can’t read, Radar shows a copyableClusterRole + ClusterRoleBinding request to hand to a cluster admin (reason rbac_denied), and distinguishes that from a kind Radar’s own ServiceAccount can’t read, where a user-level grant wouldn’t help (reason unavailable, no snippet). The “Your access on this cluster” dialog lists the core cluster-scoped kinds being hidden alongside your effective rules. Namespaces you can’t access don’t appear.
A namespace-scoped ServiceAccount (RoleBinding without a ClusterRole) is fully supported - Radar detects this at startup and works within the permitted namespace.
RBAC granularity (auth enabled):
- Namespaced resources (Pods, Deployments, Services, …) are filtered by namespace: read access is granted in any namespace where the user has list-pods or list-deployments. Secrets are gated independently - a user sees Secret objects (including Helm release storage) only in namespaces where their own RBAC grants
list secrets, even when they have broader access in that namespace. RBAC objects and webhook configurations are likewise re-checked per user. Other cached resource types are visible within a namespace once the user has workload-read access there. - Cluster-scoped resources (Nodes, PVs, StorageClasses, ClusterRoles, cluster-scoped CRDs, …) are gated per-kind via SubjectAccessReview. Cluster-wide pod visibility does NOT imply Node visibility - every cluster-scoped read goes through its own RBAC check, with results cached per user.
rbac.create: false in the Helm values and apply the custom Role/RoleBinding above. Radar will detect the namespace-scoped permissions and work within my-team only.
Authentication
For shared team access, enable authentication so each user gets per-user permissions via Kubernetes RBAC. See the Authentication & Authorization Guide for full setup instructions. Quick start with proxy auth:Security Considerations
When deploying Radar in-cluster: The Helm chart explicitly sets--listen-address=0.0.0.0 so its ClusterIP
Service can reach the pod. Unlike the native CLI’s loopback-only default, this
makes Radar reachable on the pod network; the following controls are therefore
part of the deployment boundary.
- Authentication: Always enable authentication when exposing via ingress. Use built-in auth (proxy or OIDC mode) or basic auth (shown above) at minimum.
-
RBAC scope: The default ClusterRole grants cluster-wide read access. For namespace-restricted access, set
rbac.create: falseand create a custom Role/RoleBinding. Radar will gracefully adapt to the available permissions. -
Privileged features: Terminal (
podExec) and port forwarding grant significant access. Only enable these in trusted environments or when using per-user authentication. - Network access: Consider using NetworkPolicies to restrict which pods can reach Radar.
Timeline Storage: memory vs sqlite vs postgres
Radar’s timeline records every cluster change. Three backends:memory(default): events live in-process, lost on pod restart. Lowest footprint; pick this if you only need recent activity (last few hours).sqlite: events persist to a PVC across restarts. Multi-day audit trail; pick this for long-running in-cluster deployments where you care about history surviving pod cycles. Requirespersistence.enabled=true.postgres: events persist in an externally managed PostgreSQL database. Pick this for durability across restarts and rolling updates, or when you want to avoid the single-PVC constraint. Use a dedicated database per Radar deployment. The DSN must be provided via an existing Kubernetes Secret (timeline.postgres.existingSecret); Helm never touches the credential.
timeline.retention (Go duration; 0 disables age cleanup), timeline.maxSize, and persistence.size together. Keep timeline.maxSize below the PVC size so Radar prunes oldest events before the volume fills. timeline.maxSize is ignored for postgres and memory.
Cleanup runs hourly + once at startup. Confirm it’s keeping up via /api/diagnostics - the timeline.maxStorageBytes, timeline.lastCleanupAt, timeline.lastCleanupDeletedRows, timeline.lastCleanupError, and timeline.storageBytes fields surface the state without requiring kubectl logs.
PostgreSQL requirements
- PostgreSQL 14+ (tested against 17).
- A dedicated database and a user with DDL permissions so Radar can create/update the
radar_timeline_*tables, indexes, and migrations on first startup. sslmodeand other TLS settings are controlled through the DSN string.- The DSN is read from a Secret; never put it in Helm values or
config.json. - Restart the Radar Deployment after rotating the Secret because Kubernetes does not refresh environment variables in running containers.
- There is no built-in import path from SQLite to PostgreSQL. Migrating historical events is not supported.
- Radar treats an unreachable PostgreSQL as fatal rather than falling back to an in-memory timeline, so a pod that cannot reach the database starts in disconnected mode and serves errors instead of cluster data. This is deliberate: silently degrading to memory would hand you a timeline that disappears on the next restart, without saying so. It also means the database is on Radar’s startup path - treat its availability accordingly, and prefer one that lives close to the cluster.
- Recovery after a database outage is not automatic. Once PostgreSQL is reachable again, either use the retry action in the UI or restart the pod. Verified TLS modes:
requireandverify-full.
Configuration Reference
See Helm Chart README for all available values.
Response compression: Radar gzip-compresses HTTP responses by default (streaming endpoints like SSE are excluded). The level defaults to
1 (best speed), since on large clusters peak response size coincides with peak CPU. Set the RADAR_COMPRESS_LEVEL environment variable (via the chart’s pod env) to 0 to disable, or 2-9 to trade CPU for smaller bodies on bandwidth-bound deployments.
Troubleshooting
Pod not starting
Ingress not working
Host header. Preserving Host is the compatibility requirement across browsers and proxies; Fetch Metadata is an additional signal only when both sides forward it. Radar logs rejected handshakes with both Origin and Host.
Basic auth prompt not appearing
Verify the secret format:Uninstalling
radar is a dedicated namespace and contains nothing you need to retain,
delete it separately with kubectl delete namespace radar.