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
21 changes: 21 additions & 0 deletions docker/server/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,27 @@ The admin user token is 'bbae0f28-d3dd-4820-bf61-8f4bb40815da'
For more details on server configuration options, see the
[server deployment](https://dstack.ai/docs/guides/server-deployment.md) guide.

### Run with PostgreSQL and the SSH proxy

In production, the `dstack` server is usually run with
[PostgreSQL](https://dstack.ai/docs/guides/server-deployment#postgresql) instead of the default
SQLite, and with the [SSH proxy](https://dstack.ai/docs/guides/server-deployment#ssh-proxy). The
[`docker-compose.yml`](https://github.com/dstackai/dstack/blob/master/docker/server/docker-compose.yml)
runs that combination locally, so you can try or test a production-like server on your own machine.
A full production deployment would also configure external
[logs storage](https://dstack.ai/docs/guides/server-deployment#logs-storage) and
[file storage](https://dstack.ai/docs/guides/server-deployment#file-storage).

```shell
docker compose -f docker/server/docker-compose.yml up
```

This starts PostgreSQL, the `dstack` server at `http://localhost:3000`, and the SSH proxy at
`localhost:30022`. The admin token is printed to the logs (`docker compose logs server`).

To access the server from the CLI, add it as a project with `dstack project add`, using the
admin token from the logs (see [Set up the CLI](#set-up-the-cli) below).

## Set up the CLI

To point the CLI to the `dstack` server, configure it
Expand Down
73 changes: 73 additions & 0 deletions docker/server/docker-compose.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
name: dstack

services:
postgres:
image: postgres:16
restart: unless-stopped
environment:
POSTGRES_USER: ${DSTACK_POSTGRES_USER:-dstack}
POSTGRES_PASSWORD: ${DSTACK_POSTGRES_PASSWORD:-dstack}
POSTGRES_DB: ${DSTACK_POSTGRES_DB:-dstack}
volumes:
- postgres-data:/var/lib/postgresql/data
healthcheck:
test: ["CMD-SHELL", "pg_isready -U $$POSTGRES_USER -d $$POSTGRES_DB"]
interval: 5s
timeout: 5s
retries: 10

server:
image: dstackai/dstack:latest # multi-arch — no platform override needed
restart: unless-stopped
depends_on:
postgres:
condition: service_healthy
environment:
DSTACK_DATABASE_URL: postgresql+asyncpg://${DSTACK_POSTGRES_USER:-dstack}:${DSTACK_POSTGRES_PASSWORD:-dstack}@postgres:5432/${DSTACK_POSTGRES_DB:-dstack}
DSTACK_SERVER_LOG_FORMAT: rich # human-readable console logs (image defaults to json)
# Shared secret between the server and the SSH proxy. The default works locally;
# override with a real secret for non-local deployments.
DSTACK_SSHPROXY_API_TOKEN: ${DSTACK_SSHPROXY_API_TOKEN:-dstack-sshproxy-token}
# Address clients use to reach the SSH proxy. `localhost:30022` is correct for a
# client on the same host; use a publicly reachable address for multi-host setups.
DSTACK_SERVER_SSHPROXY_ADDRESS: localhost:30022
volumes:
- server-data:/root/.dstack/server # config.yml + run logs (Postgres holds the rest)
ports:
- "3000:3000"

# One-shot init: generates the SSH proxy's host key into a shared volume so no manual
# ssh-keygen is needed. The proxy refuses to start without a host key.
sshproxy-keygen:
image: alpine:3
command:
- sh
- -c
- |
apk add --no-cache openssh-keygen >/dev/null
[ -f /keys/host_key ] || ssh-keygen -t ed25519 -f /keys/host_key -N "" -C dstack-sshproxy
volumes:
- sshproxy-keys:/keys

sshproxy:
image: dstackai/sshproxy:latest
platform: linux/amd64 # image is amd64-only; emulated on Apple Silicon
restart: unless-stopped
depends_on:
sshproxy-keygen:
condition: service_completed_successfully
server:
condition: service_started
environment:
DSTACK_SSHPROXY_API_URL: http://server:3000
DSTACK_SSHPROXY_API_TOKEN: ${DSTACK_SSHPROXY_API_TOKEN:-dstack-sshproxy-token}
command: ["--host-key", "/keys/host_key"]
volumes:
- sshproxy-keys:/keys
ports:
- "30022:30022"

volumes:
postgres-data:
server-data:
sshproxy-keys:
6 changes: 6 additions & 0 deletions mkdocs/docs/guides/server-deployment.md
Original file line number Diff line number Diff line change
Expand Up @@ -165,6 +165,9 @@ If you're using a smaller DB instance, you may need to set lower `DSTACK_DB_POOL

If you encounter errors, please [submit an issue](https://github.com/dstackai/dstack/issues/new/choose).

> For a local setup running PostgreSQL and the [SSH proxy](#ssh-proxy) together, see the example
> [`docker-compose.yml`](https://github.com/dstackai/dstack/blob/master/docker/server/docker-compose.yml).

## Logs storage

By default, `dstack` stores workload logs locally in `~/.dstack/server/projects/<project_name>/logs`.
Expand Down Expand Up @@ -370,6 +373,9 @@ To enable SSH proxy integration on the `dstack` server side, set the following e
* `DSTACK_SSHPROXY_API_TOKEN` – a token used to authenticate SSH proxy API requests, must be the same value as when deploying `dstack-sshproxy`.
* `DSTACK_SERVER_SSHPROXY_ADDRESS` – an address where SSH proxy is available to `dstack` users, in the `HOSTNAME[:PORT]` form, where `HOSTNAME` is a domain name or an IP address, and `PORT`, if not specified, defaults to 22.

> For a local setup running [PostgreSQL](#postgresql) and the SSH proxy together, see the example
> [`docker-compose.yml`](https://github.com/dstackai/dstack/blob/master/docker/server/docker-compose.yml).

## Encryption

By default, `dstack` stores data in plaintext. To enforce encryption, you
Expand Down
Loading