Вопрос

Как запустить произвольную службу от имени произвольного пользователя при загрузке с помощью сеанса входа в систему (в частности, включая все полезные функции в разделе /run/user/uid), созданного для этого пользователя, и без необходимости явного входа в систему под этим пользователем?

Фон

Я нахожусь в процессе преобразования развертывания docker-compose для использования с сервисами podman + systemd без рута. Я разобрался с большей частью материала podman, но мне особенно сложно заставить его работать через systemd.

В моем предыдущем развертывании я создал учетную запись пользователя для каждой службы и настроил контейнеры для запуска от имени этого пользователя. Это было очень удобно с точки зрения контроля и обслуживания файловой системы, и это действительно основное свойство, которое я хочу сохранить.

С этой целью я нашел этот вопрос askubuntu, который дает мне возможность внедрить пользователя непосредственно в мое задание systemd и выполнить его от имени указанного пользователя. Идеально.

А теперь ключевой момент: Fedora перешла на cgroups v2, которая теперь обрабатывается systemd и, по сути, в первую очередь является причиной этих усилий. В результате podman требует возможности общаться с systemd, что, в свою очередь, в основном требует сеанса входа, настроенного logind (если я правильно понимаю this корректна). Я не эксперт по systemd, поэтому, пожалуйста, поправьте меня в этом.

Я нашел еще один вопрос о ожидание сеанса пользователя, который близок к тому, что мне нужно, но, похоже, указывает на то, что это невозможно. Мой случай отличается в двух основных отношениях:

  • Я не хочу ждать какого-либо сеанса (например, он должен запускаться при загрузке без взаимодействия).
  • Мое решение должно быть достаточно надежным, чтобы выдерживать ручное вмешательство, включающее и отключающее сервис.

Итак, как указано выше, я действительно ищу любой способ заставить службу systemd работать от имени конкретного пользователя с достаточной средой входа в систему, чтобы приложение службы могло подключаться к systemd (или, по крайней мере, cgroups v2). его часть).

Наконец, ниже приведен пример файла модуля systemd для одной из служб, которая работает должным образом, пока не потребуется подключиться к systemd. Кроме того, вызов podman полностью работает, когда он выполняется вручную от моего вошедшего в систему пользователя.

[Unit]
Description=Emby Podman Container

[Service]
User=emby
Group=emby
Restart=on-failure
ExecStartPre=/usr/bin/rm -f /%t/%n-pid /home/emby/%n-cid
ExecStart=/usr/bin/podman run --conmon-pidfile /%t/%n-pid --cidfile /home/emby/%n-cid -d --name=emby --cgroup-manager=systemd -e TZ="$TZ" -p 8096:8096 -p 8920:8920 -v /opt/docker/storage/emby:/config -v /media/media/:/media emby/embyserver
ExecStop=/usr/bin/sh -c "/usr/bin/podman rm -f `cat /home/emby/%n-cid`"
KillMode=none
Type=forking
PIDFile=/%t/%n-pid

[Install]
WantedBy=multi-user.target

1
MysteryMoose 2 Июн 2020 в 04:29

1 ответ

Лучший ответ

Итак, после долгих раздумий я смог найти работоспособное решение, которое оказалось проще, хотя и менее элегантным, чем я думал. Давайте перейдем к делу и посмотрим на файл функционального модуля:

[Unit]
Description=Emby Podman Container
BindsTo=user@1012.service
After=user@1012.service

[Service]
User=emby
Group=media
Restart=on-failure
ExecStartPre=/usr/bin/rm -f /home/emby/%n-pid /home/emby/%n-cid
ExecStartPre=-/usr/bin/podman rm emby
ExecStart=/usr/bin/podman run --conmon-pidfile /home/emby/%n-pid --cidfile /home/emby/%n-cid \
          --name=emby --rm --cgroup-manager=systemd \
          -e TZ="$TZ" \
          -p 8096:8096 -p 8920:8920 \
          -v /opt/docker/storage/emby:/config \
          -v /media/media/:/media \
          emby/embyserver
ExecStop=/usr/bin/sh -c "/usr/bin/podman rm -f `cat /home/emby/%n-cid`"
KillMode=none
Type=forking
PIDFile=/home/emby/%n-pid

[Install]
WantedBy=multi-user.target

Ключевым моментом здесь является то, чтобы позволить systemd самому управлять пользовательским сеансом (не то, чтобы он позволял вам делать что-то еще). Использование BindsTo и After имеет важное значение в этой конфигурации, поскольку они заставят полностью создать пользовательский сеанс для пользователя emby до фактического запуска службы emby. Кроме того, это делает так, что администратору (читай: мне) не нужно будет входить в систему для каждого пользователя, чтобы включить сеанс, что должно помочь по мере добавления новых служб и пользователей.

Еще несколько полезных замечаний по настройке:

Некоторые другие подходы, которые я пробовал, но не сработали:

Дополнительные ссылки:


РЕДАКТИРОВАТЬ:

Конечно, как только я публикую это, мне удается найти волшебную строку поиска, которая приводит меня к статья, которая противоречит моему подходу.

В интересах краткости основные моменты из приведенной выше статьи включают запуск службы от имени пользователя root и использование --uidmap/--gidmap для сопоставления пользователя root контейнера с желаемым пользователем системы.

Это решение, однако, специфично для podman, поэтому я оставлю вышеизложенное на месте для всех, чьи процессы без полномочий root и без podman нуждаются в доступе к systemd.

Наконец, я думаю, что мое решение является более безопасным, поскольку, если злоумышленник скомпрометирует среду выполнения контейнера, область действия по-прежнему будет ограничена моим непривилегированным пользователем. Хотя это может быть компенсировано увеличенной поверхностью атаки другой запущенной пользовательской службы, так что, возможно, это обман.

2
MysteryMoose 5 Июн 2020 в 01:25