Skip to content

feat(deploy): distroless runtime and private key via env var - #42

Merged
amintalebi merged 1 commit into
mainfrom
distroless-env-key
Jun 14, 2026
Merged

amintalebi merged 1 commit into
mainfrom
distroless-env-key

Conversation

@amintalebi

Copy link
Copy Markdown
Contributor
  • Use gcr.io/distroless/cc-debian12:debug-nonroot to skip apt and restore the built-in HEALTHCHECK via busybox wget.
  • Read ERC4337_BUNDLER_PRIVATE_KEY directly from the environment, like the RPC URL, removing the /run/secrets/bundler_private_key file mount.
  • Update docker-compose.yml, docs/DEPLOYMENT.md and .env.example accordingly.
  • Remove obsolete secrets/ example file.

@coderabbitai

coderabbitai Bot commented Jun 14, 2026 •

Copy link
Copy Markdown

Review Change Stack

Caution

Review failed

Pull request was closed or merged during review

📝 Walkthrough

Summary by CodeRabbit

  • Configuration

    • Bundler private key is now provided via ERC4337_BUNDLER_PRIVATE_KEY (supports optional 0x prefix) instead of a file/secret mount.
  • Infrastructure & Deployment

    • Migrated to a distroless, non-root runtime image for a smaller, more secure container.
    • Updated Docker and Docker Compose settings to align with the environment-variable approach.
    • Health checks now use the container’s built-in healthcheck command rather than probing the /live endpoint.
    • Updated deployment documentation and local setup steps accordingly.

Walkthrough

The PR transitions the bundler runtime to a distroless cc-debian12:nonroot image, implements an internal healthcheck subcommand to replace shell-based probes, switches private key delivery from Docker file-mounted secrets to the ERC4337_BUNDLER_PRIVATE_KEY environment variable, and updates .env.example, Dockerfile, docker-compose.yml, and deployment documentation accordingly.

Changes

Distroless Image Migration and Env-Var Key Delivery

