Переменные окружения на сервере: как настроить без ошибок
Переменные окружения помогают передать настройки приложению без правок кода, но не превращают секреты в невидимые данные. Разбираем варианты для systemd: где хранить конфигурацию, как ограничить доступ и что проверить после изменения.

Если приложение на сервере читает настройки из переменных окружения, хранить их в исходниках или запускать сервис вручную с длинной командой — ненадёжно: конфигурация теряется при деплое, а секрет может попасть в историю терминала или логи. Для сервиса под systemd обычно выбирают между директивой Environment= в unit-файле и отдельным файлом через EnvironmentFile=. Ниже — практика для systemd и Linux; примеры рассчитаны на systemd 252 и новее.
Что подготовить до настройки
Нужны доступ к серверу с правами на изменение unit-файла, имя systemd-сервиса и команда, которой запускается приложение. Сначала выясните, от какого пользователя работает сервис и где лежит его основной unit: настройки в локальном override-файле обычно переживают обновление пакета лучше, чем правки системного unit напрямую.
Узнать состояние сервиса и его конфигурацию можно так:
systemctl status myapp.service
systemctl cat myapp.service
Замените myapp.service на имя своего сервиса. В выводе systemctl cat найдите строку User=, а также текущие Environment= и EnvironmentFile=, если они есть. Не публикуйте этот вывод целиком: в unit-файлах могут оказаться секреты.
Два способа передать настройки приложению
Environment= в unit-файле
Так удобно задавать несекретные параметры, которые относятся именно к этому сервису: режим запуска, уровень логирования, адрес внутреннего компонента. Для редактирования локального override используйте:
sudo systemctl edit myapp.service
Открывшийся редактор создаст override для сервиса. Например, можно добавить:
[Service]
Environment="APP_ENV=production" "LOG_LEVEL=info"
Сохраните файл, затем перезагрузите конфигурацию systemd и перезапустите сервис:
sudo systemctl daemon-reload
sudo systemctl restart myapp.service
systemctl status myapp.service
Проверка: сервис должен перейти в состояние active. Если приложение пишет диагностические сообщения при старте, проверьте их через journalctl -u myapp.service -n 50 --no-pager. Не выводите секретные переменные в лог ради проверки.
EnvironmentFile= для отдельного файла
Файл удобнее, когда параметров несколько или их меняют отдельно от unit-файла. Создайте его от имени администратора:
sudo install -o root -g root -m 600 /dev/null /etc/myapp.env
sudoedit /etc/myapp.env
Добавьте в файл строки в формате ИМЯ=значение, например:
APP_ENV=production
LOG_LEVEL=info
Укажите файл в override:
[Service]
EnvironmentFile=/etc/myapp.env
Сохраните изменения и примените их:
sudo systemctl daemon-reload
sudo systemctl restart myapp.service
systemctl status myapp.service
Проверка: сервис запускается, а приложение получает ожидаемое поведение. Если конфигурация не читается, посмотрите сообщения запуска через journalctl -u myapp.service -n 50 --no-pager. Не добавляйте в отчёт команды содержимое файла.
Что выбрать
| Способ | Когда подходит | Цена и риск |
|---|---|---|
Environment= | Пара несекретных настроек, тесно связанных с конкретным сервисом | Просто поддерживать, но значение видно тому, у кого есть доступ к unit-файлу и его копиям |
EnvironmentFile= | Настроек много или конфигурацию нужно отделить от описания сервиса | Можно ограничить права на файл; его содержимое всё равно доступно процессу и администратору |
| Менеджер секретов | Секреты нужно выдавать, менять и отзывать централизованно для нескольких сервисов | Потребуются отдельная инфраструктура, права доступа и настройка интеграции |
Для обычных параметров сервиса начните с EnvironmentFile=, если файл удобно защищать отдельными правами. Для секретов не считайте этот файл полноценным хранилищем секретов: права 600 снижают риск случайного чтения, но не защищают от администратора, компрометации приложения или резервной копии, в которую попал файл. Если у команды уже есть менеджер секретов, используйте его штатную интеграцию, а не дублируйте секреты в нескольких местах.
Переменная окружения — способ передать настройку процессу, а не способ сделать её секретной.
Что ломается чаще всего
- Изменили файл, но не перезапустили сервис. Новый процесс получает окружение при запуске. После правок unit или файла конфигурации примените их и перезапустите службу.
- Забыли daemon-reload после правки unit. systemd продолжает использовать загруженную конфигурацию. Выполните
sudo systemctl daemon-reload, затем перезапустите сервис. - Неверно оформлена строка. В файле окружения используйте формат
ИМЯ=значение, без пробелов вокруг знака равенства. Если значение содержит пробелы или специальные символы, проверьте правила разбора для используемой версии systemd в документации. - У процесса не хватает прав на файл. Сверьте владельца и режим доступа с пользователем сервиса. Не исправляйте проблему выдачей прав на чтение всем пользователям без оценки риска.
- Проверили только наличие переменной. Приложение может ожидать другое имя или значение. Сверьте точное имя с документацией самого приложения и проверьте его поведение, не печатая секрет в журнал.
Термин: окружение процесса — набор пар «имя — значение», который программа получает при запуске. Дочерний процесс может унаследовать это окружение, поэтому секрет способен оказаться доступным не только основному приложению.
Граничные случаи: где подход ломается
Переменная может отсутствовать, быть пустой или содержать значение, которое приложение трактует не так, как вы ожидали. Например, пустой адрес базы данных и отсутствующий адрес — не обязательно одно и то же. Уточните поведение в документации приложения и проверьте запуск на тестовой конфигурации.
Ещё один риск — утечка через диагностику. Не запускайте команды, которые печатают всё окружение процесса, в общей сессии или CI-логе. Не вставляйте значения секретов в командную строку: shell может сохранить их в истории. Доступ к файлам, резервным копиям и журналам тоже входит в модель защиты.
Если приложение запускается не через systemd, этот материал не описывает его способ конфигурации: Docker, Kubernetes и панели хостинга управляют переменными по своим правилам. Не переносите настройки из одного механизма в другой, не проверив документацию платформы.
Что сделать дальше
Составьте список переменных сервиса: имя, назначение, обязательность и признак секрета. Затем проверьте права на unit-файл и конфигурацию, процедуру перезапуска и то, что попадает в журналы и резервные копии. После деплоя следите за кодом выхода и сообщениями запуска: это быстрее покажет ошибку конфигурации, чем случайная проверка приложения вручную.
Тест и проверочная: Быстрые ответы с объяснением, почему остальные варианты неверны
Спросить за 10 ₽Источники: systemd.exec — окружение процессов и параметры исполнения, systemd.unit — настройки unit-файлов и drop-in
Частые вопросы
Можно ли хранить пароль базы данных в EnvironmentFile?
Нужно ли перезапускать сервис после изменения переменной?
Почему приложение не видит переменную из файла?
Можно ли посмотреть переменные уже запущенного процесса?
Подойдут ли эти шаги для Docker или Kubernetes?
Как понять, что настройка применилась?
Материал носит информационный характер и подготовлен редакцией «Агентуры». Он не является офертой, рекламой или индивидуальной консультацией. Упомянутые продукты, компании и торговые знаки принадлежат их правообладателям. Перед принятием решений, влекущих юридические или финансовые последствия, обратитесь к профильному специалисту.