Переменные окружения: что это, использование и настройка в мобильных проектах

Автор: IT Sectr Опубликовано: 2026-05-31 Время чтения: 8 мин

Переменные окружения — динамические значения, которые передаются приложению на этапе запуска для настройки поведения без изменения кода. Они позволяют разделять конфигурации разработки, тестирования и продакшна. По данным Twelve-Factor App, 2025, конфигурация должна храниться в переменных окружения, а не в коде. Переменные окружения обеспечивают безопасное управление API-ключами, URL бэкенда и флагами функциональности.

Главное

  • Переменные окружения отделяют конфигурацию приложения от исходного кода для разных сред запуска
  • .env файлы хранят переменные в формате KEY=VALUE и исключаются из репозитория через .gitignore
  • iOS использует xcconfig и Build Settings для передачи переменных на этапе компиляции
  • Android использует BuildConfig и gradle.properties для генерации конфигурационных полей
  • Безопасность: ключи и токены должны загружаться через CI/CD, а не храниться в коде или репозитории

Что такое переменные окружения

Переменные окружения — это пара ключ-значение, доступная процессу приложения через API операционной системы. Они передаются в процесс при его создании и существуют только во время его работы. В отличие от параметров конфигурации, встроенных в исходный код, переменные окружения не требуют перекомпиляции для изменения значений. Это фундаментальный принцип Twelve-Factor App, который обеспечивает чёткое разделение между кодом и конфигурацией.

В мобильной разработке переменные окружения решают проблему разных конфигураций для сред: разработчик использует локальный сервер, тестировщик — staging, пользователи — production. Вместо того чтобы хранить три URL бэкенда в коде с условными операторами if-else, разработчик передаёт один URL через переменную окружения на этапе сборки. Это упрощает код и исключает риск случайного использования продакшн-сервера в тестовой среде.

Основное преимущество — безопасность: чувствительные данные не попадают в репозиторий кода. API-ключи, секреты Firebase, токены доступа к бэкенду и сертификаты загружаются через CI/CD непосредственно в окружение сборки. Если злоумышленник получит доступ к репозиторию кода, он не найдёт там секретов, так как они хранятся в защищённых хранилищах CI-системы и передаются только на этапе сборки бинарного файла.

Зачем нужны переменные окружения в мобильной разработке

Мобильные проекты имеют минимум три среды: development, staging и production. Каждая среда требует своего набора конфигураций: URL сервера, имя пакета, схема подписи и сертификаты push-уведомлений. Без переменных окружения разработчику приходится вручную менять конфигурацию перед каждой сборкой, что приводит к ошибкам: забытый продакшн-ключ в тестовой сборке может вызвать отправку уведомлений реальным пользователям или расход платного API.

Разделение сред

Переменные окружения позволяют переключать бэкенд без изменения кода: достаточно заменить значение в переменной API_BASE_URL. Флаги функциональности (feature flags) управляются через переменные типа FEATURE_CHAT_ENABLED=true, что позволяет включать новые возможности в staging без влияния на продакшн. Для каждой среды создаётся свой .env файл, который загружается на этапе сборки.

dart
class AppConfig {
  static final String apiBaseUrl =
    const String.fromEnvironment('API_BASE_URL',
      defaultValue: 'http://localhost:8080');
}

Безопасность ключей

Жёстко закодированные ключи — распространённая уязвимость мобильных приложений. Злоумышленник декомпилирует APK или IPA с помощью инструментов типа jadx или Hopper и извлекает секреты из бинарного файла. Даже обфускация не защищает строковые литералы — они легко находятся в коде после декомпиляции. Переменные окружения решают эту проблему, передавая ключи на этапе сборки через CI/CD, где они маскируются в логах.

kotlin
object Config {
    val apiKey: String =
        System.getenv("API_KEY") ?: throw
            IllegalStateException("API_KEY not set")
}

CI/CD интеграция

