Skip to main content

Instance metadata service

The instance metadata service answers HTTP/1.1 requests from inside an instance about that instance. For how it works, see How instance metadata works.

Address​

FamilyAddressPort
IPv4169.254.169.254TCP 80
IPv6fd00:ec2::254TCP 80

The IPv6 address answers only on an instance whose NIC has an IPv6 address. Plain HTTP only. The source MAC and source IP of the request must be the pair assigned to the instance's NIC. Any other packet addressed to a metadata address, including UDP, ICMP, and TCP to another port, is dropped without a reply.

Authentication​

HeaderSent onValue
X-aws-ec2-metadata-token-ttl-secondsPUT /latest/api/tokenToken lifetime in seconds. Required. An integer; values below 1 become 1, values above 21600 become 21600.
X-aws-ec2-metadata-tokenEvery other requestThe token from PUT /latest/api/token.

A token is an HS256 JWT signed with a key held by the compute node. It is bound to the instance and to the network port the PUT arrived on, and expires at the requested lifetime, with 5 seconds of clock leeway. A token does not verify on another instance or on another compute node.

Routes​

MethodPathTokenReturns
PUT/latest/api/tokenNoA new token, as the body.
GET/latest/meta-dataYesThe names under meta-data/, one per line.
GET/latest/meta-data/<KEY>YesThe value of meta-data/<KEY>, or a listing when <KEY> has children.
GET/latest/user-dataYesThe value of user-data.
GET/latest/dynamicYesThe names under dynamic/. No key exists there, so this returns 404.
GET/latest/dynamic/<KEY>YesThe value of dynamic/<KEY>. Any path under iam returns 404.
GET/triton/dynamic/realizedYesEvery key the guest can read, as one JSON object. See The realized view.
GET/triton/systemYesThe names under triton/system/.
GET/triton/system/<KEY>YesThe value of triton/system/<KEY>, or a listing.
GET/triton/<TREE>YesThe names under <TREE>/, for example /triton/config.
GET/triton/<TREE>/<KEY>YesThe value of <TREE>/<KEY>, or a listing.
PUT/triton/guest/<KEY>YesUpdates the existing key guest/<KEY>. See Guest writeback.
DELETE/triton/guest/<KEY>Yes501. Not implemented.

<KEY> can contain /. A path with no matching route returns 404 with an empty body.

Response format​

ValueBodyContent-Type
JSON stringThe string itself, with no quotes and no trailing newlinetext/plain; charset=utf-8
Any other JSON valueThe JSON encodingapplication/json
ListingOne child name per line, sorted, each line ending in a newline. A name with children of its own ends in /.text/plain; charset=utf-8

A path that names no key and has visible keys below it returns the listing.

Computed keys​

The platform computes these from the instance's records. They are read-only.

KeyPathValue
meta-data/instance-id/latest/meta-data/instance-idInstance UUID.
meta-data/ami-id/latest/meta-data/ami-idImage UUID.
meta-data/instance-type/latest/meta-data/instance-type<CPU>vcpu-<MIB>m, for example 2vcpu-4096m.
meta-data/hostname/latest/meta-data/hostnameInstance name, or tritond-<INSTANCE_UUID> when the name is empty.
meta-data/local-hostname/latest/meta-data/local-hostnameSame as hostname.
meta-data/mac/latest/meta-data/macPrimary NIC MAC address.
meta-data/local-ipv4/latest/meta-data/local-ipv4Primary NIC IPv4 address. Absent without one.
meta-data/local-ipv6/latest/meta-data/local-ipv6Primary NIC IPv6 address. Absent without one.
meta-data/public-keys/<N>/openssh-key/latest/meta-data/public-keys/<N>/openssh-keyThe SSH public keys attached at create, numbered from 0.
triton/system/vpc-id/triton/system/vpc-idVPC UUID of the primary NIC.
triton/system/subnet-id/triton/system/subnet-idSubnet UUID of the primary NIC.
triton/system/vni/triton/system/vniThe VPC's virtual network identifier, as a JSON number.
triton/system/image-id/triton/system/image-idImage UUID.
triton/system/image-name/triton/system/image-nameImage name.
triton/system/image-os/triton/system/image-osImage operating system.
triton/system/image-version/triton/system/image-versionImage version.
triton/system/brand/triton/system/brandInstance brand, for example bhyve.
triton/system/cpu/triton/system/cpuVirtual CPUs, as a JSON number.
triton/system/memory-mib/triton/system/memory-mibMemory in MiB, as a JSON number.
triton/system/owner/tenant/triton/system/owner/tenantTenant UUID.
triton/system/owner/project/triton/system/owner/projectProject UUID.
triton/system/created-at/triton/system/created-atCreation time, RFC 3339.
triton/system/fstab/triton/system/fstabShared filesystem mounts, one <SERVER>:<EXPORT> <PATH> <OPTIONS> line each.
triton/system/filesystems/triton/system/filesystemsThe same mounts, as a JSON object.

