99from ..logger import log
1010from ..constants import DOCKER_DEPS , DOCKER_PKGS , ROOTLESS_DOCKER_DEPS
1111from .apt_tools import apt_install , ensure_apt_repo
12- from .user_mgmt import add_user_to_group
12+ from .user_mgmt import add_user_to_group , require_user
1313
1414def _get_os_release () -> Dict [str , str ]:
1515 """
@@ -188,12 +188,6 @@ def install_docker_and_add_users(
188188 log .success ("Docker installation complete." )
189189
190190
191- def _user_exists (user : str ) -> bool :
192- return subprocess .run (
193- ['id' , user ], stdout = subprocess .DEVNULL , stderr = subprocess .DEVNULL
194- ).returncode == 0
195-
196-
197191def _get_uid (user : str ) -> int :
198192 return int (subprocess .run (
199193 ['id' , '-u' , user ], capture_output = True , text = True , check = True
@@ -240,17 +234,39 @@ def _ensure_subid_range(exec_obj: Executor, path: str, user: str) -> None:
240234 exec_obj .run (f"echo '{ user } :{ next_start } :65536' | tee -a { path } > /dev/null" , force_sudo = True )
241235
242236
237+ def _machinectl_shell (exec_obj : Executor , user : str , uid : int , inner_cmd : str ) -> None :
238+ """
239+ Runs inner_cmd as user via 'machinectl shell', with XDG_RUNTIME_DIR and
240+ DBUS_SESSION_BUS_ADDRESS set.
241+
242+ 'sudo -u user' does NOT create a real login session, so the user's
243+ systemd --user instance / D-Bus bus either isn't reachable or isn't the
244+ persistent one lingering keeps alive — dockerd-rootless-setuptool.sh and
245+ systemctl --user then silently fall back to a non-systemd path ("systemd
246+ not detected") or fail with "Unit docker.service does not exist".
247+ machinectl shell attaches to the real per-user session that
248+ loginctl enable-linger keeps running.
249+ """
250+ script = (
251+ f"export XDG_RUNTIME_DIR=/run/user/{ uid } ; "
252+ 'export DBUS_SESSION_BUS_ADDRESS="unix:path=${XDG_RUNTIME_DIR}/bus"; '
253+ f"{ inner_cmd } "
254+ )
255+ exec_obj .run (f"machinectl shell { user } @ /bin/bash -c '{ script } '" , force_sudo = True , check = True )
256+
257+
243258def _setup_rootless_docker (exec_obj : Executor , user : str ) -> None :
244259 """
245260 Configures rootless Docker for *user*: uidmap prerequisites, subuid/subgid
246261 ranges, lingering (so their systemd --user instance survives without an
247- active login), then runs dockerd-rootless-setuptool.sh as that user.
262+ active login), then runs dockerd-rootless-setuptool.sh as that user via
263+ 'machinectl shell' (see _machinectl_shell for why not plain sudo -u).
248264
249265 --force is passed to the setuptool because the system-wide dockerd is
250266 intentionally left running for other services; rootless and rootful
251267 Docker run side by side using separate sockets.
252268 """
253- if not _user_exists ( user ):
269+ if not require_user ( exec_obj , user , prompt_before_create = True ):
254270 log .warning (f"User '{ user } ' does not exist; skipping rootless Docker setup." )
255271 return
256272
@@ -272,21 +288,13 @@ def _setup_rootless_docker(exec_obj: Executor, user: str) -> None:
272288 else :
273289 log .warning (f"{ runtime_dir } did not appear after enabling linger; proceeding anyway." )
274290
275- env_prefix = f"XDG_RUNTIME_DIR={ runtime_dir } PATH=/usr/bin:$PATH"
276-
277291 log .info (f"Running dockerd-rootless-setuptool.sh for '{ user } '..." )
278- exec_obj .run (
279- f"{ env_prefix } dockerd-rootless-setuptool.sh install --force" ,
280- user = user ,
281- check = True ,
292+ _machinectl_shell (
293+ exec_obj , user , uid , "PATH=/usr/bin:$PATH dockerd-rootless-setuptool.sh install --force"
282294 )
283295
284296 log .info (f"Enabling and starting the rootless docker.service for '{ user } '..." )
285- exec_obj .run (
286- f"XDG_RUNTIME_DIR={ runtime_dir } systemctl --user enable --now docker.service" ,
287- user = user ,
288- check = True ,
289- )
297+ _machinectl_shell (exec_obj , user , uid , "systemctl --user enable --now docker.service" )
290298
291299 _add_rootless_env_to_shell_rc (exec_obj , user , uid )
292300 _verify_rootless_docker (exec_obj , user , runtime_dir )
0 commit comments