Skip to content

Conversation

@AnthonyRonning
Copy link
Contributor

@AnthonyRonning AnthonyRonning commented Jan 5, 2026

Summary

Switches from extracting pre-built binaries from Docker containers to building continuum-proxy from source using Nix.

Problem

Starting with v1.31.0, the privatemode-proxy Docker images ship dynamically linked binaries that depend on specific Nix store paths (e.g., /nix/store/yi5zymrhcqm4f0qdsl28v4jc4hnv64vr-glibc-aarch64-unknown-linux-gnu-2.40-66). This breaks standalone usage outside their container environment.

Previous versions (v1.28.0, v1.30.0) were statically linked and worked fine.

Solution

  • Add privatemode-public as a git submodule (MIT licensed for the proxy component)
  • Build from source using nix build which produces statically linked binaries
  • Update to v1.32.0

New Commands

just build-continuum-proxy              # Build from current submodule version
just update-continuum-proxy v1.33.0     # Update version and rebuild
just update-continuum-proxy-version v1.33.0  # Just update submodule version

Testing

  • Binary builds successfully (statically linked)
  • ./continuum-proxy --version works
  • PCR values updated for dev and prod

Summary by CodeRabbit

  • Chores
    • Switched Continuum Proxy update flow to versioned source builds for more reliable, reproducible releases.
    • Added targets to support checking out specific proxy versions and building the proxy from source.
    • Updated submodule configuration to point to the public privatemode repository.
    • Appended new security attestation (PCR) records to dev and prod histories.

✏️ Tip: You can customize this high-level summary in your review settings.

@coderabbitai
Copy link

coderabbitai bot commented Jan 5, 2026

Walkthrough

Adds a Git submodule entry for privatemode-public, replaces the container-based continuum-proxy update with a git-tagged, source-based Nix build workflow (new justfile targets), and appends new PCR snapshot entries to both pcrDevHistory.json and pcrProdHistory.json.

Changes