The primary NIC is the NIC on the instance's primary subnet. When no NIC is on that subnet, it is the first NIC attached to the instance. A key whose source record is missing, such as a NIC that does not exist yet, is absent. The two filesystem keys are absent when the mounts cannot be read.

Stored keys​

Stored keys are set with tritonctl meta set at tenant, project, or instance scope, or by the operator at silo scope. For one instance, the narrowest scope that sets a key wins: instance, then project, then tenant, then silo.

NamespacePathScopesGuest-visible by default
config/<KEY>/triton/config/<KEY>AnyYes
state/<KEY>/triton/state/<KEY>AnyYes
instance/<KEY>/triton/instance/<KEY>AnyAt project and instance scope
guest/<KEY>/triton/guest/<KEY>AnyAt project and instance scope
user-data/latest/user-dataInstance onlyYes

A key the guest cannot see behaves as absent. --guest-visible on tritonctl meta set overrides the default. The platform's generated passwords, instance/root_pw and instance/administrator_pw, are stored hidden from the guest.

Key rules, enforced when a key is set:

RuleLimit
Length1 to 256 bytes
Charactersa to z, 0 to 9, ., _, -, /. The first character is a letter or digit.
SegmentsAt most 8, separated by /, none empty
Namespacesconfig/, state/, instance/, and guest/ need at least one segment after the namespace. user-data takes none.
Value size65536 bytes, as encoded JSON
user-data valueA JSON string

Keys under meta-data/, system/, and dynamic/ are reserved and cannot be set.

Service options​

Two stored keys control the service for the instances under the scope that sets them.

KeyTypeDefaultEffect
config/imds/enabledBooleantrue, or the operator's cluster defaultfalse turns the service off for the instance.
config/imds/hop-limitInteger, 1 to 641The IP time-to-live, or IPv6 hop limit, of every reply.

When config/imds/enabled is false on an instance that had the service, PUT /latest/api/token and the GET routes answer 404, imds disabled. Paths under /latest/dynamic/iam answer 404, not found, as they always do, and DELETE /triton/guest/<KEY> answers 501. If the service was off for an instance when its network configuration was last compiled, the instance has no route to the metadata address, and its requests time out.

A changed hop limit applies to connections the guest opens after the agent re-reads it, which it does every 30 seconds through its 30-second cache. A connection already open keeps the hop limit it was accepted with.

The realized view​

GET /triton/dynamic/realized returns one JSON object. Each member is a key the guest can read:

{
"meta-data/instance-id": { "value": "<INSTANCE_UUID>", "from": "system" },
"config/app/mode": { "value": "production", "from": "project" }
}

from is system for a computed key, or silo, tenant, project, or instance for the scope a stored key came from.

Guest writeback​

PUT /triton/guest/<KEY> replaces the value of guest/<KEY>. The body is stored as JSON when it parses as JSON, and as a JSON string otherwise. The key must already exist and carry guest_writable. The write lands at the scope the key already lives in, and keeps its guest_visible and guest_writable flags. tritonctl meta set --guest-writable sets the flag, on guest/ keys at tenant, project, or instance scope.

A successful write returns 200 with the stored entry as JSON, and the next read from the same instance sees it.

StatusCause
400, body must be UTF-8The body is not JSON and not UTF-8.
400The value breaks a key rule, such as the size limit.
403The key is not guest_writable, or lives at silo scope.
404No such key for this instance.
502The agent could not complete the write with the control plane.

Limits​

LimitValue
Request rate100 per second for each instance, with a burst of 200. PUT /latest/api/token does not count.
Open connections8 for each NIC at once
Idle connectionClosed after 30 seconds without progress
FreshnessValues are cached for 30 seconds in the agent. A guest write clears the cache for that instance.
Token lifetime1 to 21600 seconds

Errors​

StatusBodyReturned byCause
400missing X-aws-ec2-metadata-token-ttl-seconds headerPUT /latest/api/tokenNo TTL header.
400non-ascii X-aws-ec2-metadata-token-ttl-seconds headerPUT /latest/api/tokenThe TTL header is not ASCII.
400X-aws-ec2-metadata-token-ttl-seconds must be an integerPUT /latest/api/tokenThe TTL header is not an integer.
401missing IMDS tokenEvery route except the token routeNo token header.
401invalid IMDS tokenEvery route except the token routeThe token is malformed, expired, or issued to another instance or on another compute node.
404imds disabledPUT /latest/api/token and the GET routes, except paths under /latest/dynamic/iamconfig/imds/enabled is false for the instance.
404not foundGET routesNo visible key at the path, and none below it.
429rate limit exceededEvery route except the token routeThe instance exceeded the request rate.
500mint failedPUT /latest/api/tokenThe agent could not sign the token.
501Starts with IMDS handler not yet implementedDELETE /triton/guest/<KEY>Not implemented.
503realized view unavailableGET routes, except paths under /latest/dynamic/iamThe agent's 30-second copy of the instance's metadata expired, and it could not fetch a new one from the control plane.

Each body ends with a newline. The token header is checked before the rate limit, and both before the imds disabled check, so a request without a token gets 401 even when the service is off.

See also​