Le variabili d'ambiente sono un tassello fondamentale di ogni applicazione Laravel. Vengono usate per dati sensibili, chiavi API, credenziali di accesso ai database e per altri valori di configurazione utilizzati dall'applicazione. Cosa succede se ci si dimentica di definire una variabile .env o la si valorizza in maniera errata? Si possono verificare bug, problemi di deploy o — peggio ancora — problemi di sicurezza
E qui entra in gioco Laravel Health Env Vars. Questo package per Laravel aiuta a controllare la presenza e la validità delle variabili .env durante i controlli sullo stato di salute dell'applicativo.

Perché è importante

Se lavori da solo sul tuo portatile, è piuttosto difficile che ti dimenticherai di aggiungere una variabile d'ambiente su un server di produzione. Tuttavia, potrebbe succedere e, ancora peggio, potresti impostarla al valore sbagliato.
Le cose si fanno più complicate in un team di sviluppo: con più sviluppatori — o anche solo lo stesso sviluppatore che utilizza più postazioni — aggiornare una variabile d'ambiente implica che ogni soggetto coinvolto venga notificato (via e-mail, Slack, Discord, Teams, Telegram, a voce), ed è facile dimenticarsi. Qualcuno è destinato a perdersi un pezzo.

Persino gli sviluppatori più esperti a volte dimenticato di impostare su un nuovo server o in una pipeline CI/CD una variabile d'ambiente richiesta. Scordarsene può portare a:

  • errori di runtime
  • integrazioni mancanti o parti applicative non funzionanti
  • errori in produzione difficili da identificare e risolvere

Controllando in modo proattivo le proprie variabili .env, puoi identificare ed evitare potenziali problemi prima che si verifichino e abbiano ripercussioni sugli utenti finali.

Cosa fa questo package

In Encodia utilizziamo da tempo l'eccellente package Laravel Health di Spatie, per il quale sembrava che non ci fosse un controllo dedicato per le variabili .env. Per questo motivo, ho sviluppato Laravel Health Env Vars, che si integra con il package di Spatie per fornire uno strumento di controllo semplice ma efficace:

  • verifica che le variabili .env richieste siano presenti
  • opzionalmente, verifica i loro valori
  • può eseguire controlli solo su determinati ambienti
  • fa fallire gli health check se qualcosa risulta mancante o non configurato correttamente

Puoi eseguire i controlli sullo stato di salute dell'applicazione in diversi casi:

  • quando configuri/allineai un progetto in locale: ad esempio, in Encodia abbiamo sviluppato uno strumento da riga di comando ad uso interno chiamato EDIT per semplificare la vita agli sviluppatori — gestire compiti come clonare un repository GIT o fare pull, installare le dipendenze via Composer o NPM, lanciare le migration e i seed, ecc. Uno dei compiti principali di EDIT è quella di eseguire automaticamente gli health check, in modo da assicurarsi che sia tutto configurato correttamente prima di iniziare a sviluppare
  • in fase di deploy: che sia in una pipeline CI/CD, in uno script bash, o tramite altro workflow, i controlli sulla salute applicativa possono essere eseguiti per verificare che tutte le variabili d'ambiente richieste siano presenti e valide, prima di aver terminato il deploy.

Cosa non fa questo package

Laravel Health Env Vars non controlla le variabili .env una volta che il deploy è terminato — e ora ti spiego perché. Nella maggior parte dei deploy, è buona norma eseguire php artisan config:cache. Dopo aver lanciato quel comando, ogni chiamata a env('VARIABLE') restituirà null. Consulta la sezione Avvertenze per maggiori dettagli.

Installazione e setup

Installare il package è semplice:

composer require encodia/laravel-health-env-vars

Utilizzo

Registra un controllo come ogni altro check di Laravel Health:

// typically, in a service provider

use Spatie\Health\Facades\Health;
use Spatie\Health\Checks\Checks\UsedDiskSpaceCheck;
use Encodia\Health\Checks\EnvVars;

