-
Notifications
You must be signed in to change notification settings - Fork 1.6k
feat(runtime): add TLS support to TCP request plane #10921
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Merged
Changes from all commits
Commits
Show all changes
18 commits
Select commit
Hold shift + click to select a range
fa68b7e
feat(runtime): add TLS support to TCP request plane
walkoss 58402e5
feat(runtime): address review feedback — CLI flags, timeout, and cleanup
walkoss ec50785
fix(runtime): honor --no-tcp-tls-insecure over inherited env var
walkoss bf0650c
style: fix black formatting for long env var assignment
walkoss e86c36d
refactor(frontend): decouple HTTP TLS from TCP TLS
walkoss 33279ca
Merge upstream/main into walid/tcp-tls
walkoss 9af0d1a
Merge upstream/main into walid/tcp-tls
walkoss dc44774
Merge upstream/main into walid/tcp-tls
walkoss f1e8d67
Merge upstream/main into walid/tcp-tls
walkoss 73db19f
docs(kubernetes): add TCP TLS configuration guide
walkoss 3edbc96
docs(kubernetes): clarify TCP TLS scope covers response stream path only
walkoss c6a8bed
Merge upstream/main into walid/tcp-tls
walkoss e9ff9e0
fix(runtime): use dynamo-truthy for TCP TLS boolean parsing
walkoss 3706336
docs(kubernetes): fix TLS page navigation and k8s deployment example
walkoss 3c42432
Merge upstream/main into walid/tcp-tls
walkoss d3943d0
docs(tls): move TLS doc to reference/components
walkoss 78ba919
docs(request-plane): link to the TLS reference from TCP config options
walkoss 5277065
Merge branch 'main' into walid/tcp-tls
GuanLuo File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Some comments aren't visible on the classic Files Changed page.
There are no files selected for viewing
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
147 changes: 147 additions & 0 deletions
147
docs/fern/pages/reference/components/tls-configuration.mdx
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,147 @@ | ||
| --- | ||
| # SPDX-FileCopyrightText: Copyright (c) 2025-2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved. | ||
| # SPDX-License-Identifier: Apache-2.0 | ||
| title: TCP TLS | ||
| subtitle: Encrypt TCP streaming connections between frontend and workers | ||
| --- | ||
|
|
||
| Dynamo supports opt-in TLS encryption on the TCP call-home streaming transport | ||
| (implemented by `TcpStreamServer` and `TcpClient`, handling both response | ||
| streams and request streams between frontends and workers). When enabled, all TCP | ||
| connections on this path are upgraded to TLS using | ||
| [rustls](https://github.com/rustls/rustls) with the `ring` cryptographic | ||
| provider. When no TLS configuration is provided, the transport operates in | ||
| plaintext exactly as before. | ||
|
|
||
| ## Environment variables | ||
|
|
||
| All TLS configuration is driven by environment variables. The Rust runtime | ||
| reads these directly at first connection (lazy initialization). | ||
|
|
||
| Both frontends and workers act as TCP server and client depending on the | ||
| stream direction (response streams: worker dials frontend; request streams: | ||
| frontend dials worker). All TLS env vars should be set on every pod. | ||
|
|
||
| ### Server role (accepting connections) | ||
|
|
||
| | Variable | Description | | ||
| |---|---| | ||
| | `DYN_TCP_TLS_CERT_PATH` | Path to the PEM certificate file. When set together with `DYN_TCP_TLS_KEY_PATH`, TLS is enabled on the TCP server. | | ||
| | `DYN_TCP_TLS_KEY_PATH` | Path to the PEM private key for the server certificate. | | ||
|
|
||
| ### Client role (dialing connections) | ||
|
|
||
| | Variable | Description | | ||
| |---|---| | ||
| | `DYN_TCP_TLS_CA_CERT_PATH` | Path to the PEM CA certificate used to verify the peer's server certificate. | | ||
| | `DYN_TCP_TLS_INSECURE` | Set to `1` or `true` to skip certificate verification. For local development only. | | ||
| | `DYN_TCP_TLS_SERVER_NAME` | Override the TLS SNI hostname. Useful when connecting by IP to a server whose certificate has a DNS SAN. | | ||
| | `DYN_TCP_TLS_HANDSHAKE_TIMEOUT_SECS` | TLS handshake timeout in seconds (default: 3). | | ||
|
|
||
| ## CLI flags | ||
|
|
||
| The same configuration is available via command-line flags on all backends | ||
| (vllm, sglang, trtllm, tokenspeed) through `DynamoRuntimeArgGroup`: | ||
|
|
||
| ``` | ||
| --tcp-tls-cert-path PATH Server certificate (PEM) | ||
| --tcp-tls-key-path PATH Server private key (PEM) | ||
| --tcp-tls-ca-cert-path PATH CA certificate for server verification (PEM) | ||
| --tcp-tls-insecure Disable certificate verification | ||
| --tcp-tls-server-name NAME Override TLS SNI hostname | ||
| --tcp-tls-handshake-timeout N Handshake timeout in seconds (default: 3) | ||
| ``` | ||
|
|
||
| The frontend (`dynamo.frontend`) also accepts `--tcp-tls-cert-path`, | ||
| `--tcp-tls-key-path`, and `--tcp-tls-ca-cert-path`. | ||
|
|
||
| ## Quick start | ||
|
|
||
| Generate a self-signed certificate for local testing: | ||
|
|
||
| ```bash | ||
| # Generate CA | ||
| openssl req -x509 -newkey rsa:2048 -keyout ca-key.pem -out ca-cert.pem \ | ||
| -days 365 -nodes -subj "/CN=DynamoCA" | ||
|
|
||
| # Generate server cert with SAN | ||
| openssl req -newkey rsa:2048 -keyout server-key.pem -out server-csr.pem \ | ||
| -nodes -subj "/CN=localhost" \ | ||
| -addext "subjectAltName=DNS:localhost,IP:127.0.0.1" | ||
|
|
||
| openssl x509 -req -in server-csr.pem -CA ca-cert.pem -CAkey ca-key.pem \ | ||
| -CAcreateserial -out server-cert.pem -days 365 -copy_extensions copyall | ||
| ``` | ||
|
|
||
| Both frontend and worker need the same flags (both act as server and client): | ||
|
|
||
| ```bash | ||
| python -m dynamo.vllm \ | ||
| --tcp-tls-cert-path server-cert.pem \ | ||
| --tcp-tls-key-path server-key.pem \ | ||
| --tcp-tls-ca-cert-path ca-cert.pem \ | ||
| --tcp-tls-server-name localhost \ | ||
| ... | ||
|
|
||
| python -m dynamo.frontend \ | ||
| --tcp-tls-cert-path server-cert.pem \ | ||
| --tcp-tls-key-path server-key.pem \ | ||
| --tcp-tls-ca-cert-path ca-cert.pem \ | ||
| --tcp-tls-server-name localhost \ | ||
| ... | ||
| ``` | ||
|
|
||
| ## Kubernetes deployment | ||
|
|
||
| In Kubernetes, TLS certificates are typically delivered by a certificate | ||
| management system (e.g., cert-manager) and mounted into pods. Set the | ||
| environment variables on each component's pod template in the | ||
| `DynamoGraphDeployment` spec: | ||
|
|
||
| ```yaml | ||
| spec: | ||
| components: | ||
| - name: Frontend | ||
| podTemplate: | ||
| spec: | ||
| containers: | ||
| - name: main | ||
| env: | ||
| - name: DYN_TCP_TLS_CERT_PATH | ||
| value: /etc/certs/server/cert.pem | ||
| - name: DYN_TCP_TLS_KEY_PATH | ||
| value: /etc/certs/server/key.pem | ||
| - name: DYN_TCP_TLS_CA_CERT_PATH | ||
| value: /etc/certs/ca/ca.pem | ||
| - name: VllmWorker | ||
| podTemplate: | ||
| spec: | ||
| containers: | ||
| - name: main | ||
| env: | ||
| - name: DYN_TCP_TLS_CERT_PATH | ||
| value: /etc/certs/server/cert.pem | ||
| - name: DYN_TCP_TLS_KEY_PATH | ||
| value: /etc/certs/server/key.pem | ||
| - name: DYN_TCP_TLS_CA_CERT_PATH | ||
| value: /etc/certs/ca/ca.pem | ||
| ``` | ||
|
|
||
| Both components need the same TLS env vars because each acts as both TCP | ||
| server and client depending on the stream direction. | ||
|
|
||
| > **Note:** A future PR ([#10809](https://github.com/ai-dynamo/dynamo/issues/10809)) | ||
| > will add operator-level TLS configuration via `InfrastructureConfiguration`, | ||
| > allowing TLS to be configured once at the platform level and auto-injected | ||
| > into all DGD pods without per-component env var setup. | ||
|
|
||
| ## Design notes | ||
|
|
||
| - TLS configuration is cached after the first TCP connection via `OnceCell`. | ||
| Certificate rotation requires a process restart. | ||
| - The TLS handshake is spawned per-connection on the server side so the accept | ||
| loop is never blocked by a slow handshake. | ||
| - When server and client TLS configurations are mismatched (e.g., server has TLS | ||
| but client does not), a warning is logged at startup. | ||
| - An empty CA certificate file is detected at load time and rejected with a | ||
| clear error message. |
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.