Cohort / File(s) Summary
Submodule Configuration
\.gitmodules`, `privatemode-public``
Adds privatemode-public submodule entry and updates submodule pointer (new submodule URL: https://github.com/edgelesssys/privatemode-public.git).
Build Workflow
\justfile``
Removes old container-based update-continuum-proxy target; adds update-continuum-proxy-version (checks out requested tag), build-continuum-proxy (Nix build, produce continuum-proxy binary), and a versioned update-continuum-proxy wrapper (e.g., v1.32.0).
PCR History Records
\pcrDevHistory.json`, `pcrProdHistory.json``
Appends a new PCR history object (PCR0, PCR1, PCR2, timestamp, signature) to each JSON history array.

Sequence Diagram(s)

sequenceDiagram
    autonumber
    actor Developer
    participant Just as "Justfile"
    participant Git as "Git (privatemode-public)"
    participant Nix as "Nix Build"
    participant FS as "Filesystem"

    rect rgb(235,245,255)
    Note over Developer,FS: Continuum-proxy versioned source build flow
    end

    Developer->>Just: update-continuum-proxy version="v1.32.0"
    Just->>Git: fetch tags & checkout v1.32.0
    Git-->>Just: source at tag
    Just->>Nix: build-continuum-proxy (Nix)
    Nix->>Nix: compile from source
    Nix->>FS: emit binary artifact
    Just->>FS: rename -> continuum-proxy, chmod +x
    Just-->>Developer: print version & finish
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Possibly related PRs

Poem

🐰 A rabbit hops to build and fetch,
Tags and Nix beneath my stretch,
Submodule sewn and histories grown,
Binary baked, the garden's sown.
thump 🎉

Pre-merge checks and finishing touches

✅ Passed checks (3 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately describes the main change: switching continuum-proxy from container-based binary extraction to a Nix-based static build from source.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
✨ Finishing touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch fix/continuum-proxy-static-build

Warning

There were issues while running some tools. Please review the errors and either fix the tool's configuration or disable the tool if it's a critical failure.

🔧 Gitleaks (8.30.0)
.gitmodules

panic: allocator_unix: failed to reserve memory: cannot allocate memory

goroutine 1 [running]:
github.com/wasilibs/wazero-helpers/allocator.alloc(0x1911020?, 0x100000000)
/Users/zrice/Go/pkg/mod/github.com/wasilibs/wazero-helpers@v0.0.0-20240620070341-3dff1577cd52/allocator/nonmoving_unix.go:33 +0x10e
github.com/tetratelabs/wazero/experimental.MemoryAllocatorFunc.Allocate(0xa84539?, 0xd4ac60?, 0x47d43a?)
/Users/zrice/Go/pkg/mod/github.com/tetratelabs/wazero@v1.9.0/experimental/memory.go:28 +0x1c
github.com/tetratelabs/wazero/internal/wasm.NewMemoryInstance(0xc000013da0, {0x7f04761e7a00?, 0xe87630?}, {0xf90c48, 0xc000035680})
/Users/zrice/Go/pkg/mod/github.com/tetratelabs/wazero@v1.9.0/internal/wasm/memory.go:78 +0xab
github.com/tetratelabs/wazero/internal/wasm.(*ModuleInstance).buildMemory(0xc0000f8f00, 0xc0001e71e0, {0x7f04761e7a00?, 0xe87630?})
/Users/zrice/Go/pkg/mod/github.com/tetratelabs/wazero@v1.9.0/internal/wasm/module.go:653 +0x4c
github.com/tetratelabs/wazero/internal/wa

... [truncated 302 characters] ...

2a0, {0xf8a300, 0xc000224a80}, 0x0?, {0xe18d1d?, 0x0?}, 0x0?, {0x1932260, 0x0, 0x0})
/Users/zrice/Go/pkg/mod/github.com/tetratelabs/wazero@v1.9.0/internal/wasm/store.go:327 +0x5a
github.com/tetratelabs/wazero.(*runtime).InstantiateModule(0xc0002258c0, {0xf8a300, 0xc000224a80}, {0xf8e7e0, 0xc000256740}, {0xf92da0, 0xc00026e1e0})
/Users/zrice/Go/pkg/mod/github.com/tetratelabs/wazero@v1.9.0/runtime.go:337 +0x1e5
github.com/tetratelabs/wazero.(*runtime).InstantiateWithConfig(0xc0002258c0, {0xf8a300, 0xc000224a80}, {0x1528cd0?, 0xd45020?, 0xe87630?}, {0xf92da0, 0xc00026e1e0})
/Users/zrice/Go/pkg/mod/github.com/tetratelabs/wazero@v1.9.0/runtime.go:302 +0x74
github.com/wasilibs/go-re2/internal.init.0()
/Users/zrice/Go/pkg/mod/github.com/wasilibs/go-re2@v1.9.0/internal/re2_wazero.go:184 +0x39c

justfile

panic: allocator_unix: failed to reserve memory: cannot allocate memory

goroutine 1 [running]:
github.com/wasilibs/wazero-helpers/allocator.alloc(0x1911020?, 0x100000000)
/Users/zrice/Go/pkg/mod/github.com/wasilibs/wazero-helpers@v0.0.0-20240620070341-3dff1577cd52/allocator/nonmoving_unix.go:33 +0x10e
github.com/tetratelabs/wazero/experimental.MemoryAllocatorFunc.Allocate(0xa84539?, 0xd4ac60?, 0x47d43a?)
/Users/zrice/Go/pkg/mod/github.com/tetratelabs/wazero@v1.9.0/experimental/memory.go:28 +0x1c
github.com/tetratelabs/wazero/internal/wasm.NewMemoryInstance(0xc000013d70, {0x7f3aca4c0a00?, 0xe87630?}, {0xf90c48, 0xc000035680})
/Users/zrice/Go/pkg/mod/github.com/tetratelabs/wazero@v1.9.0/internal/wasm/memory.go:78 +0xab
github.com/tetratelabs/wazero/internal/wasm.(*ModuleInstance).buildMemory(0xc0000f8f00, 0xc0001e71e0, {0x7f3aca4c0a00?, 0xe87630?})
/Users/zrice/Go/pkg/mod/github.com/tetratelabs/wazero@v1.9.0/internal/wasm/module.go:653 +0x4c
github.com/tetratelabs/wazero/internal/wa

... [truncated 302 characters] ...

2a0, {0xf8a300, 0xc000222a80}, 0x0?, {0xe18d1d?, 0x0?}, 0x0?, {0x1932260, 0x0, 0x0})
/Users/zrice/Go/pkg/mod/github.com/tetratelabs/wazero@v1.9.0/internal/wasm/store.go:327 +0x5a
github.com/tetratelabs/wazero.(*runtime).InstantiateModule(0xc0002238c0, {0xf8a300, 0xc000222a80}, {0xf8e7e0, 0xc000256740}, {0xf92da0, 0xc00026e1e0})
/Users/zrice/Go/pkg/mod/github.com/tetratelabs/wazero@v1.9.0/runtime.go:337 +0x1e5
github.com/tetratelabs/wazero.(*runtime).InstantiateWithConfig(0xc0002238c0, {0xf8a300, 0xc000222a80}, {0x1528cd0?, 0xd45020?, 0xe87630?}, {0xf92da0, 0xc00026e1e0})
/Users/zrice/Go/pkg/mod/github.com/tetratelabs/wazero@v1.9.0/runtime.go:302 +0x74
github.com/wasilibs/go-re2/internal.init.0()
/Users/zrice/Go/pkg/mod/github.com/wasilibs/go-re2@v1.9.0/internal/re2_wazero.go:184 +0x39c

