Skip to content

Commit

Permalink
Increase request body size limit for services (#1934)
Browse files Browse the repository at this point in the history
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.
  • Loading branch information
jvstme authored Oct 31, 2024
1 parent 0723df6 commit 19cd2fd
Show file tree
Hide file tree
Showing 9 changed files with 23 additions and 1 deletion.
1 change: 1 addition & 0 deletions docs/docs/reference/cli/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -421,6 +421,7 @@ $ dstack pool delete --help
* `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`.
* `DSTACK_SERVER_CLOUDWATCH_LOG_GROUP` – (Optional) The CloudWatch Logs group for workloads logs. If not set, the default file-based log storage is used.
* `DSTACK_SERVER_CLOUDWATCH_LOG_REGION` — (Optional) The CloudWatch Logs region. Defaults to `None`.
* `DSTACK_DEFAULT_SERVICE_CLIENT_MAX_BODY_SIZE` – (Optional) Request body size limit for services, in bytes. Defaults to 64 MiB.
* `DSTACK_SERVER_DIR` – (Optional) Sets path to store data and server configs. Defaults to `~/.dstack/server`.

??? info "Internal environment variables"
Expand Down
11 changes: 10 additions & 1 deletion gateway/src/dstack/gateway/core/nginx.py
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,8 @@ class ServiceConfig(SiteConfig):
project: str
service_id: str
auth: bool
# Default for compatibility with older state.json. TODO: remove after a few releases
client_max_body_size: int = 1024 * 1024
servers: Dict[str, str] = {}


Expand Down Expand Up @@ -75,7 +77,13 @@ async def set_acme_settings(
)

async def register_service(
self, project: str, service_id: str, domain: str, https: bool, auth: bool
self,
project: str,
service_id: str,
domain: str,
https: bool,
auth: bool,
client_max_body_size: int,
):
config_name = self.get_config_name(domain)
conf = ServiceConfig(
Expand All @@ -84,6 +92,7 @@ async def register_service(
domain=domain,
https=https,
auth=auth,
client_max_body_size=client_max_body_size,
)

async with self._lock:
Expand Down
3 changes: 3 additions & 0 deletions gateway/src/dstack/gateway/core/store.py
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,8 @@ class Service(BaseModel):
domain: str
https: bool = True
auth: bool
# Default for compatibility with older state.json. TODO: remove after a few releases
client_max_body_size: int = 1024 * 1024
options: dict
replicas: List[Replica] = []

Expand Down Expand Up @@ -107,6 +109,7 @@ async def register_service(self, project: str, service: Service, ssh_private_key
service.domain,
service.https,
service.auth,
service.client_max_body_size,
)
stack.push_async_callback(
supress_exc_async(self.nginx.unregister_domain, service.domain)
Expand Down
1 change: 1 addition & 0 deletions gateway/src/dstack/gateway/registry/routes.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ async def post_register_service(
https=body.https,
auth=body.auth,
options=body.options,
client_max_body_size=body.client_max_body_size,
),
body.ssh_private_key,
)
Expand Down
1 change: 1 addition & 0 deletions gateway/src/dstack/gateway/registry/schemas.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ class RegisterServiceRequest(BaseModel):
domain: str
https: bool = True
auth: bool = True
client_max_body_size: int
options: dict = {}
ssh_private_key: str

Expand Down
1 change: 1 addition & 0 deletions gateway/src/dstack/gateway/resources/nginx/service.jinja2
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ server {
server_name {{ domain }};

access_log /var/log/nginx/dstack.access.log dstack_stat;
client_max_body_size {{ client_max_body_size }};

location / {
{% if auth %}
Expand Down
1 change: 1 addition & 0 deletions src/dstack/_internal/server/services/gateways/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -412,6 +412,7 @@ async def _register_service_in_gateway(
service_https=service_https,
gateway_https=gateway_https,
auth=run_spec.configuration.auth,
client_max_body_size=settings.DEFAULT_SERVICE_CLIENT_MAX_BODY_SIZE,
options=service_spec.options,
ssh_private_key=run_model.project.ssh_private_key,
)
Expand Down
2 changes: 2 additions & 0 deletions src/dstack/_internal/server/services/gateways/client.py
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@ async def register_service(
service_https: bool,
gateway_https: bool,
auth: bool,
client_max_body_size: int,
options: dict,
ssh_private_key: str,
):
Expand All @@ -59,6 +60,7 @@ async def register_service(
"domain": domain,
"https": service_https,
"auth": auth,
"client_max_body_size": client_max_body_size,
"options": options,
"ssh_private_key": ssh_private_key,
}
Expand Down
3 changes: 3 additions & 0 deletions src/dstack/_internal/server/settings.py
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,9 @@
ACME_SERVER = os.getenv("DSTACK_ACME_SERVER")
ACME_EAB_KID = os.getenv("DSTACK_ACME_EAB_KID")
ACME_EAB_HMAC_KEY = os.getenv("DSTACK_ACME_EAB_HMAC_KEY")
DEFAULT_SERVICE_CLIENT_MAX_BODY_SIZE = int(
os.getenv("DSTACK_DEFAULT_SERVICE_CLIENT_MAX_BODY_SIZE", 64 * 1024 * 1024)
)

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

Expand Down

0 comments on commit 19cd2fd

Please sign in to comment.