npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@varlock/kubernetes-plugin

v1.0.0

Published

Varlock plugin to load values from Kubernetes Secrets and ConfigMaps

Readme

@varlock/kubernetes-plugin

Load values from Kubernetes Secrets and ConfigMaps into your Varlock configuration.

Scope

This plugin is read-only. It performs get requests on Secrets and ConfigMaps in a configured namespace and surfaces the values to your .env schema — nothing more. It does not create, update, or delete cluster resources, generate or template manifests, watch for changes, or manage deployments.

Typical use cases:

  • Local development — pull dev/staging Secrets and ConfigMaps from a cluster into your local app without copying values by hand
  • In-cluster runtime — read additional Secrets/ConfigMaps at runtime that aren't already mounted into the pod via envFrom/valueFrom
  • CI/CD — read Secrets/ConfigMaps from a cluster using an explicit service account token

Deeper Kubernetes integration is on our radar. If you have ideas, a use case this plugin doesn't cover, or feedback from running it in production, come chat on Discord — we'd love to hear from you.

Features

  • Zero-config local development using your default kubeconfig
  • In-cluster authentication using the pod's mounted service account
  • Explicit auth via cluster API URL + bearer token (CI/CD, deployed apps)
  • Fetch individual keys from Secrets and ConfigMaps
  • Bulk-load whole Secrets or ConfigMaps with @setValuesBulk
  • Configurable default Secret / ConfigMap so common cases don't repeat themselves
  • Multiple plugin instances for different namespaces or clusters
  • Auto-decode base64 Secret values and ConfigMap binaryData

Installation

npm install @varlock/kubernetes-plugin

Then load it from your .env.schema:

# @plugin(@varlock/kubernetes-plugin)

Setup + Auth

Automatic auth (Recommended for local dev)

For local development, just initialize the plugin and it will use your default kubeconfig ($KUBECONFIG or ~/.kube/config):

# @plugin(@varlock/kubernetes-plugin)
# @initKubernetes(namespace=default)

Inside a pod, omit kubeconfig-related settings and the plugin will use the mounted service account credentials at /var/run/secrets/kubernetes.io/serviceaccount/.

Explicit cluster server + token (For CI/CD)

For deployments without a kubeconfig, provide the API server URL and a bearer token directly:

# @plugin(@varlock/kubernetes-plugin)
# @initKubernetes(
#   namespace=default,
#   clusterServer="https://kubernetes.example.com:6443",
#   token=$KUBERNETES_TOKEN
# )
# ---

# @type=kubernetesBearerToken @sensitive @internal
KUBERNETES_TOKEN=

See Kubernetes Setup below for how to mint a long-lived service account token.

Raw kubeconfig

You can also pass a full kubeconfig as a string (YAML or JSON) — useful when injecting credentials from a secret manager:

# @initKubernetes(kubeconfig=$KUBECONFIG_DATA)
# ---
# @sensitive
KUBECONFIG_DATA=

Authentication priority

The plugin tries authentication methods in this order:

  1. Explicit cluster server + token — if clusterServer is provided
  2. Explicit kubeconfig — if kubeconfig is provided (file path or raw YAML/JSON)
  3. In-cluster service account — auto-detected via KUBERNETES_SERVICE_HOST / KUBERNETES_SERVICE_PORT
  4. Default kubeconfig$KUBECONFIG or ~/.kube/config

You can override the active kubeconfig context with context=....

Multiple instances

To read from multiple namespaces or clusters, register named instances:

# @initKubernetes(id=dev, namespace=dev)
# @initKubernetes(id=prod, namespace=prod, context=prod-cluster)
# ---

DEV_DATABASE_URL=k8sSecret(dev, app-secrets, DATABASE_URL)
PROD_DATABASE_URL=k8sSecret(prod, app-secrets, DATABASE_URL)

Reading values

How Secrets and ConfigMaps are structured

A Kubernetes Secret/ConfigMap is a named resource that holds a map of key/value pairs:

apiVersion: v1
kind: Secret
metadata:
  name: app-secrets       # ← the resource name
data:
  DATABASE_URL: cG9zdGdyZXM6...    # ← keys inside the resource
  API_KEY: c2VjcmV0LWtleQ==

