Variabilele de mediu sunt valori dinamice transmise aplicației la pornire pentru a-i configura comportamentul fără modificarea codului. Ele permit separarea configurațiilor de dezvoltare, testare și producție. Potrivit Twelve-Factor App, 2025, configurația trebuie stocată în variabile de mediu, nu în cod. Variabilele de mediu asigură gestionarea sigură a cheilor API, URL-urilor backend și flagurilor de funcționalități.
Principalele puncte
Variabilele de mediu sunt o pereche cheie-valoare, accesibilă procesului aplicației prin API-ul sistemului de operare. Ele sunt transmise procesului la crearea sa și există doar pe durata funcționării acestuia. Spre deosebire de parametrii de configurație încorporați în codul sursă, variabilele de mediu nu necesită recompilare pentru modificarea valorilor. Acesta este un principiu fundamental Twelve-Factor App, care asigură o separare clară între cod și configurație.
În dezvoltarea mobilă, variabilele de mediu rezolvă problema diferitelor configurații pentru medii: dezvoltatorul folosește serverul local, testerul — staging, utilizatorii — producția. În loc să stocheze trei URL-uri backend în cod cu operatori condiționali if-else, dezvoltatorul transmite un singur URL printr-o variabilă de mediu la etapa de build. Aceasta simplifică codul și elimină riscul utilizării accidentale a serverului de producție în mediul de testare.
Principalul avantaj este securitatea: datele sensibile nu ajung în depozitul de cod. Cheile API, secretele Firebase, tokenurile de acces la backend și certificatele sunt încărcate prin CI/CD direct în mediul de build. Dacă un atacator obține acces la depozitul de cod, nu va găsi secrete acolo, deoarece acestea sunt stocate în depozitele protejate ale sistemului CI și sunt transmise doar la etapa de build a fișierului binar.
Proiectele mobile au cel puțin trei medii: development, staging și producție. Fiecare mediu necesită propriul set de configurații: URL-ul serverului, numele pachetului, schema de semnare și certificatele de notificări push. Fără variabile de mediu, dezvoltatorul trebuie să modifice manual configurația înainte de fiecare build, ceea ce duce la erori: o cheie de producție uitată într-un build de test poate cauza trimiterea de notificări utilizatorilor reali sau consumul unui API plătit.
Variabilele de mediu permit schimbarea backend-ului fără modificarea codului: este suficient să înlocuiți valoarea din variabila API_BASE_URL. Flagurile de funcționalități (feature flags) sunt gestionate prin variabile de tipul FEATURE_CHAT_ENABLED=true, ceea ce permite activarea noilor funcționalități în staging fără impact asupra producției. Pentru fiecare mediu se creează propriul fișier .env, care este încărcat la etapa de build.
class AppConfig {
static final String apiBaseUrl =
const String.fromEnvironment('API_BASE_URL',
defaultValue: 'http://localhost:8080');
}
Cheile codificate fix sunt o vulnerabilitate comună a aplicațiilor mobile. Un atacator decomplilează APK sau IPA cu instrumente precum jadx sau Hopper și extrage secretele din fișierul binar. Chiar și ofuscarea nu protejează literalii de șiruri — aceștia sunt ușor de găsit în cod după decomplilare. Variabilele de mediu rezolvă această problemă, transmițând cheile la etapa de build prin CI/CD, unde sunt mascate în loguri.
object Config {
val apiKey: String =
System.getenv("API_KEY") ?: throw
IllegalStateException("API_KEY not set")
}
Variabilele de mediu se integrează cu pipeline-urile de build: GitHub Actions, GitLab CI, Bitrise și CircleCI acceptă variabile secrete care nu sunt afișate în loguri. La etapa de build, CI înlocuiește valorile corespunzătoare în funcție de ramură sau tag: pentru ramura develop se folosește staging, pentru tag-ul v* — producția. Aceasta automatizează procesul și elimină factorul uman, garantând că fiecare build primește setul corect de configurație.
Fișierul .env este metoda standard de stocare a variabilelor de mediu în format KEY=VALUE. Nu este inclus în depozit, în schimb în depozit se adaugă .env.example cu șablonul tuturor variabilelor și valori goale. Fiecare dezvoltator își creează propriul fișier .env cu setări locale, fără a afecta configurația celorlalți membri ai echipei. Pentru medii diferite se folosesc fișiere separate: .env.dev, .env.stage, .env.prod.
# .env.example — șablon pentru dezvoltatori
API_BASE_URL=http://localhost:8080
FEATURE_CHAT_ENABLED=true
SENTRY_DSN=
Pentru proiecte mobile există biblioteci specializate pentru lucrul cu fișierele .env:
Setările de ramură în CI/CD permit înlocuirea diferitelor fișiere .env: .env.dev pentru servere de test, .env.stage pentru pre-lansare și .env.prod pentru publicarea în magazinele de aplicații. Fișierele cu secrete sunt încărcate din depozitul securizat (Vault, AWS Secrets Manager) și nu sunt stocate în depozit. Aceasta garantează că, chiar și în cazul compromiterii sistemului de control al versiunilor, secretele rămân protejate.
Ecosistemul iOS folosește fișiere xcconfig pentru gestionarea variabilelor la nivel de build. Acestea se conectează la schemele Xcode și permit suprascrierea valorilor pentru configurațiile Debug și Release. Fișierele xcconfig acceptă moștenirea: se poate crea un fișier de bază cu setări comune și fișiere specifice pentru fiecare mediu.
Fișierele xcconfig stochează variabilele în format KEY = VALUE și se conectează la schema de build în Xcode prin setările Configuration. Variabilele din xcconfig sunt accesibile în Info.plist prin sintaxa $(VARIABLE_NAME), ceea ce permite utilizarea diferitelor identificatoare de pachet și nume de aplicație pentru diferite scheme. Pentru identificarea rapidă a mediului, la numele aplicației se adaugă sufixul Dev sau Staging.
# Config/Dev.xcconfig — configurație de dezvoltare
API_BASE_URL = http://localhost:3000
BUNDLE_ID_SUFFIX = .dev
APP_DISPLAY_NAME = MyApp Dev
Pentru accesul în runtime la variabile în iOS se folosește fișierul Configuration.swift, care citește valorile din Info.plist prin Bundle.main.object(forInfoDictionaryKey:). Această abordare garantează că variabilele sunt determinate la etapa de build și disponibile aplicației imediat după pornire. Valorile sunt citite o singură dată la inițializarea modulului și sunt memorate în cache pentru acces rapid pe parcursul ciclului de viață al aplicației.
enum AppEnvironment {
static var apiBaseURL: URL {
guard let urlString = Bundle.main
.object(forInfoDictionaryKey: "API_BASE_URL"),
let url = URL(string: urlString as! String)
else { fatalError("API_BASE_URL is not configured") }
return url
}
static var isChatEnabled: Bool {
Bundle.main.object(
forInfoDictionaryKey: "FEATURE_CHAT_ENABLED"
) as? Bool ?? false
}
}
Android acceptă variabilele de mediu prin BuildConfig — o clasă generată automat ale cărei câmpuri sunt definite în fișierul build.gradle al modulului. BuildConfig este creat la etapa de compilare pentru fiecare flavor și tip de build separat. Aceasta permite valori diferite pentru debug și release fără a utiliza operatori condiționali în cod, ceea ce sporește performanța și securitatea.
Câmpurile BuildConfig se setează prin buildConfigField în defaultConfig sau în buildTypes specifice. Pentru fiecare mediu se creează un buildType sau productFlavor separat. Aceasta asigură o izolare strictă a configurațiilor: debug folosește serverul local, release — producția. Câmpurile BuildConfig sunt tipizate static, ceea ce elimină erorile la referirea la ele în cod.
// build.gradle (Module: app)
android {
defaultConfig {
buildConfigField "String", "API_BASE_URL",
"\"http://localhost:8080\""
}
buildTypes {
debug {
buildConfigField "String", "API_BASE_URL",
"\"http://dev.api.itsectr.com\""
}
release {
buildConfigField "String", "API_BASE_URL",
"\"https://api.itsectr.com\""
}
}
}
Fișierul gradle.properties din rădăcina proiectului stochează variabilele globale Gradle. Acestea sunt accesibile în toate modulele prin sintaxa $variableName și sunt utilizate pentru specificarea versiunilor dependențelor, flagurilor de build și cheilor API. Spre deosebire de BuildConfig, gradle.properties funcționează doar la etapa de configurare Gradle, nu în runtime-ul aplicației. Prin urmare, parolele și cheile API specificate în gradle.properties nu sunt vizibile în codul decomplilat, deoarece sunt utilizate doar pentru generarea BuildConfig la etapa de compilare.
# gradle.properties
SENTRY_DSN=https://key@sentry.io/project
MAPS_API_KEY=AIzaSy...
Pentru transmiterea sigură a secretelor în proiectele Android se recomandă utilizarea local.properties (exclus din VCS) sau încărcarea valorilor din variabilele CI/CD în build.gradle prin System.getenv(). Aceasta garantează că cheile nu ajung în depozit. La publicarea în Google Play Console, asigurați-vă că toate cheile de debug au fost înlocuite cu versiunile de producție prin buildTypes sau productFlavors diferite cu valorile BuildConfig corespunzătoare.
Întrebări frecvente
Da, Flutter acceptă variabilele de mediu prin pachetul flutter_dotenv pentru acces în runtime sau prin canale native pentru variabile de platformă. În Dart este disponibil și constructorul String.fromEnvironment pentru transmiterea valorilor la etapa de compilare prin --dart-define, ceea ce reprezintă metoda preferată pentru proiectele Flutter.
BuildConfig este o clasă Java cu câmpuri tipizate, generată la etapa de compilare pentru fiecare buildType și flavor. gradle.properties este un fișier text cu perechi cheie-valoare, accesibil tuturor modulelor Gradle la etapa de configurare a build-ului. BuildConfig funcționează în runtime-ul aplicației, gradle.properties — doar în scripturile Gradle.
Adăugați .env în fișierul .gitignore al depozitului dumneavoastră. În depozit faceți commit doar cu .env.example cu valori goale și descrierea fiecărei variabile. Pentru CI/CD, utilizați secrete criptate în setările GitHub Actions, GitLab CI sau Bitrise, care sunt mascate în loguri și imposibil de citit după finalizarea build-ului.
Majoritatea sistemelor CI acceptă variabile de mediu secrete. În GitHub Actions acestea sunt Secrets, în GitLab CI — CI/CD Variables, în Bitrise — Secrets. La etapa de build, ele sunt transmise scriptului de build prin process.env sau System.getenv(). Variabilele secrete nu sunt afișate în logurile de build și nu sunt disponibile în fork-urile depozitului.
Feature flags sunt variabile booleene care controlează activarea sau dezactivarea funcționalităților fără recompilarea codului. Exemplu: FEATURE_NEW_PAYMENT=true activează noul sistem de plată în staging pentru testare. în producție același flag este setat pe false până la implementarea completă a backend-ului. Aceasta permite implementarea sigură a modificărilor în etape și revenirea lor în caz de probleme.
Rezumat
Vom dezvolta o aplicație mobilă la cheie
IT Sectr creează aplicații iOS și Android pentru startup-uri și afaceri din 2017. Vă vom consilia și vă vom propune cea mai bună soluție.
Citiți și