Custom agent images
Build and supply your own VM or container images with the tools your agents need, while preserving the runtime contract.
Choose the image boundary
A VM image defines the guest operating system, system services, and installed runtime. An OCI container image defines a userspace environment inside a compatible host runtime. An OCI image is not a bootable VM disk. Your deployment determines which artifact is used and how it is selected for an agent’s new sessions.
Start from a clean, approved runtime base that already contains the agreed harness and bootstrap behavior. Add the tools, language dependencies, and CA certificates your tasks need. The examples below extend that base; they do not install or register an Entergenie runtime.
Extend a container image
For a Debian- or Ubuntu-based runtime, download this Dockerfile. Supply the approved base by digest and its non-root runtime UID and GID. The existing startup command and working directory are inherited. For another distribution, use its package manager.
# Supply a Debian/Ubuntu-based runtime image approved for your deployment.
# Use its immutable digest; this example does not install an agent harness.
ARG BASE_IMAGE
FROM ${BASE_IMAGE}
# Match the non-root runtime identity in the approved base image.
ARG RUNTIME_USER=1000:1000
USER root
RUN apt-get update \
&& apt-get install -y --no-install-recommends git jq ca-certificates \
&& rm -rf /var/lib/apt/lists/*
USER ${RUNTIME_USER}
# Inherit the base image's ENTRYPOINT, CMD, and WORKDIR.
# Do not bake credentials, SSH keys, session data, or connection secrets here.
# Set these to values from your deployment and private registry.
: "${BASE_IMAGE:?Set the approved runtime reference, including @sha256:digest}"
: "${RUNTIME_USER:?Set the runtime UID:GID}"
: "${CUSTOM_IMAGE:?Set a private registry/repository:version}"
docker build --pull \
--build-arg BASE_IMAGE="$BASE_IMAGE" \
--build-arg RUNTIME_USER="$RUNTIME_USER" \
-t "$CUSTOM_IMAGE" .
# Override the entrypoint only for this local tool smoke test.
docker run --rm --network=none --entrypoint /bin/sh "$CUSTOM_IMAGE" \
-c 'test "$(id -u)" -ne 0 && git --version && jq --version'
# Authenticate using your registry's approved credential helper first.
docker push "$CUSTOM_IMAGE"
docker image inspect "$CUSTOM_IMAGE" --format '{{json .RepoDigests}}'Run these commands in a directory containing only the downloaded Dockerfile. Resolve the pushed artifact’s digest for the target platform and retain it for deployment. Package installs resolve against current repositories; use your approved package snapshots or pinned versions where reproducible rebuilds are required. The artifact digest identifies the resulting image.
Preserve the runtime’s user, startup, workspace, and shutdown contract. See the Dockerfile reference and Docker image building practices.
Build a custom VM image with Packer
This AWS example creates an encrypted AMI from an approved Ubuntu base that already contains your runtime. It uses a private build instance. Run Packer from a network that can SSH to the build subnet; that subnet also needs approved access to package repositories. Select an instance type matching the base AMI’s architecture.
# AWS example: extend an approved Ubuntu VM image with the runtime installed.
# Build from a clean base image, never an active agent session VM.
packer {
required_plugins {
amazon = {
source = "github.com/hashicorp/amazon"
version = ">= 1.0.0, < 2.0.0"
}
}
}
variable "region" { type = string }
variable "base_ami" { type = string }
variable "vpc_id" { type = string }
variable "subnet_id" { type = string }
variable "ssh_username" { type = string }
variable "instance_type" { type = string }
source "amazon-ebs" "agent" {
region = var.region
source_ami = var.base_ami
vpc_id = var.vpc_id
subnet_id = var.subnet_id
instance_type = var.instance_type
ssh_username = var.ssh_username
ssh_interface = "private_ip"
associate_public_ip_address = false
ami_name = "entergenie-agent-{{timestamp}}"
encrypt_boot = true
imds_support = "v2.0"
metadata_options {
http_endpoint = "enabled"
http_tokens = "required"
}
tags = { Purpose = "entergenie-agent" }
}
build {
sources = ["source.amazon-ebs.agent"]
provisioner "shell" {
inline = [
"sudo env DEBIAN_FRONTEND=noninteractive apt-get update",
"sudo env DEBIAN_FRONTEND=noninteractive apt-get install -y --no-install-recommends git jq ca-certificates",
"sudo rm -rf /var/lib/apt/lists/*",
"git --version && jq --version"
]
}
}
# Supply actual values from your AWS environment. Packer reads PKR_VAR_*.
: "${PKR_VAR_region:?Set the AWS region}"
: "${PKR_VAR_base_ami:?Set the approved clean base AMI ID}"
: "${PKR_VAR_vpc_id:?Set the build VPC ID}"
: "${PKR_VAR_subnet_id:?Set the private build subnet ID}"
: "${PKR_VAR_ssh_username:?Set the base image SSH user}"
: "${PKR_VAR_instance_type:?Set a compatible build instance type}"
export PKR_VAR_region PKR_VAR_base_ami PKR_VAR_vpc_id
export PKR_VAR_subnet_id PKR_VAR_ssh_username PKR_VAR_instance_type
packer init ./agent-vm.pkr.hcl
packer fmt -check ./agent-vm.pkr.hcl
packer validate ./agent-vm.pkr.hcl
# Launches billable build infrastructure and creates an AMI.
packer build ./agent-vm.pkr.hclUse your normal AWS credential chain and a build role with the required EC2 and encryption-key permissions. The base image must support passwordless sudo for the build user. Preserve its first-boot initialization so new VMs receive distinct machine identities and SSH host keys. Build from a clean base rather than capturing a live session with user data.
Record the resulting AMI ID, region, architecture, base version, and build revision. Grant the execution account access to the image and its encrypted snapshots through your cloud permissions. Other clouds use their own VM image identifiers and sharing mechanisms. See the Packer Amazon EBS builder reference.
Provide the image to your deployment
- Publish the immutable artifact in your own registry or cloud image service.
- Give your Platform Owner the OCI digest or VM image identifier, region, architecture, runtime version, operating user, startup requirements, and build provenance.
- Grant the execution infrastructure pull or image-launch access using its service identity. Supply secret references separately.
- Configure the agreed image reference for the target agent or execution environment through your deployment’s supported UI, CLI, or Terraform configuration.
- Launch an isolated test session. Verify bootstrap, tools, workspace permissions, policy enforcement, connection access, and stop/cleanup behavior before rollout.
Image selection fields, provisioning APIs, and runtime bootstrap packages are deployment-specific. Use the schema supplied for your environment. The browser playground does not build, upload, or launch images.
Keep images separate from session data
Inject short-lived credentials and connection configuration at runtime. Keep private keys, model tokens, source-system secrets, and customer records out of image layers and build logs. Use fresh workspace storage per session and define its retention separately from the reusable image.
Assign an image owner, scan each artifact, retain build records, and rebuild for security updates. Roll out to new sessions with a pinned reference, retain the previous approved image for rollback, and decide separately whether running sessions should be drained or terminated. Replacing an image does not patch an already running VM.