Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions mkdocs.yml
Original file line number Diff line number Diff line change
Expand Up @@ -306,6 +306,7 @@ nav:
- Troubleshooting: docs/guides/troubleshooting.md
- More:
- Protips: docs/guides/protips.md
- Tenant isolation: docs/guides/tenant-isolation.md
- Upgrade: docs/guides/upgrade.md
- Migration:
- Slurm: docs/guides/migration/slurm.md
Expand Down
2 changes: 1 addition & 1 deletion mkdocs/docs/concepts/exports.md
Original file line number Diff line number Diff line change
Expand Up @@ -184,7 +184,7 @@ fleets:
</div>
!!! info "Tenant isolation"
Exported fleets share the same access model as regular fleets. See [Tenant isolation](fleets.md#tenant-isolation) for details.
Exported fleets share the same access model as regular fleets. See [Tenant isolation](../guides/tenant-isolation.md) for details.
!!! info "What's next?"
1. Check the [`dstack export` CLI reference](../reference/cli/dstack/export.md)
Expand Down
9 changes: 0 additions & 9 deletions mkdocs/docs/concepts/fleets.md
Original file line number Diff line number Diff line change
Expand Up @@ -463,15 +463,6 @@ ssh_config:
!!! info "Reference"
The fleet configuration file supports additional options, including [`instance_types`](../reference/dstack.yml/fleet.md#instance_types), [`max_price`](../reference/dstack.yml/fleet.md#max_price), [`regions`](../reference/dstack.yml/fleet.md#max_price), among others. For the complete list, see the [reference](../reference/dstack.yml/fleet.md).

## Tenant isolation

Users running workloads on a fleet have access to the host, including the folders that may be used as instance volumes,
and containers use host network mode unless the host has multiple [blocks](#blocks) configured and the job uses only a subset of them.

Tighter isolation is on the roadmap, including [SSH reverse proxy](https://github.com/dstackai/dstack/issues/3644){:target="_blank"} and rootless access to the host.

When [exporting fleets](exports.md) to other projects, the same access model applies to members of the importer projects.

## Export fleets

Fleets can be exported to other projects, allowing those projects to use the exported fleets
Expand Down
96 changes: 96 additions & 0 deletions mkdocs/docs/guides/tenant-isolation.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
---
title: Tenant isolation
description: Restricting access to hosts managed by dstack
---

# Tenant isolation

`dstack` assumes mutual trust between users of the same project. While users' jobs run in Docker containers, users and their containers may have broad access to the underlying hosts. This guide explains how to restrict access to the host when stronger boundaries are required.

!!! info "Disclaimer"
Even with all precautions, complete isolation on shared hardware is hardly achievable — container escape vulnerabilities are common. The best way to provide true isolation between users is to place them in different `dstack` projects and not share hardware between them.

## Host SSH access

While attached to a run, users can SSH directly into the host machine — not just the container — using:

```shell
ssh <run-name>-host
```

This gives unrestricted access to the underlying instance, bypassing container boundaries.

If desired, host SSH access can be disabled server-wide by configuring the [SSH proxy](server-deployment.md#ssh-proxy) and setting the following environment variable when starting the `dstack` server:
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

DOn't we want to include a guide on how to set up SSH proxy here?


```shell
DSTACK_SERVER_SSHPROXY_ENFORCED=1
```

With this setting, all users' SSH connections go through the SSH proxy, which only allows connections into the container and not into the host.

## Privileged mode

Running a container in privileged mode gives it full access to the host kernel, making container escape straightforward. `dstack` supports requesting privileged mode through several configuration properties:

| Property | Applies to |
|---|---|
| `privileged: true` | Tasks, dev environments, services |
| `docker: true` | Tasks, dev environments, services |
| `replicas[i].privileged: true` | Services with replica groups |
| `replicas[i].docker: true` | Services with replica groups |

To block runs that request privileged mode, write a [REST plugin](../reference/plugins/rest/index.md) or a [Python plugin](../reference/plugins/python/index.md) with an apply policy.

<div editor-title="src/isolation_plugin/__init__.py">

```python
class NoPrivilegedPolicy(ApplyPolicy):
def on_run_apply(self, user: str, project: str, spec: RunSpec) -> RunSpec:
conf = spec.configuration

if conf.privileged or conf.docker:
raise ValueError("Privileged mode and Docker-in-Docker are not allowed")

if isinstance(conf, ServiceConfiguration) and isinstance(conf.replicas, list):
for group in conf.replicas:
if group.privileged or group.docker:
raise ValueError(
f"Replica group '{group.name}' requests privileged mode, which is not allowed"
)

return spec
```

</div>

## Instance volumes

[Instance volumes](../concepts/volumes.md#instance-volumes) mount a path from the host filesystem directly into the container. A user with access to this feature can mount arbitrary host paths — including sensitive directories such as `/etc`, `/proc`, or `/var`.

You can disallow instance volumes or restrict access to certain paths by writing a [REST plugin](../reference/plugins/rest/index.md) or a [Python plugin](../reference/plugins/python/index.md).

## Host network access

By default, most `dstack` jobs run in host networking mode, sharing the network namespace of the instance. This is significant because the instance also runs internal `dstack` services — including APIs used to manage containers and SSH authorized keys. A container on the host network can reach these APIs.

The `DSTACK_SERVER_JOB_NETWORK_MODE` environment variable controls which jobs get host vs. bridge networking:

| Value | Name | Behavior |
|---|---|---|
| `1` | `HOST_FOR_MULTINODE_ONLY` | Host for distributed tasks, bridge otherwise |
| `2` | `HOST_WHEN_POSSIBLE` | Host whenever the job occupies a full instance (default) |
| `3` | `FORCED_BRIDGE` | Always bridge, including distributed tasks |
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Must be explicit that this prevents both distributed tasks and PD disaggregation to work


### No distributed tasks

If you don't need distributed tasks or other runs with inter-job communication, set `DSTACK_SERVER_JOB_NETWORK_MODE=3` when starting the server:

```shell
DSTACK_SERVER_JOB_NETWORK_MODE=3
```

This forces bridge networking for all jobs on the server without exception, preventing access to internal `dstack` APIs.

### Allow distributed tasks in selected projects

If you want distributed tasks or other runs with inter-job communication to be available in some projects but not others, use `DSTACK_SERVER_JOB_NETWORK_MODE=1` instead. With this mode, single-node jobs get bridge networking, while distributed tasks still run with host networking. They can then be selectively blocked per project or user by writing a [REST plugin](../reference/plugins/rest/index.md) or a [Python plugin](../reference/plugins/python/index.md).
4 changes: 4 additions & 0 deletions mkdocs/docs/reference/env.md
Original file line number Diff line number Diff line change
Expand Up @@ -141,6 +141,10 @@ For more details on the options below, refer to the [server deployment](../guide
- `DSTACK_SERVER_DEFAULT_DOCKER_REGISTRY`{ #DSTACK_SERVER_DEFAULT_DOCKER_REGISTRY } – A default Docker registry to use for job images that do not specify an explicit registry. E.g., if set to `registry.example`, then `image: ubuntu` becomes equivalent to `image: registry.example/ubuntu`. **Note**: This setting should only be used for configuring registries that act as a pull-through cache for Docker Hub. The default `dstack` images are also pulled from the configured registry.
- `DSTACK_SERVER_DEFAULT_DOCKER_REGISTRY_USERNAME`{ #DSTACK_SERVER_DEFAULT_DOCKER_REGISTRY_USERNAME } – Username for authenticating with the default Docker registry. See `DSTACK_SERVER_DEFAULT_DOCKER_REGISTRY_PASSWORD`.
- `DSTACK_SERVER_DEFAULT_DOCKER_REGISTRY_PASSWORD`{ #DSTACK_SERVER_DEFAULT_DOCKER_REGISTRY_PASSWORD } – Password for authenticating with the default Docker registry. Applied only when the image has no explicit registry and the run configuration does not specify `registry_auth`. **Note**: The value may be visible to anyone who can SSH into instances managed by `dstack`, which usually includes all users of that `dstack` server.
- `DSTACK_SSHPROXY_API_TOKEN`{ #DSTACK_SSHPROXY_API_TOKEN } – Authentication token for the SSH proxy API. Required to enable SSH proxy integration; must match the token configured when deploying [`dstack-sshproxy`](https://github.com/dstackai/sshproxy).
- `DSTACK_SERVER_SSHPROXY_ADDRESS`{ #DSTACK_SERVER_SSHPROXY_ADDRESS } – Address of the SSH proxy exposed to users, in `HOSTNAME[:PORT]` form. `PORT` defaults to `22` if omitted. Required together with `DSTACK_SSHPROXY_API_TOKEN` to enable SSH proxy integration.
- `DSTACK_SERVER_SSHPROXY_ENFORCED`{ #DSTACK_SERVER_SSHPROXY_ENFORCED } – When set to any value, restricts all SSH connections to go through the SSH proxy.
- `DSTACK_SERVER_JOB_NETWORK_MODE`{ #DSTACK_SERVER_JOB_NETWORK_MODE } – Controls the network mode assigned to jobs. Accepts an integer value: `1` forces bridge networking for single-node jobs while distributed tasks still use host networking; `2` uses host networking whenever the job occupies a full instance (default); `3` forces bridge networking for all jobs including distributed tasks.

??? info "Internal environment variables"
The following environment variables are intended for development purposes:
Expand Down
Loading