После ProtectSystem сервис не пишет данные: задаём writable-пути
Службе включили ProtectSystem=strict, после чего она перестала сохранять результаты. Обычные права каталога разрешают запись, а запуск той же команды вручную работает. Внутри службы может действовать другое представление файловой системы: доступ ограничен на уровне mount namespace.
Отличить readonly от прав владельца
systemctl cat report.service
systemctl show report.service -p ProtectSystem -p ReadWritePaths -p ReadOnlyPaths -p StateDirectory
journalctl -u report.service -b --no-pager
stat -c '%n %U %G %a' /var/lib/reportТочное сообщение важно: Read-only file system направляет к mount-ограничению, Permission denied — к проверке доступа и другим слоям. Но приложение может скрыть системную ошибку за общим «не удалось сохранить», поэтому при необходимости используйте его подробный журнал на стенде.
Выделить состояние приложения
[Service]
User=reportbot
ProtectSystem=strict
StateDirectory=report
ReadWritePaths=/var/lib/report
ExecStart=/usr/local/bin/report-worker --state-dir=/var/lib/reportЭто пример для приложения с настраиваемым каталогом состояния. ProtectSystem=strict делает большую часть файловой иерархии readonly для службы. StateDirectory создаёт управляемый каталог постоянных данных; такие управляемые каталоги имеют специальное взаимодействие с защитой. Явный ReadWritePaths здесь показывает требуемую writable-границу и может быть избыточен для самого StateDirectory.
Если каталог уже управляется иначе, можно описать разрешённый путь через ReadWritePaths, предварительно создав его и задав владельца. Этот параметр не выдаёт пользователю DAC-права и не способен сделать физически readonly-файловую систему writable. Оба условия должны разрешать запись. Детали ограничений — в systemd.exec.
Не расширять доступ до всего /var
Сначала перечислите реальные записи приложения: постоянная база, временные файлы, кэш и собственные текстовые журналы. Задайте им отдельные каталоги через поддерживаемые параметры программы. Если приложение пишет рядом с исполняемым файлом, лучше исправить расположение состояния, чем открыть весь /usr или /opt.
Например, после переноса состояния в /var/lib/report база сохраняется, но генератор ещё пытается писать временный файл в /etc/report. Это отдельная ошибка размещения. Сделайте путь временных файлов явным и повторите задачу. Не добавляйте каждый отказавший родительский каталог целиком в writable-список.
Проверить положительное и отрицательное поведение
На стенде выполните штатное сохранение результата и убедитесь, что данные пережили перезапуск. Затем безопасной учебной операцией проверьте отказ записи в область, которая должна оставаться readonly. Если успех зависит от запуска вручную вне службы, тест проходит мимо действующего ограничения.
Существующие Unix-сокеты и другие возможности взаимодействия требуют отдельного анализа: readonly пути не являются универсальным запретом IPC. Также результат зависит от поддержки namespaces и окружения менеджера. Проверьте сообщения systemd о применении настроек на целевой машине.
Критерий готовности — служба выполняет все нужные операции, а её постоянные и временные записи перечислены и ограничены осмысленными путями. Посмотрите программу Linux и Bash для DevOps-инженеров: понимание прав, файловой системы и systemd помогает находить именно тот слой, который запрещает операцию.
Ещё по теме
Продолжить на практике
- Linux и Bash для DevOps-инженеров ↗
Linux для работы с серверами: процессы, права, systemd, сеть, диски и логи. Автоматизируйте повседневные задачи на Bash и разберите типичные сбои сервиса — от занятого порта до переполненного диска.