Переменные окружения интегрируются с пайплайнами сборки: GitHub Actions, GitLab CI, Bitrise и CircleCI поддерживают секретные переменные, которые не отображаются в логах. На этапе сборки CI подставляет нужные значения в зависимости от ветки или тега: для ветки develop используется staging, для тега v* — production. Это автоматизирует процесс и исключает человеческий фактор, гарантируя, что каждая сборка получает правильный набор конфигурации.

.env файлы и библиотеки для управления

Файл .env — стандартный способ хранения переменных окружения в формате KEY=VALUE. Он не включается в репозиторий, а вместо этого в репозиторий добавляется .env.example с шаблоном всех переменных и пустыми значениями. Каждый разработчик создаёт свой .env файл с локальными настройками, не затрагивая конфигурацию других членов команды. Для разных сред используются отдельные файлы: .env.dev, .env.stage, .env.prod.

bash
# .env.example — шаблон для разработчиков
API_BASE_URL=http://localhost:8080
FEATURE_CHAT_ENABLED=true
SENTRY_DSN=

Для мобильных проектов существуют специализированные библиотеки для работы с .env файлами:

  • flutter_dotenv (Flutter) — загружает переменные из .env в runtime через dotenv.load()
  • BuildConfig (Android) — генерирует типизированные поля из значений build.gradle
  • xcconfig (iOS) — подключает файлы конфигурации к разным схемам сборки Xcode
  • react-native-config (React Native) — управление переменными через .env файлы

Настройки ветвления в CI/CD позволяют подставлять разные .env файлы: .env.dev для тестовых серверов, .env.stage для предрелиза и .env.prod для публикации в магазины приложений. Файлы с секретами загружаются из безопасного хранилища (Vault, AWS Secrets Manager) и не хранятся в репозитории. Это гарантирует, что даже при компрометации системы контроля версий секреты остаются защищёнными.

Переменные окружения в iOS проектах

iOS экосистема использует xcconfig файлы для управления переменными на уровне сборки. Они подключаются к схемам Xcode и позволяют переопределять значения для Debug и Release конфигураций. xcconfig файлы поддерживают наследование: можно создать базовый файл с общими настройками и специфические файлы для каждой среды.

Настройка xcconfig файлов

Файлы xcconfig хранят переменные в формате KEY = VALUE и подключаются к схеме сборки в Xcode через настройки Configuration. Переменные из xcconfig доступны в Info.plist через синтаксис $(VARIABLE_NAME), что позволяет использовать разные идентификаторы бандла и названия приложения для разных схем. Для быстрой идентификации окружения к названию приложения добавляется суффикс Dev или Staging.

bash
# Config/Dev.xcconfig — конфигурация разработки
API_BASE_URL = http://localhost:3000
BUNDLE_ID_SUFFIX = .dev
APP_DISPLAY_NAME = MyApp Dev

Swift код для чтения переменных

Для runtime-доступа к переменным в iOS используется файл Configuration.swift, который читает значения из Info.plist через Bundle.main.object(forInfoDictionaryKey:). Этот подход гарантирует, что переменные определяются на этапе сборки и доступны приложению сразу после запуска. Значения читаются один раз при инициализации модуля и кэшируются для быстрого доступа в течение жизненного цикла приложения.

swift
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 проектах

Android поддерживает переменные окружения через BuildConfig — автоматически генерируемый класс, поля которого определяются в build.gradle файле модуля. BuildConfig создаётся на этапе компиляции для каждого флейвора и типа сборки отдельно. Это позволяет иметь разные значения для debug и release без использования условных операторов в коде, что повышает производительность и безопасность.

Настройка BuildConfig полей

Поля BuildConfig задаются через buildConfigField в defaultConfig или в конкретных buildTypes. Для каждой среды создаётся отдельный buildType или productFlavor. Это обеспечивает строгую изоляцию конфигураций: debug использует локальный сервер, release — продакшн. Поля BuildConfig статически типизированы, что исключает ошибки при обращении к ним в коде.

