EC2
Amazon EC2 — the full 769-operation control plane. VPCs, subnets, security groups, instances, EBS, AMIs, transit gateways, VPN, IPAM, Verified Access, and the entire networking long tail at 100% Smithy conformance.
fakecloud implements 769 of 769 AWS EC2 operations at 100% Smithy conformance — the complete control plane for the largest service surface in AWS. Request/response shapes, flattened ec2Query XML lists, field names, enum validation, and integer/length bounds are checked against AWS's own Smithy model on every commit.
Supported features
- Core networking — VPCs (+ secondary CIDRs, tenancy), DHCP option sets, subnets (+ CIDR reservations), security groups (rules, references, VPC associations), route tables, internet / egress-only / NAT gateways, and elastic IPs with transfer/move flows.
- Compute —
RunInstancesand the full instance lifecycle (start/stop/reboot/terminate/monitor), instance attributes, credit specifications, metadata + maintenance options, instance types, and topology. Key pairs and placement groups. Instances are backed by real Docker/Podman containers —RunInstancesboots a container per instance, runs your user-data at boot, and maps start/stop/reboot/terminate onto the container lifecycle (falling back to a metadata-only control plane when no container runtime is present). - Storage — EBS volumes (+ modifications, recycle bin), snapshots (+ copy, tier, lock, fast restores, block-public-access), AMIs (register/copy/deprecate/deregistration-protection), and EBS encryption defaults.
- Seeded public AMI catalogue — every account starts with a small catalogue of public Amazon-owned (Amazon Linux 2, Amazon Linux 2023 x86_64/arm64, Windows Server) and Canonical-owned (Ubuntu 22.04/24.04) AMIs, just like a real account.
DescribeImageshonours theOwnerparam (amazon/aws-marketplace/self/ account id) andnamefilters with*wildcards, so the standard Terraformdata "aws_ami"pattern (most_recent = true,owners = ["amazon"], anameglob) resolves to a real image instead of returning empty — and anything that chains off it (anaws_instance, an ELBv2 target-group attachment) can be planned. - Interfaces — elastic network interfaces with attachments, permissions, IPv4/IPv6 address assignment, and prefix lists.
- Edge / advanced networking — network ACLs, VPC peering, VPC endpoints + PrivateLink (services, connection notifications), flow logs, launch templates (+ versions), spot requests / fleets / EC2 fleets, capacity reservations (+ fleets), reserved instances, dedicated hosts.
- Transit Gateway — the complete 74-op surface: gateways, attachments, route tables (+ associations / propagations / prefix-list refs), peering, Connect + Connect peers, policy tables, route-table announcements, multicast domains (+ group members/sources), metering policies, and Client-VPN attachments.
- Site-to-Site & Client VPN — customer gateways, virtual private gateways, VPN connections (+ routes / tunnels / device configs), VPN concentrators, and full Client VPN (endpoints, routes, authorization rules, target networks, connections, certificate/config export-import).
- IPAM — IPAMs, scopes, pools, pool CIDRs + allocations, resource CIDRs, address history, resource discovery (+ associations, discovered getters), BYOASN, BYOIP-to-IPAM, external resource verification tokens, policies (+ allocation rules / org targets), and prefix-list resolvers (+ targets / rules / versions).
- Verified Access — instances, trust providers (+ attach/detach), groups, endpoints, policies (group + endpoint), logging configuration, and client-config export.
- Network Insights — reachability paths + analyses and access scopes + scope analyses (content, findings).
- Outpost / hybrid — carrier gateways, CoIP pools + CIDRs, local-gateway route tables, routes, VPC + virtual-interface-group associations, virtual interfaces, and groups.
- Access & diagnostics — EC2 Instance Connect endpoints, fast launch, serial-console access, console output / screenshot, and password data.
GetConsoleOutputreturns the instance container's real console log (its combined stdout/stderr, including anything user-data printed at boot), base64-encoded as on AWS. - Cross-cutting — tag specifications on create,
CreateTags/DeleteTags/DescribeTags,Filter.Nfiltering, andMaxResults/NextTokenpagination across everyDescribe*.
Protocol
EC2 uses the ec2Query protocol: form-encoded requests and flattened-XML responses (no <member> wrapper, lower-camel element names, lowercase <requestId>, no <Result> envelope). Because EC2 declares no per-operation error shapes, fakecloud is lenient on not-found and validates only wire-observable negatives — missing required scalars, invalid enum values, out-of-range integers / MaxResults, and bad lengths.
Introspection
GET /_fakecloud/ec2/instances— list every fakecloud-managed EC2 instance across all account partitions with its control-plane metadata (instanceId,imageId,instanceType,state,privateIp,publicIp,subnetId,vpcId,keyName,securityGroupIds,availabilityZone,launchTime) pluscontainerId— the backing Docker container id or Kubernetes Pod name, ornullwhen the instance runs metadata-only (no container runtime). Lets tests assert on instance state (and which container backs it) without re-parsingDescribeInstancesXML. Exposed through every fakecloud introspection SDK —fc.ec2().getInstances()(Go/Java/TS/PHP),fc.ec2.get_instances()(Python),fc.ec2().get_instances()(Rust).GET /_fakecloud/ec2/instance-networks— inspect each instance's real backing network: the Docker/Podman network (fakecloud-subnet-<id>) or k8s NetworkPolicy (fakecloud-ec2-<id>) that backs it, its container IP, theisolationBackend(docker/podman/kubernetes/none), thesecurityGroupEnforcementmechanism (nftables/networkpolicy/disabled), and whether enforcement is currentlyenforcementActive. A debugging aid for "why can't X reach Y". Exposed through every introspection SDK —fc.ec2().getInstanceNetworks()(Go/Java/TS/PHP),fc.ec2.get_instance_networks()(Python),fc.ec2().get_instance_networks()(Rust).
Instance metadata service (IMDS)
fakecloud serves the EC2 instance metadata service on /latest/* so an app that resolves credentials through IMDS (rather than static keys) runs unmodified. Point the SDK's IMDS client at fakecloud with AWS_EC2_METADATA_SERVICE_ENDPOINT=http://<host>:<port>/ and the default credential chain resolves locally with no code change.
Both IMDSv1 (plain GET) and IMDSv2 (PUT /latest/api/token then GET with X-aws-ec2-metadata-token) are supported; fakecloud hands out a token but does not enforce it. Served paths: meta-data/iam/security-credentials/ (role name) and meta-data/iam/security-credentials/{role} (credential JSON, from the same registered-credential cache as /_fakecloud/credentials, so it verifies under --verify-sigv4), meta-data/iam/info, meta-data/instance-id, meta-data/placement/region, meta-data/placement/availability-zone, and dynamic/instance-identity/document. The reported instance ID is set with --imds-instance-id. See the Run an app unmodified guide.
Network isolation
VPC/subnet/security-group/NACL metadata isn't just stored — fakecloud gives instances real network isolation backed by the container runtime:
Default VPC — every account+region ships a default VPC (
172.31.0.0/16) with an internet gateway, a main route table, one default subnet per AZ, adefaultsecurity group, and a default NACL, exactly like AWS.RunInstanceswith noSubnetIdlands in the default subnet and attaches thedefaultsecurity group.L3 isolation (Docker/Podman) — each subnet gets its own daemon network (
fakecloud-subnet-<id>); instances in the same subnet share a bridge and can talk, while instances in different VPCs/subnets land on different bridges and cannot route to each other. Private subnets (no0.0.0.0/0 → igwroute) back onto--internalnetworks with no NAT to the host.Security-group + NACL enforcement (Docker/Podman) — when enabled, security-group and NACL rules are translated into an nftables ruleset applied on the host, so SG rules actually block/allow traffic. This needs
CAP_NET_ADMIN+nft, so it is opt-in viaFAKECLOUD_EC2_SG_ENFORCEMENT=1and degrades gracefully: without the capability (CI, Docker Desktop, rootless podman) the rules are tracked but not enforced, with a one-time startup warning — L3 isolation still holds. The published image shipsnft(pluskmod/procps, which it needs to load and enable bridge netfilter so same-subnet traffic is actually filtered); you only need to grant the capability and set the env var. Withdocker run:docker run -e FAKECLOUD_EC2_SG_ENFORCEMENT=1 --cap-add=NET_ADMIN \ -p 4566:4566 -v /var/run/docker.sock:/var/run/docker.sock \ ghcr.io/faiscadev/fakecloud:latestor in
docker-compose.yml, uncomment thecap_add: [NET_ADMIN]andFAKECLOUD_EC2_SG_ENFORCEMENTlines in the shipped compose. Confirm it took effect viaGET /_fakecloud/ec2/instance-networks—securityGroupEnforcementreadsnftablesandenforcementActiveistruewhen active.Kubernetes — on the k8s backend, isolation is expressed as NetworkPolicy objects (one per instance, derived from its security groups) and enforced by the cluster CNI. fakecloud detects the CNI (Calico/Cilium enforce; kindnet does not) and warns when NetworkPolicy won't be enforced, but always creates the policies.
Compose interop — to let your own containers reach an instance by its private IP, attach them to the instance's subnet network:
docker network connect fakecloud-subnet-<id> <your-container>(find<id>via/_fakecloud/ec2/instance-networks). Cross-VPC traffic stays isolated by design.
Known limitations
- Instances run as containers, not VMs —
RunInstancesboots a real container per instance (Amazon Linux by default, overridable viaFAKECLOUD_EC2_DEFAULT_IMAGE) and runs user-data at boot, but it is a container, not a full virtual machine: no kernel modules, no nested virtualization, and the instance type / EBS sizing is metadata only. The container runs as a local Docker/Podman container by default, or as a native Kubernetes Pod whenFAKECLOUD_EC2_BACKEND=k8s(or the globalFAKECLOUD_CONTAINER_BACKEND=k8s) is set — mirroring the Lambda/ECS/RDS/ElastiCache backends, so fakecloud running inside Kubernetes needs no Docker daemon. On the k8s backend a stopped instance's Pod is deleted and recreated on start (instances are not persistent disks). When no container runtime is available at all, the control plane degrades to a metadata-only instance so every API call still succeeds. - A handful of model operations are absent from the vendored AWS SDK (
DescribeIpamPoolAllocations,ModifyIpamPoolAllocation, the capacity-reservation cancellation-quote pair, and theAttachImageWatermark/DetachImageWatermarkAMI watermark pair). They are implemented and conformance-probed via rawec2Query, and graduate to typed SDK calls on the next SDK refresh. - Security-group / NACL packet filtering needs host privileges. Real enforcement (above) requires
CAP_NET_ADMIN+nfton Docker/Podman, or a NetworkPolicy-enforcing CNI on Kubernetes. Where neither is available the rules are stored and returned faithfully but tracked-only; L3 (per-subnet/VPC) isolation still applies. ICMP and IPv6 rules are modeled best-effort. On Docker/Podman, fakecloud enables bridge netfilter (net.bridge.bridge-nf-call-iptables) so same-subnet traffic is actually filtered. - Enforced security-group source matching uses real container IPs, not the AWS address space. A backing container has a Docker/Podman bridge IP, not an address in the VPC's CIDR. So an enforced ingress rule keyed on a specific AWS CIDR (e.g.
10.0.0.0/8) won't match a peer instance's real source IP — only0.0.0.0/0(anywhere) and referenced security groups (which resolve to member instances' real IPs, like thedefaultgroup's allow-from-self) match as intended. Metadata (DescribeSecurityGroups) is unaffected; this only concerns the optional packet-filtering path.