Skip to main content

Documentation Index

Fetch the complete documentation index at: https://infisical.com/docs/llms.txt

Use this file to discover all available pages before exploring further.

The Infisical Operator is a collection of Kubernetes controllers that streamline how secrets are managed between Infisical and your Kubernetes cluster. It provides multiple Custom Resource Definitions (CRDs) which enable you to:
  • Sync secrets from Infisical into Kubernetes.
  • Push new secrets from Kubernetes to Infisical.
  • Manage dynamic secrets and automatically create time-bound leases.
When these CRDs are configured, the Infisical Operator will continuously monitor for changes and perform necessary updates to keep your Kubernetes secrets up to date. It can also automatically reload dependent Deployment resources whenever relevant secrets are updated.
The operator supports two CRD API versions: v1beta1 and v1alpha1. Use v1beta1 for new installations; v1alpha1 is legacy and will be deprecated soon.
If you are already using the External Secrets operator, you can view the integration documentation for it here.
The following Kubernetes minor releases are currently supported. The latest operator version is tested against each Kubernetes version. It may work with other versions of Kubernetes, but those are not officially supported.
  • 1.33
  • 1.32
  • 1.31
  • 1.30
  • 1.29

Install

The operator can be installed via Helm. Helm is a package manager for Kubernetes that allows you to define, install, and upgrade Kubernetes applications. Install the latest Helm repository
helm repo add infisical-helm-charts 'https://dl.cloudsmith.io/public/infisical/helm-charts/helm/charts/' 
helm repo update
The operator can be installed either cluster-wide or restricted to a specific namespace. If you require stronger isolation and stricter access controls, a namespace-scoped installation may make more sense.
When installing the operator cluster-wide, the operator will watch and manage CRDs across all namespaces in the cluster. This is the default installation method and the quickest way to get started with using the operator. Cluster-wide installations are useful for:
  • Simplified Management: A single operator instance manages secrets across all namespaces
  • Centralized Operations: One deployment to monitor, update, and maintain
  • Cross-Namespace Flexibility: Easily manage secrets for applications spanning multiple namespaces
  • Quick Setup: Works out of the box with no additional RBAC configuration required
helm install --generate-name infisical-helm-charts/secrets-operator

Using your own service account

By default a service account is created for the operator based on the operator release name. You can bring your own service account by setting controllerManager.serviceAccount.create to false and setting controllerManager.serviceAccount.name to the name of the service account you want to use in your values.yaml file. Example values.yaml file:
values.yaml
controllerManager:
  serviceAccount:
    create: false
    name: my-service-account
# other values...
Please note that if you set controllerManager.serviceAccount.create to false, the service account needs to already exist in the namespace you are installing the operator in.
Custom service accounts are supported in chart version 0.10.11 and above. Please upgrade your helm chart to 0.10.11 or above before attempting to use custom service accounts.

Custom Resource Definitions

Metrics and Prometheus

The operator exposes Prometheus metrics on /metrics for monitoring reconciliation performance, errors, and resource utilization.

Configuration

Enable the ServiceMonitor during installation. This will create a prometheus ServiceMonitor resource in the same namespace as the operator.
values.yaml
telemetry:
  serviceMonitor:
    enabled: true
    # ... other telemetry configuration (optional) ...
Enable ServiceMonitor for Prometheus Operator. Defaults to false.
Additional labels for ServiceMonitor. Defaults to {}.
Scheme to use for the ServiceMonitor. Defaults to https.
Port to use for the ServiceMonitor. Defaults to https.
Path to use for the ServiceMonitor. Defaults to /metrics.
Scrape interval. Defaults to 30s.
Scrape timeout. Defaults to 10s.
Bearer token file. Defaults to /var/run/secrets/kubernetes.io/serviceaccount/token.
full-example-values.yaml
telemetry:
  serviceMonitor:
    enabled: true

    selectors: {}
    scheme: https
    port: https
    path: /metrics
    bearerTokenFile: /var/run/secrets/kubernetes.io/serviceaccount/token
    interval: 30s
    scrapeTimeout: 10s