Health::checks([
    // From Spatie's examples
    UsedDiskSpaceCheck::new()
        ->warnWhenUsedSpaceIsAbovePercentage(70)
        ->failWhenUsedSpaceIsAbovePercentage(90),

    // Many other checks...

    /*
     * Check that SOME_API_KEY and MAIL_FROM_ADDRESS variables are
     * set (no matter in which environment)
     */
    EnvVars::new()
        ->requireVars([
            'SOME_API_KEY',
            'MAIL_FROM_ADDRESS',
        ])
]);

Quando esegui php artisan health:check --fail-command-on-failing-check, se SOME_API_KEY o MAIL_FROM_ADDRESS non sono state impostate nel file .env, il comando mostrerà un errore e ritornerà un exit code diverso da zero.

Potresti aver bisogno di controllare che una variabile sia valorizzata solo in un ambiente specifico (o in più di uno).
Supponiamo che tu voglia controllare che EXTENDED_DEBUG_MODE sia stata valorizzata (solo in ambiente local) e che lo sia stata anche BUGSNAG_API_KEY (solo in produzione, perché non vogliamo che BugSnag sia abilitato negli ambienti di test/locale/staging/UAT):


use Spatie\Health\Facades\Health;
use Encodia\Health\Checks\EnvVars;

Health::checks([
    // ...
    // (other checks)
    // ...

    /*
     * Check that SOME_API_KEY and MAIL_FROM_ADDRESS variables are
     * set (no matter in which environment).
     * 
     * Only in staging, ensure EXTENDED_DEBUG_MODE has been set.
     * 
     * Additionally, only in production,
     * ensure BUGSNAG_API_KEY has been set.
     */
    EnvVars::new()
        ->requireVars([
            'SOME_API_KEY',
            'MAIL_FROM_ADDRESS',
        ])
        ->requireVarsForEnvironment('local', [
            'EXTENDED_DEBUG_MODE'
        ])
        ->requireVarsForEnvironment('production', [
            'BUGSNAG_API_KEY'
        ]);
]);

Hai bisogno di verificare che una variabile sia stata valorizzata a un valore specifico? Puoi usare requireVarsMatchValues() per effettuare questo controllo, indipendentemente dall'ambiente corrente di esecuzione.
Se hai bisogno di eseguire questo controllo solo se l'ambiente di corrente corrisponde a quello desiderato o quelli desiderati, puoi usare requireVarsForEnvironment() o requireVarsForEnvironments().
Vediamo un esempio:


use Encodia\Health\Checks\EnvVars;
use Spatie\Health\Facades\Health;

Health::checks([
    EnvVars::new()
        // ... other methods ...
        ->requireVarsMatchValues([
            // Ensure that APP_LOCALE is set to 'en' (no matter which is the current environment)
            'APP_LOCALE' => 'en',
            // Ensure that APP_TIMEZONE is set to 'UTC' (no matter which is the current environment)
            'APP_TIMEZONE' => 'UTC',
        ])
        ->requireVarsMatchValuesForEnvironment('staging', [
            // Only if current environment is 'staging', we don't want to send e-mails to real customers
            'MAIL_MAILER' => 'log',        
        ])
        ->requireVarsMatchValuesForEnvironments(['qa', 'production'], [
            // Only if current environment is 'qa' or 'production, we want to log 'info' events or above
            'LOG_LEVEL' => 'info',
            // Only if current environment is 'qa' or 'production, we want to store assets to S3
            'FILESYSTEM_DISK' => 's3',        
        ]);
]);

⚠️ Quando controlli i valori, non cablare mai e poi mai password, chiavi o altri valori critici — finirebbero nel tuo repository GIT e, come sappiamo tutti, non si fa nel modo più assoluto.

Per concludere

Le variabili d'ambiente sono un piccolo ma molto importante tassello. Con Laravel Health Env Vars, puoi assicurarti che siano sempre presenti e contenenti valori validi, in modo da ridurre gli errori e risparmiare tempo sia durante lo sviluppo che in produzione.

Provarlo e dacci un riscontro su GitHub — se vuoi contribuire con una PR sei il benvenuto!

Articolo precedente