pcrDevHistory.json

panic: allocator_unix: failed to reserve memory: cannot allocate memory

goroutine 1 [running]:
github.com/wasilibs/wazero-helpers/allocator.alloc(0x1911020?, 0x100000000)
/Users/zrice/Go/pkg/mod/github.com/wasilibs/wazero-helpers@v0.0.0-20240620070341-3dff1577cd52/allocator/nonmoving_unix.go:33 +0x10e
github.com/tetratelabs/wazero/experimental.MemoryAllocatorFunc.Allocate(0xa84539?, 0xd4ac60?, 0x47d43a?)
/Users/zrice/Go/pkg/mod/github.com/tetratelabs/wazero@v1.9.0/experimental/memory.go:28 +0x1c
github.com/tetratelabs/wazero/internal/wasm.NewMemoryInstance(0xc000013c00, {0x7fa362afbc00?, 0xe87630?}, {0xf90c48, 0xc000035680})
/Users/zrice/Go/pkg/mod/github.com/tetratelabs/wazero@v1.9.0/internal/wasm/memory.go:78 +0xab
github.com/tetratelabs/wazero/internal/wasm.(*ModuleInstance).buildMemory(0xc0000f8f00, 0xc0001671e0, {0x7fa362afbc00?, 0xe87630?})
/Users/zrice/Go/pkg/mod/github.com/tetratelabs/wazero@v1.9.0/internal/wasm/module.go:653 +0x4c
github.com/tetratelabs/wazero/internal/wa

... [truncated 302 characters] ...

