Perché migrare segreti in variabili d'ambiente
Su una VPS Linux, tenere password database, token API, SMTP credentials e chiavi private dentro file di configurazione leggibili dal web server o dal codice applicativo aumenta il rischio di esposizione accidentale. La migrazione verso variabili d'ambiente è una misura di hardening pratica, perché separa il codice dai segreti, riduce la probabilità di commit involontari su repository, semplifica la rotazione delle credenziali e rende più facile gestire configurazioni diverse tra sviluppo, staging e produzione.
Questa soluzione non è perfetta in assoluto: le variabili d'ambiente vanno protette bene quanto i file, perché possono essere lette da processi, dump di debug, servizi mal configurati o utenti con privilegi elevati. Però, se implementata correttamente, è un passo netto avanti rispetto a segreti sparsi in file PHP, `.env` lasciati esposti, script di deploy, backup non cifrati o configurazioni versionate per errore.
L’obiettivo di questo articolo è guidare una migrazione sicura e reversibile su Linux, con un approccio adatto a VPS comuni, stack LAMP/LEMP, applicazioni PHP, Node.js, Python e servizi custom. L’idea è semplice: i segreti non devono vivere nel codice, devono essere forniti all’applicazione in modo controllato, verificabile e documentato.
Quando conviene farlo subito
La migrazione è particolarmente utile se trovi uno di questi casi:
- credenziali DB scritte in chiaro dentro file PHP, YAML, JSON o config pubbliche;
- chiavi API usate da WordPress, Laravel, Symfony, Node.js o script custom;
- configurazioni replicate in più ambienti con rischio di confusione;
- repository Git con file di configurazione contenenti segreti;
- backup accessibili a più persone o conservati senza cifratura;
- accessi SSH condivisi tra più operatori e poca tracciabilità delle modifiche.
Se hai anche solo uno di questi punti, la migrazione è una priorità di sicurezza ragionevole.
Diagnosi preliminare: capire dove sono i segreti oggi
Prima di cambiare configurazione, bisogna mappare con precisione dove vengono letti i segreti. L’errore più comune è spostare solo una parte delle credenziali e lasciare il resto in file vecchi, con comportamenti incoerenti tra servizi.
Verifica questi punti:
- File applicativi: cerca stringhe come `DB_PASSWORD`, `API_KEY`, `SECRET`, `TOKEN`, `MAIL_PASSWORD` nei file del progetto e nelle directory di deploy.
- Servizi systemd: controlla se il servizio usa `Environment=` o `EnvironmentFile=`.
- Web server: verifica se Nginx o Apache passano variabili al runtime tramite FastCGI, proxy o wrapper.
- Scheduler e cron: controlla script eseguiti da cron che potrebbero usare config vecchie.
- Backup e repository: identifica copie storiche dei file con segreti, perché il problema non finisce con la modifica del file attivo.
Un controllo semplice e utile, da eseguire dalla directory del progetto, è questo:
grep -RInE 'DB_PASSWORD|DB_USER|API_KEY|SECRET|TOKEN|MAIL_PASSWORD' /var/www /home 2>/dev/nullEsito atteso: ottieni un elenco dei file che contengono credenziali o riferimenti a credenziali. Se non trovi nulla, non significa che i segreti non ci siano; possono essere in file non indicizzati, in servizi systemd o in variabili caricate altrove.
Strategia consigliata: migrazione graduale e reversibile
Il modo più sicuro è procedere in tre fasi:
- creare un punto di backup della configurazione attuale;
- aggiungere il nuovo canale di lettura da variabili d’ambiente senza rompere il vecchio;
- verificare il funzionamento e solo dopo rimuovere i segreti dai file.
Questa sequenza riduce il rischio di downtime. Se qualcosa va storto, puoi tornare rapidamente alla configurazione precedente.
Soluzione pratica su VPS Linux
1. Fai un backup completo dei file coinvolti
Prima di modificare qualsiasi cosa, salva una copia dei file di configurazione attuali e annota quali servizi dipendono da essi. Se usi file di ambiente dedicati, salva anche quelli.
mkdir -p ~/backup-hardening-$(date +%F)cp -a /var/www/tuo-progetto/.env ~/backup-hardening-$(date +%F)/ 2>/dev/null || truecp -a /etc/systemd/system/tuo-servizio.service ~/backup-hardening-$(date +%F)/ 2>/dev/null || trueEsito atteso: hai una copia recuperabile dei file originali. Se i percorsi sono diversi, sostituiscili con quelli reali del tuo stack.
2. Crea un file di ambiente separato e protetto
Per servizi custom o applicazioni PHP/Node/Python, una buona pratica è usare un file dedicato in una posizione non pubblica, ad esempio sotto `/etc/tuo-servizio/` o `/opt/tuo-servizio/`, con permessi stretti.
sudo install -d -m 750 /etc/tuo-serviziosudo nano /etc/tuo-servizio/secret.envInserisci valori del tipo:
DB_HOST=127.0.0.1
DB_NAME=nome_database
DB_USER=utente_db
DB_PASSWORD=password_lunga_e_unica
API_KEY=chiave_api_lunga
MAIL_PASSWORD=password_mailPoi imposta i permessi corretti:
sudo chown root:root /etc/tuo-servizio/secret.env
sudo chmod 600 /etc/tuo-servizio/secret.envEsito atteso: solo root può leggere il file. Se il servizio gira con un utente dedicato, valuta un gruppo ristretto e permessi 640 solo se serve davvero, ma il default più sicuro resta 600.
3. Carica le variabili nel servizio, non nel codice
Il metodo migliore dipende dal tipo di servizio.
Con systemd, modifica l’unità del servizio per includere un file ambiente. Fai prima un backup del file:
sudo cp -a /etc/systemd/system/tuo-servizio.service /etc/systemd/system/tuo-servizio.service.bakApri il file e aggiungi una riga come questa nella sezione `Service`:
EnvironmentFile=/etc/tuo-servizio/secret.envSe vuoi evitare che il processo legga file aggiuntivi, puoi anche definire singole variabili con `Environment=`. Però `EnvironmentFile=` è più gestibile quando i valori sono molti.
Dopo la modifica:
sudo systemctl daemon-reload
sudo systemctl restart tuo-servizio
sudo systemctl status tuo-servizio --no-pagerEsito atteso: il servizio deve tornare `active (running)` senza errori di parsing o file mancanti.
Con PHP-FPM, se l’app è PHP e gira dietro pool dedicati, puoi definire variabili nel pool config. Il file tipico è sotto `/etc/php/*/fpm/pool.d/*.conf` o percorso equivalente. Prima fai backup:
sudo cp -a /etc/php/8.2/fpm/pool.d/www.conf /etc/php/8.2/fpm/pool.d/www.conf.bakAggiungi righe come:
env[DB_HOST] = 127.0.0.1
env[DB_NAME] = nome_database
env[DB_USER] = utente_db
env[DB_PASSWORD] = password_lunga_e_unicaRiavvia PHP-FPM e verifica:
sudo systemctl restart php8.2-fpm
sudo systemctl status php8.2-fpm --no-pagerEsito atteso: pool attivo e nessun errore nel log.
Con Nginx o Apache, evita di inserire segreti direttamente nel virtual host se non strettamente necessario. In genere è meglio farli passare a PHP-FPM o al servizio applicativo. Se usi applicazioni che leggono configurazioni da `.env`, assicurati che il file non sia servito dal web server e non finisca nella document root.
4. Modifica l’applicazione per leggere da ambiente
Questo è il passaggio che rende la migrazione reale. Il codice deve usare le variabili d’ambiente come fonte primaria, e solo come fallback temporaneo i vecchi file se vuoi una transizione graduale.
Esempio PHP:
$dbHost = getenv('DB_HOST');
$dbName = getenv('DB_NAME');
$dbUser = getenv('DB_USER');
$dbPass = getenv('DB_PASSWORD');Esempio Node.js:
const dbHost = process.env.DB_HOST;
const apiKey = process.env.API_KEY;Esempio Python:
import os
db_host = os.getenv('DB_HOST')
api_key = os.getenv('API_KEY')Esito atteso: l’applicazione parte e usa i valori letti dal processo, non quelli scritti in chiaro nel repository.
5. Rimuovi i segreti dai file di codice solo dopo la verifica
Non eliminare subito le vecchie credenziali se non hai ancora validato tutto. Prima fai un test completo: login, query database, invio email, chiamate API, job schedulati, upload o qualsiasi funzione dipendente da quei segreti.
Quando il test è positivo, sostituisci i valori sensibili nei file vecchi con placeholder o rimuovili del tutto, mantenendo eventualmente solo i nomi delle variabili documentati. Per esempio, invece di salvare la password, puoi lasciare un commento che indichi dove viene caricata.
Importante: se il file vecchio era già stato committato in Git o copiato in backup, la rimozione dal file attivo non basta. Devi considerare anche la rotazione del segreto, perché la credenziale potrebbe essere già esposta in storico o copie.
Rotazione credenziali: quando è obbligatoria
La rotazione è necessaria se uno di questi casi è vero:
- il file con il segreto è stato nel repository Git;
- hai inviato il file via email o chat;
- il file è stato esposto per errore via web;
- non sai chi abbia avuto accesso alle copie;
- il segreto è stato usato in ambienti non fidati.
In questi casi, cambiare solo il percorso del segreto non basta. Devi generare nuove credenziali e aggiornare l’applicazione con le nuove chiavi. Per il database, cambia la password dell’utente applicativo. Per le API esterne, rigenera il token dal pannello del provider. Per SMTP e servizi terzi, sostituisci la password o la chiave secondo le procedure del fornitore.
La regola è semplice: se il segreto potrebbe essere stato visto da qualcuno non autorizzato, consideralo compromesso.
Hardening aggiuntivo consigliato
Una volta completata la migrazione, conviene consolidare la postura di sicurezza con alcuni interventi a basso costo e alto impatto:
- Permessi minimi: il file di ambiente deve essere leggibile solo dal processo che lo usa, non da utenti generici.
- Directory fuori dal web root: non mettere mai file con segreti dentro cartelle servite da Apache o Nginx.
- Backup cifrati: se fai backup automatici, cifra almeno i dataset che contengono configurazioni sensibili.
- Logging prudente: evita di stampare variabili d’ambiente nei log applicativi o nei dump di debug.
- Separazione ambienti: usa file e credenziali diverse per sviluppo, staging e produzione.
- Aggiornamenti regolari: mantieni aggiornati sistema, web server, runtime e librerie critiche.
Se gestisci più VPS, considera anche un approccio centralizzato con secret manager o vault. È più complesso, ma diventa utile quando i servizi aumentano e i file locali non sono più sufficienti.
Verifiche immediate dopo il cambio
Dopo la migrazione, esegui almeno questi controlli:
- Controllo processo: il servizio deve essere attivo e senza errori nei log.
- Controllo funzionale: accesso all’app, query DB, invio email e chiamate API devono funzionare.
- Controllo esposizione: verifica che il file segreto non sia raggiungibile via web e che non compaia in output pubblici.
- Controllo permessi: il file ambiente deve risultare con permessi stretti e proprietario corretto.
Comandi utili:
sudo ls -l /etc/tuo-servizio/secret.env
sudo journalctl -u tuo-servizio -n 50 --no-pagerEsito atteso: permessi `-rw-------` o equivalenti e assenza di errori relativi a variabili mancanti, file non trovato o accessi negati.
Come evitare errori comuni
Gli errori più frequenti durante questa migrazione sono prevedibili. Il primo è mettere il file `.env` nella document root e dimenticare di bloccarne l’accesso. Il secondo è usare variabili d’ambiente nel servizio ma non nel processo che realmente esegue l’applicazione, per esempio PHP-FPM invece del solo virtual host. Il terzo è cambiare i file ma non riavviare il servizio, quindi il processo continua a usare vecchi valori in memoria.
Un altro problema classico è la differenza tra shell interattiva e processo di servizio: una variabile esportata nel terminale non è automaticamente disponibile al demone systemd o al pool PHP-FPM. Per questo i segreti devono essere definiti dove il servizio li carica davvero, non solo nella sessione SSH.
Infine, attenzione ai container e ai task schedulati. Se l’app gira in Docker o in un job cron, devi aggiornare anche lì la fonte delle variabili, altrimenti avrai un ambiente metà nuovo e metà vecchio.
Esempio di piano operativo sicuro
Se vuoi fare la migrazione in modo ordinato, puoi seguire questa sequenza:
- mappa i segreti attuali e individua i processi che li usano;
- fai backup dei file interessati;
- crea il file ambiente fuori dalla web root con permessi stretti;
- aggiorna il servizio o il pool PHP-FPM per leggere l’ambiente;
- modifica il codice per usare `getenv()` o `process.env`;
- riavvia il servizio e testa le funzioni critiche;
- rimuovi i segreti dai vecchi file solo dopo il test;
- ruota le credenziali se c’è stato rischio di esposizione;
- controlla log, permessi e backup.
Questa sequenza è semplice, ma molto efficace per evitare interruzioni.
Rollback rapido se qualcosa va storto
Se dopo il cambio l’app smette di funzionare, il rollback deve essere immediato e reversibile:
- ripristina il backup del file di configurazione precedente;
- riavvia il servizio interessato;
- verifica i log per capire quale variabile manca o è errata;
- se il problema riguarda i permessi, correggi owner e chmod del file ambiente;
- se il problema è nel codice, reintroduci temporaneamente il vecchio path solo come emergenza, poi correggi con calma.
Comando di verifica tipico:
sudo systemctl restart tuo-servizio
sudo systemctl status tuo-servizio --no-pagerCondizione di successo: il servizio torna operativo e le funzioni dipendenti da DB o API riprendono a rispondere correttamente.
Conclusione operativa
Migrare DB credentials e API keys in variabili d’ambiente è una delle misure di hardening più utili su una VPS Linux, soprattutto quando il progetto cresce e più persone toccano la configurazione. Il punto chiave non è solo spostare i valori, ma farlo in modo controllato: backup prima, modifica minima, verifica subito dopo e rotazione delle credenziali quando serve.
Se la tua infrastruttura è già abbastanza complessa, il passo successivo può essere l’adozione di un sistema dedicato alla gestione dei segreti. Se invece gestisci un singolo server o pochi servizi, una struttura pulita con `EnvironmentFile`, permessi stretti e backup cifrati è spesso il miglior compromesso tra sicurezza, semplicità e manutenzione.
Assunzione operativa: i servizi coinvolti sono gestiti da systemd, PHP-FPM o processi equivalenti su una VPS Linux standard.
Commenti (0)
Nessun commento ancora.
Segnala contenuto
Elimina commento
Eliminare definitivamente questo commento?
L'azione non si può annullare.