Запуск непривилегированных контейнеров LXC
Контейнеры LXC бывают двух типов: обычные (привилегированные) и непривилегированные. Первые создаются и работают от имени суперпользователя, что не всегда хорошо с точки зрения безопасности. Опасность заключается в том, что при некоторых обстоятельствах человек, имея root права внутри контейнера, может выполнить так называемый «побег» (root escape) и получить полные права внутри host-системы. Непривилегированный же контейнер в свою очередь работает от имени обычного пользователя, которому даже не обязательно иметь права на работу с sudo. Но при этом сохраняется возможность работы с полными правами внутри виртуального пространства.
В Интернете есть несколько инструкций по запуску таких LXC контейнеров, но они были написаны для более старых версий ПО и на данный момент не работают. В результате ковыряния документации и сообщений об ошибках мной была составлена новая инструкция.

Выделяем UID’ы и GID’ы необходимому пользователю, а также раздаём права на некоторые каталоги:
# sudo usermod --add-subuids 100000-165536 myuser
# sudo usermod --add-subgids 100000-165536 myuser
# sudo chmod +x /home/username
# sudo chmod +x /home/username/.local
# sudo chmod +x /home/username/.local/share
В файл /etc/lxc/lxc-usernet пишем:
# USERNAME TYPE BRIDGE COUNT
myuser veth lxcbr0 100
Так мы разрешили пользователю создать 100 подключений контейнеров в бриджу. Если вы собираетесь присоединять контейнеры к другому бриджу, то вместо lxcbr0 укажите соответственно его (например, br0). Иначе при запуске налетите на ошибку нехватки ресурсов.
Теперь заходим под пользователем myuser и создаём каталог для настроек LXC:
$ mkdir -p ~/.config/lxc
Копируем /etc/lxc/default.conf в ~/.config/lxc/default.conf и дописываем в конце:
lxc.include = /etc/lxc/default.conf
lxc.idmap = u 0 100000 65536
lxc.idmap = g 0 100000 65536
Этого уже достаточно, чтобы начать создавать непривилегированные контейнеры, но нас ждёт одна проблема: такие контейнеры не будут запускаться автоматически при старте системы. Поэтому сразу решим её:
Создаём файл ~/.config/systemd/user/lxc-autostart.service со следующим содержимым:
[Unit]
Description="Lxc-autostart for lxc user"
[Service]
Type=oneshot
ExecStart=/usr/bin/lxc-autostart
ExecStop=/usr/bin/lxc-autostart -s
RemainAfterExit=1
[Install]
WantedBy=default.target
Далее выполняем команду:
$ systemctl --user enable lxc-autostart
И следующую:
# sudo loginctl enable-linger myuser
Это необходимо для запуска экземпляра systemd для пользователя при загрузке системы. В противном случае контейнер запустится только в момент входа пользователя.
Ну вот и всё. Давайте создадим контейнер от имени пользователя:
$ lxc-create -t download -n test1 -- -d ubuntu -r jammy -a amd64
Пока всё хорошо? Не торопитесь его запускать. Вы в него не попадёте. Дело в том, что по-умолчанию LXC контейнер создаётся без пароля суперпользователя и к тому же без установленного SSH демона. Соответственно, lxc-console не даст подключиться, а команда lxc-attach вообще не работает в непривилегированном режиме.
Но выход есть. Ставим пароль на root с помощью команды:
$ lxc-execute -n test1 -- passwd
Теперь можно и запустить контейнер. Кстати, делается это так:
$ systemd-run --unit=foo --user --scope -p "Delegate=yes" -- lxc-start -n test1
Подключаемся к терминалу виртуального пространства:
$ lxc-console -n test1
Вот теперь, находясь в терминале, можно и установить SSH, чтобы затем подключаться уже более удобным способом.
