wandres.dev
VARIABLES Y SECRETOS · vars y Secrets Store

Entornos: staging y production sin mezclar credenciales

Variables y secretos por entorno en Cloudflare Workers: los entornos con nombre en `wrangler.jsonc`, cómo cada uno es un Worker propio con sus `vars` y sus secretos, la trampa de la herencia, y por qué no se mezclan credenciales entre staging y production.

⏱ 16 min

El mismo Worker vive en más de un mundo: el de pruebas, donde puede romperse sin consecuencias, y el de producción, donde atiende a usuarios reales. Cada mundo necesita su propia configuración —otra URL, otra base de datos— y, sobre todo, sus propias credenciales. Wrangler modela esto con entornos con nombre: variantes del mismo Worker declaradas en un solo manifiesto. La parte técnica es sencilla; la disciplina que exige —no dejar que una credencial de producción se acerque jamás a staging— es lo que separa un despliegue serio de un accidente esperando a ocurrir.

🎯 Al terminar esta lección sabrás
  • Declarar entornos con nombre en wrangler.jsonc y desplegar con --env.
  • Definir vars y secretos separados para staging y para production.
  • Reconocer que cada entorno es, de hecho, un Worker distinto con su propio almacén.
  • Aislar las credenciales por entorno para contener el radio de una fuga.

Un Worker por entorno

Un entorno con nombre es una sección bajo la clave env del manifiesto que sobreescribe la configuración de nivel superior para ese entorno concreto. Declaras staging y production, y cada uno puede tener su nombre, sus rutas, sus vars y sus bindings:

{
  "name": "tienda-api",
  "main": "src/index.ts",
  "compatibility_date": "2026-01-01",
  "env": {
    "staging": {
      "vars": {
        "ENTORNO": "staging",
        "API_BASE": "https://staging.api.tienda.example"
      }
    },
    "production": {
      "vars": {
        "ENTORNO": "produccion",
        "API_BASE": "https://api.tienda.example"
      }
    }
  }
}

Despliegas cada uno indicando el entorno:

# Despliega a staging: crea o actualiza tienda-api-staging
wrangler deploy --env staging

# Despliega a produccion
wrangler deploy --env production

Y aquí está el hecho que lo explica todo: cada entorno con nombre es, físicamente, un Worker distinto en tu cuenta. Wrangler deriva su nombre añadiendo un sufijo —tienda-api-staging, tienda-api-production—, con su propia URL, su propia configuración y, crucialmente, su propio almacén de secretos. No son dos configuraciones de un Worker: son dos Workers que comparten código.

En el panel de Cloudflare verás, por tanto, tantos Workers como entornos hayas desplegado, cada uno con su nombre derivado, sus métricas y su lista de secretos. Esto que al principio sorprende —por qué tengo tres Workers si solo escribí uno— es justamente la garantía que buscas: la separación no es una convención que dependa de tu disciplina, es física.

Esa fisicalidad tiene un coste que conviene aceptar de buen grado: configurar dos entornos es, literalmente, configurar dos Workers, con su despliegue y sus secretos por separado. Quien busca atajar esa duplicación compartiendo credenciales está deshaciendo, por comodidad, justo la barrera que hace segura la separación.

Conviene, eso sí, no confundir separación con divergencia. Los entornos deben diferir solo en los valores, no en su forma; si staging acumula bindings o variables que producción no tiene, deja de ser un ensayo fiel y vuelve a engañarte. La meta es que la única diferencia observable entre entornos sea el contenido de sus almacenes, nunca su estructura.

vars y secretos por entorno

Como cada entorno es un Worker propio, sus secretos también lo son. Para subir un secreto a un entorno concreto, se lo indicas a wrangler secret put:

# Este secreto solo existe en el Worker de produccion
wrangler secret put DB_URL --env production

# Y este, solo en el de staging: valores distintos, almacenes distintos
wrangler secret put DB_URL --env staging

El mismo nombre, DB_URL, apunta a dos valores cifrados en dos almacenes separados. El Worker de staging jamás ve la cadena de conexión de producción, porque vive en otro Worker. En local, el mismo patrón se reproduce con archivos como .dev.vars.staging y .dev.vars.production, que wrangler dev --env <nombre> selecciona según el entorno.

