Skip to content

Commit 19cd2fd

Browse files
authored
Increase request body size limit for services (#1934)
This commit increases the limit from 1 MiB to 64 MiB and makes it configurable with a new dstack-server environment variable. The design will also allow to make the limit configurable per-gateway and/or per-service in the future.
1 parent 0723df6 commit 19cd2fd

9 files changed

Lines changed: 23 additions & 1 deletion

File tree

docs/docs/reference/cli/index.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -421,6 +421,7 @@ $ dstack pool delete --help
421421
* `DSTACK_DATABASE_URL` – (Optional) The database URL to use instead of default SQLite. Currently `dstack` supports Postgres. Example: `postgresql+asyncpg://myuser:mypassword@localhost:5432/mydatabase`. Defaults to `None`.
422422
* `DSTACK_SERVER_CLOUDWATCH_LOG_GROUP` – (Optional) The CloudWatch Logs group for workloads logs. If not set, the default file-based log storage is used.
423423
* `DSTACK_SERVER_CLOUDWATCH_LOG_REGION` — (Optional) The CloudWatch Logs region. Defaults to `None`.
424+
* `DSTACK_DEFAULT_SERVICE_CLIENT_MAX_BODY_SIZE` – (Optional) Request body size limit for services, in bytes. Defaults to 64 MiB.
424425
* `DSTACK_SERVER_DIR` – (Optional) Sets path to store data and server configs. Defaults to `~/.dstack/server`.
425426

426427
??? info "Internal environment variables"

gateway/src/dstack/gateway/core/nginx.py

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,8 @@ class ServiceConfig(SiteConfig):
3737
project: str
3838
service_id: str
3939
auth: bool
40+
# Default for compatibility with older state.json. TODO: remove after a few releases
41+
client_max_body_size: int = 1024 * 1024
4042
servers: Dict[str, str] = {}
4143

4244

@@ -75,7 +77,13 @@ async def set_acme_settings(
7577
)
7678

7779
async def register_service(
78-
self, project: str, service_id: str, domain: str, https: bool, auth: bool
80+
self,
81+
project: str,
82+
service_id: str,
83+
domain: str,
84+
https: bool,
85+
auth: bool,
86+
client_max_body_size: int,
7987
):
8088
config_name = self.get_config_name(domain)
8189
conf = ServiceConfig(
@@ -84,6 +92,7 @@ async def register_service(
8492
domain=domain,
8593
https=https,
8694
auth=auth,
95+
client_max_body_size=client_max_body_size,
8796
)
8897

8998
async with self._lock:

gateway/src/dstack/gateway/core/store.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,8 @@ class Service(BaseModel):
3838
domain: str
3939
https: bool = True
4040
auth: bool
41+
# Default for compatibility with older state.json. TODO: remove after a few releases
42+
client_max_body_size: int = 1024 * 1024
4143
options: dict
4244
replicas: List[Replica] = []
4345

@@ -107,6 +109,7 @@ async def register_service(self, project: str, service: Service, ssh_private_key
107109
service.domain,
108110
service.https,
109111
service.auth,
112+
service.client_max_body_size,
110113
)
111114
stack.push_async_callback(
112115
supress_exc_async(self.nginx.unregister_domain, service.domain)

gateway/src/dstack/gateway/registry/routes.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ async def post_register_service(
2424
https=body.https,
2525
auth=body.auth,
2626
options=body.options,
27+
client_max_body_size=body.client_max_body_size,
2728
),
2829
body.ssh_private_key,
2930
)

gateway/src/dstack/gateway/registry/schemas.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ class RegisterServiceRequest(BaseModel):
88
domain: str
99
https: bool = True
1010
auth: bool = True
11+
client_max_body_size: int
1112
options: dict = {}
1213
ssh_private_key: str
1314

gateway/src/dstack/gateway/resources/nginx/service.jinja2

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ server {
1111
server_name {{ domain }};
1212

1313
access_log /var/log/nginx/dstack.access.log dstack_stat;
14+
client_max_body_size {{ client_max_body_size }};
1415

1516
location / {
1617
{% if auth %}

src/dstack/_internal/server/services/gateways/__init__.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -412,6 +412,7 @@ async def _register_service_in_gateway(
412412
service_https=service_https,
413413
gateway_https=gateway_https,
414414
auth=run_spec.configuration.auth,
415+
client_max_body_size=settings.DEFAULT_SERVICE_CLIENT_MAX_BODY_SIZE,
415416
options=service_spec.options,
416417
ssh_private_key=run_model.project.ssh_private_key,
417418
)

src/dstack/_internal/server/services/gateways/client.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,7 @@ async def register_service(
4747
service_https: bool,
4848
gateway_https: bool,
4949
auth: bool,
50+
client_max_body_size: int,
5051
options: dict,
5152
ssh_private_key: str,
5253
):
@@ -59,6 +60,7 @@ async def register_service(
5960
"domain": domain,
6061
"https": service_https,
6162
"auth": auth,
63+
"client_max_body_size": client_max_body_size,
6264
"options": options,
6365
"ssh_private_key": ssh_private_key,
6466
}

src/dstack/_internal/server/settings.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,9 @@
5050
ACME_SERVER = os.getenv("DSTACK_ACME_SERVER")
5151
ACME_EAB_KID = os.getenv("DSTACK_ACME_EAB_KID")
5252
ACME_EAB_HMAC_KEY = os.getenv("DSTACK_ACME_EAB_HMAC_KEY")
53+
DEFAULT_SERVICE_CLIENT_MAX_BODY_SIZE = int(
54+
os.getenv("DSTACK_DEFAULT_SERVICE_CLIENT_MAX_BODY_SIZE", 64 * 1024 * 1024)
55+
)
5356

5457
USER_PROJECT_DEFAULT_QUOTA = int(os.getenv("DSTACK_USER_PROJECT_DEFAULT_QUOTA", 10))
5558

0 commit comments

Comments
 (0)