So fetching a value is always a two-level lookup: which resource (name), and which key inside it (key).

Secret keys

Secret data values are base64-decoded automatically.

# Auto-infer key from item name (fetches app-secrets.data.DATABASE_URL)
DATABASE_URL=k8sSecret(app-secrets)

# Explicit key name
DB_URL=k8sSecret(app-secrets, DATABASE_URL)

# Named args also work
DB_URL=k8sSecret(name=app-secrets, key=DATABASE_URL)

ConfigMap keys

Both data (strings) and binaryData (base64-decoded) fields are supported.

PUBLIC_API_HOST=k8sConfigMap(app-config)
API_HOST=k8sConfigMap(app-config, PUBLIC_API_HOST)

Default Secret / ConfigMap

The idiomatic k8s pattern is one Secret + one ConfigMap per app. Set defaults on the init decorator and skip the name argument:

# @plugin(@varlock/kubernetes-plugin)
# @initKubernetes(
#   namespace=default,
#   defaultSecret=app-secrets,
#   defaultConfigMap=app-config,
# )
# ---

# Both default to app-secrets / app-config and infer the key from the item name
DATABASE_URL=k8sSecret()
API_KEY=k8sSecret()
PUBLIC_API_HOST=k8sConfigMap()

# Override just the key while still using the default Secret
STRIPE_KEY=k8sSecret(key=stripe_api_key)

# Override the resource name to read from a different Secret
SHARED_TOKEN=k8sSecret(shared-secrets, AUTH_TOKEN)

You can mix positional and named arguments, but providing the same field both ways (e.g. k8sSecret(app-secrets, name=other)) is a schema error.

Bulk loading

Use bulk loading when one Secret or ConfigMap contains several env vars. The bulk resolvers return a JSON object, which pairs with @setValuesBulk:

# @plugin(@varlock/kubernetes-plugin)
# @initKubernetes(namespace=default)
# @setValuesBulk(k8sSecretBulk(app-secrets), format=json)
# @setValuesBulk(k8sConfigMapBulk(app-config), format=json)
# ---

DATABASE_URL=
API_KEY=
PUBLIC_API_HOST=

Only items declared in your schema will be populated — extra keys in the resource are ignored. Bulk resolvers also pick up defaultSecret / defaultConfigMap, so the names can be omitted.

Optional values

By default, fetching from a missing Secret/ConfigMap throws. To resolve missing resources or keys to undefined, set allowMissing=true:

# @initKubernetes(namespace=default, allowMissing=true)
# ---

# @required=false
OPTIONAL_FLAG=k8sConfigMap(feature-flags, NEW_UI)

Mark optional items with @required=false (or wrap with fallback()) so validation doesn't fail.

Reference

Root decorators

@initKubernetes()

Initialize a Kubernetes plugin instance for the resolvers below.