Fíjate en que los secretos nunca aparecen en la sección env del manifiesto: ahí solo declaras vars y bindings por entorno. El secreto se sube aparte, con --env, y por eso el manifiesto puede vivir tranquilo en el repositorio aunque describa la forma de todos tus entornos. La estructura es pública; los valores sensibles van cada uno a su almacén cifrado y separado.

💡
Mismo nombre, distinto valor, en cada entorno

Usa deliberadamente los mismos nombres de secreto en todos los entornos —DB_URL, STRIPE_KEY— y deja que sea el valor lo único que cambie. Así tu código es idéntico entre entornos y no necesita saber en cuál corre para elegir el nombre correcto. El día que veas nombres distintos por entorno, como DB_URL_PROD, sospecha: casi siempre es la señal de un código que se ramifica según el entorno cuando debería ser el entorno quien le sirve el valor.

⚠️
La trampa de la herencia: los entornos no heredan las vars

Este es el error que muerde a todo el mundo una vez. Las claves como vars, los secretos y los bindings NO se heredan automáticamente del nivel superior a los entornos con nombre: son claves no heredables. Si defines vars en la raíz y luego declaras un env.production sin repetir esas vars, el Worker de producción se despliega con esas vars ausentes, no con las de la raíz. La regla defensiva es tratar cada entorno como autónomo: define explícitamente en cada uno todas sus vars, secretos y bindings, y no confíes en que algo del nivel superior se cuele por herencia, porque no lo hará.

La contrapartida de esta autonomía es cierta verbosidad: repetirás bloques de vars y bindings casi idénticos en cada entorno. Es tentador combatir esa repetición con trucos, pero aquí la repetición explícita es una virtud: cada entorno declara por completo de qué depende, y nadie tiene que razonar sobre qué heredó de dónde para saber con qué corre en producción.

No mezclar credenciales

La separación de entornos no es una comodidad de organización: es una frontera de seguridad. La razón se entiende pensando en el radio de daño. Si staging y producción comparten la misma clave de base de datos, entonces staging —el entorno donde pruebas código a medio hacer, donde los permisos son laxos y donde un log descuidado es lo normal— tiene las llaves de los datos reales de tus usuarios. Una fuga en el entorno más expuesto se convierte en una fuga del entorno más crítico.

Aislar credenciales invierte esa lógica: cada entorno tiene claves que solo funcionan en su propio ámbito. La base de datos de staging es una copia de usar y tirar; su clave, aunque se filtre, no abre nada que importe. La de producción vive solo en el Worker de producción, cuyo acceso está restringido a quien despliega de verdad. El principio es el de mínimo privilegio aplicado al eje del entorno: ningún entorno debe poseer una credencial cuyo alcance exceda lo que ese entorno legítimamente necesita tocar.

Piensa en un caso concreto. Una persona recién incorporada necesita depurar staging, así que le das acceso al Worker de staging y a sus secretos. Si staging comparte la clave de la base de datos con producción, acabas de dar a alguien que llegó ayer acceso efectivo a los datos reales de tus clientes sin habértelo propuesto. Con credenciales separadas, ese mismo acceso a staging es inofensivo: abre una base de datos de juguete y nada más. La separación no protege solo de atacantes sofisticados, protege del reparto cotidiano de accesos que toda organización hace sin pensar.

flowchart TD
CODE[un solo codigo fuente] --> WS[worker staging]
CODE --> WP[worker production]
WS --> SS[secretos de staging]
WP --> SP[secretos de production]
SS --> DBS[base de datos de pruebas]
SP --> DBP[base de datos real]
style WP fill:#f38ba8,color:#11111b
style WS fill:#89b4fa,color:#11111b
style SP fill:#fab387,color:#11111b

Herencia, previews y despliegue

Conviene precisar qué se hereda y qué no, porque la trampa anterior tiene su reverso útil. Wrangler distingue claves heredables de no heredables. Las heredables —como el main, la compatibility_date o la base del name— se propagan del nivel superior a cada entorno sin repetirlas. Las no heredables —vars, los secretos y los bindings a KV, D1, R2 y demás— deben declararse en cada entorno de forma explícita. La lógica es deliberada: lo que define la identidad del código se comparte; lo que conecta con recursos y datos concretos se aísla, para que ningún entorno herede por accidente un acceso que no le corresponde.

💻

Local (dev)