Available Metrics

The operator exposes standard controller-runtime metrics. For a complete list of available metrics, see the Kubebuilder metrics reference. Key metrics to monitor:
  • controller_runtime_reconcile_total - Reconciliation count
  • controller_runtime_reconcile_errors_total - Error count
  • controller_runtime_reconcile_time_seconds - Reconciliation duration
v1beta1 controllers: InfisicalStaticSecret, InfisicalAuth, InfisicalConnection v1alpha1 controllers: InfisicalSecret, InfisicalPushSecret, InfisicalDynamicSecret

Example Prometheus Setup

1

Install Prometheus Operator

helm repo add prometheus-community https://prometheus-community.github.io/helm-charts
helm repo update

helm install prometheus prometheus-community/kube-prometheus-stack \
  --namespace monitoring \
  --create-namespace
2

Install Operator with Metrics Enabled

helm repo add infisical-helm-charts 'https://dl.cloudsmith.io/public/infisical/helm-charts/helm/charts/'

helm install infisical-secrets-operator infisical-helm-charts/secrets-operator \
  --set telemetry.serviceMonitor.enabled=true
3

Verify ServiceMonitor

kubectl get servicemonitor
Check that the ServiceMonitor appears in your operator’s namespace.
4

Access Prometheus

kubectl port-forward -n monitoring svc/prometheus-kube-prometheus-prometheus 9090:9090
Open http://localhost:9090/targets and verify the operator target shows UP.

Example Queries

# Total reconciliations
controller_runtime_reconcile_total

# P99 latency
histogram_quantile(0.99, rate(controller_runtime_reconcile_time_seconds_bucket[5m]))

# Memory usage (MB)
process_resident_memory_bytes / 1024 / 1024

General Configuration

Private/self-signed certificate

To connect to Infisical instances behind a private/self-signed certificate, you can configure TLS settings to point to a CA certificate stored in a Kubernetes secret resource.

Templating

Fetching secrets from Infisical as-is via the operator may not be enough. This is where templating functionality may be helpful. Using Go templates, you can format, combine, and create new key-value pairs from secrets fetched from Infisical before storing them as Kubernetes Secrets or ConfigMaps. When a template is set, only the keys defined in template.data are included in the output. When no template is set, all fetched secrets are included as-is. Each secret is available in the template context as .SECRET_KEY, which is an object with two accessors:
  • .Value: the secret value.
  • .SecretPath: the path of the secret in Infisical.

Key/value template map

targets:
  - name: my-app-config
    namespace: default
    kind: Secret
    creationPolicy: Owner
    template:
      engineVersion: v1
      data:
        DSN: "{{ .SECRET.Value }}.namespace:{{ .SECRET2.Value }}"
        ANOTHER_ONE: "{{ .SECRET3.Value }}"

Bulk string template with a loop

targets:
  - name: all-secrets
    namespace: default
    kind: Secret
    creationPolicy: Owner
    template:
      engineVersion: v1
      data: |
        {{- range $key, $secret := . }}
        {{ $key }}: "{{ $secret.Value }}"
        {{- end }}
To help transform your secrets further, the operator provides a set of built-in functions that you can use in your templates.

Available helper functions

The Infisical Secrets Operator exposes a wide range of helper functions to make it easier to work with secrets in Kubernetes.
Encodes a string to a base64-encoded string (e.g. hello world becomes aGVsbG8gd29ybGQ=).Signature
encodeBase64(plainString string) string
Template usage
template:
  data:
    ENCODED_SECRET: "{{ .MY_SECRET.Value | encodeBase64 }}"
Decodes a base64-encoded string back to its original value (e.g. aGVsbG8gd29ybGQ= becomes hello world).Signature
decodeBase64ToBytes(encodedString string) string
Template usage
template:
  data:
    DECODED_SECRET: "{{ .MY_BASE64_SECRET.Value | decodeBase64ToBytes }}"
