Phase 9 splits into two independent Wave 1 plans: - 09-01: Custom Hermes Docker image (ngn-agent:latest) with aws-cli, terraform, helm, kubectl, and datadog CLI (pup), version-pinned - 09-02: Portable setup-ngn-agent.sh with argument parsing, prerequisite checks, interactive secret prompts, config generation, skill/script embedding, and cron registration Also marks Phase 8 as complete (cron reporting shipped 2026-06-15).
225 lines
11 KiB
Markdown
225 lines
11 KiB
Markdown
---
|
|
phase: 09-tooling-portable-setup
|
|
plan: 01
|
|
type: execute
|
|
wave: 1
|
|
depends_on: []
|
|
files_modified:
|
|
- ngn-agent/docker/Dockerfile
|
|
- ngn-agent/docker/build.sh
|
|
autonomous: true
|
|
requirements: [TOOL-01]
|
|
|
|
must_haves:
|
|
truths:
|
|
- "Custom Docker image can be built with a single command (docker/build.sh)"
|
|
- "Built image includes aws-cli v2, terraform, helm, kubectl, and datadog CLI (pup)"
|
|
- "Image is tagged ngn-agent:latest (local only, no registry push)"
|
|
- "Each tool version is pinned for reproducibility"
|
|
- "Build uses Dockerfile from the project repo (ngn-agent/docker/Dockerfile)"
|
|
artifacts:
|
|
- path: "ngn-agent/docker/Dockerfile"
|
|
provides: "Custom Hermes-compatible Docker image definition with 5 platform tools"
|
|
min_lines: 80
|
|
- path: "ngn-agent/docker/build.sh"
|
|
provides: "Single-command image build entry point"
|
|
min_lines: 15
|
|
key_links:
|
|
- from: "ngn-agent/docker/build.sh"
|
|
to: "ngn-agent/docker/Dockerfile"
|
|
via: "docker build -f"
|
|
pattern: "docker build.*-f.*Dockerfile"
|
|
- from: "Dockerfile"
|
|
to: "aws-cli v2"
|
|
via: "curl → unzip → aws/install"
|
|
pattern: "awscli\\.amazonaws\\.com/awscli-exe"
|
|
- from: "Dockerfile"
|
|
to: "terraform"
|
|
via: "HashiCorp apt repo"
|
|
pattern: "apt\\.releases\\.hashicorp\\.com"
|
|
- from: "Dockerfile"
|
|
to: "helm"
|
|
via: "Buildkite apt repo"
|
|
pattern: "packages\\.buildkite\\.com/helm"
|
|
- from: "Dockerfile"
|
|
to: "kubectl"
|
|
via: "Google Kubernetes apt repo"
|
|
pattern: "pkgs\\.k8s\\.io"
|
|
- from: "Dockerfile"
|
|
to: "pup (Datadog CLI)"
|
|
via: "GitHub releases binary download"
|
|
pattern: "github\\.com/DataDog/pup/releases"
|
|
---
|
|
|
|
<objective>
|
|
**Custom Hermes Docker Image with Platform Engineering Tools**
|
|
|
|
Create a custom Docker image extending `nikolaik/python-nodejs:python3.11-nodejs20` with five platform engineering CLI tools pre-installed: AWS CLI v2, Terraform, Helm, kubectl, and Datadog CLI (pup). The image is buildable with a single `docker/build.sh` command and tagged `ngn-agent:latest` for local use.
|
|
|
|
**Purpose:** Eliminate per-session tool installation overhead — tools are baked into the Docker image so every Hermes session has immediate access to aws-cli, terraform, helm, kubectl, and pup without runtime installs.
|
|
|
|
**Output:**
|
|
- `ngn-agent/docker/Dockerfile` — Version-pinned tool installations on top of the base Hermes image
|
|
- `ngn-agent/docker/build.sh` — Single-command build entry point
|
|
</objective>
|
|
|
|
<execution_context>
|
|
@/Users/bapung/.config/opencode/gsd-core/workflows/execute-plan.md
|
|
@/Users/bapung/.config/opencode/gsd-core/templates/summary.md
|
|
</execution_context>
|
|
|
|
<context>
|
|
@.planning/ROADMAP.md
|
|
@.planning/phases/09-tooling-portable-setup/09-CONTEXT.md
|
|
@.planning/phases/09-tooling-portable-setup/09-RESEARCH.md
|
|
</context>
|
|
|
|
<tasks>
|
|
|
|
<task type="auto">
|
|
<name>Task 1: Create Dockerfile with version-pinned tool installations</name>
|
|
<files>ngn-agent/docker/Dockerfile</files>
|
|
<action>
|
|
Create `ngn-agent/docker/Dockerfile` that:
|
|
|
|
1. **FROM** extends `nikolaik/python-nodejs:python3.11-nodejs20` (per D-01). Add a comment above FROM noting: "D-01: Base image tag python3.11-nodejs20 — verify availability at build time; if manifest not found, update to python3.11-nodejs22-bookworm (Node.js 20 EOL April 2026)."
|
|
|
|
2. **LABEL** with `description="ngn-agent: Custom Hermes Docker image with platform engineering tools"` and `maintainer="ngn-agent"`.
|
|
|
|
3. **ARGs for version pinning** (per D-02):
|
|
- `TERRAFORM_VERSION=1.15.6`
|
|
- `HELM_VERSION=4.2.1`
|
|
- `KUBECTL_VERSION=1.36.1`
|
|
- `PUPP_VERSION=1.1.0`
|
|
(AWS CLI v2 is the latest stable — per D-03, install without version pinning but pin to latest known at time of build.)
|
|
|
|
4. **Install system dependencies** in a single RUN:
|
|
`curl`, `ca-certificates`, `unzip`, `gnupg`, `wget` — clean apt lists after install.
|
|
|
|
5. **Install AWS CLI v2** (per D-03):
|
|
Use the official curl → unzip → `./aws/install` method (no apt repo for v2). Install to `/usr/local/bin` and `/usr/local/aws-cli`. Clean up zip and extracted files. Reference D-03 in a comment.
|
|
|
|
6. **Install Terraform** (per D-03):
|
|
Add HashiCorp GPG key, add HashiCorp apt repo, `apt-get install -y terraform=${TERRAFORM_VERSION}`. Clean apt lists. Reference D-03.
|
|
|
|
7. **Install kubectl** (per D-03):
|
|
Add Google Kubernetes GPG key, add kubernetes apt repo for v1.36, `apt-get install -y kubectl`. Do NOT version-pin kubectl (it must match the target cluster version — per D-03: "latest stable matching cluster version"). Clean apt lists. Reference D-03.
|
|
|
|
8. **Install Helm** (per D-03):
|
|
Add Buildkite GPG key, add Helm apt repo, `apt-get install -y helm=${HELM_VERSION}`. Clean apt lists. Reference D-03.
|
|
|
|
9. **Install Datadog CLI (pup)** (per D-03):
|
|
Download the Linux x86_64 tarball from GitHub Releases, extract `pup` binary to `/usr/local/bin/`, clean up. Reference D-03.
|
|
|
|
10. **Verify step**: Single RUN with `echo "=== Tool versions ===" && aws --version && terraform --version && helm version --short && kubectl version --client --output=yaml 2>/dev/null | grep gitVersion && pup --version`. Use `|| true` on version checks that may exit non-zero so build doesn't fail on a single tool being unreachable.
|
|
|
|
11. **CMD** `["bash"]` — matching base image behavior.
|
|
|
|
**Build hygiene:**
|
|
- Do NOT `COPY .` or any full-directory copy — this prevents leaking secrets into image layers (T-09-02 mitigation).
|
|
- Order tool installs from most-frequently-changed to least-changed to optimize layer caching.
|
|
- Use `--no-install-recommends` on all apt-get install commands.
|
|
- Remove apt lists after each apt install to keep image small.
|
|
- All tool downloads use HTTPS URLs (T-09-01 mitigation).
|
|
- Add inline comments referencing each D-NN decision for traceability.
|
|
</action>
|
|
<verify>
|
|
<automated>test -f /Users/bapung/Razer/ngn-agent/docker/Dockerfile && wc -l /Users/bapung/Razer/ngn-agent/docker/Dockerfile</automated>
|
|
</verify>
|
|
<done>
|
|
- Dockerfile exists at ngn-agent/docker/Dockerfile
|
|
- All 5 tools (aws-cli, terraform, helm, kubectl, pup) are installed via RUN commands
|
|
- Tool versions are pinned via ARGs (except kubectl which matches cluster version)
|
|
- D-01 through D-03 are referenced in comments
|
|
- No `COPY .` or directory-wide copy present
|
|
</done>
|
|
</task>
|
|
|
|
<task type="auto">
|
|
<name>Task 2: Create build.sh and verify image builds successfully</name>
|
|
<files>ngn-agent/docker/build.sh</files>
|
|
<action>
|
|
Create `ngn-agent/docker/build.sh` (per D-04):
|
|
|
|
1. Shebang: `#!/bin/bash` with `set -euo pipefail`.
|
|
|
|
2. Constants:
|
|
- `IMAGE_NAME="ngn-agent"`
|
|
- `IMAGE_TAG="latest"`
|
|
- `DOCKER_DIR` resolved from script location: `"$(cd "$(dirname "$0")" && pwd)"`
|
|
|
|
3. Print build banner: `echo "==> Building ${IMAGE_NAME}:${IMAGE_TAG}..."`
|
|
|
|
4. `docker build` command:
|
|
- `-t "${IMAGE_NAME}:${IMAGE_TAG}"`
|
|
- `-f "${DOCKER_DIR}/Dockerfile"`
|
|
- Build context: `"${DOCKER_DIR}"` (not the repo root — prevents leaking files)
|
|
- Per D-05: tag is `ngn-agent:latest` (local only, no registry push)
|
|
|
|
5. Print completion banner: `echo "==> Build complete: ${IMAGE_NAME}:${IMAGE_TAG}"` followed by `docker images "${IMAGE_NAME}:${IMAGE_TAG}"`.
|
|
|
|
6. Make the script executable: `chmod +x /Users/bapung/Razer/ngn-agent/docker/build.sh`.
|
|
|
|
**Verify the build** by running `docker/build.sh` (or `bash docker/build.sh` if script path issues). If the base image tag `python3.11-nodejs20` fails with a manifest error, update the Dockerfile FROM line to `nikolaik/python-nodejs:python3.11-nodejs22-bookworm` as recommended by research, add a comment noting the change, and retry. After successful build:
|
|
|
|
- Run `docker run --rm ngn-agent:latest aws --version` — confirms aws-cli is installed and executable
|
|
- Run `docker run --rm ngn-agent:latest terraform --version` — confirms terraform works
|
|
- Run `docker run --rm ngn-agent:latest helm version --short` — confirms helm works
|
|
- Run `docker run --rm ngn-agent:latest kubectl version --client` — confirms kubectl works
|
|
- Run `docker run --rm ngn-agent:latest pup --version` — confirms pup works
|
|
|
|
If any tool fails in the container, fix the Dockerfile and rebuild. The image must have all 5 tools working.
|
|
</action>
|
|
<verify>
|
|
<automated>docker run --rm ngn-agent:latest sh -c 'aws --version && terraform --version && helm version --short && kubectl version --client && pup --version'</automated>
|
|
</verify>
|
|
<done>
|
|
- build.sh exists and is executable
|
|
- `ngn-agent:latest` image builds successfully
|
|
- All 5 tools execute correctly inside the container
|
|
- Build script references D-04 and D-05 decisions
|
|
- If base image tag was updated to python3.11-nodejs22-bookworm due to deprecation, the FROM line is updated and a comment explains the change
|
|
</done>
|
|
</task>
|
|
|
|
</tasks>
|
|
|
|
<threat_model>
|
|
## Trust Boundaries
|
|
|
|
| Boundary | Description |
|
|
|----------|-------------|
|
|
| Docker build host → Docker daemon | Docker context is read by build daemon |
|
|
| Docker build → external tool repos | Tool downloads cross HTTPS boundaries |
|
|
| Docker image layers → local storage | Built image stored on host filesystem |
|
|
|
|
## STRIDE Threat Register
|
|
|
|
| Threat ID | Category | Component | Disposition | Mitigation Plan |
|
|
|-----------|----------|-----------|-------------|-----------------|
|
|
| T-09-01 | Tampering | Tool download MITM (curl/wget from S3, GitHub, apt repos) | mitigate | All downloads use HTTPS. apt repos use GPG key verification to sign packages. |
|
|
| T-09-02 | Information Disclosure | Build context leak (COPY . could send .env into Docker daemon) | mitigate | Build context is `docker/` directory only — not repo root. Dockerfile does not COPY . anywhere. |
|
|
| T-09-03 | Tampering | Base image supply chain (nikolaik/python-nodejs) | accept | Widely used community image; no custom base image available. |
|
|
| T-09-04 | Denial of Service | Base image tag python3.11-nodejs20 may not exist | mitigate | Dockerfile comment flags potential deprecation. If build fails with manifest error, update to python3.11-nodejs22-bookworm. |
|
|
|
|
## Package Legitimacy Gate
|
|
|
|
| Package | Registry | Verdict | Disposition |
|
|
|---------|----------|---------|-------------|
|
|
| (none) | — | — | No npm/pip/cargo packages installed. All tools via apt or curl binary downloads. |
|
|
</threat_model>
|
|
|
|
<verification>
|
|
- Automated: `docker run --rm ngn-agent:latest sh -c 'aws --version && terraform --version && helm version --short && kubectl version --client && pup --version'` passes with all 5 tools
|
|
- Manual: User can inspect `docker/images` output to confirm tag and creation date
|
|
</verification>
|
|
|
|
<success_criteria>
|
|
1. The image `ngn-agent:latest` exists in local Docker daemon
|
|
2. Running `docker run --rm ngn-agent:latest <tool> --version` succeeds for all 5 tools
|
|
3. `docker/build.sh` is the single entry point for rebuilding
|
|
4. Both files are committed to the ngn-agent git repo
|
|
5. Tool versions are pinned (ARGS in Dockerfile) for future reproducibility
|
|
</success_criteria>
|
|
</objective>
|