Layer / File(s) Summary
Internal healthcheck subcommand
cmd/healthcheck.go
New subcommand performs HTTP GET to liveness endpoint (default http://127.0.0.1:4337/live), exits 0 on 200 OK, exits 1 on error or non-200 status. Registered with rootCmd during init().
Distroless image migration and healthcheck wiring
Dockerfile
Build stage creates and chowns /data to uid/gid 65532. Runtime switches base image from debian:bookworm-slim to gcr.io/distroless/cc-debian12:nonroot, copies binary and /data with --chown=65532:65532, sets USER nonroot:nonroot. HEALTHCHECK invokes the bundler's internal healthcheck subcommand.
ERC4337_BUNDLER_PRIVATE_KEY environment variable setup
.env.example, docker-compose.yml
.env.example adds ERC4337_BUNDLER_PRIVATE_KEY placeholder with 0x-prefix guidance and removes Docker secrets comment. docker-compose.yml comment and environment section now require ERC4337_BUNDLER_PRIVATE_KEY as an env var instead of file-mount. secrets/bundler_private_key.txt.example placeholder is cleared.
Docker Compose configuration updates
docker-compose.yml
Service healthcheck updated to invoke /app/qubenode-bundler healthcheck subcommand. Custom entrypoint that validated and transformed the private key from a mounted file is removed.
Deployment documentation
docs/DEPLOYMENT.md
"How the key is wired" and Dokploy Steps sections rewritten for env-var delivery; File Mount workflow removed. Local testing updated to copy .env.example to .env and set required variables. New "Notes on the runtime image" section documents distroless image, healthcheck probe, and nonroot UID 65532.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Possibly related PRs

  • qubenodeorg/bundler#40: Directly modifies the same docker-compose.yml and Dockerfile healthcheck and ERC4337_BUNDLER_PRIVATE_KEY wiring.
  • qubenodeorg/bundler#41: Modifies docker-compose.yml and docs/DEPLOYMENT.md for the same /run/secrets/bundler_private_key file-mount vs. env-var key ingestion pattern.

Poem

🐰 No more shell scripts in the deploy,
A healthcheck subcommand leads the way.
Distroless and lean, the bundler runs tight,
Env vars carry secrets—no files in sight.
Nonroot hops safely through the night,
The bunny's config: clean, secure, and bright! 🎉

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The title directly summarizes the main changes: switching to a distroless Docker runtime and moving private key handling from file-based secrets to environment variables.
Description check ✅ Passed The description clearly relates to the changeset, detailing the specific modifications to Docker runtime, private key configuration, and documentation updates that align with the file changes.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch distroless-env-key

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

@gemini-code-assist gemini-code-assist Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Code Review

This pull request transitions the bundler deployment from using Docker secrets/file mounts for the private key to using a plaintext environment variable (ERC4337_BUNDLER_PRIVATE_KEY). It also migrates the runtime container to a distroless base image (gcr.io/distroless/cc-debian12:debug-nonroot) and updates the healthcheck to use busybox's wget. Feedback highlights two key security and architectural concerns: first, exposing the private key in environment variables introduces a security regression, and it is recommended to support reading the key from a file path instead; second, using the debug variant of the distroless image in production increases the attack surface, and implementing a native healthcheck subcommand in the Go binary would allow using the standard, more secure nonroot image.

Important

The consumer version of Gemini Code Assist on GitHub is being sunset. Starting June 18, 2026, new organization installations will be blocked, and all code review activity will officially cease on July 17, 2026.
For more details on the timeline and next steps, please review the Help Documentation.

Comment thread docker-compose.yml Resolved
Comment thread Dockerfile Resolved

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 2

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@docker-compose.yml`:
- Around line 24-27: The ERC4337_BUNDLER_PRIVATE_KEY is currently sourced only
from an environment variable, which increases security exposure in production.
Modify the docker-compose.yml configuration to support file-backed secrets for
the bundler private key. Add a volume mount for a secrets file path and update
the ERC4337_BUNDLER_PRIVATE_KEY setting to read from the mounted secret file in
production while maintaining the environment variable fallback for local
development convenience. This ensures the private key can be managed as a
file-mounted secret in production deployments while keeping developer experience
intact for local setups.

In `@docs/DEPLOYMENT.md`:
- Around line 23-26: The fenced code block in the "Set required config" section
is missing a language identifier on the opening fence, which violates the
markdownlint MD040 rule. Add a language tag (such as env or sh) to the opening
triple backticks (```) to specify the code block type. This will help with
syntax highlighting and satisfy the linter requirement.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro Plus

Run ID: 96cc69cf-98d6-4b7a-90e0-f2fb8871c1c3

📥 Commits

Reviewing files that changed from the base of the PR and between 2dabd0c and 4b3e204.

📒 Files selected for processing (5)
  • .env.example
  • Dockerfile
  • docker-compose.yml
  • docs/DEPLOYMENT.md
  • secrets/bundler_private_key.txt.example
💤 Files with no reviewable changes (1)
  • secrets/bundler_private_key.txt.example

Comment thread docker-compose.yml Resolved
Comment thread docs/DEPLOYMENT.md Resolved
- Use gcr.io/distroless/cc-debian12:debug-nonroot to skip apt and restore
  the built-in HEALTHCHECK via busybox wget.
- Read ERC4337_BUNDLER_PRIVATE_KEY directly from the environment, like the
  RPC URL, removing the /run/secrets/bundler_private_key file mount.
- Update docker-compose.yml, docs/DEPLOYMENT.md and .env.example accordingly.
- Remove obsolete secrets/ example file.
@amintalebi
amintalebi force-pushed the distroless-env-key branch from 4b3e204 to efa6c24 Compare June 14, 2026 11:05
@amintalebi
amintalebi merged commit 900a11f into main Jun 14, 2026
7 of 8 checks passed
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.

1 participant