Extracts all private keys from a PKCS#12 archive and returns them as PKCS#8 PEM-encoded blocks (-----BEGIN PRIVATE KEY-----...). The archive must not be password-protected — use pkcs12keyPass for password-protected archives.Signature
pkcs12key(input string) string
Template usage
template:
  data:
    tls.key: "{{ .TLS_CERT_PKCS12.Value | pkcs12key }}"
Same as pkcs12key, but uses the provided password to decrypt the PKCS#12 archive.Signature
pkcs12keyPass(password string, input string) string
Template usage
template:
  data:
    tls.key: '{{ pkcs12keyPass "my-password" .TLS_CERT_PKCS12.Value }}'
Extracts all certificates from a PKCS#12 archive and returns them as an ordered PEM chain (-----BEGIN CERTIFICATE-----...). Sort order: leaf → intermediate(s) → root. If disjunct or multiple leaf certs are provided, they are returned as-is. The archive must not be password-protected — use pkcs12certPass for password-protected archives.Signature
pkcs12cert(input string) string
Template usage
template:
  data:
    tls.crt: "{{ .TLS_CERT_PKCS12.Value | pkcs12cert }}"
Same as pkcs12cert, but uses the provided password to decrypt the PKCS#12 archive.Signature
pkcs12certPass(password string, input string) string
Template usage
template:
  data:
    tls.crt: '{{ pkcs12certPass "my-password" .TLS_CERT_PKCS12.Value }}'
Takes a PEM-encoded certificate and private key and creates a base64-encoded PKCS#12 archive. The output is not password-protected — use pemToPkcs12Pass to set a password.Signature
pemToPkcs12(cert string, key string) string
Template usage
template:
  data:
    keystore.p12: '{{ pemToPkcs12 .TLS_CERT.Value .TLS_KEY.Value }}'
Same as pemToPkcs12, but encrypts the PKCS#12 archive with the provided password.Signature
pemToPkcs12Pass(cert string, key string, password string) string
Template usage
template:
  data:
    keystore.p12: '{{ pemToPkcs12Pass .TLS_CERT.Value .TLS_KEY.Value "my-password" }}'
Takes a full PEM-encoded certificate chain (leaf + intermediates + root) and a private key, and creates a base64-encoded PKCS#12 archive that includes the entire chain. The output is not password-protected — use fullPemToPkcs12Pass to set a password.Signature
fullPemToPkcs12(cert string, key string) string
Template usage
template:
  data:
    keystore.p12: '{{ fullPemToPkcs12 .TLS_FULL_CHAIN.Value .TLS_KEY.Value }}'
Same as fullPemToPkcs12, but encrypts the PKCS#12 archive with the provided password.Signature
fullPemToPkcs12Pass(cert string, key string, password string) string
Template usage
template:
  data:
    keystore.p12: '{{ fullPemToPkcs12Pass .TLS_FULL_CHAIN.Value .TLS_KEY.Value "my-password" }}'
Filters PEM blocks by type from a bundle containing multiple PEM blocks (e.g. extract only CERTIFICATE or PRIVATE KEY blocks). Common PEM types: CERTIFICATE, PRIVATE KEY, PUBLIC KEY, RSA PRIVATE KEY.Signature
filterPEM(pemType string, input string) string
Template usage
template:
  data:
    ca.crt: '{{ filterPEM "CERTIFICATE" .TLS_BUNDLE.Value }}'
    tls.key: '{{ filterPEM "PRIVATE KEY" .TLS_BUNDLE.Value }}'