Parameters:

  • id?: string (static) - Instance identifier for multiple instances (defaults to _default)
  • namespace?: string - Kubernetes namespace. Defaults to the kubeconfig context namespace, the in-cluster service account namespace, or default
  • context?: string - Kubeconfig context name (overrides the current context)
  • kubeconfig?: string - Path to a kubeconfig file, or raw kubeconfig YAML/JSON content
  • clusterServer?: string - Kubernetes API server URL for explicit auth (e.g., https://kubernetes.example.com:6443)
  • token?: string - Bearer token for explicit auth
  • skipTlsVerify?: boolean - Skip TLS verification (only applies to explicit clusterServer + token auth)
  • allowMissing?: boolean - Missing resources or keys resolve to undefined instead of throwing
  • defaultSecret?: string - Default Secret name for k8sSecret() / k8sSecretBulk()
  • defaultConfigMap?: string - Default ConfigMap name for k8sConfigMap() / k8sConfigMapBulk()

Functions

All resolvers accept positional and named arguments. The same field cannot be provided both ways.

k8sSecret()

Fetch a single key from a Secret. Values are base64-decoded automatically.

Signatures:

  • k8sSecret() - Uses defaultSecret, infers key from item name
  • k8sSecret(name) - Uses given Secret, infers key from item name
  • k8sSecret(name, key) - Explicit name and key
  • k8sSecret(instanceId, name, key) - With explicit instance
  • k8sSecret(name=..., key=..., id=...) - Same with named args

k8sConfigMap()

Fetch a single key from a ConfigMap. Both data and binaryData are supported.

Signatures: same shape as k8sSecret() — substitute k8sConfigMap and defaultConfigMap.

k8sSecretBulk()

Fetch all keys from a Secret as a JSON object. Designed for @setValuesBulk(..., format=json).

Signatures:

  • k8sSecretBulk() - Uses defaultSecret
  • k8sSecretBulk(name) - Explicit Secret name
  • k8sSecretBulk(instanceId, name) - With explicit instance
  • k8sSecretBulk(name=..., id=...) - Same with named args

k8sConfigMapBulk()

Same shape as k8sSecretBulk() — substitute k8sConfigMapBulk and defaultConfigMap.

Data Types

  • kubernetesBearerToken - Kubernetes service account / API server bearer token (sensitive)

Kubernetes Setup

Required RBAC permissions

The identity used by the plugin (your kubeconfig user, an in-cluster service account, or an explicit token) needs read access to Secrets and/or ConfigMaps in the target namespace.

The minimum permissions are get on secrets and configmaps:

# varlock-rbac.yaml
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
  name: varlock-reader
  namespace: default
rules:
  - apiGroups: [""]
    resources: ["secrets", "configmaps"]
    verbs: ["get"]
kubectl apply -f varlock-rbac.yaml

For least privilege, omit "secrets" if you only need ConfigMaps. Prefer namespaced Roles over ClusterRoles whenever possible.

Service account for in-cluster use

kubectl create serviceaccount varlock-reader -n default

Bind the role to the service account:

# varlock-rolebinding.yaml
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
  name: varlock-reader-binding
  namespace: default
subjects:
  - kind: ServiceAccount
    name: varlock-reader
    namespace: default
roleRef:
  kind: Role
  name: varlock-reader
  apiGroup: rbac.authorization.k8s.io

Then use it in your pod spec:

spec:
  serviceAccountName: varlock-reader
  containers:
    - name: app
      image: my-app:latest

Generate a bearer token for explicit auth

For CI/CD or other external use cases, create a long-lived service account token:

kubectl apply -f - <<EOF
apiVersion: v1
kind: Secret
metadata:
  name: varlock-reader-token
  namespace: default
  annotations:
    kubernetes.io/service-account.name: varlock-reader
type: kubernetes.io/service-account-token
EOF

kubectl get secret varlock-reader-token -n default -o jsonpath='{.data.token}' | base64 -d

Verify access

kubectl auth can-i get secrets -n default
kubectl auth can-i get configmaps -n default --as=system:serviceaccount:default:varlock-reader

Troubleshooting

Secret or ConfigMap not found (404)

  • Verify the resource exists: kubectl get secret <name> -n <namespace>
  • Double-check the namespace — the plugin only reads from the configured namespace
  • Resource names are case-sensitive and namespace-scoped
  • If the resource is genuinely optional, set allowMissing=true on @initKubernetes() and @required=false on the item

Permission denied (403)

  • Check that the active identity has the required RBAC: kubectl auth can-i get secrets -n <namespace>
  • For in-cluster use, verify the pod's serviceAccountName is set and bound to a Role/ClusterRole that grants get on secrets/configmaps
  • The error message includes the exact Role snippet you need to grant

Authentication failed (401)

  • Local dev: Run kubectl config current-context and kubectl get secrets to confirm your kubeconfig works
  • Explicit token: Verify the token isn't expired or revoked
  • In-cluster: Check the pod's mounted service account token at /var/run/secrets/kubernetes.io/serviceaccount/token

Connection refused or TLS errors

  • Verify the cluster API URL is reachable from your machine/pod
  • For clusters with self-signed certificates and explicit auth, set skipTlsVerify=true (development only)
  • If kubectl works but the plugin doesn't, your kubeconfig may rely on an exec credential plugin (aws eks get-token, gke-gcloud-auth-plugin, kubelogin) — ensure the helper binary is on your $PATH

Wrong namespace

  • The plugin uses (in order): explicit namespace argument, kubeconfig context namespace, pod's mounted SA namespace, or default
  • Force a specific namespace with @initKubernetes(namespace=my-ns)