Skip to content

Commit c8b49a9

Browse files
committed
git-launcher: rename trusted workload launcher
1 parent 42c97a4 commit c8b49a9

9 files changed

Lines changed: 108 additions & 74 deletions

File tree

.github/workflows/trusted-workload-launcher-release.yml renamed to .github/workflows/git-launcher-release.yml

Lines changed: 12 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
1-
name: trusted-workload-launcher Release
1+
name: git-launcher Release
22
on:
33
workflow_dispatch: {}
44
push:
55
tags:
6-
- 'trusted-workload-launcher-v*'
6+
- 'git-launcher-v*'
77

88
permissions:
99
contents: write
@@ -16,14 +16,14 @@ jobs:
1616
runs-on: ubuntu-latest
1717
env:
1818
IMAGE_REGISTRY: docker.io
19-
IMAGE_REPOSITORY: ${{ vars.DOCKERHUB_ORG }}/trusted-workload-launcher
19+
IMAGE_REPOSITORY: ${{ vars.DOCKERHUB_ORG }}/git-launcher
2020
steps:
2121
- name: Checkout repository
2222
uses: actions/checkout@v4
2323

2424
- name: Parse version from tag
2525
run: |
26-
VERSION=${GITHUB_REF#refs/tags/trusted-workload-launcher-v}
26+
VERSION=${GITHUB_REF#refs/tags/git-launcher-v}
2727
if [ -z "${VERSION}" ]; then
2828
echo "Unable to parse version from ref: ${GITHUB_REF}" >&2
2929
exit 1
@@ -33,7 +33,7 @@ jobs:
3333
echo "Parsed version: ${VERSION}"
3434
3535
- name: Run launcher tests
36-
working-directory: trusted-workload-launcher
36+
working-directory: git-launcher
3737
run: ./tests/run-tests.sh
3838

3939
- name: Set up Docker Buildx
@@ -50,21 +50,21 @@ jobs:
5050
id: build-and-push
5151
uses: docker/build-push-action@v5
5252
with:
53-
context: trusted-workload-launcher
54-
file: trusted-workload-launcher/docker/Dockerfile
53+
context: git-launcher
54+
file: git-launcher/docker/Dockerfile
5555
push: true
56-
tags: docker.io/${{ vars.DOCKERHUB_ORG }}/trusted-workload-launcher:${{ env.VERSION }}
56+
tags: docker.io/${{ vars.DOCKERHUB_ORG }}/git-launcher:${{ env.VERSION }}
5757
platforms: linux/amd64
5858
labels: |
59-
org.opencontainers.image.title=trusted-workload-launcher
59+
org.opencontainers.image.title=git-launcher
6060
org.opencontainers.image.source=${{ github.server_url }}/${{ github.repository }}
6161
org.opencontainers.image.revision=${{ github.sha }}
6262
org.opencontainers.image.version=${{ env.VERSION }}
6363
6464
- name: Generate artifact attestation
6565
uses: actions/attest-build-provenance@v1
6666
with:
67-
subject-name: docker.io/${{ vars.DOCKERHUB_ORG }}/trusted-workload-launcher
67+
subject-name: docker.io/${{ vars.DOCKERHUB_ORG }}/git-launcher
6868
subject-digest: ${{ steps.build-and-push.outputs.digest }}
6969
push-to-registry: true
7070

@@ -74,7 +74,7 @@ jobs:
7474
IMAGE_DIGEST: ${{ steps.build-and-push.outputs.digest }}
7575
run: |
7676
{
77-
echo "## trusted-workload-launcher image"
77+
echo "## git-launcher image"
7878
echo ""
7979
echo "- Tag: \`${IMAGE_REFERENCE}\`"
8080
echo "- Digest: \`${IMAGE_DIGEST}\`"
@@ -85,7 +85,7 @@ jobs:
8585
uses: softprops/action-gh-release@v1
8686
with:
8787
body: |
88-
## trusted-workload-launcher image (SHA256)
88+
## git-launcher image (SHA256)
8989
9090
- Image: `${{ env.IMAGE_REFERENCE }}`
9191
- Digest: `${{ steps.build-and-push.outputs.digest }}`

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -231,7 +231,7 @@ Implementation details and infrastructure patterns.
231231
| Example | Description |
232232
|---------|-------------|
233233
| [launcher](./launcher) | Generic launcher pattern for Docker Compose apps (auto-update) |
234-
| [trusted-workload-launcher](./trusted-workload-launcher) | Run a pinned Git commit in a TEE. |
234+
| [git-launcher](./git-launcher) | Run a pinned Git commit in a TEE. |
235235
| [prelaunch-script](./prelaunch-script) | Pre-launch script patterns (Phala Cloud) |
236236
| [private-docker-image-deployment](./private-docker-image-deployment) | Using private Docker registries |
237237
| [attestation/rtmr3-based](./attestation/rtmr3-based) | RTMR3-based attestation (legacy) |
Lines changed: 40 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,16 @@
1-
# trusted-workload-launcher
1+
# git-launcher
22

3-
A minimal, auditable launcher image for dstack. Given a config file that
3+
A minimal, auditable Git launcher image for dstack. Given a config file that
44
names an upstream Git repo and a full commit SHA, the launcher fetches that
55
exact commit, verifies `HEAD` after checkout, and runs the workload's own
66
entry point script — with no fallback to branches, tags, or short SHAs.
77

8-
"Trusted" in the name refers to what a dstack deployment using this image
9-
can produce — a *trusted workload deployment* — not to any intrinsic
10-
property of the workload code. The launcher's job is to make the identity
11-
of what runs in the TEE checkable: it combines TEE attestation with an
12-
auditable image digest and an attested config that names the workload
13-
commit. Whether the workload at that commit is itself trustworthy is up to
14-
the auditor.
8+
The name is literal: this image launches arbitrary Git input, but only at an
9+
explicit commit selected by attested config. It does not make the workload
10+
trustworthy by itself. Its job is to make the identity of what runs in the TEE
11+
checkable by combining TEE attestation, an auditable launcher image digest, and
12+
an attested config that names the workload commit. Whether the workload at that
13+
commit is itself trustworthy is up to the auditor.
1514

1615
By convention, **the workload repo provides its own bash entry point at
1716
`entrypoint.sh`** (default mode). This keeps install/build/run logic inside
@@ -109,10 +108,10 @@ given (launcher image digest, attested config) pair.
109108
## CLI
110109

111110
```
112-
trusted-workload-launcher <config-file>
111+
git-launcher <config-file>
113112
```
114113

115-
The launcher is a single bash script (`bin/trusted-workload-launcher`). It
114+
The launcher is a single bash script (`bin/git-launcher`). It
116115
depends only on `bash`, `git`, and POSIX coreutils. It is **not** sourced
117116
and **does not source** the config. In default mode, the only bytes it
118117
executes are those of the workload repo's `entrypoint.sh` at the pinned
@@ -191,14 +190,28 @@ audited alongside `COMMIT_SHA`.
191190
mode it executes `INSTALL_CMD` / `RUN_CMD` via `bash -c`. Nothing else
192191
from the config reaches a shell.
193192

193+
### Persistent volume and reboot behavior
194+
195+
`WORK_DIR` should normally live on a persistent Docker volume, for example
196+
`/var/lib/git-launcher/<workload>`. On first boot, `git-launcher` creates the
197+
directory and clones `REPO_URL` there. On reboot or container restart, the same
198+
directory is reused only if it is already a git checkout whose `origin` exactly
199+
matches `REPO_URL`.
200+
201+
Every boot still runs the same verification path: fetch from `origin`, detach
202+
checkout to `COMMIT_SHA`, then assert `git rev-parse HEAD == COMMIT_SHA`.
203+
Persistent state is therefore only a cache. It does not decide what runs. If
204+
the volume is empty, the launcher reclones. If the volume is non-empty but not a
205+
git checkout, or if it points at a different origin, startup fails.
206+
194207
## Example
195208

196209
See [`examples/web-app.conf`](./examples/web-app.conf). Adapt `REPO_URL`,
197210
`COMMIT_SHA`, and (if you need it) `REPO_SUBDIR` for your workload, and
198211
make sure the workload repo has a `entrypoint.sh` at the pinned commit.
199212

200213
```sh
201-
./bin/trusted-workload-launcher ./examples/web-app.conf
214+
./bin/git-launcher ./examples/web-app.conf
202215
```
203216

204217
The launcher logs the resolved repo, commit, workdir, and selected mode at
@@ -235,11 +248,11 @@ reflected in the dstack attestation.
235248
```yaml
236249
services:
237250
workload:
238-
image: docker.io/<org>/trusted-workload-launcher@sha256:<launcher-digest>
239-
command: ["/etc/trusted-workload-launcher/config.conf"]
251+
image: docker.io/<org>/git-launcher@sha256:<launcher-digest>
252+
command: ["/etc/git-launcher/config.conf"]
240253
volumes:
241-
- ./web-app.conf:/etc/trusted-workload-launcher/config.conf:ro
242-
- workload-checkout:/var/lib/trusted-workload-launcher
254+
- ./web-app.conf:/etc/git-launcher/config.conf:ro
255+
- workload-checkout:/var/lib/git-launcher
243256
- /var/run/dstack.sock:/var/run/dstack.sock
244257
restart: unless-stopped
245258

@@ -257,13 +270,13 @@ against the one they audited:
257270
```yaml
258271
services:
259272
workload:
260-
image: docker.io/<org>/trusted-workload-launcher@sha256:<launcher-digest>
261-
command: ["/etc/trusted-workload-launcher/config.conf"]
273+
image: docker.io/<org>/git-launcher@sha256:<launcher-digest>
274+
command: ["/etc/git-launcher/config.conf"]
262275
configs:
263276
- source: pin
264-
target: /etc/trusted-workload-launcher/config.conf
277+
target: /etc/git-launcher/config.conf
265278
volumes:
266-
- workload-checkout:/var/lib/trusted-workload-launcher
279+
- workload-checkout:/var/lib/git-launcher
267280
- /var/run/dstack.sock:/var/run/dstack.sock
268281
restart: unless-stopped
269282

@@ -272,7 +285,7 @@ configs:
272285
content: |
273286
REPO_URL=https://github.com/example-org/example-web-app.git
274287
COMMIT_SHA=<full-40-or-64-hex-sha>
275-
WORK_DIR=/var/lib/trusted-workload-launcher/example-web-app
288+
WORK_DIR=/var/lib/git-launcher/example-web-app
276289
277290
volumes:
278291
workload-checkout:
@@ -288,9 +301,9 @@ If you want a single digest to fully determine the workload, build a small
288301
downstream image that copies the config in:
289302

290303
```dockerfile
291-
FROM docker.io/<org>/trusted-workload-launcher@sha256:<launcher-digest>
292-
COPY web-app.conf /etc/trusted-workload-launcher/config.conf
293-
CMD ["/etc/trusted-workload-launcher/config.conf"]
304+
FROM docker.io/<org>/git-launcher@sha256:<launcher-digest>
305+
COPY web-app.conf /etc/git-launcher/config.conf
306+
CMD ["/etc/git-launcher/config.conf"]
294307
```
295308

296309
Deploy that derived image (pinned by its own `@sha256:…`). The derived
@@ -331,11 +344,11 @@ unprivileged in CI or on a developer laptop.
331344

332345
## Release image provenance
333346

334-
The release workflow (`.github/workflows/trusted-workload-launcher-release.yml`
347+
The release workflow (`.github/workflows/git-launcher-release.yml`
335348
in this repository's root `.github/`) follows the dstack-examples pattern:
336349

337350
1. run `./tests/run-tests.sh`;
338-
2. build and push `docker.io/${DOCKERHUB_ORG}/trusted-workload-launcher:<tag>`;
351+
2. build and push `docker.io/${DOCKERHUB_ORG}/git-launcher:<tag>`;
339352
3. call `actions/attest-build-provenance@v1` with the Docker build digest;
340353
4. write the digest and a Sigstore search link into both the GitHub Actions
341354
step summary and the GitHub release body.
@@ -349,7 +362,7 @@ compare that digest before trusting the launcher image.
349362
If you are reviewing this directory at commit `L` before signing off on a
350363
launcher image, the relevant audit surface is:
351364

352-
1. `bin/trusted-workload-launcher` — every line. Confirm:
365+
1. `bin/git-launcher` — every line. Confirm:
353366
* No `eval`, no `source`/`.`, no command substitution applied to config
354367
values during parsing.
355368
* `git checkout` always uses the verbatim `COMMIT_SHA` and the result is
Lines changed: 19 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
1-
# Verifying a trusted-workload-launcher deployment
1+
# Verifying a git-launcher deployment
22

33
How a relying party verifies that a dstack CVM is running
4-
`trusted-workload-launcher` and that the workload commit executed inside the
4+
`git-launcher` and that the workload commit executed inside the
55
TEE is the one they audited.
66

77
## Quick path (default mode, 4 steps)
@@ -170,7 +170,7 @@ command and assert equality:
170170
A one-shot reference-comparison script looks roughly like this:
171171

172172
```sh
173-
expected_image=docker.io/<org>/trusted-workload-launcher@sha256:<L>
173+
expected_image=docker.io/<org>/git-launcher@sha256:<L>
174174
expected_compose_hash=$(sha256sum < audited-app_compose.json | awk '{print $1}')
175175
expected_mrtd=<from dstack release notes>
176176
expected_rtmr0=<from dstack release notes>
@@ -197,7 +197,7 @@ into `rtmr3` if your verifier supports it.
197197

198198
### 3. Verify launcher image provenance via Sigstore
199199

200-
The `trusted-workload-launcher-release.yml` workflow publishes an
200+
The `git-launcher-release.yml` workflow publishes an
201201
`actions/attest-build-provenance` attestation bound to the pushed image
202202
digest. The attestation is not a claim of bit-for-bit reproducibility — it
203203
is a signed statement that *this* OCI digest was produced by *this*
@@ -207,7 +207,7 @@ the GitHub OIDC identity.
207207
```sh
208208
gh attestation verify \
209209
--owner Dstack-TEE \
210-
oci://docker.io/<org>/trusted-workload-launcher@sha256:<L>
210+
oci://docker.io/<org>/git-launcher@sha256:<L>
211211
```
212212

213213
or equivalently with `cosign verify-attestation` against
@@ -219,7 +219,7 @@ or equivalently with `cosign verify-attestation` against
219219

220220
That commit is the source of truth for the launcher's bytes. Treat the
221221
Sigstore attestation as the chain of custody from the
222-
`trusted-workload-launcher/` source at that commit to the deployed image
222+
`git-launcher/` source at that commit to the deployed image
223223
digest.
224224

225225
If you want to go further you can rebuild the image from that commit and
@@ -266,10 +266,10 @@ during config summary, then the checkout/verify lines, then the `exec`
266266
line, so they appear in this order):
267267

268268
```
269-
[trusted-workload-launcher] mode: default (workload repo entrypoint.sh)
270-
[trusted-workload-launcher] checking out <COMMIT_SHA>
271-
[trusted-workload-launcher] HEAD verified: <COMMIT_SHA>
272-
[trusted-workload-launcher] exec in <WORK_DIR>[/<REPO_SUBDIR>]: bash entrypoint.sh
269+
[git-launcher] mode: default (workload repo entrypoint.sh)
270+
[git-launcher] checking out <COMMIT_SHA>
271+
[git-launcher] HEAD verified: <COMMIT_SHA>
272+
[git-launcher] exec in <WORK_DIR>[/<REPO_SUBDIR>]: bash entrypoint.sh
273273
```
274274

275275
Advanced mode logs `mode: advanced (RUN_CMD)` early on, and the last
@@ -292,7 +292,7 @@ suite. The compose-hash binding it demonstrates is identical:
292292

293293
| Field | Value |
294294
| --- | --- |
295-
| Launcher image | `docker.io/h4x3rotab/trusted-workload-launcher-smoke@sha256:0d3f2dbda5e6ae9513ea4e8e69dcbc87c1f3af29744f0e36b9814685e5739866` |
295+
| Launcher image | `docker.io/h4x3rotab/git-launcher-smoke@sha256:0d3f2dbda5e6ae9513ea4e8e69dcbc87c1f3af29744f0e36b9814685e5739866` |
296296
| Compose pattern | inline `configs:` with `content:` block carrying the launcher config |
297297
| Workload repo | `https://github.com/octocat/Hello-World.git` |
298298
| Pinned commit | `7fd1a60b01f91b314f59955a4e4d4e80d8edf11d` |
@@ -310,16 +310,16 @@ get a different attestation.
310310
the expected launcher digest. `phala logs --cvm-id <id>` showed:
311311

312312
```
313-
[trusted-workload-launcher] checking out 7fd1a60b01f91b314f59955a4e4d4e80d8edf11d
314-
[trusted-workload-launcher] HEAD verified: 7fd1a60b01f91b314f59955a4e4d4e80d8edf11d
315-
[trusted-workload-launcher] exec in /var/lib/trusted-workload-launcher/hello: ...
316-
TWL_PINNED_HEAD=7fd1a60b01f91b314f59955a4e4d4e80d8edf11d
317-
TWL_README_BYTES=13
318-
TWL_READY
313+
[git-launcher] checking out 7fd1a60b01f91b314f59955a4e4d4e80d8edf11d
314+
[git-launcher] HEAD verified: 7fd1a60b01f91b314f59955a4e4d4e80d8edf11d
315+
[git-launcher] exec in /var/lib/git-launcher/hello: ...
316+
GIT_LAUNCHER_PINNED_HEAD=7fd1a60b01f91b314f59955a4e4d4e80d8edf11d
317+
GIT_LAUNCHER_README_BYTES=13
318+
GIT_LAUNCHER_READY
319319
```
320320

321-
`TWL_PINNED_HEAD` is from `git rev-parse HEAD` evaluated *inside the TEE
322-
container* by the workload's `RUN_CMD`, so it is independent
321+
`GIT_LAUNCHER_PINNED_HEAD` is from `git rev-parse HEAD` evaluated *inside
322+
the TEE container* by the workload's `RUN_CMD`, so it is independent
323323
corroboration that the bytes running are the pinned commit.
324324

325325
## Limitations

trusted-workload-launcher/bin/trusted-workload-launcher renamed to git-launcher/bin/git-launcher

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
#!/usr/bin/env bash
2-
# trusted-workload-launcher: minimal launcher for a workload pinned at a
2+
# git-launcher: minimal launcher for a workload pinned at a
33
# specific upstream Git commit.
44
#
55
# Reads one env-file config, clones the configured repo, hard-pins to the

trusted-workload-launcher/docker/Dockerfile renamed to git-launcher/docker/Dockerfile

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ RUN apt-get update \
1313
openssh-client \
1414
&& rm -rf /var/lib/apt/lists/*
1515

16-
COPY bin/trusted-workload-launcher /usr/local/bin/trusted-workload-launcher
17-
RUN chmod 0755 /usr/local/bin/trusted-workload-launcher
16+
COPY bin/git-launcher /usr/local/bin/git-launcher
17+
RUN chmod 0755 /usr/local/bin/git-launcher
1818

19-
ENTRYPOINT ["trusted-workload-launcher"]
19+
ENTRYPOINT ["git-launcher"]

trusted-workload-launcher/examples/web-app.conf renamed to git-launcher/examples/web-app.conf

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@
2626

2727
REPO_URL=https://github.com/example-org/example-web-app.git
2828
COMMIT_SHA=0000000000000000000000000000000000000000
29-
WORK_DIR=/var/lib/trusted-workload-launcher/example-web-app
29+
WORK_DIR=/var/lib/git-launcher/example-web-app
3030

3131
# Optional: cd into a subdirectory of the upstream repo before exec'ing
3232
# entrypoint.sh. Useful if the workload lives in a monorepo subpath.
@@ -41,7 +41,7 @@ WORK_DIR=/var/lib/trusted-workload-launcher/example-web-app
4141
# environment of entrypoint.sh. Use this for runtime configuration (listen
4242
# address, secrets, etc.) — keeping it separate from the pin config means
4343
# config-only edits do not perturb the trust-bearing fields above.
44-
# CHILD_ENV_FILE=/etc/trusted-workload-launcher/web-app.env
44+
# CHILD_ENV_FILE=/etc/git-launcher/web-app.env
4545

4646
# Advanced mode (use only if the workload repo cannot host its own
4747
# entrypoint.sh — e.g. you are pinning a third-party repo unchanged):

0 commit comments

Comments
 (0)