Skip to content

Commit 6f9b8e0

Browse files
committed
feat(key-provider): single-container image with systemd lifecycle management
Consolidate aesmd and gramine-sealing-key-provider into a single container to eliminate cross-container startup ordering issues that caused cascading failures after power outage reboots. Move config to /etc so it no longer depends on external disk mounts.
1 parent f87c977 commit 6f9b8e0

4 files changed

Lines changed: 175 additions & 0 deletions

File tree

Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
# SPDX-FileCopyrightText: © 2025 Phala Network <dstack@phala.network>
2+
#
3+
# SPDX-License-Identifier: Apache-2.0
4+
5+
name: Key Provider Release
6+
7+
on:
8+
workflow_dispatch:
9+
push:
10+
tags:
11+
- 'key-provider-v*'
12+
13+
permissions:
14+
attestations: write
15+
id-token: write
16+
contents: write
17+
packages: write
18+
19+
jobs:
20+
build-and-push:
21+
runs-on: ubuntu-latest
22+
steps:
23+
- name: Checkout repository
24+
uses: actions/checkout@v4
25+
26+
- name: Parse version from tag
27+
run: |
28+
VERSION=${GITHUB_REF#refs/tags/key-provider-v}
29+
echo "VERSION=$VERSION" >> $GITHUB_ENV
30+
echo "Parsed version: $VERSION"
31+
32+
- name: Log in to GHCR
33+
uses: docker/login-action@v3
34+
with:
35+
registry: ghcr.io
36+
username: ${{ github.actor }}
37+
password: ${{ secrets.GITHUB_TOKEN }}
38+
39+
- name: Set up Docker Buildx
40+
uses: docker/setup-buildx-action@v3
41+
42+
- name: Build and push Docker image
43+
id: build-and-push
44+
uses: docker/build-push-action@v5
45+
with:
46+
context: key-provider-build
47+
push: true
48+
tags: |
49+
ghcr.io/${{ github.repository }}/gramine-sealing-key-provider:${{ env.VERSION }}
50+
ghcr.io/${{ github.repository }}/gramine-sealing-key-provider:latest
51+
platforms: linux/amd64
52+
provenance: false
53+
54+
- name: Generate artifact attestation
55+
uses: actions/attest-build-provenance@v1
56+
with:
57+
subject-name: "ghcr.io/${{ github.repository }}/gramine-sealing-key-provider"
58+
subject-digest: ${{ steps.build-and-push.outputs.digest }}
59+
push-to-registry: true

key-provider-build/Dockerfile

Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
# SPDX-FileCopyrightText: © 2024-2025 Phala Network <dstack@phala.network>
2+
#
3+
# SPDX-License-Identifier: Apache-2.0
4+
5+
# Stage 1: Build
6+
FROM gramineproject/gramine:1.9-jammy@sha256:84b3d222e0bd9ab941f0078a462af0dbc5518156b99b147c10a7b83722ac0c38 AS builder
7+
8+
RUN apt-get update && apt-get install -y \
9+
git \
10+
build-essential \
11+
&& rm -rf /var/lib/apt/lists/*
12+
13+
RUN curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh -s -- --default-toolchain 1.85 -y
14+
ENV PATH="/root/.cargo/bin:${PATH}"
15+
16+
ENV SGX=1 DEBUG=0 DEV_MODE=0 RUST_LOG=info
17+
18+
RUN git clone https://github.com/MoeMahhouk/gramine-sealing-key-provider && \
19+
cd gramine-sealing-key-provider && \
20+
git checkout 180ff4691dce5aae7cd7d6c1344c3e1ec872f174
21+
22+
WORKDIR /gramine-sealing-key-provider
23+
COPY Cargo.lock .
24+
25+
RUN make target/release/gramine-sealing-key-provider && \
26+
gramine-sgx-gen-private-key && \
27+
make RUST_LOG=info
28+
29+
# Stage 2: Runtime
30+
# Same base image = same /lib/x86_64-linux-gnu/ (except libgcc-s1 from build-essential)
31+
FROM gramineproject/gramine:1.9-jammy@sha256:84b3d222e0bd9ab941f0078a462af0dbc5518156b99b147c10a7b83722ac0c38
32+
33+
# libgcc-s1: only /lib/x86_64-linux-gnu/ addition from build-essential, needed for manifest hash match
34+
# libsgx-dcap-default-qpl: not in base image, needed by aesmd for DCAP
35+
RUN curl -fsSL https://download.01.org/intel-sgx/sgx_repo/ubuntu/intel-sgx-deb.key \
36+
| gpg --dearmor -o /usr/share/keyrings/intel-sgx-deb.gpg && \
37+
echo 'deb [arch=amd64 signed-by=/usr/share/keyrings/intel-sgx-deb.gpg] https://download.01.org/intel-sgx/sgx_repo/ubuntu jammy main' \
38+
> /etc/apt/sources.list.d/intel-sgx.list && \
39+
apt-get update && apt-get install -y \
40+
libgcc-s1 \
41+
libsgx-dcap-default-qpl \
42+
&& rm -rf /var/lib/apt/lists/*
43+
44+
COPY --from=builder /gramine-sealing-key-provider/target/release/gramine-sealing-key-provider /gramine-sealing-key-provider/target/release/gramine-sealing-key-provider
45+
COPY --from=builder /gramine-sealing-key-provider/gramine-sealing-key-provider.manifest.sgx /gramine-sealing-key-provider/
46+
COPY --from=builder /gramine-sealing-key-provider/gramine-sealing-key-provider.sig /gramine-sealing-key-provider/
47+
48+
WORKDIR /gramine-sealing-key-provider
49+
50+
COPY entrypoint.sh /entrypoint.sh
51+
RUN chmod +x /entrypoint.sh
52+
53+
EXPOSE 3443
54+
55+
ENTRYPOINT ["/entrypoint.sh"]
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
[Unit]
2+
Description=Gramine Sealing Key Provider
3+
After=docker.service
4+
Requires=docker.service
5+
6+
[Service]
7+
Type=simple
8+
ExecStartPre=-/usr/bin/docker rm -f gramine-sealing-key-provider
9+
ExecStart=/usr/bin/docker run --rm \
10+
--name gramine-sealing-key-provider \
11+
--privileged \
12+
--device /dev/sgx_enclave:/dev/sgx_enclave \
13+
--device /dev/sgx_provision:/dev/sgx_provision \
14+
-v /etc/dstack-key-provider/sgx_default_qcnl.conf:/etc/sgx_default_qcnl.conf \
15+
-p 127.0.0.1:3443:3443 \
16+
ghcr.io/dstack-tee/dstack/gramine-sealing-key-provider:latest
17+
ExecStop=/usr/bin/docker stop gramine-sealing-key-provider
18+
Restart=on-failure
19+
RestartSec=5
20+
21+
[Install]
22+
WantedBy=multi-user.target

key-provider-build/entrypoint.sh

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
#!/bin/sh
2+
3+
# SPDX-FileCopyrightText: © 2025 Phala Network <dstack@phala.network>
4+
#
5+
# SPDX-License-Identifier: Apache-2.0
6+
7+
set -e
8+
9+
# Start AESM service in background
10+
echo "Starting AESM service..."
11+
mkdir -p /var/run/aesmd
12+
chmod 755 /var/run/aesmd
13+
export AESM_PATH=/opt/intel/sgx-aesm-service/aesm
14+
export LD_LIBRARY_PATH=/opt/intel/sgx-aesm-service/aesm
15+
/opt/intel/sgx-aesm-service/aesm/aesm_service --no-daemon &
16+
AESM_PID=$!
17+
18+
# Clean up aesmd on exit
19+
trap "kill $AESM_PID 2>/dev/null; exit" INT TERM EXIT
20+
21+
# Wait for AESM socket
22+
echo "Waiting for AESM socket..."
23+
AESM_SOCKET="/var/run/aesmd/aesm.socket"
24+
while [ ! -S "$AESM_SOCKET" ]; do
25+
if ! kill -0 "$AESM_PID" 2>/dev/null; then
26+
echo "Error: AESM service exited unexpectedly"
27+
exit 1
28+
fi
29+
sleep 1
30+
done
31+
echo "AESM socket is available."
32+
33+
# Show enclave info
34+
echo "Enclave info:"
35+
gramine-sgx-sigstruct-view --output-format json gramine-sealing-key-provider.sig
36+
37+
# Replace shell with gramine-sgx so it receives signals directly as PID 1
38+
echo "Starting Gramine Sealing Key Provider"
39+
exec gramine-sgx gramine-sealing-key-provider

0 commit comments

Comments
 (0)