Filters PEM certificates by their position in a certificate chain. The chain is automatically ordered before filtering. Accepted types: leaf (end-entity certificate), intermediate (all intermediate CA certificates), root (root CA certificate). Returns an empty string if the requested type is not present in the chain.Signature
filterCertChain(certType string, input string) string
Template usage
template:
  data:
    tls.crt: '{{ filterCertChain "leaf" .TLS_CHAIN.Value }}'
    ca.crt: '{{ filterCertChain "root" .TLS_CHAIN.Value }}'
    intermediate.crt: '{{ filterCertChain "intermediate" .TLS_CHAIN.Value }}'
Takes a JSON-serialized JWK and returns a PEM block of type PUBLIC KEY containing the public key. Uses x509.MarshalPKIXPublicKey internally.Signature
jwkPublicKeyPem(jwkJson string) string
Template usage
template:
  data:
    public.pem: "{{ .MY_JWK.Value | jwkPublicKeyPem }}"
Takes a JSON-serialized JWK and returns a PEM block of type PRIVATE KEY containing the private key. Uses x509.MarshalPKCS8PrivateKey internally.Signature
jwkPrivateKeyPem(jwkJson string) string
Template usage
template:
  data:
    private.pem: "{{ .MY_JWK.Value | jwkPrivateKeyPem }}"
Marshals a value to a YAML string. Returns an empty string on marshal error.Signature
toYaml(v any) string
Template usage
template:
  data:
    config.yaml: "{{ .APP_CONFIG.Value | fromYaml | toYaml }}"
Parses a YAML string into a map[string]any, useful for extracting individual fields from a YAML-formatted secret (e.g. (fromYaml .DB_CONFIG.Value).host returns the host field).Signature
fromYaml(str string) map[string]any
Template usage
template:
  data:
    DB_HOST: '{{ (fromYaml .DB_CONFIG.Value).host }}'
    DB_PORT: '{{ (fromYaml .DB_CONFIG.Value).port }}'

Sprig functions

The Infisical Secrets Operator integrates with the Sprig library to provide additional helper functions.
We’ve removed expandEnv and env from the supported functions for security reasons.

Migrating from v1alpha1 to v1beta1

This migration guide applies to InfisicalSecret only. InfisicalPushSecret and InfisicalDynamicSecret do not have v1beta1 replacements yet and should continue to be used as-is.
The v1beta1 API introduces a cleaner separation of concerns. Instead of defining authentication and connection details inline in each secret CRD, you now create dedicated InfisicalConnection and InfisicalAuth resources that can be shared across multiple secret resources.

Key changes

  • Secret resource: InfisicalSecret -> InfisicalStaticSecret InfisicalStaticSecret replaces the v1alpha1 InfisicalSecret CRD. Instead of defining auth and connection settings inline, it references dedicated InfisicalAuth and InfisicalConnection resources.
  • Authentication: inline authentication -> InfisicalAuth Authentication config is now defined in a standalone InfisicalAuth resource that can be reused across CRDs. Authenticated credentials are cached and shared by all resources referencing the same InfisicalAuth.
  • Connection: inline hostAPI / tls -> InfisicalConnection Connection config is now defined in a standalone InfisicalConnection resource that can be reused by auth and secret resources.

Migration steps

1

Create an InfisicalConnection resource

Extract the hostAPI and tls settings from your existing CRD into a new InfisicalConnection resource. See the InfisicalConnection CRD documentation for the full spec.
2

Create an InfisicalAuth resource

Extract the authentication block from your existing CRD into a new InfisicalAuth resource. See the InfisicalAuth CRD documentation for the full spec.
3

Replace InfisicalSecret with InfisicalStaticSecret

Create a new InfisicalStaticSecret resource that references your InfisicalConnection and InfisicalAuth resources. See the InfisicalStaticSecret CRD documentation for the full spec.
4

Delete the old v1alpha1 resource

Once you have verified that the new v1beta1 resources are working, delete the old InfisicalSecret CRD instance.

Uninstall Operator

The managed secret created by the operator will not be deleted when the operator is uninstalled. Uninstall Infisical Helm repository
  helm uninstall <release name>