diff --git a/examples/ec2-vpc-region-vpcN/apps/test-instances/.gitignore b/examples/ec2-vpc-region-vpcN/apps/test-instances/.gitignore
new file mode 100644
index 0000000..bcc7663
--- /dev/null
+++ b/examples/ec2-vpc-region-vpcN/apps/test-instances/.gitignore
@@ -0,0 +1 @@
+setup/*-keypair
diff --git a/examples/ec2-vpc-region-vpcN/apps/test-instances/.terraform-docs.yml b/examples/ec2-vpc-region-vpcN/apps/test-instances/.terraform-docs.yml
new file mode 100644
index 0000000..8391b9d
--- /dev/null
+++ b/examples/ec2-vpc-region-vpcN/apps/test-instances/.terraform-docs.yml
@@ -0,0 +1,44 @@
+formatter: markdown table
+
+header-from: main.tf
+footer-from: ""
+
+sections:
+## hide: []
+ show:
+ - data-sources
+ - header
+ - footer
+ - inputs
+ - modules
+ - outputs
+ - providers
+ - requirements
+ - resources
+
+output:
+ file: README.md
+ mode: inject
+ template: |-
+
+ {{ .Content }}
+
+
+## output-values:
+## enabled: false
+## from: ""
+##
+## sort:
+## enabled: true
+## by: name
+##
+## settings:
+## anchor: true
+## color: true
+## default: true
+## description: false
+## escape: true
+## indent: 2
+## required: true
+## sensitive: true
+## type: true
diff --git a/examples/ec2-vpc-region-vpcN/apps/test-instances/README.md b/examples/ec2-vpc-region-vpcN/apps/test-instances/README.md
new file mode 100644
index 0000000..0639b0c
--- /dev/null
+++ b/examples/ec2-vpc-region-vpcN/apps/test-instances/README.md
@@ -0,0 +1,42 @@
+
+## Requirements
+
+No requirements.
+
+## Providers
+
+| Name | Version |
+|------|---------|
+| [aws](#provider\_aws) | n/a |
+| [local](#provider\_local) | n/a |
+| [null](#provider\_null) | n/a |
+
+## Modules
+
+| Name | Source | Version |
+|------|--------|---------|
+| [role](#module\_role) | git@github.e.it.census.gov:terraform-modules/aws-iam-role.git | n/a |
+
+## Resources
+
+| Name | Type |
+|------|------|
+| [aws_instance.test](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/instance) | resource |
+| [aws_key_pair.keypair](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/key_pair) | resource |
+| [local_file.test_addresses](https://registry.terraform.io/providers/hashicorp/local/latest/docs/resources/file) | resource |
+| [null_resource.generate_keypair](https://registry.terraform.io/providers/hashicorp/null/latest/docs/resources/resource) | resource |
+| [aws_ami.test_arm](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/ami) | data source |
+| [aws_ami.test_x86](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/ami) | data source |
+| [aws_security_groups.test](https://registry.terraform.io/providers/hashicorp/aws/latest/docs/data-sources/security_groups) | data source |
+
+## Inputs
+
+No inputs.
+
+## Outputs
+
+| Name | Description |
+|------|-------------|
+| [keypair](#output\_keypair) | EC2 keypair for test instances |
+| [test\_instances](#output\_test\_instances) | Details about test instances |
+
\ No newline at end of file
diff --git a/examples/ec2-vpc-region-vpcN/apps/test-instances/data.tf b/examples/ec2-vpc-region-vpcN/apps/test-instances/data.tf
new file mode 100644
index 0000000..d804ded
--- /dev/null
+++ b/examples/ec2-vpc-region-vpcN/apps/test-instances/data.tf
@@ -0,0 +1,55 @@
+data "aws_ami" "test_x86" {
+ most_recent = true
+ owners = ["self", "amazon", "aws-marketplace"]
+
+ filter {
+ name = "description"
+ values = ["Amazon Linux 2*"]
+ }
+ filter {
+ name = "root-device-type"
+ values = ["ebs"]
+ }
+ filter {
+ name = "virtualization-type"
+ values = ["hvm"]
+ }
+ filter {
+ name = "architecture"
+ values = ["x86_64"]
+ }
+}
+
+data "aws_ami" "test_arm" {
+ most_recent = true
+ owners = ["self", "amazon", "aws-marketplace"]
+
+ filter {
+ name = "description"
+ values = ["Amazon Linux 2*"]
+ }
+ filter {
+ name = "root-device-type"
+ values = ["ebs"]
+ }
+ filter {
+ name = "virtualization-type"
+ values = ["hvm"]
+ }
+ filter {
+ name = "architecture"
+ values = ["arm64"]
+ }
+}
+
+data "aws_security_groups" "test" {
+ filter {
+ name = "vpc-id"
+ values = [local.vpc_id]
+ }
+ filter {
+ name = "group-name"
+ values = ["*linux*"]
+ }
+}
+
diff --git a/examples/ec2-vpc-region-vpcN/apps/test-instances/ec2-keypair.tf b/examples/ec2-vpc-region-vpcN/apps/test-instances/ec2-keypair.tf
new file mode 100644
index 0000000..ea9d6e4
--- /dev/null
+++ b/examples/ec2-vpc-region-vpcN/apps/test-instances/ec2-keypair.tf
@@ -0,0 +1,39 @@
+#---
+# ec2 keypairs
+#---
+locals {
+ keypair_name = format("%v-test-ec2-keypair", local.vpc_short_name)
+}
+
+# two-step process to create
+# terraform apply -target=null_resource.generate_keypair
+# terraform apply
+# when done, add to git
+# cd setup
+# echo *-keypair >> .gitignore
+# git-secret add *-ec2-keypair
+# git-secret hide
+# git add *-ec2-keypair.{pub,secret}
+# git commit -m'add ec2-keypair: *-ec2-keypair' *-ec2-keypair.{pub,secret} .gitignore
+
+resource "null_resource" "generate_keypair" {
+ provisioner "local-exec" {
+ command = "test -d setup || mkdir setup"
+ }
+ provisioner "local-exec" {
+ working_dir = "./setup"
+ # command = "ssh-keygen -f ${local.keypair_name} -N '' -t dsa -b 1024 -C '${local.keypair_name}@${var.vpc_domain_name}'"
+ command = "ssh-keygen -f ${local.keypair_name} -N '' -t rsa -b 2048 -C '${local.keypair_name}@${var.vpc_domain_name}'"
+ }
+}
+
+resource "aws_key_pair" "keypair" {
+ key_name = local.keypair_name
+ public_key = file("setup/${local.keypair_name}.pub")
+ depends_on = [null_resource.generate_keypair]
+}
+
+output "keypair" {
+ description = "EC2 keypair for test instances"
+ value = aws_key_pair.keypair.key_name
+}
diff --git a/examples/ec2-vpc-region-vpcN/apps/test-instances/ec2-role.tf b/examples/ec2-vpc-region-vpcN/apps/test-instances/ec2-role.tf
new file mode 100644
index 0000000..f572dc5
--- /dev/null
+++ b/examples/ec2-vpc-region-vpcN/apps/test-instances/ec2-role.tf
@@ -0,0 +1,8 @@
+module "role" {
+ source = "git@github.e.it.census.gov:terraform-modules/aws-iam-role.git"
+
+ role_name = local.ec2_role_name
+ attached_policies = [data.terraform_remote_state.common.outputs.managed_policies["ReadOnlyAccess"]]
+ enable_instance_profile = true
+ assume_policy_document = data.terraform_remote_state.common.outputs.custom_policy_documents["ec2_assume"].policy
+}
diff --git a/examples/ec2-vpc-region-vpcN/apps/test-instances/ec2.tf b/examples/ec2-vpc-region-vpcN/apps/test-instances/ec2.tf
new file mode 100644
index 0000000..0fac107
--- /dev/null
+++ b/examples/ec2-vpc-region-vpcN/apps/test-instances/ec2.tf
@@ -0,0 +1,66 @@
+resource "aws_instance" "test" {
+ for_each = local.private_subnets_id_map
+
+ ami = local.ami
+ instance_type = local.my_instance_type
+ availability_zone = each.value.availability_zone
+ key_name = local.key_name
+ subnet_id = each.value.id
+ vpc_security_group_ids = local.security_groups
+ iam_instance_profile = module.role.instance_profile_name
+
+ root_block_device {
+ encrypted = true
+ volume_type = "gp2"
+ volume_size = local.root_volume_size > 0 ? local.root_volume_size : 30
+ delete_on_termination = true
+ }
+
+ volume_tags = merge(
+ local.common_tags,
+ tomap({ "Name" = format("v-ebs-%v-test-%v:%v", local.vpc_short_name, each.value.label, "/") }),
+ )
+
+ provisioner "remote-exec" {
+ inline = [
+ # "sudo bash /tmp/bootstrap.sh /tmp/${var.git_deploy_path} ${local.bootstrap_args} |& tee /tmp/bootstrap.log",
+ "sleep 60",
+ "sudo yum install -y iperf3 bind-utils curl nc awscli",
+ # set region in default profile
+ "aws configure --profile default set region ${local.region}",
+ "aws configure --profile default set output json",
+ "sudo aws configure --profile default set region ${local.region}",
+ "sudo aws configure --profile default set output json",
+ ]
+ # on_failure = continue
+ on_failure = fail
+
+ connection {
+ type = "ssh"
+ user = "ec2-user"
+ host = self.private_ip
+ agent = false
+ private_key = file("${path.root}/setup/${local.key_name}")
+ }
+ }
+
+ tags = merge(
+ local.common_tags,
+ tomap({ "Name" = format("%v-test-%v", local.vpc_short_name, each.value.label) }),
+ )
+}
+
+output "test_instances" {
+ description = "Details about test instances"
+ value = { for k, v in aws_instance.test : k => {
+ name = k
+ id = v.id
+ ip_address = v.private_ip
+ subnet_id = v.subnet_id
+ } }
+}
+
+resource "local_file" "test_addresses" {
+ content = templatefile("${path.root}/templates/test-ips.txt.tpl", { instances = aws_instance.test })
+ filename = "${path.root}/test-ips.txt"
+}
diff --git a/examples/ec2-vpc-region-vpcN/apps/test-instances/locals.tf b/examples/ec2-vpc-region-vpcN/apps/test-instances/locals.tf
new file mode 100644
index 0000000..b7b1696
--- /dev/null
+++ b/examples/ec2-vpc-region-vpcN/apps/test-instances/locals.tf
@@ -0,0 +1,4 @@
+locals {
+ region = var.region
+}
+
diff --git a/examples/ec2-vpc-region-vpcN/apps/test-instances/settings.tf b/examples/ec2-vpc-region-vpcN/apps/test-instances/settings.tf
new file mode 100644
index 0000000..4bbe1d5
--- /dev/null
+++ b/examples/ec2-vpc-region-vpcN/apps/test-instances/settings.tf
@@ -0,0 +1,20 @@
+locals {
+ vpc_outputs = data.terraform_remote_state.vpc_west_vpc3.outputs
+ vpc_short_name = local.vpc_outputs.vpc_info["vpc_short_name"]
+
+ private_subnets_ids = local.vpc_outputs.private_subnets_ids
+ private_subnets_id_map = { for v in local.vpc_outputs.private_subnets_ids : v.label => v if length(regexall("endpoints", v.label)) == 0 }
+ vpc_id = local.vpc_outputs.vpc_id
+ security_groups = tolist(data.aws_security_groups.test.ids)
+
+ ami = data.aws_ami.test_x86.id
+ instance_type = "t3.nano"
+ key_name = local.keypair_name
+ root_volume_size = 50
+ ec2_role_name = format("%v-test-ec2-role", local.vpc_short_name)
+
+ # my_subnet_id = "subnet-02f7a7960321abec0"
+ # my_ami = "ami-01deaf79b0a2fb6dc"
+ my_instance_type = "t3.medium"
+ # my_availability_zone = "us-gov-east-1a"
+}
diff --git a/examples/ec2-vpc-region-vpcN/apps/test-instances/show-tunnel-status.sh b/examples/ec2-vpc-region-vpcN/apps/test-instances/show-tunnel-status.sh
new file mode 100755
index 0000000..7185f31
--- /dev/null
+++ b/examples/ec2-vpc-region-vpcN/apps/test-instances/show-tunnel-status.sh
@@ -0,0 +1,25 @@
+#!/bin/bash
+
+PROFILE=$1
+if [ -z $PROFILE ]
+then
+ echo "* missing profile"
+ exit 1
+fi
+
+REGION=$2
+if [ -z $REGION ]
+then
+ echo "* missing region"
+ exit 1
+fi
+
+VPC=$3
+if [ -z "$VPC" ]
+then
+ VPC="*vpc3*"
+fi
+
+echo "* using profile $PROFILE region $REGION for VPC filter $VPC"
+
+aws --profile $PROFILE --region $REGION ec2 describe-vpn-connections --filters Name=tag:Name,Values="$VPC" --output text|grep -iE "VGW|TAG.*Name|customer.*cgw-"
diff --git a/examples/ec2-vpc-region-vpcN/apps/test-instances/templates/test-ip.txt.tpl b/examples/ec2-vpc-region-vpcN/apps/test-instances/templates/test-ip.txt.tpl
new file mode 100644
index 0000000..8e33c53
--- /dev/null
+++ b/examples/ec2-vpc-region-vpcN/apps/test-instances/templates/test-ip.txt.tpl
@@ -0,0 +1,3 @@
+%{ for k,v in instances ~}
+v.private_ip
+%{ endfor ~}
diff --git a/examples/ec2-vpc-region-vpcN/apps/test-instances/test-ping.sh b/examples/ec2-vpc-region-vpcN/apps/test-instances/test-ping.sh
new file mode 100755
index 0000000..53b8273
--- /dev/null
+++ b/examples/ec2-vpc-region-vpcN/apps/test-instances/test-ping.sh
@@ -0,0 +1,30 @@
+#!/bin/bash
+
+DURATION=$1
+if [ -z $DURATION ]
+then
+ DURATION=15
+fi
+COUNT=$(( $DURATION * 60 ))
+if [ $COUNT == 0 ]
+then
+ COUNT=60
+fi
+
+STAMP=$(date "+%Y%m%d.%s")
+start=$(date +%s)
+
+echo "* running ping with count=$COUNT at $(date) start=$start"
+
+TIMEOUT=$(( $COUNT * 2 ))
+
+for f in $(cat test-ips.txt)
+do
+ echo " * host $f"
+ ping -c $COUNT -w $TIMEOUT $f > ping.$f.$STAMP.log 2>&1 &
+done
+
+end=$(date +%s)
+elapsed=$(( $end - $start ))
+
+echo "* done running ping with count=$COUNT at $(date) start=$start end=$end elapsed=$elapsed"
diff --git a/examples/ec2-vpc-region-vpcN/apps/test-instances/test-ssh.sh b/examples/ec2-vpc-region-vpcN/apps/test-instances/test-ssh.sh
new file mode 100755
index 0000000..d44daa5
--- /dev/null
+++ b/examples/ec2-vpc-region-vpcN/apps/test-instances/test-ssh.sh
@@ -0,0 +1,28 @@
+#!/bin/bash
+
+DURATION=$1
+if [ -z $DURATION ]
+then
+ DURATION=5
+fi
+
+STAMP=$(date "+%Y%m%d.%s")
+start=$(date +%s)
+
+TIMEOUT=$DURATION
+
+KEYPAIR=$(ls setup/*-keypair)
+echo "* running ssh timeout=$TIMEOUT with keypair=$KEYPAIR at $(date) start=$start"
+
+count=1
+for f in $(cat test-ips.txt)
+do
+ echo " * $count host $f"
+ SSH_AUTH_SOCK="" timeout $TIMEOUT ssh -o StrictHostKeyChecking=false -o IdentityFile=$KEYPAIR ec2-user@$f "hostname -f; date +%s"
+ count=$(( $count + 1 ))
+done
+
+end=$(date +%s)
+elapsed=$(( $end - $start ))
+
+echo "* done running ssh at $(date) count=$count start=$start end=$end elapsed=$elapsed"
diff --git a/examples/ec2-vpc-region-vpcN/apps/test-instances/tf-run.data b/examples/ec2-vpc-region-vpcN/apps/test-instances/tf-run.data
new file mode 100644
index 0000000..080b674
--- /dev/null
+++ b/examples/ec2-vpc-region-vpcN/apps/test-instances/tf-run.data
@@ -0,0 +1,16 @@
+VERSION 1.1.1
+REMOTE-STATE
+COMMAND tf-directory-setup.py -l none -f
+COMMAND setup-new-directory.sh
+COMMAND tf-init -upgrade
+null_resource.generate_keypair
+COMMAND ln -sf ../variables.vpc.auto.tfvars .
+COMMAND ln -sf ../variables.vpc.tf .
+ALL
+COMMAND tf-directory-setup.py -l s3
+
+COMMENT echo *-keypair >> .gitignore
+COMMENT git-secret add *-ec2-keypair
+COMMENT git-secret hide
+COMMENT git add *-ec2-keypair.{pub,secret}
+COMMENT git commit -m'add ec2-keypair: *-ec2-keypair' *-ec2-keypair.{pub,secret} .gitignore