// SPDX-License-Identifier: PMPL-1.0-or-later
// Copyright (c) 2026 Jonathan D.A. Jewell (hyperpolymath) <j.d.a.jewell@open.ac.uk>
= {{PROJECT_NAME}} Container Templates
:toc: left
:toclevels: 3
:sectnums:
== Overview
This directory contains container templates for the
https://github.com/hyperpolymath/stapeln[stapeln] container ecosystem.
The stapeln stack provides verified container packaging, edge gateway
policies, runtime monitoring, and supply-chain signing for Podman-based
deployments using https://www.chainguard.dev/[Chainguard] Wolfi base images.
All files use `{{PLACEHOLDER}}` tokens that are replaced by `just container-init`
(or by the top-level `just init` during project bootstrap).
== File Reference
[cols="1,3"]
|===
| File | Purpose
| `compose.toml`
| **selur-compose** stack definition. Declares services, volumes, networks,
and health checks. The primary orchestration file for local and production
deployment. Use `selur-compose up` or fall back to `podman compose`.
| `compose.example.toml`
| Concrete multi-service example with detailed comments. Copy and customise
for your own stack. Not used directly by any tooling.
| `Containerfile`
| Multi-stage OCI container build specification. Stage 1 builds the
application; Stage 2 produces a minimal runtime image on
`cgr.dev/chainguard/wolfi-base`. Uses Podman (never Docker).
| `manifest.toml`
| **cerro-torre** bundle metadata. Describes the `.ctp` verified container
package: provenance, dependencies, attestations, and runtime security
profile. Used by `ct pack` and `ct verify`.
| `.gatekeeper.yaml`
| **svalinn** edge gateway policy. Controls authentication, rate limiting,
container trust, request validation, CORS, and audit logging at the
network boundary.
| `ct-build.sh`
| Build, sign, and verify pipeline script. Five stages: build (Podman),
pack (cerro-torre `.ctp`), sign (Ed25519), verify, and push (optional).
Gracefully degrades when cerro-torre tools are not installed.
| `entrypoint.sh`
| Container entrypoint with signal handling (SIGTERM, SIGINT), startup
logging, and `exec` into the main application process.
| `vordr.toml`
| **vordr** runtime monitoring configuration. Defines health endpoints,
crash detection, resource thresholds, and log output.
| `deploy.k9.ncl`
| **k9-svc** deployment component at Hunt trust level. Full pedigree
(L1--L5), environment configs (dev/staging/prod), container
configuration, and rolling deployment strategy.
| `0-AI-MANIFEST.a2ml`
| AI-readable manifest describing the container directory, file
interconnections, and the stapeln ecosystem.
|===
== The stapeln Ecosystem
The stapeln container ecosystem comprises six interconnected tools:
**selur** (compose)::
Container orchestration with zero-copy IPC for co-located services.
Reads `compose.toml` files. Falls back to standard Podman Compose
when the selur driver is unavailable.
**cerro-torre** (bundles and signing)::
Verified container packaging. Produces `.ctp` bundles from OCI images,
signs them with Ed25519, and verifies the full chain. Tools: `ct pack`,
`ct sign`, `ct verify`, `ct push`, `ct explain`.
**svalinn** (edge gateway)::
Policy-driven reverse proxy. Enforces authentication, rate limiting,
CORS, and container trust policies defined in `.gatekeeper.yaml`.
**vordr** (monitoring)::
Runtime container monitoring. Watches health endpoints, detects crashes,
tracks resource usage, and emits structured logs.
**rokur** (secrets)::
Secrets management for container deployments. Injects secrets at runtime
without baking them into images. Currently a stub/placeholder.
**k9-svc** (deployment components)::
Nickel-based deployment specification. Components declare their pedigree
(identity, target, security, validation, recipes) and execute at one of
three trust levels: Kennel (data only), Yard (evaluation), Hunt (full
execution with cryptographic handshake).
== How to Initialise
[source,bash]
----
# Option 1: During project bootstrap (includes all placeholders)
just init
# Option 2: Container-specific initialisation
just container-init
----
The `container-init` recipe prompts for container-specific values
(service name, port, registry) and substitutes all `{{PLACEHOLDER}}`
tokens in the `container/` directory.
== Development Workflow
[source,bash]
----
# 1. Build the container image
just container-build
# 2. Verify the compose configuration
just container-verify
# 3. Start the stack locally
just container-up --detach
# 4. Check logs
podman compose --file container/compose.toml logs -f
# 5. Stop the stack
just container-down
----
== Production Deployment
[source,bash]
----
# 1. Build, sign, and verify the .ctp bundle
just container-sign
# 2. Push the signed bundle to the registry
just container-push
# 3. Deploy on the target host
selur-compose up --detach
----
For k9-svc managed deployments:
[source,bash]
----
# Validate the deployment component
nickel typecheck container/deploy.k9.ncl
# Deploy (requires Hunt-level authorisation)
k9-svc deploy container/deploy.k9.ncl --env production
----
== Base Images
All Containerfiles use Chainguard Wolfi base images:
* **Builder stage:** `cgr.dev/chainguard/wolfi-base:latest`
* **Runtime stage:** `cgr.dev/chainguard/wolfi-base:latest` (or
`cgr.dev/chainguard/static:latest` for statically-linked binaries)
Chainguard images are minimal, CVE-free, and rebuilt daily. They use the
`apk` package manager (Alpine-compatible).
== Container Runtime
This project uses **Podman** (never Docker). All scripts, compose files,
and documentation reference Podman commands. The OCI Containerfile format
is compatible with Podman, Docker, and nerdctl.