2a0, {0xf8a300, 0xc0001a2a80}, 0x0?, {0xe18d1d?, 0x0?}, 0x0?, {0x1932260, 0x0, 0x0})
/Users/zrice/Go/pkg/mod/github.com/tetratelabs/wazero@v1.9.0/internal/wasm/store.go:327 +0x5a
github.com/tetratelabs/wazero.(*runtime).InstantiateModule(0xc0001a38c0, {0xf8a300, 0xc0001a2a80}, {0xf8e7e0, 0xc0001de740}, {0xf92da0, 0xc0001f61e0})
/Users/zrice/Go/pkg/mod/github.com/tetratelabs/wazero@v1.9.0/runtime.go:337 +0x1e5
github.com/tetratelabs/wazero.(*runtime).InstantiateWithConfig(0xc0001a38c0, {0xf8a300, 0xc0001a2a80}, {0x1528cd0?, 0xd45020?, 0xe87630?}, {0xf92da0, 0xc0001f61e0})
/Users/zrice/Go/pkg/mod/github.com/tetratelabs/wazero@v1.9.0/runtime.go:302 +0x74
github.com/wasilibs/go-re2/internal.init.0()
/Users/zrice/Go/pkg/mod/github.com/wasilibs/go-re2@v1.9.0/internal/re2_wazero.go:184 +0x39c

  • 2 others

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 0

🧹 Nitpick comments (2)
justfile (2)

184-186: Add submodule initialization check before git operations.

The recipe assumes the privatemode-public submodule is already initialized. If someone clones the repository without --recursive or forgets to run git submodule init && git submodule update, this will fail with a confusing error.

🔎 Suggested improvement with submodule initialization
 # Update continuum-proxy submodule to a specific version
 update-continuum-proxy-version version:
+    git submodule update --init privatemode-public
     cd privatemode-public && git fetch --tags && git checkout {{version}}

Alternatively, add a verification script to provide a clearer error message:

 # Update continuum-proxy submodule to a specific version
 update-continuum-proxy-version version:
+    #!/usr/bin/env bash
+    if [ ! -d "privatemode-public/.git" ]; then
+        echo "Initializing privatemode-public submodule..."
+        git submodule update --init privatemode-public
+    fi
     cd privatemode-public && git fetch --tags && git checkout {{version}}

188-197: Consider verifying static linking after build.

The build process looks solid, but since the PR motivation mentions that v1.31.0+ ships dynamically linked binaries, it would be valuable to verify that the built binary is indeed statically linked.

🔎 Optional: Add static linking verification
 # Build continuum-proxy from source using Nix (produces statically linked binary)
 build-continuum-proxy:
     nix build ./privatemode-public#privatemode-proxy.bin -o continuum-proxy-build
     chmod u+w continuum-proxy || true
     cp continuum-proxy-build/bin/privatemode-proxy continuum-proxy
     chmod +x continuum-proxy
     rm continuum-proxy-build
     @echo "Built continuum-proxy:"
     @file continuum-proxy
     @./continuum-proxy --version
+    @echo "Verifying static linking:"
+    @ldd continuum-proxy 2>&1 | grep -q "not a dynamic executable" && echo "✅ Binary is statically linked" || echo "⚠️  Warning: Binary may be dynamically linked"

This provides immediate feedback if the build produces a dynamically linked binary instead of the expected static binary.

📜 Review details

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between e23d768 and 26f2b43.

⛔ Files ignored due to path filters (2)
  • pcrDev.json is excluded by !pcrDev.json
  • pcrProd.json is excluded by !pcrProd.json
📒 Files selected for processing (6)
  • .gitmodules
  • continuum-proxy
  • justfile
  • pcrDevHistory.json
  • pcrProdHistory.json
  • privatemode-public
⏰ Context from checks skipped due to timeout of 100000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (2)
  • GitHub Check: Greptile Review
  • GitHub Check: Development Reproducible Build
🔇 Additional comments (5)
privatemode-public (1)

1-1: Submodule commit verified. The commit b4c884d9ed037ced2d6326b42e989335caef5bbb exists in the edgelesssys/privatemode-public repository and references mirrored public components. No further action needed.

.gitmodules (1)

4-6: LGTM! Submodule configuration is correct.

The submodule entry follows Git conventions and is consistent with the existing nitro-toolkit submodule structure.

