Skip to content

Commit 4893cb3

Browse files
authored
Change /dstack/venv ownership to the current user (#3437)
Part-of: #3436
1 parent dde66b5 commit 4893cb3

File tree

3 files changed

+34
-13
lines changed

3 files changed

+34
-13
lines changed

src/dstack/_internal/server/services/jobs/configurators/base.py

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -220,6 +220,17 @@ def _dstack_image_commands(self) -> List[str]:
220220
):
221221
return []
222222
return [
223+
f"eval $(echo 'export DSTACK_VENV_DIR={DSTACK_DIR}/venv' | sudo tee -a {DSTACK_PROFILE_PATH})",
224+
# Make sure /dstack/venv is owned by the current user.
225+
# XXX: Generally, /dstack and all its descendants should be owned by root, as it is
226+
# intended to be a place for files shared by all users, but since a non-root user
227+
# should be able to install packages via pip and we want to avoid cluttering the user's
228+
# home dir if possible, we make the venv dir owned by the current user rather than
229+
# creating it inside the user's home or (even worse) making /dstack/venv
230+
# world-writable.
231+
"sudo rm -rf $DSTACK_VENV_DIR",
232+
"sudo mkdir $DSTACK_VENV_DIR",
233+
"sudo chown $(id -u):$(id -g) $DSTACK_VENV_DIR",
223234
# `uv` may emit:
224235
# > warning: `VIRTUAL_ENV=/dstack/venv` does not match the project environment path
225236
# > `.venv` and will be ignored; use `--active` to target the active environment
@@ -228,9 +239,8 @@ def _dstack_image_commands(self) -> List[str]:
228239
# used for legacy `pip`-based configurations). `--no-active` suppresses the warning.
229240
# Alternatively, the user can call `deactivate` once before using `uv`.
230241
# If the user really wants to reuse dstack's venv, they must spefify `--active`.
231-
f"uv venv -q --prompt dstack -p {self._python()} --seed {DSTACK_DIR}/venv",
232-
f"echo '. {DSTACK_DIR}/venv/bin/activate' >> {DSTACK_PROFILE_PATH}",
233-
f". {DSTACK_DIR}/venv/bin/activate",
242+
f"uv venv -q --prompt dstack -p {self._python()} --seed $DSTACK_VENV_DIR",
243+
f"eval $(echo '. $DSTACK_VENV_DIR/bin/activate' | sudo tee -a {DSTACK_PROFILE_PATH})",
234244
]
235245

236246
def _app_specs(self) -> List[AppSpec]:

src/tests/_internal/server/routers/test_runs.py

Lines changed: 12 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -115,9 +115,12 @@ def get_dev_env_run_plan_dict(
115115
"-i",
116116
"-c",
117117
(
118-
"uv venv -q --prompt dstack -p 3.13 --seed /dstack/venv"
119-
" && echo '. /dstack/venv/bin/activate' >> /dstack/profile"
120-
" && . /dstack/venv/bin/activate"
118+
"eval $(echo 'export DSTACK_VENV_DIR=/dstack/venv' | sudo tee -a /dstack/profile)"
119+
" && sudo rm -rf $DSTACK_VENV_DIR"
120+
" && sudo mkdir $DSTACK_VENV_DIR"
121+
" && sudo chown $(id -u):$(id -g) $DSTACK_VENV_DIR"
122+
" && uv venv -q --prompt dstack -p 3.13 --seed $DSTACK_VENV_DIR"
123+
" && eval $(echo '. $DSTACK_VENV_DIR/bin/activate' | sudo tee -a /dstack/profile)"
121124
" && (echo 'pip install ipykernel...'"
122125
" && pip install -q --no-cache-dir ipykernel 2> /dev/null)"
123126
" || echo 'no pip, ipykernel was not installed'"
@@ -344,9 +347,12 @@ def get_dev_env_run_dict(
344347
"-i",
345348
"-c",
346349
(
347-
"uv venv -q --prompt dstack -p 3.13 --seed /dstack/venv"
348-
" && echo '. /dstack/venv/bin/activate' >> /dstack/profile"
349-
" && . /dstack/venv/bin/activate"
350+
"eval $(echo 'export DSTACK_VENV_DIR=/dstack/venv' | sudo tee -a /dstack/profile)"
351+
" && sudo rm -rf $DSTACK_VENV_DIR"
352+
" && sudo mkdir $DSTACK_VENV_DIR"
353+
" && sudo chown $(id -u):$(id -g) $DSTACK_VENV_DIR"
354+
" && uv venv -q --prompt dstack -p 3.13 --seed $DSTACK_VENV_DIR"
355+
" && eval $(echo '. $DSTACK_VENV_DIR/bin/activate' | sudo tee -a /dstack/profile)"
350356
" && (echo 'pip install ipykernel...'"
351357
" && pip install -q --no-cache-dir ipykernel 2> /dev/null)"
352358
" || echo 'no pip, ipykernel was not installed'"

src/tests/_internal/server/services/jobs/configurators/test_task.py

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -98,10 +98,15 @@ async def test_with_commands_no_image(self, shell: Optional[str], expected_shell
9898
expected_shell,
9999
"-i",
100100
"-c",
101-
"uv venv -q --prompt dstack -p 3.12 --seed /dstack/venv"
102-
" && echo '. /dstack/venv/bin/activate' >> /dstack/profile"
103-
" && . /dstack/venv/bin/activate"
104-
" && sleep inf",
101+
(
102+
"eval $(echo 'export DSTACK_VENV_DIR=/dstack/venv' | sudo tee -a /dstack/profile)"
103+
" && sudo rm -rf $DSTACK_VENV_DIR"
104+
" && sudo mkdir $DSTACK_VENV_DIR"
105+
" && sudo chown $(id -u):$(id -g) $DSTACK_VENV_DIR"
106+
" && uv venv -q --prompt dstack -p 3.12 --seed $DSTACK_VENV_DIR"
107+
" && eval $(echo '. $DSTACK_VENV_DIR/bin/activate' | sudo tee -a /dstack/profile)"
108+
" && sleep inf"
109+
),
105110
]
106111

107112
async def test_no_commands(self, image_config_mock: ImageConfig):

0 commit comments

Comments
 (0)