Ir al contenido principal
Laravel, shipping fast.
Capitulo 14 · DevOps e infraestructura

Secretos que nunca llegan al repositorio

Julian Beaujardin

Cada fichero de configuración de esta flota es el único sitio donde viven las llamadas a env():

// config/database.php
declare(strict_types=1);

return [
    'connections' => [
        'mysql' => [
            'driver' => 'mysql',
            'database' => env('DB_DATABASE', 'laravel'),
            'username' => env('DB_USERNAME', 'root'),
            'password' => env('DB_PASSWORD', ''),
        ],
        // ...other connections
    ],
];

Por qué importa esto no es una preferencia de estilo. php artisan config:cache, que todo despliegue de producción debería ejecutar, lee cada fichero de configuración una vez, resuelve cada llamada a env() en ese momento y escribe el resultado en un único fichero compilado. Después de que exista esa caché, Laravel deja de leer .env por completo para las búsquedas de configuración. Una llamada a env() dentro de un controlador o un job, en lugar de en un fichero de configuración, queda horneada mal o devuelve null tras el cacheo, según cuándo corra respecto a la construcción de la caché. Eso no es una regla de estilo: es un fallo en tiempo de ejecución esperando al primer despliegue que ejecute config:cache.

Los valores reales nunca viven en el repositorio. .env y sus variantes están en .gitignore. Lo que se confirma es el nombre de la clave, envuelto en env(), con un valor por defecto seguro para desarrollo local. El valor vive en el servidor, fuera por completo de git pull. Un despliegue que trae código nuevo nunca toca secretos, porque los secretos nunca fueron algo que un despliegue traiga.

Aprovisionar de forma repetible

Aprovisionar un servidor a mano, una vez, con cuidado, es fácil. Hacerlo igual la quinta vez, a las once de la noche, bajo presión, sin saltarte calladamente el paso que siempre te saltas, es donde el aprovisionamiento manual falla de verdad.

Este libro ha dedicado doce capítulos a defender una idea aplicada a las licencias: no escribas a mano una llamada a un sistema externo en línea; pon un Manager detrás de una Facade, un Driver detrás del Manager, y deja que el resto de tu código dependa de la interfaz en lugar del proveedor.

El aprovisionamiento merece el mismo trato, por la misma razón. Un aprovisionador de servidores que es un caso de un enum, junto a GitHub y Stripe, es un aprovisionador del que tus jobs pueden depender, contra el que pueden reintentar y cuyos fallos pueden reportar, usando exactamente la misma maquinaria que este libro ya construyó para reintentos, esperas y cargas cifradas. Un aprovisionador que es un script que alguien ejecuta desde su propia terminal, recordando las banderas de memoria, es un aprovisionador que falla distinto cada vez que lo ejecuta alguien nuevo.

El aprovisionamiento repetible no es una disciplina distinta de los patrones de este libro. Es la misma disciplina —DTOs para lo que el proveedor necesita saber, un contrato tipado para lo que devuelve, un Manager que oculta qué proveedor hay debajo— aplicada a servidores en lugar de a licencias.

Resumen

Antes de desplegar

  • [X] La integración continua ejecuta los mismos format, check y test que ejecuta una persona en local, y hace fallar la construcción si alguno falla
  • [X] Las versiones se construyen en un directorio aislado y se intercambian atómicamente, así ninguna petición es servida por un código a medio actualizar
  • [X] Las migraciones son aditivas y se protegen con Schema::hasTable() / Schema::hasColumn(), seguras de ejecutar dos veces
  • [X] Los secretos existen sólo como llamadas a env() dentro de ficheros de configuración, nunca en línea en el código de aplicación

Cuando algo va mal

  • [X] Revierte el código primero, cambiando el enlace simbólico, antes de tocar el esquema
  • [X] Trata migrate:rollback como último recurso, no como primera respuesta: un down() puede borrar datos que tu reversión nunca pretendió tocar
  • [X] Reinicia los workers de cola después de cada despliegue

Un despliegue que nadie nota es un despliegue que funcionó. Eso no es un listón bajo: es todo el trabajo.