Package Exports
- @composurecdk/ec2
Readme
@composurecdk/ec2
EC2 and VPC builders for ComposureCDK.
This package provides fluent builders for AWS EC2 instances and VPCs with secure, AWS-recommended defaults. It wraps the CDK Instance and Vpc constructs — refer to the CDK documentation for the full set of configurable properties.
Instance Builder
import { createInstanceBuilder } from "@composurecdk/ec2";
import { InstanceClass, InstanceSize, InstanceType, MachineImage } from "aws-cdk-lib/aws-ec2";
const server = createInstanceBuilder()
.vpc(vpc)
.instanceType(InstanceType.of(InstanceClass.T3, InstanceSize.MICRO))
.machineImage(MachineImage.latestAmazonLinux2023())
.build(stack, "MyInstance");Every InstanceProps property is available as a fluent setter on the builder, except vpc which is set via the dedicated .vpc() method to support cross-component wiring with ref<T>(...).
Secure Defaults
createInstanceBuilder applies the following defaults. Each can be overridden via the builder's fluent API.
| Property | Default | Rationale |
|---|---|---|
requireImdsv2 |
true |
IMDSv2 requires a session token, blocking the SSRF-based credential exfiltration common to IMDSv1. |
detailedMonitoring |
true |
1-minute CloudWatch metric granularity is required for short-window alarm evaluation. |
ssmSessionPermissions |
true |
Attaches AmazonSSMManagedInstanceCore — Session Manager replaces SSH entirely (no key pairs, bastions). |
ebsOptimized |
true |
Dedicated EBS bandwidth. Free on current-generation instance types. |
blockDevices |
8 GiB GP3 root volume at /dev/xvda, encrypted |
Encrypted at rest with the account's default EBS KMS key. |
Three properties intentionally have no default — they are application-specific and must be supplied explicitly:
vpc(via the.vpc()method)instanceTypemachineImage
The defaults are exported as INSTANCE_DEFAULTS for visibility and testing:
import { INSTANCE_DEFAULTS } from "@composurecdk/ec2";Recommended Alarms
The builder creates AWS-recommended CloudWatch alarms by default. No alarm actions are configured — wire actions via alarmActionsPolicy from @composurecdk/cloudwatch, or by accessing alarms from the build result.
| Alarm | Metric | Default threshold | Created when |
|---|---|---|---|
cpuUtilization |
CPUUtilization (Average, 1 min) | > 80% over 5 min | Always |
statusCheckFailed |
StatusCheckFailed (Sum, 1 min) | > 0 over 2 min | Always |
attachedEbsStatusCheckFailed |
StatusCheckFailed_AttachedEBS (Maximum, 1 min) | >= 1 over 10 min | Always |
cpuCreditBalance |
CPUCreditBalance (Minimum, 5 min) | < 50 over 3 x 5 min | instanceType is burstable (T2, T3, T3a, T4g family) |
The defaults are exported as INSTANCE_ALARM_DEFAULTS for visibility and testing:
import { INSTANCE_ALARM_DEFAULTS } from "@composurecdk/ec2";Customizing thresholds
Override individual alarm properties via recommendedAlarms. Unspecified fields keep their defaults.
const server = createInstanceBuilder()
.vpc(vpc)
.instanceType(InstanceType.of(InstanceClass.T3, InstanceSize.MICRO))
.machineImage(MachineImage.latestAmazonLinux2023())
.recommendedAlarms({
cpuUtilization: { threshold: 90, evaluationPeriods: 3, datapointsToAlarm: 3 },
});Disabling alarms
Disable all recommended alarms:
builder.recommendedAlarms(false);
// or
builder.recommendedAlarms({ enabled: false });Disable individual alarms:
builder.recommendedAlarms({ cpuCreditBalance: false });Custom alarms
Add custom alarms alongside the recommended ones via addAlarm. The callback receives an AlarmDefinitionBuilder typed to the Instance.
import { Metric, Stats } from "aws-cdk-lib/aws-cloudwatch";
import { Duration } from "aws-cdk-lib";
const server = createInstanceBuilder()
.vpc(vpc)
.instanceType(InstanceType.of(InstanceClass.T3, InstanceSize.MICRO))
.machineImage(MachineImage.latestAmazonLinux2023())
.addAlarm("networkIn", (alarm) =>
alarm
.metric(
(instance) =>
new Metric({
namespace: "AWS/EC2",
metricName: "NetworkIn",
dimensionsMap: { InstanceId: instance.instanceId },
statistic: Stats.AVERAGE,
period: Duration.minutes(1),
}),
)
.threshold(1_000_000_000)
.greaterThanOrEqual()
.description("Inbound network traffic is unusually high"),
);VPC Builder
import { createVpcBuilder } from "@composurecdk/ec2";
const network = createVpcBuilder().maxAzs(3).natGateways(3).build(stack, "Network");Every VpcProps property is available as a fluent setter on the builder.
VPC Defaults
| Property | Default | Rationale |
|---|---|---|
maxAzs |
2 |
Meaningful HA without overspending. Override to 3+ for stricter production guarantees. |
natGateways |
1 |
Cost-conscious default. Production HA workloads should set natGateways to match maxAzs. |
enableDnsSupport |
true |
Required for most AWS managed services (ALB, RDS, VPC endpoints). |
enableDnsHostnames |
true |
Required for instances to receive public DNS hostnames. |
restrictDefaultSecurityGroup |
true |
Strips rules from the default SG, forcing explicit SG design. |
| Flow logs | Auto-created CloudWatch log group | Network audit trail with well-architected retention and removal policies via @composurecdk/logs. |
The defaults are exported as VPC_DEFAULTS for visibility and testing:
import { VPC_DEFAULTS } from "@composurecdk/ec2";Flow logs
By default, the builder auto-creates a CloudWatch-Logs-backed flow log with a managed LogGroup from @composurecdk/logs (two-year retention, RemovalPolicy.RETAIN).
Customize the auto-created LogGroup:
createVpcBuilder().flowLogs({
configure: (lg) => lg.retention(RetentionDays.NINETY_DAYS).removalPolicy(RemovalPolicy.DESTROY),
});Use a user-managed destination (e.g. an S3 bucket):
createVpcBuilder().flowLogs({
destination: FlowLogDestination.toS3(myBucket),
});Disable flow logs entirely:
createVpcBuilder().flowLogs(false);For multiple flow logs against the same VPC, omit this config and create additional FlowLog constructs directly against the returned vpc.
Composing EC2 + VPC
Compose the builders into a single system — the instance is wired to the VPC via ref:
import { compose, ref } from "@composurecdk/core";
import { createInstanceBuilder, createVpcBuilder, type VpcBuilderResult } from "@composurecdk/ec2";
import type { Vpc } from "aws-cdk-lib/aws-ec2";
compose(
{
network: createVpcBuilder(),
server: createInstanceBuilder()
.vpc(ref<VpcBuilderResult>("network").map((r): Vpc => r.vpc))
.instanceType(InstanceType.of(InstanceClass.T3, InstanceSize.MICRO))
.machineImage(MachineImage.latestAmazonLinux2023()),
},
{ network: [], server: ["network"] },
).build(stack, "Ec2App");Examples
- Ec2Stack — VPC + EC2 instance with alarms wired to an SNS topic via
alarmActionsPolicy.