| title | Periscope Helm values reference — every chart option |
|---|---|
| description | Canonical reference for every value in the Periscope and periscope-agent Helm charts. Image, replicas, RBAC, OIDC, audit, agent — every configurable value with types, defaults, and operator notes. |
Canonical reference for every value in the Periscope and
periscope-agent Helm charts. For walkthroughs and the "why" behind
each block, follow the per-topic links — this page is the
exhaustive flat list operators reach for during a helm upgrade.
The source of truth is each chart's values.yaml. This doc is
re-derived from those files; if a value here disagrees with the
chart, the chart wins and please file a docs bug.
- Chart:
deploy/helm/periscope/values.yaml - Agent chart:
deploy/helm/periscope-agent/values.yaml - Schema validators (run on every
helm install/template):values.schema.jsonand the agent'svalues.schema.json
Every value documented here is part of the v1.0 public configuration surface and covered by semver: breaking changes (rename, type change, removal) require a major bump (v2). New values may land additively in any minor release with safe defaults.
| Value | Type | Default | Notes |
|---|---|---|---|
image.repository |
string | ghcr.io/gnana997/periscope |
OCI repo for the server image. |
image.tag |
string | "" (defaults to Chart.AppVersion) |
Pin to a specific release tag in production. |
image.pullPolicy |
string | IfNotPresent |
Standard K8s pull policy. |
imagePullSecrets |
list | [] |
[{name: <secret>}] entries for private registries. |
| Value | Type | Default | Notes |
|---|---|---|---|
replicaCount |
int | 1 |
v1.0 is single-replica only — the in-memory session store is per-pod. HA / multi-replica is a post-1.0 follow-up. |
| Value | Type | Default | Notes |
|---|---|---|---|
serviceAccount.create |
bool | true |
When false, set serviceAccount.name to an existing SA. |
serviceAccount.name |
string | "" (derived from release name) |
The SA the Deployment runs as. |
serviceAccount.annotations |
map | {} |
IRSA path: set eks.amazonaws.com/role-arn here. |
podIdentity.enabled |
bool | false |
Pod Identity path (preferred for new EKS). When true, no IRSA annotation is rendered — create the association out-of-band. |
See deploy.md for the IRSA vs Pod Identity decision.
OIDC, session, and authorization settings. Written verbatim into
the rendered auth.yaml ConfigMap. See auth0.md /
okta.md for IdP-specific values, and
cluster-rbac.md for authorization mode
trade-offs.
| Value | Type | Default | Notes |
|---|---|---|---|
auth.oidc.issuer |
string | "" |
OIDC discovery URL. |
auth.oidc.clientID |
string | "" |
OIDC client ID. |
auth.oidc.clientSecret |
string | ${OIDC_CLIENT_SECRET} |
Reference into the chosen secrets.mode. |
auth.oidc.redirectURL |
string | "" |
Periscope's /api/auth/callback URL. |
auth.oidc.scopes |
list | [openid, profile, email, offline_access] |
Standard scopes; usually leave as-is. |
auth.oidc.audience |
string | "" |
Auth0 only; leave empty for Okta and most IdPs. |
auth.oidc.postLogoutRedirect |
string | "" |
URL the browser lands on after IdP logout. |
auth.session.cookieName |
string | periscope_session |
Session cookie name. |
auth.session.idleTimeout |
duration | 30m |
Idle timeout before the session is invalidated. |
auth.session.absoluteTimeout |
duration | 8h |
Hard cap on session lifetime. |
auth.session.cookieDomain |
string | unset | Optional explicit Domain= attribute on the cookie. |
auth.authorization.mode |
enum | shared |
shared | tier | raw. See RFC 0002 4 and cluster-rbac.md. |
auth.authorization.groupTiers |
map | {} |
tier-mode only: IdP group → tier (read|triage|write|maintain|admin). |
auth.authorization.defaultTier |
string | "" |
tier-mode only: tier applied when no group matches. "" = deny. |
auth.authorization.groupPrefix |
string | periscope: |
raw-mode only: prefix prepended to each impersonated group. |
auth.authorization.groupsClaim |
string | groups |
IdP token claim that holds the groups list. Auth0 needs a custom namespaced claim. |
auth.authorization.allowedGroups |
list | [] |
All modes: gate on these IdP groups. Empty = any authenticated user. |
auth.authorization.auditAdminGroups |
list | [] |
IdP groups granted full /api/audit visibility across all users. |
auth.dev.subject |
string | dev@local |
Local-dev only; identity used when no OIDC is configured. |
auth.dev.email |
string | dev@local |
Local-dev only. |
auth.dev.groups |
list | [dev] |
Local-dev only. |
The cluster registry. Written verbatim into the rendered
clusters.yaml ConfigMap. Three backends — see
deploy.md and
agent-onboarding.md.
| Value | Type | Default | Notes |
|---|---|---|---|
clusters |
list | [] |
Each entry has name + backend plus backend-specific fields. |
Per-entry fields by backend:
backend: eks — name, backend: eks, region, arn.
backend: kubeconfig — name, backend: kubeconfig, kubeconfigPath, optional kubeconfigContext.
backend: in-cluster — name, backend: in-cluster. The chart auto-binds the Periscope SA to the impersonator role.
backend: agent — name, backend: agent. No other backend-specific fields; the agent dialing in with a matching mTLS CN supplies the connection.
Per-cluster overrides (any backend):
| Field | Type | Notes |
|---|---|---|
exec.enabled |
bool | false disables exec entirely on this cluster. |
exec.serverIdleSeconds |
int | Overrides global idle timeout for this cluster. |
exec.idleWarnSeconds |
int | Overrides global idle-warn lead. |
exec.heartbeatSeconds |
int | Overrides global heartbeat. |
exec.maxSessionsPerUser |
int | Overrides global per-user cap. |
exec.maxSessionsTotal |
int | Overrides global per-cluster cap. |
environment |
string | Free-form label, surfaced on the fleet card (e.g. prod, staging). |
How the OIDC client secret reaches the pod. Pick exactly one mode.
| Value | Type | Default | Notes |
|---|---|---|---|
secrets.mode |
enum | existing |
existing | plain | external | native. |
secrets.existing.name |
string | periscope-oidc |
Name of the pre-applied K8s Secret. |
secrets.existing.key |
string | OIDC_CLIENT_SECRET |
Key in the Secret + env-var name on the pod. |
secrets.plain.clientSecret |
string | "" |
Used only when mode=plain. Renders a kind: Secret from values — fine for kind/minikube, never for prod. |
secrets.external.storeName |
string | "" |
External Secrets Operator: SecretStore / ClusterSecretStore name. |
secrets.external.storeKind |
enum | ClusterSecretStore |
Or SecretStore. |
secrets.external.refreshInterval |
duration | 1h |
Resync interval on the rendered ExternalSecret. |
secrets.external.remoteKey |
string | "" |
Upstream secret path / name. |
secrets.external.remoteProperty |
string | "" |
JSON key to extract when the upstream value is JSON-shaped. |
secrets.native.enabled |
bool | true |
No K8s Secret at all; Periscope's resolver fetches from AWS Secrets Manager / SSM at startup. Point auth.oidc.clientSecret at e.g. aws-secretsmanager://periscope/oidc#client_secret. |
| Value | Type | Default | Notes |
|---|---|---|---|
env |
list | [] |
Extra name: value pairs. Rarely needed — the chart maps documented PERISCOPE_* vars from typed values. |
| Value | Type | Default | Notes |
|---|---|---|---|
service.type |
string | ClusterIP |
Standard K8s Service type. |
service.port |
int | 8080 |
Periscope listens on :8080 inside the pod. |
ingress.enabled |
bool | false |
When true, an Ingress resource is rendered. |
ingress.className |
string | "" |
IngressClass name (nginx, alb, …). |
ingress.annotations |
map | {} |
Controller-specific annotations. |
ingress.host |
string | "" |
Hostname the Ingress matches. |
ingress.path |
string | / |
Path to match. |
ingress.pathType |
string | Prefix |
Standard pathType. |
ingress.tls.enabled |
bool | false |
Render a TLS section. |
ingress.tls.secretName |
string | "" |
TLS Secret name when enabled. |
| Value | Type | Default | Notes |
|---|---|---|---|
resources.requests.cpu |
quantity | 100m |
|
resources.requests.memory |
quantity | 128Mi |
|
resources.limits.cpu |
quantity | 500m |
|
resources.limits.memory |
quantity | 512Mi |
|
podAnnotations |
map | {} |
Extra annotations on the Deployment's pod template. |
podSecurityContext.runAsNonRoot |
bool | true |
|
podSecurityContext.runAsUser |
int | 65532 |
Distroless nonroot UID. |
podSecurityContext.runAsGroup |
int | 65532 |
|
podSecurityContext.fsGroup |
int | 65532 |
|
podSecurityContext.seccompProfile.type |
string | RuntimeDefault |
|
containerSecurityContext.allowPrivilegeEscalation |
bool | false |
|
containerSecurityContext.readOnlyRootFilesystem |
bool | true |
|
containerSecurityContext.capabilities.drop |
list | [ALL] |
|
nodeSelector |
map | {} |
Standard. |
tolerations |
list | [] |
Standard. |
affinity |
map | {} |
Standard. |
Audit log persistence. See audit.md for retention
sizing and the "stdout always on, SQLite optional" model.
| Value | Type | Default | Notes |
|---|---|---|---|
audit.enabled |
bool | false |
When true, also writes audit events to a local SQLite DB. stdout JSON emission is unconditional. |
audit.retentionDays |
int | 30 |
Time-based retention. 0 disables time-based pruning. |
audit.maxSizeMB |
int | 1024 |
Application-level on-disk cap. 0 disables size-based pruning. |
audit.vacuumInterval |
duration | 24h |
How often the prune+VACUUM loop runs. |
audit.storage.type |
enum | pvc |
pvc (persistent) | emptyDir (ephemeral). |
audit.storage.size |
quantity | 5Gi |
PVC request size. Used only when type=pvc. |
audit.storage.storageClass |
string | "" |
Empty = cluster default StorageClass. |
audit.storage.accessMode |
string | ReadWriteOnce |
v1.0 single-replica needs only RWO. |
Pod-exec global defaults. Per-cluster overrides go under
clusters[].exec. See pod-exec.md for the
operator guide.
| Value | Type | Default | Notes |
|---|---|---|---|
exec.serverIdleSeconds |
int | 600 |
Server-side idle timeout. |
exec.idleWarnSeconds |
int | 30 |
Browser warning lead before the cut. |
exec.heartbeatSeconds |
int | 20 |
WebSocket heartbeat ping interval. |
exec.maxSessionsPerUser |
int | 5 |
Concurrent sessions per OIDC subject. |
exec.maxSessionsTotal |
int | 50 |
Concurrent sessions per cluster. |
exec.probeClustersOnBoot |
bool | false |
Pre-warm IAM creds + exec policy at startup. |
There is intentionally no global exec.enabled switch. Disable
exec per-cluster via clusters[i].exec.enabled: false.
SSE live-list configuration. See
watch-streams.md for the kind registry,
group aliases, and fallback behavior.
| Value | Type | Default | Notes |
|---|---|---|---|
watchStreams.kinds |
string | "" |
Empty / all / off / none / comma-separated kinds / group aliases. |
watchStreams.perUserLimit |
int | 60 |
Per-user concurrent stream cap. 0 disables (not recommended). |
Group aliases: core, config, workloads, networking,
storage, cluster. Per-kind tokens: see watchStreams: block in
values.yaml.
| Value | Type | Default | Notes |
|---|---|---|---|
pdb.enabled |
bool | true |
Render a PodDisruptionBudget. |
pdb.maxUnavailable |
int | 1 |
v1.0 single-replica: 1 allows drains. Switch to minAvailable per replica when HA lands post-1.0. |
See networkpolicy.md for the full recipe.
| Value | Type | Default | Notes |
|---|---|---|---|
networkPolicy.enabled |
bool | false |
Render a NetworkPolicy. |
networkPolicy.ingress.fromNamespaces |
list | [] |
namespaceSelector matchLabels for permitted ingress sources. |
networkPolicy.ingress.extra |
list | [] |
Raw NetworkPolicyIngressRule entries appended. |
networkPolicy.egress.extra |
list | [] |
Raw NetworkPolicyEgressRule entries (e.g. IdP CIDRs, EKS endpoints). DNS to kube-dns is always added. |
Tier-mode RBAC manifests rendered for the central cluster. See
cluster-rbac.md.
| Value | Type | Default | Notes |
|---|---|---|---|
clusterRBAC.enabled |
bool | false |
Render the periscope-tier ClusterRoles + bindings. |
clusterRBAC.bridgeGroup |
string | periscope-bridge |
K8s group your EKS Access Entry binds the pod principal to. |
clusterRBAC.adminTier.enabled |
bool | false |
(#84) Render the periscope-tier:admin ClusterRoleBinding. OFF by default so CIS 5.1.1 / AWS Guardrails pass. Set true to restore v1.0.x behaviour. |
clusterRBAC.adminTier.clusterRoleName |
string | cluster-admin |
Target ClusterRole for the admin tier when enabled. Repoint at a tighter custom role for a less-permissive admin tier. |
clusterRBAC.sharedRoleName |
string | view |
(#142) When auth.authorization.mode: shared and any clusters[].backend: in-cluster, the chart auto-renders a periscope-shared ClusterRoleBinding pointing the SA at this ClusterRole. Default view is read-only. Use edit for write access, or empty "" to suppress entirely. |
Server-side agent backend (#42) — opens the mTLS tunnel listener
and the registration endpoints. See
agent-onboarding.md and
../architecture/agent-tunnel.md.
| Value | Type | Default | Notes |
|---|---|---|---|
agent.enabled |
bool | false |
Master switch — opens :8443, mounts /api/agents/* routes, pre-creates the CA Secret. |
agent.listenAddr |
string | :8443 |
Bind address for the mTLS tunnel listener. |
agent.tunnelSANs |
string | localhost |
Comma-separated SANs baked into the server cert agents present on the tunnel. |
agent.caSecretName |
string | periscope-agent-ca |
K8s Secret holding the per-deployment CA. |
agent.tunnelService.enabled |
bool | false |
Render a second Service to expose the tunnel listener externally. |
agent.tunnelService.type |
string | LoadBalancer |
NLB recommended (TLS-passthrough). |
agent.tunnelService.port |
int | 8443 |
External port for the tunnel Service. |
agent.tunnelService.annotations |
map | {} |
Cloud-LB-specific annotations. |
Each managed cluster runs ONE periscope-agent Deployment. Most
fields are install-time identity; the rest can stay at defaults.
See agent-onboarding.md for the
topology decision matrix.
| Value | Type | Default | Notes |
|---|---|---|---|
image.repository |
string | ghcr.io/gnana997/periscope-agent |
|
image.tag |
string | "" (defaults to Chart.AppVersion) |
|
image.pullPolicy |
string | IfNotPresent |
|
imagePullSecrets |
list | [] |
| Value | Type | Default | Notes |
|---|---|---|---|
agent.serverURL |
string | "" |
Required. WebSocket URL of the central tunnel listener (wss://...:8443/api/agents/connect). |
agent.clusterName |
string | "" |
Required. Must match a clusters[].name of backend: agent on the server. |
agent.registrationToken |
string | "" |
Required on first install only. Bootstrap token from POST /api/agents/tokens. Single-use, 15-min TTL. |
agent.registrationURL |
string | "" |
Set when registration uses a different LB than the tunnel (Topology B — split ALB+NLB). Empty = derive from serverURL. |
agent.serverCAHash |
string | "" |
SPKI hash (sha256:...) for self-signed registration endpoints (Topology C). |
agent.stateSecretName |
string | periscope-agent-state |
Persisted mTLS cert + key + server CA. |
agent.healthAddr |
string | :8081 |
Liveness / readiness probe port. |
agent.logLevel |
enum | "" (binary default = info) |
debug | info | warn | error. Set debug for per-request access logs. |
agent.execIdleSeconds |
int | 600 |
Per-connection idle timeout (seconds) for hijacked exec WS / SPDY streams. Mirrors the server's PERISCOPE_EXEC_IDLE_SECONDS; set the same value here so stuck streams get reaped on the agent side if the server crashes mid-session. Activity = any successful read; only idle streams are killed. 0 disables (relies entirely on server-side cascade close + OS TCP keepalive — not recommended). |
| Value | Type | Default | Notes |
|---|---|---|---|
replicaCount |
int | 1 |
Tunnel sessions are 1:1 with agent pods. HA needs server-side peer routing (post-1.0). |
serviceAccount.create |
bool | true |
|
serviceAccount.name |
string | "" |
|
serviceAccount.annotations |
map | {} |
| Value | Type | Default | Notes |
|---|---|---|---|
clusterRole.enabled |
bool | true |
Bind the agent SA to a ClusterRole granting get/list/watch on every kind + impersonate on users/groups/SAs. |
clusterRBAC.enabled |
bool | true |
Install tier ClusterRoleBindings on the managed cluster (periscope-tier-read/write/triage/maintain (the admin binding is opt-in — see below)). Required for impersonation to actually authorize. |
clusterRBAC.adminTier.enabled |
bool | false |
(#84) Render the periscope-tier:admin ClusterRoleBinding on the managed cluster. OFF by default so CIS 5.1.1 / AWS Guardrails pass. Set true to restore v1.0.x behaviour. |
clusterRBAC.adminTier.clusterRoleName |
string | cluster-admin |
Target ClusterRole for the admin tier when enabled. Repoint at a tighter custom role you ship out-of-band. |
Mirrors the server chart's defaults; same fields, just with agent-appropriate request/limit values.
| Value | Type | Default |
|---|---|---|
resources.requests.cpu |
quantity | 50m |
resources.requests.memory |
quantity | 64Mi |
resources.limits.cpu |
quantity | 500m |
resources.limits.memory |
quantity | 256Mi |
podSecurityContext.runAsNonRoot |
bool | true |
podSecurityContext.runAsUser |
int | 65532 |
podSecurityContext.runAsGroup |
int | 65532 |
podSecurityContext.seccompProfile.type |
string | RuntimeDefault |
containerSecurityContext.allowPrivilegeEscalation |
bool | false |
containerSecurityContext.readOnlyRootFilesystem |
bool | true |
containerSecurityContext.capabilities.drop |
list | [ALL] |
nodeSelector |
map | {} |
tolerations |
list | [] |
affinity |
map | {} |
podAnnotations |
map | {} |
env |
list | [] |
Surfaces Inspector v2 findings inline on the Nodes / Pods / Workloads pages.
Default: disabled. Existing v1.0.x deployments stay byte-identical on upgrade. To turn it on:
- Enable Amazon Inspector v2 in the AWS account you want scanned (per-scan billing applies; this is an operator decision).
- Grant the periscope-server's Pod Identity / IRSA role the four
inspector2:*permissions listed incluster-rbac.md. - Set
inspector.enabled: truein your Helm values.
When at least one entry in clusters[] uses backend: in-cluster, the chart auto-renders a periscope-inspector ClusterRole + ClusterRoleBinding granting the server's ServiceAccount the K8s reads (nodes, pods, customresourcedefinitions) the background hydrate / image-digest watch / karpenter detect need. See cluster-rbac.md K8s RBAC for in-cluster backend for the full rationale. Agent-backed clusters cover this via the agent chart's own ClusterRole.
| Value | Type | Default | Description |
|---|---|---|---|
inspector.enabled |
bool | false |
Master switch. Renders no env vars (and no goroutines run) when false. |
inspector.refreshInterval |
duration | 6h |
Per-entry TTL. Catches newly-published CVEs against unchanged digests. |
inspector.evictAfter |
duration | 24h |
Cooldown before a zero-ref entry is dropped. Keeps recently-deleted pod digests warm. |
inspector.hydrateBatchSize |
int | 50 |
Inspector ListFindings batch size during cold-path hydrate. Capped at 50 (SDK BatchGet limit). |
Maps one-to-one to PERISCOPE_INSPECTOR_* env vars; see environment-variables.md.
Architecture: per-cluster in-memory cache hydrated lazily on first activation (~10-30s scan), kept fresh via the pod watch hook + the 6h TTL, served at <1ms thereafter. The SPA never calls Inspector directly. See issue #163 for the design notes.
When Inspector v2 is not enabled on the AWS account (or the IAM grant is missing), the store flips to a "disabled" state and the UI renders an "Inspector v2 not enabled" hint instead of a generic error — no AccessDenied loop, no retries until the next process restart.
environment-variables.md—PERISCOPE_*env vars the binary reads (one-to-one mapping with most typed values above).deploy.md— full install walkthrough.agent-onboarding.md— multi-cluster agent install with topology decision matrix.