pcrProdHistory.json (1)

477-484: LGTM! PCR history entry is well-formed.

The new entry follows the established schema with all required fields (PCR0, PCR1, PCR2, timestamp, signature) and maintains consistency with existing entries.

pcrDevHistory.json (1)

477-484: LGTM! PCR history entry is well-formed.

The new entry maintains the established schema with all required fields and is properly appended to the history array.

justfile (1)

199-202: Good composition pattern with reasonable defaults.

The recipe cleanly combines version update and build steps. The default version (v1.32.0) provides a convenient starting point while still allowing customization.

@greptile-apps
Copy link

greptile-apps bot commented Jan 5, 2026

Greptile Summary

This PR transitions continuum-proxy from extracting pre-built Docker binaries to building from source using Nix, resolving dynamic linking issues introduced in v1.31.0.

Key Changes:

  • Added privatemode-public as a git submodule for building continuum-proxy from source
  • Replaced Docker-based extraction with Nix build commands producing statically-linked binaries
  • Updated from v1.28.0 to v1.32.0 (MIT-licensed proxy component)
  • Added three new justfile commands: build-continuum-proxy, update-continuum-proxy-version, and update-continuum-proxy
  • Updated PCR0 and PCR2 values for both dev and prod environments to reflect the new binary
  • Appended signed PCR history entries maintaining attestation integrity

Technical Implementation:
The new build process uses nix build ./privatemode-public#privatemode-proxy.bin which produces statically-linked binaries, eliminating dependency on Nix store paths that caused failures in v1.31.0's dynamically-linked binaries.

Confidence Score: 5/5

  • This PR is safe to merge with minimal risk - it solves a critical dependency issue with a well-structured approach
  • The changes are well-implemented with proper version control via submodules, reproducible Nix builds, and correctly updated PCR attestations. The approach solves the dynamic linking problem described in the PR, and all security measurements have been properly signed and appended to history files. The binary size increased slightly (~1.6KB) which is expected when switching build methods.
  • No files require special attention - all changes are correctly implemented

Important Files Changed

Filename Overview
.gitmodules Added privatemode-public submodule reference pointing to edgelesssys repository
justfile Replaced Docker-based binary extraction with Nix-based source build, added version management commands
continuum-proxy Updated binary from v1.28.0 to v1.32.0, built statically from source using Nix
pcrDev.json Updated PCR0 and PCR2 values reflecting new continuum-proxy binary in dev environment
pcrProd.json Updated PCR0 and PCR2 values reflecting new continuum-proxy binary in prod environment

Sequence Diagram

sequenceDiagram
    participant Dev as Developer
    participant Just as Justfile
    participant Sub as privatemode-public<br/>Submodule
    participant Nix as Nix Build System
    participant Bin as continuum-proxy<br/>Binary
    participant PCR as PCR Files

    Dev->>Just: just update-continuum-proxy v1.32.0
    Just->>Sub: Update submodule to version
    Sub->>Sub: git fetch --tags && git checkout v1.32.0
    Just->>Nix: nix build ./privatemode-public#privatemode-proxy.bin
    Nix->>Nix: Build from source (statically linked)
    Nix-->>Bin: Output binary to continuum-proxy-build
    Just->>Bin: Copy binary to continuum-proxy
    Just->>Bin: chmod +x continuum-proxy
    Just->>Bin: Verify with --version
    
    Note over Dev,PCR: PCR Update Process
    Dev->>Just: just update-pcr-all
    Just->>Nix: nix build .?submodules=1#eif-dev
    Nix-->>PCR: Generate PCR values
    Just->>PCR: Copy to pcrDev.json
    Just->>PCR: Sign PCR0 and append to pcrDevHistory.json
    Just->>Nix: nix build .?submodules=1#eif-prod
    Nix-->>PCR: Generate PCR values
    Just->>PCR: Copy to pcrProd.json
    Just->>PCR: Sign PCR0 and append to pcrProdHistory.json
