Разбираем, что считать секретом, а что конфигурацией, и как настроить Infisical для Unity‑проекта так, чтобы новый разработчик получал доступ к сборке за пару минут.
Проблемы, которые решает эта статья:
Как безопасно хранить секреты;
Как автоматически собрать production без ручного ввода паролей;
Где взять
.envновому разработчику.
В этой статье разберём подход с Infisical, Unity.
В своем опыте стартап‑команд и аутсорса, несмотря на отделы контроля, я встречал хард‑код секретов, либо нежелание какой‑либо автоматизации процесса — ввод данных для подписи Android сборки при каждой сборке по стандартным механизмам Unity.
Вероятно, такое приходилось видеть, потому что в Unity нет штатной интеграции с .env, и разработчики, которые работали только с играми могут о таком понятии и не знать.
1. Как хранят секреты
Существует соглашение: хранить секреты в файле .env в корне проекта, добавляя его в .gitignore, чтобы он не попал в репозиторий git.
Чтобы .env не попадал в git добавьте в .gitignore:
.env .env.* !.env.example
Почему секреты не хранят в репозитории:
Компрометация при доступе. Передавая репозиторий третьим лицам (например, фрилансерам) или случайно сделав его публичным, вы мгновенно дарите злоумышленникам доступ к своей инфраструктуре.
История коммитов. Удаление секретов из кода свежим коммитом не поможет — они останутся в
git history. Чтобы их вычистить, придется переписывать историю репозитория.Нарушение безопасности (Least Privilege). Все, у кого есть доступ к коду (включая стажеров), автоматически получают доступ к боевым базам данных и платным API.
Пример .env на Unity проекте выглядит примерно так:
ANDROID_KEYSTORE_PASSWORD=secret ANDROID_KEY_ALIAS=release ANDROID_KEY_PASSWORD=secret ADDRESSABLES_SSH_HOST=cdn.example.com ADDRESSABLES_SSH_USER=deploy ADDRESSABLES_SSH_PRIVATE_KEY=/Users/me/.ssh/game_deploy TELEGRAM_BOT_TOKEN=123456:ABC... TELEGRAM_CHAT_ID=123456789
И шаблон:
ANDROID_KEYSTORE_PASSWORD= ANDROID_KEY_ALIAS= ANDROID_KEY_PASSWORD= ADDRESSABLES_SSH_HOST= ADDRESSABLES_SSH_USER= ADDRESSABLES_SSH_PRIVATE_KEY= TELEGRAM_BOT_TOKEN= TELEGRAM_CHAT_ID=
В Git хранится только .env.example, а .env игнорируется
В этом примере.env есть данные для подписи Unity Android сборки, данные SSH для подключения к серверу для загрузки Addressables сборки (догружаемых данных приложения), токен для оповещения в Telegram об окончании сборки.
В Unity не часто используют.env, потому что для того, чтобы хранить данные ключ‑значение — можно создать конфиг ScriptableObject, который можно будет смотреть и редактировать прямо из Unity. Это правда, и редактирование из Unity — плюс. В такие конфиги обычно пишут URL сервера и ключи для аналитики. Однако — не всякая конфигурация является секретом.
Что вообще считать секретом?
Перед тем как подключать secrets manager, стоит разобраться, какие данные туда действительно нужно помещать.
Пример конфигурации (не секрета):
ServerUrl = https://api.example.com AddressablesUrl = https://cdn.example.com
Если Unity‑клиент обращается к серверу по этому адресу, пользователь всё равно сможет узнать его из приложения или сетевого трафика.
Поэтому production‑конфигурацию вполне нормально хранить в Git. В Unity для этого отлично подходят ScriptableObject.
Секретом становится значение, утечка которого позволяет получить доступ, выполнить действие от имени команды или подписать/опубликовать артефакт.
Например:
Данные | Секрет? | Где хранить |
|---|---|---|
| Нет |
|
| Нет |
|
Keystore password | Да | Infisical |
Key alias password | Да | Infisical |
SSH private key | Да | Infisical |
Telegram bot token | Да | Infisical |
CI access token | Да | Infisical |
2. Как автоматически собрать production без ручного ввода паролей
Предлагаемая структура проекта:
UnityGame/ ├── Assets/ │ └── Config/ // Конфигурация │ ├── DevelopmentConfig.asset │ ├── StagingConfig.asset │ └── ProductionConfig.asset │ ├── .env (git-ignored) // Секреты ├── .env.example └── .gitignore
Конфигурация открыто хранится в Git:
DevelopmentConfig.asset ServerUrl = <https://dev-api.example.com> StagingConfig.asset ServerUrl = <https://staging-api.example.com> ProductionConfig.asset ServerUrl = <https://api.example.com>
Чтение.env из Unity
Можно сделать Editor‑only loader: Github Gist
using System; using System.Collections.Generic; using System.IO; public static class EnvironmentLoader { public static Dictionary<string, string> Load(string path) { if (!File.Exists(path)) throw new FileNotFoundException( $".env not found: {path}"); var result = new Dictionary<string, string>( StringComparer.OrdinalIgnoreCase); foreach (var line in File.ReadAllLines(path)) { var trimmed = line.Trim(); if (string.IsNullOrEmpty(trimmed)) continue; if (trimmed.StartsWith("#")) continue; var separator = trimmed.IndexOf('='); if (separator <= 0) continue; var key = trimmed[..separator].Trim(); var value = trimmed[(separator + 1)..].Trim(); if (value.StartsWith("\"") && value.EndsWith("\"")) { value = value[1..^1]; } result[key] = value; } return result; } public static string Required( Dictionary<string, string> env, string key) { if (!env.TryGetValue(key, out var value) || string.IsNullOrWhiteSpace(value)) { throw new InvalidOperationException( $"Required environment variable is missing: {key}"); } return value; } }
Теперь можно программно настроить Android signing: Github Gist
using UnityEditor; using UnityEngine; public static class AndroidSigningConfig { [MenuItem("Build/Load Signing Credentials")] public static void Load() { var env = EnvironmentLoader.Load(".env"); PlayerSettings.Android.keystorePass = EnvironmentLoader.Required( env, "ANDROID_KEYSTORE_PASSWORD"); PlayerSettings.Android.keyaliasName = EnvironmentLoader.Required( env, "ANDROID_KEY_ALIAS"); PlayerSettings.Android.keyaliasPass = EnvironmentLoader.Required( env, "ANDROID_KEY_PASSWORD"); Debug.Log("Android signing configuration loaded."); } }
Теперь пароль не нужно каждый раз вводить руками через Unity UI. При желании можно добавить [InitializeOnLoad] к классу, чтобы креды вбивались при запуске проекта.
А остальные секреты (при наличии) имплементировать в приложение самому.
На проекте может быть больше использований.env чем заполнить Android signing — например, подключение к серверу для загрузки Asset Bundles, Addressables, Content Directory, правки/просмотра своих реализаций Remote Config, быстрого lookup в аналитику на бекенде, чтобы проверить жив ли какой‑то ивент.
Все эти доступы не должны лежать хардкодом в репозитории.
3. Централизованное хранение секретов
Последняя проблема — файл нужно передавать новым разработчикам, синхронизировать между машинами и CI, ротировать при компрометации. Для таких задач существуют secrets manager. Себе я выбрал Infisical, хотя на рынке популярных вариантов как минимум три.
Настройка
Для начала нужно регнуть учетку infisical, создать компанию, создать проект и секретов в него. Ссылка на US сервер‑ https://app.infisical.com/.
Проблема с которой можно столкнуться
У сервиса несколько субдоменов — на 10.2026 есть как минимум как минимум app. (US server), eu. (EU server). Аккаунты и проекты у них раздельные. Выбирайте одинаковый сервер при работе в веб интерфейсе и интеграции в CLI.
Установка (windows):
winget install infisical infisical login
Установит пакет, и запустит логин, который откроет браузер для входа. для CI/CD процесс иной, в команду вписываются данные специальной учетки Machine Identity. Для других платформ пакет называется идентично и поддерживает установку через пакетные менеджеры.
Настройка проекта:
cd myProjectPath infisical init
Это запустит интерактивное создание / привязку к проекту, по итогу в директории появится .infisical.json. Он содержит такое:
{ "workspaceId": "7a10de5f-ed66-43ff-838d-c88b6926d59a", "defaultEnvironment": "", "gitBranchToEnvironmentMapping": null }
Указанные поля по необходимости можно настроить — сопоставление среды к ветки git и среду по стандарту. А workspaceId при необходимости можно посмотреть в настройках проекта в веб интерфейсе и выставить в конфиге.
.infisical.jsonможно коммитить в репозиторий, секретов в нём нет. Далее разработчик может создать секреты в .env файл через команду:
infisical export --format dotenv --output-file=.env
После этого можно Build/Load Signing Credentials в Unity, чтобы вписать данные подписи автоматически.
Что не нужно делать
Не надо складывать в Infisical вообще всё
SERVER_URL, ADDRESSABLES_URL не становятся секретами только потому, что они находятся в .env.
Если значение является обычной конфигурацией, хранить его в Unity‑проекте часто проще и удобнее.
Не надо считать client‑side API key настоящим секретом
Если приложение должно содержать:
SENTRY_DSN FIREBASE_APP_ID PUBLIC_CLIENT_ID
то secrets manager не сделает их недоступными пользователю.
После сборки они всё равно окажутся внутри приложения.
Не надо сохранять secrets в Unity Assets
Плохо: Прочитал.env, сложил результат в ScriptableObject.
Так секреты попадут в git.
Главная идея
В результате получается довольно простое правило:
Конфигурация приложения хранится вместе с приложением. Credentials для действий от имени команды — отдельно.
Именно такое разделение начинает иметь смысл, когда Unity‑проект перестаёт быть одним локальным проектом разработчика и превращается в production pipeline команды.