groovy
// 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\""
        }
    }
}

gradle.properties для общих значений

Файл gradle.properties в корне проекта хранит глобальные переменные Gradle. Они доступны во всех модулях через синтаксис $variableName и используются для указания версий зависимостей, флагов сборки и ключей API. В отличие от BuildConfig, gradle.properties работает только на этапе конфигурации Gradle, а не в runtime приложения. Поэтому пароли и ключи API, указанные в gradle.properties, не видны в декомпилированном коде, так как они используются только для генерации BuildConfig на этапе компиляции.

groovy
# gradle.properties
SENTRY_DSN=https://key@sentry.io/project
MAPS_API_KEY=AIzaSy...

Для безопасной передачи секретов в Android проектах рекомендуется использовать local.properties (исключён из VCS) или загружать значения из CI/CD переменных в build.gradle через System.getenv(). Это гарантирует, что ключи не попадут в репозиторий. При публикации в Google Play Console убедитесь, что все отладочные ключи заменены на продакшн-версии через разные buildTypes или productFlavors с соответствующими значениями BuildConfig.

Часто задаваемые вопросы

Можно ли использовать переменные окружения в Flutter?

Да, Flutter поддерживает переменные окружения через пакет flutter_dotenv для runtime-доступа или через нативные каналы для платформенных переменных. В Dart также доступен конструктор String.fromEnvironment для передачи значений на этапе компиляции через --dart-define, что является предпочтительным способом для Flutter проектов.

В чём разница между BuildConfig и gradle.properties?

BuildConfig — это Java-класс с типизированными полями, сгенерированный на этапе компиляции для каждого buildType и flavor. gradle.properties — текстовый файл с парами ключ-значение, доступный всем модулям Gradle на этапе конфигурации сборки. BuildConfig работает в runtime приложения, gradle.properties — только в скриптах Gradle.

Как не допустить утечки .env файла в репозиторий?

Добавьте .env в файл .gitignore вашего репозитория. В репозиторий коммитьте только .env.example с пустыми значениями и описанием каждой переменной. Для CI/CD используйте зашифрованные секреты в настройках GitHub Actions, GitLab CI или Bitrise, которые маскируются в логах и недоступны для чтения после завершения сборки.

Как передать переменные окружения через CI/CD?

Большинство CI-систем поддерживают секретные переменные окружения. В GitHub Actions это Secrets, в GitLab CI — CI/CD Variables, в Bitrise — Secrets. На этапе сборки они передаются в билд-скрипт через process.env или System.getenv(). Секретные переменные не отображаются в логах сборки и недоступны в форках репозитория.

Что такое feature flags через переменные окружения?

Feature flags — это булевы переменные, управляющие включением или отключением функциональности без перекомпиляции кода. Пример: FEATURE_NEW_PAYMENT=true включает новую платёжную систему в staging для тестирования. В production тот же флаг установлен в false до полного развёртывания бэкенда. Это позволяет безопасно внедрять изменения поэтапно и откатывать их при проблемах.

Итоги

  • Переменные окружения отделяют конфигурацию от исходного кода для разных сред разработки
  • .env файлы с шаблоном .env.example — стандарт управления переменными в командах с разграничением сред
  • iOS xcconfig подключает файлы конфигурации к схемам Xcode с поддержкой наследования и Info.plist интеграции
  • Android BuildConfig генерирует типизированные поля из build.gradle для каждого buildType отдельно
  • CI/CD секреты передают чувствительные данные на этапе сборки без хранения их в репозитории
  • Feature flags через переменные позволяют включать функциональность в конкретной среде без перекомпиляции
  • Безопасность: ключи шифруются в CI и не попадают в декомпилируемый бинарный файл приложения

Мы разработаем мобильное приложение под ключ

IT Sectr создаёт приложения для iOS и Android для стартапов и бизнеса с 2017 года. Мы проконсультируем вас и предложим наилучшее решение.

Обсудить проект

Читайте также