Files
ngn-agent/.planning/phases/09-tooling-portable-setup/09-01-PLAN.md
Bagas Purwa Sentika d727c4dbce docs(09): create phase plan — custom Docker image + portable setup script
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).
2026-06-15 23:13:35 +08:00

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>