Tu máquina con wrangler dev. Secretos en .dev.vars, claves de juguete. Nada de aquí debe abrir nada real.

🔍

Preview

Despliegues efímeros por rama para revisar cambios. Credenciales de pruebas, aisladas de producción, se tiran al cerrar la rama.

🧪

Staging

El ensayo general: idéntico a producción en forma, con datos y claves propios y desechables. Donde algo se rompe sin consecuencias.

🚀

Production

El mundo real. Sus secretos viven solo aquí y solo quien despliega de verdad los toca. Máximo cuidado, mínimo acceso.

Los previews por rama merecen mención aparte porque son donde más se peca. Es cómodo que cada pull request levante un Worker de vista previa, pero si esos previews heredan credenciales de producción para que funcionen igual, has repartido las llaves del reino a cada rama en revisión. Un preview debe ser tan desechable como la rama que lo origina: credenciales de pruebas, alcance mínimo, y ni un solo secreto que duela perder.

Desde CI, el patrón que cierra el círculo es desplegar cada entorno en su propio paso protegido: wrangler deploy --env staging en la rama de integración, wrangler deploy --env production solo tras una aprobación explícita, cada uno autenticado con un token de alcance acotado a lo que ese despliegue necesita tocar. Así la separación de entornos que declaraste en el manifiesto se hace también real en quién puede publicar en cada uno.

Ese último punto cierra el bucle entre configuración y personas. De poco sirve separar los secretos de staging y producción si cualquiera que puede desplegar staging puede también desplegar producción con un --env distinto. La separación de credenciales y la de permisos de despliegue tienen que ir de la mano: el mismo mamparo que aísla los datos debe aislar también quién tiene la mano en la palanca de publicar.

Los entornos con nombre no son la única herramienta para esto: Wrangler admite también configuraciones y previews por rama, y en organizaciones grandes conviven con cuentas separadas que aíslan producción por completo. Pero el principio es invariante a la herramienta: la frontera entre lo que puede romperse y lo que no debe romperse tiene que existir a la vez en la configuración, en los secretos y en los permisos.

Mismo código, distinto mundo: la paridad que no debe alcanzar a los secretos

Hay una tensión hermosa en el corazón de los entornos que conviene nombrar. Por un lado, quieres máxima paridad: que staging se parezca a producción hasta en el último detalle, porque un entorno de pruebas que difiere del real solo sirve para darte una falsa confianza —lo que funciona en staging debería funcionar en producción precisamente porque son casi idénticos—. Por otro lado, quieres máxima separación en una sola dimensión: las credenciales. La resolución de esa tensión es el principio que debes grabar: comparte el código, la estructura, la forma de la configuración y hasta los nombres de las variables entre entornos, pero nunca compartas los valores sensibles. Un mismo DB_URL como nombre en ambos entornos es sano —demuestra que el código es idéntico—; el mismo valor de DB_URL en ambos es una brecha, porque funde en uno el radio de daño de dos mundos que existían separados justamente para contenerlo. Piénsalo como el diseño de un barco con compartimentos estancos: la razón de que existan los mamparos es que una vía de agua en un compartimento no hunda el barco entero. Mezclar las credenciales de staging y producción es abrir un boquete en el mamparo para ahorrarte el trabajo de configurar dos veces la misma clave. El día que staging haga agua —y hará agua, porque para eso está—, agradecerás cada mamparo que dejaste cerrado. La paridad te da confianza; la separación de credenciales te da que un fallo siga siendo un fallo local y no una catástrofe.

⚔️ Separa dos mundos que comparten código
  1. Declara env.staging y env.production en tu wrangler.jsonc, cada uno con sus propias vars, y despliega ambos. Comprueba que aparecen como dos Workers con nombres distintos.
  2. Sube un secreto con el mismo nombre y valores distintos a cada entorno con --env. Verifica desde cada Worker que lee el suyo.
  3. Provoca la trampa de la herencia: define una var solo en la raíz, despliega un entorno sin repetirla, y observa que llega ausente. Corrígelo.
  4. Escribe la política de credenciales de tu proyecto: qué entorno puede tener qué claves, quién puede desplegar a producción, y por qué staging nunca debe tocar datos reales.
  5. Revisa quién en tu equipo puede ejecutar wrangler deploy --env production y confirma que ese permiso está tan separado como los propios secretos de producción.