Loading

AnthonyRonning and others added 2 commits January 6, 2026 11:11
- Add privatemode-public as git submodule for reproducible builds
- Replace Docker extraction with nix build (produces statically linked binary)
- Update to v1.32.0 built from source (MIT licensed)
- New justfile commands: build-continuum-proxy, update-continuum-proxy

The Docker container images from v1.31.0+ ship dynamically linked binaries
that depend on specific Nix store paths, breaking standalone usage.
Building from source with nix ensures static linking.

Co-authored-by: factory-droid[bot] <138933559+factory-droid[bot]@users.noreply.github.com>
@AnthonyRonning AnthonyRonning force-pushed the fix/continuum-proxy-static-build branch from 26f2b43 to cd1a0e2 Compare January 6, 2026 17:42
Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 0

🧹 Nitpick comments (2)
justfile (2)

184-186: Consider validating the submodule state and version parameter.

The command assumes the privatemode-public submodule is initialized and the version parameter is valid. If the submodule doesn't exist or the version tag is invalid, the git operations will fail with cryptic errors.

🔎 Suggested improvement with validation
 # Update continuum-proxy submodule to a specific version
 update-continuum-proxy-version version:
+    @test -d privatemode-public/.git || (echo "Error: privatemode-public submodule not initialized. Run: git submodule update --init" && exit 1)
     cd privatemode-public && git fetch --tags && git checkout {{version}}
+    @echo "Updated continuum-proxy submodule to {{version}}"

188-197: Ensure Nix build success is verified before proceeding.

The command performs several operations assuming the Nix build succeeded. If nix build fails, the subsequent cp command will fail with a less clear error message.

🔎 Optional improvement for clearer error handling
 # Build continuum-proxy from source using Nix (produces statically linked binary)
 build-continuum-proxy:
     nix build ./privatemode-public#privatemode-proxy.bin -o continuum-proxy-build
+    @test -f continuum-proxy-build/bin/privatemode-proxy || (echo "Error: Nix build failed to produce binary" && exit 1)
     chmod u+w continuum-proxy || true
     cp continuum-proxy-build/bin/privatemode-proxy continuum-proxy
     chmod +x continuum-proxy
     rm continuum-proxy-build
     @echo "Built continuum-proxy:"
     @file continuum-proxy
     @./continuum-proxy --version
📜 Review details

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 26f2b43 and cd1a0e2.

⛔ Files ignored due to path filters (2)
  • pcrDev.json is excluded by !pcrDev.json
  • pcrProd.json is excluded by !pcrProd.json
📒 Files selected for processing (6)
  • .gitmodules
  • continuum-proxy
  • justfile
  • pcrDevHistory.json
  • pcrProdHistory.json
  • privatemode-public
🚧 Files skipped from review as they are similar to previous changes (2)
  • pcrDevHistory.json
  • .gitmodules
⏰ Context from checks skipped due to timeout of 100000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
  • GitHub Check: Greptile Review
🔇 Additional comments (3)
privatemode-public (1)

1-1: Submodule commit verified as v1.32.0.

The commit hash b4c884d9ed037ced2d6326b42e989335caef5bbb correctly points to the v1.32.0 release tag for edgelesssys/privatemode-public.

pcrProdHistory.json (1)

485-490: LGTM! New PCR entry structure is consistent.

The new PCR history entry follows the established format with all required fields (PCR0, PCR1, PCR2, timestamp, signature) and matches the structure of existing entries.

justfile (1)

199-202: LGTM! Clean orchestration of version update and rebuild.

The command properly chains the version update and build steps. The default version v1.32.0 matches the PR objectives.

@AnthonyRonning AnthonyRonning merged commit abcc893 into master Jan 6, 2026
8 checks passed
@AnthonyRonning AnthonyRonning deleted the fix/continuum-proxy-static-build branch January 6, 2026 18:04
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants