diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml
index 09b987703c76264d1b08685e8f912f4acb43a20f..f679ce797de02833bc7bad6c66e8ff0d84264420 100644
--- a/.gitlab-ci.yml
+++ b/.gitlab-ci.yml
@@ -9,10 +9,9 @@ workflow:
       when: never
     - when: always
 
+# include templates
 include:
-  - project: 'platform-one/big-bang/pipeline-templates/umbrella-templates'
-    file: '/global.gitlab-ci.yml'
-    ref: 0.0.1
+  - local: '/.gitlab-ci/templates.yml'
 
 stages:
   - smoke tests
@@ -183,19 +182,10 @@ release:
 #-----------------------------------------------------------------------------------------------------------------------
 # Infrastructure: Management Jobs
 #
-# .pre job for pulling pipeline contents from umbrella-templates project
-# TODO: Currently all jobs connected via "needs" must explicitly need this job, should evaluate turning this into a global cache
-fetch umbrella templates:
-  extends:
-    - .fetch
-    - .infra create
-  stage: .pre
 
 # Abstract for job manually triggering infrastructure builds
 .infra fork:
   stage: network up
-  needs:
-    - fetch umbrella templates
   rules:
     # Skip when branch name starts with "hotfix" or "patch"
     - if: '$CI_MERGE_REQUEST_SOURCE_BRANCH_NAME =~ /^(hotfix|patch)/'
@@ -229,6 +219,7 @@ fetch umbrella templates:
 #-----------------------------------------------------------------------------------------------------------------------
 # Infrastructure: Networking
 #
+
 aws/network up:
   extends:
     - .infra fork
@@ -250,6 +241,7 @@ aws/network down:
 #-----------------------------------------------------------------------------------------------------------------------
 # Infrastructure: RKE2
 #
+
 # Create RKE2 cluster on AWS
 aws/rke2/cluster up:
   stage: cluster up
@@ -257,8 +249,6 @@ aws/rke2/cluster up:
     - .infra create
     - .rke2 up
   needs:
-    - job: fetch umbrella templates
-      artifacts: true
     - job: aws/network up
 
 # Install BigBang on RKE2 cluster on AWS
@@ -268,16 +258,13 @@ aws/rke2/bigbang up:
     - .infra create
     - .bigbang
   needs:
-    - job: fetch umbrella templates
-      artifacts: true
     - job: aws/rke2/cluster up
       artifacts: true
   before_script:
     - mkdir -p ~/.kube
     - cp ${CI_PROJECT_DIR}/rke2.yaml ~/.kube/config
-
     # Deploy a default storage class for aws
-    - kubectl apply -f ${CI_PROJECT_DIR}/umbrella-templates/jobs/rke2/dependencies/k8s-resources/aws/default-ebs-sc.yaml
+    - kubectl apply -f ${CI_PROJECT_DIR}/.gitlab-ci/jobs/rke2/dependencies/k8s-resources/aws/default-ebs-sc.yaml
   script:
     - *deploy_bigbang
 
@@ -288,8 +275,6 @@ aws/rke2/bigbang test:
     - .infra create
     - .bigbang
   needs:
-    - job: fetch umbrella templates
-      artifacts: true
     - job: aws/rke2/cluster up
       artifacts: true
     - job: aws/rke2/bigbang up
@@ -310,8 +295,6 @@ aws/rke2/bigbang down:
     - .infra cleanup
     - .bigbang
   needs:
-    - job: fetch umbrella templates
-      artifacts: true
     - job: aws/rke2/cluster up
       artifacts: true
     - job: aws/rke2/bigbang test
@@ -330,7 +313,5 @@ aws/rke2/cluster down:
     - .infra cleanup
     - .rke2 down
   needs:
-    - job: fetch umbrella templates
-      artifacts: true
     - job: aws/rke2/bigbang down
 #-----------------------------------------------------------------------------------------------------------------------
\ No newline at end of file
diff --git a/.gitlab-ci/jobs/k3d/.gitlab-ci.yml b/.gitlab-ci/jobs/k3d/.gitlab-ci.yml
new file mode 100644
index 0000000000000000000000000000000000000000..94546061b6408bd59cbc3f314679c2b4880fa4ad
--- /dev/null
+++ b/.gitlab-ci/jobs/k3d/.gitlab-ci.yml
@@ -0,0 +1,32 @@
+.k3d_before_script: &k3d_before_script
+  # Starting dnsmasq for cluster dns resolution
+  - docker run -d -p 53:53/udp -p 53:53 registry.dsop.io/platform-one/big-bang/pipeline-templates/pipeline-templates/go-dnsmasq:0eddd476
+  - echo "nameserver 127.0.0.1" >> /etc/resolv.conf
+  # Standup cluster
+  - k3d cluster create ${CLUSTER_NAME}  --k3s-server-arg "--disable=traefik" --k3s-server-arg "--disable=metrics-server" -p 80:80@loadbalancer -p 443:443@loadbalancer --wait --agents $N_AGENTS --servers $N_SERVERS
+  - while ! (kubectl get node | grep "server" > /dev/null); do sleep 3; done
+  - kubectl get nodes
+  - k3d node list
+
+.k3d_after_script: &k3d_after_script
+  - k3d cluster delete ${CLUSTER_NAME}
+
+.k3d:
+  image: registry.dsop.io/platform-one/big-bang/pipeline-templates/pipeline-templates/k3d-builder:045fb1c2
+  services:
+    - registry.dsop.io/platform-one/big-bang/pipeline-templates/pipeline-templates/docker:dind
+  tags:
+    - bigbang
+    - privileged
+    - public
+  variables:
+    DOCKER_HOST: tcp://localhost:2375/
+    DOCKER_DRIVER: overlay2
+    DOCKER_TLS_CERTDIR: ""
+    CLUSTER_NAME: ${CI_COMMIT_REF_SLUG}
+    N_SERVERS: 1
+    N_AGENTS: 0
+  before_script:
+    - *k3d_before_script
+  after_script:
+    - *k3d_after_script
\ No newline at end of file
diff --git a/.gitlab-ci/jobs/networking/aws/.gitlab-ci.yml b/.gitlab-ci/jobs/networking/aws/.gitlab-ci.yml
new file mode 100644
index 0000000000000000000000000000000000000000..19a63df259b202e3bf473d4c75e790a5c2dc2667
--- /dev/null
+++ b/.gitlab-ci/jobs/networking/aws/.gitlab-ci.yml
@@ -0,0 +1,28 @@
+.calc_unique_cidr: &calc_unique_cidr
+  - apk add python3 py3-boto3
+  - echo "Calculating unique cidr range for vpc"
+  - chmod 755 ../../../get-vpc.py
+  - TF_VAR_vpc_cidr=$(terraform output vpc_cidr | tr -d '\n' | tr -d '\r' | grep 10) || TF_VAR_vpc_cidr=$(python3 ../../../get-vpc.py | tr -d '\n' | tr -d '\r')
+  - echo "Using VPC CIDR $TF_VAR_vpc_cidr for $CLUSTER_NAME cluster"
+  - export TF_VAR_vpc_cidr=$TF_VAR_vpc_cidr
+
+.network:
+  extends: .terraformer
+  variables:
+    TF_ROOT: ".gitlab-ci/jobs/networking/aws/dependencies/terraform/env/ci"
+
+.network up:
+  extends: .network
+  script:
+    - *calc_unique_cidr
+    - echo "Creating network with cidr range ${TF_VAR_vpc_cidr}"
+    - terraform apply -auto-approve
+
+.network down:
+  extends:
+    - .network
+    - .terraform destroy workspace
+  script:
+    - *calc_unique_cidr
+    - echo "Destroying network"
+    - terraform destroy -auto-approve
\ No newline at end of file
diff --git a/.gitlab-ci/jobs/networking/aws/dependencies/Pipfile b/.gitlab-ci/jobs/networking/aws/dependencies/Pipfile
new file mode 100644
index 0000000000000000000000000000000000000000..abe1b0b8bbc306db3882e51f70ff29af06e3e853
--- /dev/null
+++ b/.gitlab-ci/jobs/networking/aws/dependencies/Pipfile
@@ -0,0 +1,12 @@
+[[source]]
+name = "pypi"
+url = "https://pypi.org/simple"
+verify_ssl = true
+
+[dev-packages]
+
+[packages]
+boto3 = "*"
+
+[requires]
+python_version = "3.8"
diff --git a/.gitlab-ci/jobs/networking/aws/dependencies/Pipfile.lock b/.gitlab-ci/jobs/networking/aws/dependencies/Pipfile.lock
new file mode 100644
index 0000000000000000000000000000000000000000..6c105c2ea73148471c96ad9baf4daa8187a8d34b
--- /dev/null
+++ b/.gitlab-ci/jobs/networking/aws/dependencies/Pipfile.lock
@@ -0,0 +1,75 @@
+{
+    "_meta": {
+        "hash": {
+            "sha256": "0ba145c19353da73840755ed85984b6653241c800c6ad2c772805a6089dfb424"
+        },
+        "pipfile-spec": 6,
+        "requires": {
+            "python_version": "3.8"
+        },
+        "sources": [
+            {
+                "name": "pypi",
+                "url": "https://pypi.org/simple",
+                "verify_ssl": true
+            }
+        ]
+    },
+    "default": {
+        "boto3": {
+            "hashes": [
+                "sha256:b091cf6581dc137f100789240d628a105c989cf8f559b863fd15e18c1a29b714",
+                "sha256:bd4c26d304abba8d96817bb83917bb2e19123f5ce1a5dd26255f866daeff61c7"
+            ],
+            "index": "pypi",
+            "version": "==1.16.17"
+        },
+        "botocore": {
+            "hashes": [
+                "sha256:33f650b2d63cc1f2d5239947c9ecdadfd8ceeb4ab8bdefa0a711ac175a43bf44",
+                "sha256:81184afc24d19d730c1ded84513fbfc9e88409c329de5df1151bb45ac30dfce4"
+            ],
+            "version": "==1.19.17"
+        },
+        "jmespath": {
+            "hashes": [
+                "sha256:b85d0567b8666149a93172712e68920734333c0ce7e89b78b3e987f71e5ed4f9",
+                "sha256:cdf6525904cc597730141d61b36f2e4b8ecc257c420fa2f4549bac2c2d0cb72f"
+            ],
+            "markers": "python_version >= '2.6' and python_version not in '3.0, 3.1, 3.2, 3.3'",
+            "version": "==0.10.0"
+        },
+        "python-dateutil": {
+            "hashes": [
+                "sha256:73ebfe9dbf22e832286dafa60473e4cd239f8592f699aa5adaf10050e6e1823c",
+                "sha256:75bb3f31ea686f1197762692a9ee6a7550b59fc6ca3a1f4b5d7e32fb98e2da2a"
+            ],
+            "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3'",
+            "version": "==2.8.1"
+        },
+        "s3transfer": {
+            "hashes": [
+                "sha256:2482b4259524933a022d59da830f51bd746db62f047d6eb213f2f8855dcb8a13",
+                "sha256:921a37e2aefc64145e7b73d50c71bb4f26f46e4c9f414dc648c6245ff92cf7db"
+            ],
+            "version": "==0.3.3"
+        },
+        "six": {
+            "hashes": [
+                "sha256:30639c035cdb23534cd4aa2dd52c3bf48f06e5f4a941509c8bafd8ce11080259",
+                "sha256:8b74bedcbbbaca38ff6d7491d76f2b06b3592611af620f8426e82dddb04a5ced"
+            ],
+            "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3'",
+            "version": "==1.15.0"
+        },
+        "urllib3": {
+            "hashes": [
+                "sha256:19188f96923873c92ccb987120ec4acaa12f0461fa9ce5d3d0772bc965a39e08",
+                "sha256:d8ff90d979214d7b4f8ce956e80f4028fc6860e4431f731ea4a8c08f23f99473"
+            ],
+            "markers": "python_version != '3.4'",
+            "version": "==1.26.2"
+        }
+    },
+    "develop": {}
+}
diff --git a/.gitlab-ci/jobs/networking/aws/dependencies/get-vpc.py b/.gitlab-ci/jobs/networking/aws/dependencies/get-vpc.py
new file mode 100755
index 0000000000000000000000000000000000000000..995d570d6d841be3cea6270bbcc49a52bb6660ed
--- /dev/null
+++ b/.gitlab-ci/jobs/networking/aws/dependencies/get-vpc.py
@@ -0,0 +1,37 @@
+import boto3
+import operator
+import ipaddress
+initial_cidr = "10.10.0.0/16"
+client = boto3.client('ec2', region_name='us-gov-west-1')
+res = client.describe_vpcs(Filters=[{}])
+vpcIds = list(map(operator.itemgetter("CidrBlock"), res["Vpcs"]))
+vpcIds.sort()
+unique_cidr = False
+while not unique_cidr:
+    found_cidr_overlap = False
+    for cidr in vpcIds:
+        aws_cidr = ipaddress.IPv4Network(cidr)
+        try:
+            proposed_cidr = ipaddress.IPv4Network(initial_cidr)
+        except:
+            logger.error("Couldn't convert cidr of " + str(initial_cidr))
+            sys.exit(2)
+
+        if aws_cidr.overlaps(proposed_cidr):
+            found_cidr_overlap = True
+            break
+    allowed_private_cidr = ipaddress.IPv4Network("10.0.0.0/8")
+    if not found_cidr_overlap:
+        if allowed_private_cidr.overlaps(proposed_cidr):
+            unique_cidr = True
+            final_vpc = initial_cidr
+        else:
+            logger.error("Proposed cidr not in private ip space: " + str(initial_cidr))
+            sys.exit(2)
+    else:
+        try:
+            initial_cidr = str(ipaddress.ip_address(initial_cidr.split("/")[0]) + 65536) + "/16"
+        except:
+            logger.error("Couldn't update cidr of " + str(initial_cidr))
+            sys.exit(2)
+print(final_vpc)
diff --git a/.gitlab-ci/jobs/networking/aws/dependencies/terraform/env/ci/ci.tf b/.gitlab-ci/jobs/networking/aws/dependencies/terraform/env/ci/ci.tf
new file mode 100644
index 0000000000000000000000000000000000000000..53d4e9e4a107961197073600ef49f0a18ebd1ad2
--- /dev/null
+++ b/.gitlab-ci/jobs/networking/aws/dependencies/terraform/env/ci/ci.tf
@@ -0,0 +1,19 @@
+terraform {
+  backend "s3" {
+    bucket               = "umbrella-tf-states"
+    key                  = "terraform.tfstate"
+    region               = "us-gov-west-1"
+    dynamodb_table       = "umbrella-tf-states-lock"
+    workspace_key_prefix = "aws-networking"
+  }
+}
+
+module "ci" {
+  source = "../../main"
+
+  # Set by CI - "${CI_COMMIT_REF_SLUG}-${CI_COMMIT_SHORT_SHA}"
+  env = var.env
+
+  # Calculated in CI
+  vpc_cidr = var.vpc_cidr
+}
diff --git a/.gitlab-ci/jobs/networking/aws/dependencies/terraform/env/ci/outputs.tf b/.gitlab-ci/jobs/networking/aws/dependencies/terraform/env/ci/outputs.tf
new file mode 100644
index 0000000000000000000000000000000000000000..ae2f9895de88b0a19ccb7908927237ca3f757c12
--- /dev/null
+++ b/.gitlab-ci/jobs/networking/aws/dependencies/terraform/env/ci/outputs.tf
@@ -0,0 +1,11 @@
+output "vpc_id" {
+  value = module.ci.vpc_id
+}
+
+output "public_subnets" {
+  value = module.ci.public_subnet_ids
+}
+
+output "private_subnets" {
+  value = module.ci.private_subnet_ids
+}
\ No newline at end of file
diff --git a/.gitlab-ci/jobs/networking/aws/dependencies/terraform/env/ci/variables.tf b/.gitlab-ci/jobs/networking/aws/dependencies/terraform/env/ci/variables.tf
new file mode 100644
index 0000000000000000000000000000000000000000..0a36d0fd735faf11132803323607f7069b723938
--- /dev/null
+++ b/.gitlab-ci/jobs/networking/aws/dependencies/terraform/env/ci/variables.tf
@@ -0,0 +1,2 @@
+variable "vpc_cidr" {}
+variable "env" {}
\ No newline at end of file
diff --git a/.gitlab-ci/jobs/networking/aws/dependencies/terraform/env/dev/dev.tf b/.gitlab-ci/jobs/networking/aws/dependencies/terraform/env/dev/dev.tf
new file mode 100644
index 0000000000000000000000000000000000000000..938f4d280e34886c3d501ba2b6d014fe24f3f35e
--- /dev/null
+++ b/.gitlab-ci/jobs/networking/aws/dependencies/terraform/env/dev/dev.tf
@@ -0,0 +1,5 @@
+module "dev" {
+  source   = "../../main"
+  env      = "dev"
+  vpc_cidr = "10.255.0.0/16"
+}
diff --git a/.gitlab-ci/jobs/networking/aws/dependencies/terraform/env/dev/outputs.tf b/.gitlab-ci/jobs/networking/aws/dependencies/terraform/env/dev/outputs.tf
new file mode 100644
index 0000000000000000000000000000000000000000..808207547dabb5212db46d508ba6151eb5f948ee
--- /dev/null
+++ b/.gitlab-ci/jobs/networking/aws/dependencies/terraform/env/dev/outputs.tf
@@ -0,0 +1,11 @@
+output "vpc_id" {
+  value = module.dev.vpc_id
+}
+
+output "public_subnets" {
+  value = module.dev.public_subnet_ids
+}
+
+output "private_subnets" {
+  value = module.dev.private_subnet_ids
+}
\ No newline at end of file
diff --git a/.gitlab-ci/jobs/networking/aws/dependencies/terraform/main/main.tf b/.gitlab-ci/jobs/networking/aws/dependencies/terraform/main/main.tf
new file mode 100644
index 0000000000000000000000000000000000000000..89c29b01a470f3fdb5bb331567d1586a4f3e25cb
--- /dev/null
+++ b/.gitlab-ci/jobs/networking/aws/dependencies/terraform/main/main.tf
@@ -0,0 +1,143 @@
+## TODO: Revisit the terraform gitlab http backend
+# terraform {
+#   backend "http" {}
+# }
+
+provider "aws" {
+  region = var.aws_region
+}
+
+
+locals {
+  public_subnet_cidrs = [
+    cidrsubnet(var.vpc_cidr, ceil(log(6, 2)), 0),
+    cidrsubnet(var.vpc_cidr, ceil(log(6, 2)), 1),
+  ]
+
+  private_subnet_cidrs = [
+    cidrsubnet(var.vpc_cidr, ceil(log(6, 2)), 2),
+    cidrsubnet(var.vpc_cidr, ceil(log(6, 2)), 3),
+  ]
+
+  intra_subnet_cidrs = [
+    cidrsubnet(var.vpc_cidr, ceil(log(6, 2)), 4),
+    cidrsubnet(var.vpc_cidr, ceil(log(6, 2)), 5),
+  ]
+
+  name = "umbrella-${var.env}"
+
+  tags = {
+    "terraform" = "true",
+    "env"       = var.env,
+    "project"   = "umbrella"
+  }
+}
+
+#
+# Network
+#
+module "vpc" {
+  source = "terraform-aws-modules/vpc/aws"
+
+  name = local.name
+  cidr = var.vpc_cidr
+
+  azs             = ["${var.aws_region}a", "${var.aws_region}b", "${var.aws_region}c"]
+  public_subnets  = local.public_subnet_cidrs
+  private_subnets = local.private_subnet_cidrs
+  intra_subnets   = local.intra_subnet_cidrs
+
+  enable_nat_gateway   = true
+  single_nat_gateway   = true
+  enable_dns_hostnames = true
+  enable_dns_support   = true
+
+  # Use AWS VPC private endpoints to mirror functionality on airgapped (T)C2S environments
+  #   S3: for some vendors cluster bootstrapping/artifact storage
+  #   STS: for caller identity checks
+  #   EC2: for cloud manager type requests (such as auto ebs provisioning)
+  #   ASG: for cluster autoscaler
+  #   ELB: for auto elb provisioning
+  enable_s3_endpoint                   = true
+  enable_sts_endpoint                  = true
+  enable_ec2_endpoint                  = true
+  enable_ec2_autoscaling_endpoint      = true
+  enable_elasticloadbalancing_endpoint = true
+
+  ec2_endpoint_security_group_ids  = [aws_security_group.endpoints.id]
+  ec2_endpoint_subnet_ids          = module.vpc.intra_subnets
+  ec2_endpoint_private_dns_enabled = true
+
+  ec2_autoscaling_endpoint_security_group_ids  = [aws_security_group.endpoints.id]
+  ec2_autoscaling_endpoint_subnet_ids          = module.vpc.intra_subnets
+  ec2_autoscaling_endpoint_private_dns_enabled = true
+
+  elasticloadbalancing_endpoint_security_group_ids  = [aws_security_group.endpoints.id]
+  elasticloadbalancing_endpoint_subnet_ids          = module.vpc.intra_subnets
+  elasticloadbalancing_endpoint_private_dns_enabled = true
+
+  sts_endpoint_security_group_ids  = [aws_security_group.endpoints.id]
+  sts_endpoint_subnet_ids          = module.vpc.intra_subnets
+  sts_endpoint_private_dns_enabled = true
+
+  # Prevent creation of EIPs for NAT gateways
+  reuse_nat_ips = false
+
+  # Add in required tags for proper AWS CCM integration
+  public_subnet_tags = merge({
+    "kubernetes.io/cluster/${local.name}" = "shared"
+    "kubernetes.io/role/elb"              = "1"
+  }, local.tags)
+
+  private_subnet_tags = merge({
+    "kubernetes.io/cluster/${local.name}" = "shared"
+    "kubernetes.io/role/internal-elb"     = "1"
+  }, local.tags)
+
+  intra_subnet_tags = merge({
+    "kubernetes.io/cluster/${local.name}" = "shared"
+  }, local.tags)
+
+  tags = merge({
+    "kubernetes.io/cluster/${local.name}" = "shared"
+  }, local.tags)
+}
+
+# Shared Private Endpoint Security Group
+resource "aws_security_group" "endpoints" {
+  name        = "${local.name}-endpoint"
+  description = "${local.name} endpoint"
+  vpc_id      = module.vpc.vpc_id
+
+  ingress {
+    from_port   = 0
+    to_port     = 0
+    protocol    = "-1"
+    cidr_blocks = ["0.0.0.0/0"]
+  }
+
+  egress {
+    from_port   = 0
+    to_port     = 0
+    protocol    = "-1"
+    cidr_blocks = ["0.0.0.0/0"]
+  }
+}
+
+#
+# TGW Attachments
+# Attaches the management vpc (the hub) to the created vpc (the spokes).
+#
+module "spoke" {
+  source = "git::https://repo1.dsop.io/platform-one/big-bang/terraform-modules/spoke-tgw-attachments.git"
+
+  name       = local.name
+  hub_vpc_id = var.hub_vpc_id
+  hub_tgw    = var.hub_tgw
+  hub_tgw_rt = var.hub_tgw_rt
+  hub_tgwa   = var.hub_tgwa
+
+  spoke_vpc_id  = module.vpc.vpc_id
+  spoke_subnets = module.vpc.private_subnets
+  spoke_rt_ids  = module.vpc.private_route_table_ids
+}
diff --git a/.gitlab-ci/jobs/networking/aws/dependencies/terraform/main/outputs.tf b/.gitlab-ci/jobs/networking/aws/dependencies/terraform/main/outputs.tf
new file mode 100644
index 0000000000000000000000000000000000000000..89359c18b0d70f59763d3ba9d7436a4a8b9e6f51
--- /dev/null
+++ b/.gitlab-ci/jobs/networking/aws/dependencies/terraform/main/outputs.tf
@@ -0,0 +1,11 @@
+output "vpc_id" {
+  value = module.vpc.vpc_id
+}
+
+output "private_subnet_ids" {
+  value = module.vpc.private_subnets
+}
+
+output "public_subnet_ids" {
+  value = module.vpc.public_subnets
+}
\ No newline at end of file
diff --git a/.gitlab-ci/jobs/networking/aws/dependencies/terraform/main/variables.tf b/.gitlab-ci/jobs/networking/aws/dependencies/terraform/main/variables.tf
new file mode 100644
index 0000000000000000000000000000000000000000..f62e89ce9f84937459594088b62a498779e34be0
--- /dev/null
+++ b/.gitlab-ci/jobs/networking/aws/dependencies/terraform/main/variables.tf
@@ -0,0 +1,31 @@
+variable "env" {}
+
+variable "vpc_cidr" {
+  description = "The CIDR block for the VPC. Default value is a valid CIDR"
+  type        = string
+}
+
+variable "aws_region" {
+  type    = string
+  default = "us-gov-west-1"
+}
+
+#
+# Spoke variables
+# We can hardcode these for now... they haven't changed in 8 months
+#
+variable "hub_vpc_id" {
+  default = "vpc-5f627a3b"
+}
+
+variable "hub_tgw" {
+  default = "tgw-0c324b57d019790f4"
+}
+
+variable "hub_tgwa" {
+  default = "tgw-attach-0dce16098dd33fd2c"
+}
+
+variable "hub_tgw_rt" {
+  default = "tgw-rtb-04b66987e7d96a3d4"
+}
\ No newline at end of file
diff --git a/.gitlab-ci/jobs/rke2/.gitlab-ci.yml b/.gitlab-ci/jobs/rke2/.gitlab-ci.yml
new file mode 100644
index 0000000000000000000000000000000000000000..d5d6938fe568fd5ab93c875751a7b56b296c9748
--- /dev/null
+++ b/.gitlab-ci/jobs/rke2/.gitlab-ci.yml
@@ -0,0 +1,22 @@
+.rke2 tf:
+  extends: .terraformer
+  variables:
+    TF_ROOT: ".gitlab-ci/jobs/rke2/dependencies/terraform/env/ci"
+
+.rke2 up:
+  extends: .rke2 tf
+  script:
+    # Fetch dependencies
+    - apk add bash aws-cli
+    - terraform apply -input=false -auto-approve
+    - mv rke2.yaml ${CI_PROJECT_DIR}/rke2.yaml
+  artifacts:
+    paths:
+      - ${CI_PROJECT_DIR}/rke2.yaml
+
+.rke2 down:
+  extends:
+    - .rke2 tf
+    - .terraform destroy workspace
+  script:
+    - terraform destroy -input=false -auto-approve
\ No newline at end of file
diff --git a/.gitlab-ci/jobs/rke2/dependencies/k8s-resources/aws/default-ebs-sc.yaml b/.gitlab-ci/jobs/rke2/dependencies/k8s-resources/aws/default-ebs-sc.yaml
new file mode 100644
index 0000000000000000000000000000000000000000..0ace3effbac55bdf6623c44f29a6268cfb14b50b
--- /dev/null
+++ b/.gitlab-ci/jobs/rke2/dependencies/k8s-resources/aws/default-ebs-sc.yaml
@@ -0,0 +1,14 @@
+apiVersion: storage.k8s.io/v1
+kind: StorageClass
+metadata:
+  name: ebs
+  annotations:
+    storageclass.kubernetes.io/is-default-class: "true"
+provisioner: kubernetes.io/aws-ebs
+parameters:
+  type: gp2
+reclaimPolicy: Delete
+allowVolumeExpansion: true
+mountOptions:
+  - debug
+volumeBindingMode: Immediate
\ No newline at end of file
diff --git a/.gitlab-ci/jobs/rke2/dependencies/packer/README.md b/.gitlab-ci/jobs/rke2/dependencies/packer/README.md
new file mode 100644
index 0000000000000000000000000000000000000000..4283dff158c41dd8f9b2faa089c2f39d1ff9f66b
--- /dev/null
+++ b/.gitlab-ci/jobs/rke2/dependencies/packer/README.md
@@ -0,0 +1,9 @@
+# RKE2 Packer
+
+An _extremely_ simple packer script to pre-load rke2 dependencies for airgapped deployment.
+
+This packer script is __not__ intended to be used as a standard for airgapped rke2 deployments, it is simply a quick and dirty way to enable airgap deployments in the context of BigBang's CI.
+
+## Future Work
+
+This is currently baselined off of a vanilla RHEL8.3 ami, we should base this off of a P1 gold standard stig'd ami.
diff --git a/.gitlab-ci/jobs/rke2/dependencies/packer/packer.json b/.gitlab-ci/jobs/rke2/dependencies/packer/packer.json
new file mode 100644
index 0000000000000000000000000000000000000000..aa90b778a1cd128aada5a9f339327908f3b99c46
--- /dev/null
+++ b/.gitlab-ci/jobs/rke2/dependencies/packer/packer.json
@@ -0,0 +1,65 @@
+{
+  "variables": {
+    "aws_region": "us-gov-west-1",
+    "rke2_version": "v1.18.12+rke2r1",
+    "rke2_url": "https://github.com/rancher/rke2/releases/download",
+    "ami_name": "rhel8",
+    "ami_description": "An RKE2 base image based on RHEL 8 Build Date: {{ isotime }}",
+    "source_ami_name": "RHEL-8.3*",
+    "source_ami_owner": "309956199498",
+    "source_ami_owner_govcloud": "219670896067",
+    "source_ami_ssh_user": "ec2-user"
+  },
+  "builders": [
+    {
+      "type": "amazon-ebs",
+      "region": "{{user `aws_region`}}",
+      "ami_regions": "us-gov-west-1",
+      "source_ami_filter": {
+        "filters": {
+          "name": "{{user `source_ami_name`}}",
+          "root-device-type": "ebs",
+          "state": "available",
+          "virtualization-type": "hvm",
+          "architecture": "x86_64"
+        },
+        "owners": [ "{{user `source_ami_owner`}}", "{{user `source_ami_owner_govcloud`}}" ],
+        "most_recent": true
+      },
+      "instance_type": "m5.large",
+      "ssh_username": "{{user `source_ami_ssh_user`}}",
+      "subnet_id": "{{user `subnet_id`}}",
+      "kms_key_id": "{{user `kms_key_id`}}",
+      "launch_block_device_mappings": [
+        {
+          "device_name": "/dev/sda1",
+          "volume_size": 25,
+          "volume_type": "gp2",
+          "delete_on_termination": true
+        }
+      ],
+      "tags": {
+        "Name": "rke2-{{user `ami_name`}}-{{ timestamp }}",
+        "BuildDate": "{{ isotime }}",
+        "RKE2-Version": "{{user `rke2_version`}}"
+      },
+      "ami_name": "rke2-{{user `ami_name`}}-{{ timestamp }}",
+      "ami_description": "{{user `ami_description` }}",
+      "ami_virtualization_type": "hvm",
+      "run_tags": {
+        "Name": "packer-builder-rke2-{{user `ami_name`}}-ami"
+      }
+    }
+  ],
+  "provisioners": [
+    {
+      "type": "shell",
+      "environment_vars": [
+        "RKE2_VERSION={{ user `rke2_version` }}",
+        "RKE2_URL={{ user `rke2_url` }}"
+      ],
+      "script": "./setup.sh",
+      "execute_command": "chmod +x {{ .Path }}; sudo {{ .Vars }} {{ .Path }}"
+    }
+  ]
+}
\ No newline at end of file
diff --git a/.gitlab-ci/jobs/rke2/dependencies/packer/setup.sh b/.gitlab-ci/jobs/rke2/dependencies/packer/setup.sh
new file mode 100644
index 0000000000000000000000000000000000000000..d3fa01d87f737f5d8470ea37f97cd5cfbae5ff6b
--- /dev/null
+++ b/.gitlab-ci/jobs/rke2/dependencies/packer/setup.sh
@@ -0,0 +1,67 @@
+#!/bin/bash
+set -o pipefail
+set -o errexit
+
+# Bare minimum dependency collection
+yum install -y unzip
+yum update -y
+
+cd /usr/local/bin
+
+# RKE2
+curl -sL https://get.rke2.io -o rke2.sh
+curl -OLs "${RKE2_URL}/${RKE2_VERSION}/{rke2.linux-amd64,rke2.linux-amd64.tar.gz,rke2-images.linux-amd64.txt,rke2-images.linux-amd64.tar.gz,sha256sum-amd64.txt}"
+grep -v "e2e-*" sha256sum-amd64.txt | sha256sum -c /dev/stdin
+
+if [ $? -ne 0 ]
+  then
+    echo "[ERROR] checksum of rke2 files don't match"
+    exit 1
+fi
+
+rm -f sha256sum-amd64.txt
+
+chmod 755 rke2*
+
+# Install rke2 components (with yum so selinux components are fetched)
+INSTALL_RKE2_METHOD='yum' ./rke2.sh
+INSTALL_RKE2_METHOD='yum' INSTALL_RKE2_TYPE="agent" ./rke2.sh
+
+# Move and decompress images to pre-load dir
+mkdir -p /var/lib/rancher/rke2/agent/images/ && zcat rke2-images.linux-amd64.tar.gz > /var/lib/rancher/rke2/agent/images/rke2-images.linux-amd64.tar
+
+# AWS CLI
+curl -sL https://awscli.amazonaws.com/awscli-exe-linux-x86_64.zip -o /tmp/awscliv2.zip && unzip -qq -d /tmp /tmp/awscliv2.zip && /tmp/aws/install --bin-dir /usr/bin
+rm -rf /tmp/aws*
+
+# WARN: This sets the default region to the current region that packer is building from
+aws configure set default.region $(curl -s http://169.254.169.254/latest/meta-data/placement/region)
+
+cat <<EOF >> /etc/environment
+HISTTIMEFORMAT="%F %T "
+KUBECONFIG=/etc/rancher/rke2/rke2.yaml
+EOF
+cat <<EOF >> /root/.bash_aliases
+alias k='rke2 kubectl'
+EOF
+
+# Clean up build instance history
+rm -rf \
+  /etc/hostname \
+  /home/ec2-user/.ssh/authorized_keys \
+  /root/.ssh/authorized_keys \
+  /var/lib/cloud/data \
+  /var/lib/cloud/instance \
+  /var/lib/cloud/instances \
+  /var/lib/cloud/sem \
+  /var/log/cloud-init-output.log \
+  /var/log/cloud-init.log \
+  /var/log/secure \
+  /var/log/wtmp \
+  /var/log/apt
+> /etc/machine-id
+> /var/log/wtmp
+> /var/log/btmp
+yum clean all -y
+df -h; date
+history -c
diff --git a/.gitlab-ci/jobs/rke2/dependencies/terraform/env/ci-airgap/ci-airgap.tf b/.gitlab-ci/jobs/rke2/dependencies/terraform/env/ci-airgap/ci-airgap.tf
new file mode 100644
index 0000000000000000000000000000000000000000..8c5a886943f5d42121e3db1f965182011cf1d567
--- /dev/null
+++ b/.gitlab-ci/jobs/rke2/dependencies/terraform/env/ci-airgap/ci-airgap.tf
@@ -0,0 +1,32 @@
+terraform {
+  backend "s3" {
+    bucket               = "umbrella-tf-states"
+    key                  = "terraform.tfstate"
+    region               = "us-gov-west-1"
+    dynamodb_table       = "umbrella-tf-states-lock"
+    workspace_key_prefix = "rke2"
+  }
+}
+
+data "terraform_remote_state" "networking" {
+  backend = "s3"
+  config = {
+    bucket               = "umbrella-tf-states"
+    key                  = "terraform.tfstate"
+    region               = "us-gov-west-1"
+    workspace_key_prefix = "aws-networking"
+  }
+  workspace = var.env
+}
+
+module "ci" {
+  source = "../../main"
+
+  env     = var.env
+  vpc_id  = data.terraform_remote_state.networking.outputs.vpc_id
+  subnets = data.terraform_remote_state.networking.outputs.intra_subnets
+
+  download   = false
+  server_ami = "ami-00aab2121681e4a31"
+  agent_ami  = "ami-00aab2121681e4a31"
+}
\ No newline at end of file
diff --git a/.gitlab-ci/jobs/rke2/dependencies/terraform/env/ci-airgap/variables.tf b/.gitlab-ci/jobs/rke2/dependencies/terraform/env/ci-airgap/variables.tf
new file mode 100644
index 0000000000000000000000000000000000000000..58ca8bec63a9b8bf085a404a5f420d38276fa23d
--- /dev/null
+++ b/.gitlab-ci/jobs/rke2/dependencies/terraform/env/ci-airgap/variables.tf
@@ -0,0 +1,5 @@
+variable "aws_region" {
+  default = "us-gov-west-1"
+}
+
+variable "env" {}
\ No newline at end of file
diff --git a/.gitlab-ci/jobs/rke2/dependencies/terraform/env/ci/ci.tf b/.gitlab-ci/jobs/rke2/dependencies/terraform/env/ci/ci.tf
new file mode 100644
index 0000000000000000000000000000000000000000..d9d700441ab5de44103791d9d983e37dce056197
--- /dev/null
+++ b/.gitlab-ci/jobs/rke2/dependencies/terraform/env/ci/ci.tf
@@ -0,0 +1,29 @@
+terraform {
+  backend "s3" {
+    bucket               = "umbrella-tf-states"
+    key                  = "terraform.tfstate"
+    region               = "us-gov-west-1"
+    dynamodb_table       = "umbrella-tf-states-lock"
+    workspace_key_prefix = "rke2"
+  }
+}
+
+data "terraform_remote_state" "networking" {
+  backend = "s3"
+  config = {
+    bucket               = "umbrella-tf-states"
+    key                  = "terraform.tfstate"
+    region               = "us-gov-west-1"
+    workspace_key_prefix = "aws-networking"
+  }
+  workspace = var.env
+}
+
+module "ci" {
+  source = "../../main"
+
+  env             = var.env
+  vpc_id          = data.terraform_remote_state.networking.outputs.vpc_id
+  private_subnets = data.terraform_remote_state.networking.outputs.private_subnets
+  public_subnets  = data.terraform_remote_state.networking.outputs.public_subnets
+}
\ No newline at end of file
diff --git a/.gitlab-ci/jobs/rke2/dependencies/terraform/env/ci/variables.tf b/.gitlab-ci/jobs/rke2/dependencies/terraform/env/ci/variables.tf
new file mode 100644
index 0000000000000000000000000000000000000000..58ca8bec63a9b8bf085a404a5f420d38276fa23d
--- /dev/null
+++ b/.gitlab-ci/jobs/rke2/dependencies/terraform/env/ci/variables.tf
@@ -0,0 +1,5 @@
+variable "aws_region" {
+  default = "us-gov-west-1"
+}
+
+variable "env" {}
\ No newline at end of file
diff --git a/.gitlab-ci/jobs/rke2/dependencies/terraform/env/dev/dev.tf b/.gitlab-ci/jobs/rke2/dependencies/terraform/env/dev/dev.tf
new file mode 100644
index 0000000000000000000000000000000000000000..0b9624d3a77ab07f802e62e61f574ddedfc0ba4c
--- /dev/null
+++ b/.gitlab-ci/jobs/rke2/dependencies/terraform/env/dev/dev.tf
@@ -0,0 +1,33 @@
+provider "aws" {
+  region = "us-gov-west-1"
+}
+
+data "terraform_remote_state" "networking" {
+  backend = "local"
+  config = {
+    path = "../../../../../networking/aws/dependencies/terraform/env/dev/terraform.tfstate"
+  }
+}
+
+# Private Key
+resource "tls_private_key" "ssh" {
+  algorithm = "RSA"
+  rsa_bits  = 4096
+}
+
+resource "local_file" "pem" {
+  filename        = "rke2.pem"
+  content         = tls_private_key.ssh.private_key_pem
+  file_permission = "0600"
+}
+
+
+module "dev" {
+  source = "../../main"
+
+  env                 = "dev"
+  vpc_id              = data.terraform_remote_state.networking.outputs.vpc_id
+  private_subnets     = data.terraform_remote_state.networking.outputs.private_subnets
+  public_subnets      = data.terraform_remote_state.networking.outputs.public_subnets
+  ssh_authorized_keys = [tls_private_key.ssh.public_key_openssh]
+}
diff --git a/.gitlab-ci/jobs/rke2/dependencies/terraform/env/dev/variables.tf b/.gitlab-ci/jobs/rke2/dependencies/terraform/env/dev/variables.tf
new file mode 100644
index 0000000000000000000000000000000000000000..794825b3cded98265eb5e386868aed853e53f9b3
--- /dev/null
+++ b/.gitlab-ci/jobs/rke2/dependencies/terraform/env/dev/variables.tf
@@ -0,0 +1,3 @@
+variable "aws_region" {
+  default = "us-gov-west-1"
+}
\ No newline at end of file
diff --git a/.gitlab-ci/jobs/rke2/dependencies/terraform/main/main.tf b/.gitlab-ci/jobs/rke2/dependencies/terraform/main/main.tf
new file mode 100644
index 0000000000000000000000000000000000000000..37bbcbf0eea8f38dae600844e189a9c60b1b6dc9
--- /dev/null
+++ b/.gitlab-ci/jobs/rke2/dependencies/terraform/main/main.tf
@@ -0,0 +1,102 @@
+locals {
+  name = "umbrella-${var.env}"
+
+  tags = {
+    "project"   = "umbrella"
+    "env"       = var.env
+    "terraform" = "true"
+  }
+}
+
+module "rke2" {
+  source = "git::https://github.com/rancherfederal/rke2-aws-tf.git"
+
+  cluster_name          = local.name
+  vpc_id                = var.vpc_id
+  subnets               = var.private_subnets
+  ami                   = var.server_ami
+  servers               = var.servers
+  instance_type         = var.server_instance_type
+  ssh_authorized_keys   = var.ssh_authorized_keys
+  controlplane_internal = var.controlplane_internal
+  rke2_version          = var.rke2_version
+
+  enable_ccm = var.enable_ccm
+  download   = var.download
+
+  # TODO: These need to be set in pre-baked ami's
+  pre_userdata = <<-EOF
+# Temporarily disable selinux enforcing due to missing policies in containerd
+# The change is currently being upstreamed and can be tracked here: https://github.com/rancher/k3s/issues/2240
+setenforce 0
+
+# Tune vm sysctl for elasticsearch
+sysctl -w vm.max_map_count=262144
+EOF
+
+  tags = merge({}, local.tags, var.tags)
+}
+
+module "generic_agents" {
+  source = "git::https://github.com/rancherfederal/rke2-aws-tf.git//modules/agent-nodepool"
+
+  name                = "generic-agent"
+  vpc_id              = var.vpc_id
+  subnets             = var.private_subnets
+  ami                 = var.agent_ami
+  asg                 = var.agent_asg
+  spot                = var.agent_spot
+  instance_type       = var.agent_instance_type
+  ssh_authorized_keys = var.ssh_authorized_keys
+  rke2_version        = var.rke2_version
+
+  enable_ccm        = var.enable_ccm
+  enable_autoscaler = var.enable_autoscaler
+  download          = var.download
+
+  # TODO: These need to be set in pre-baked ami's
+  pre_userdata = <<-EOF
+# Temporarily disable selinux enforcing due to missing policies in containerd
+# The change is currently being upstreamed and can be tracked here: https://github.com/rancher/k3s/issues/2240
+setenforce 0
+
+# Tune vm sysct for elasticsearch
+sysctl -w vm.max_map_count=262144
+EOF
+
+  # Required data for identifying cluster to join
+  cluster_data = module.rke2.cluster_data
+
+  tags = merge({}, local.tags, var.tags)
+}
+
+# Example method of fetching kubeconfig from state store, requires aws cli
+resource "null_resource" "kubeconfig" {
+  depends_on = [module.rke2]
+
+  provisioner "local-exec" {
+    interpreter = ["bash", "-c"]
+    command     = "aws s3 cp ${module.rke2.kubeconfig_path} rke2.yaml"
+  }
+}
+
+## Adding tags on VPC and Subnets to match uniquely created cluster name
+resource "aws_ec2_tag" "vpc_tags" {
+  resource_id = var.vpc_id
+  key         = "kubernetes.io/cluster/${module.rke2.cluster_name}"
+  value       = "shared"
+}
+
+resource "aws_ec2_tag" "public_subnets_tags" {
+  count       = length(var.public_subnets)
+  resource_id = var.public_subnets[count.index]
+  key         = "kubernetes.io/cluster/${module.rke2.cluster_name}"
+  value       = "shared"
+}
+
+resource "aws_ec2_tag" "private_subnets_tags" {
+  count       = length(var.private_subnets)
+  resource_id = var.private_subnets[count.index]
+  key         = "kubernetes.io/cluster/${module.rke2.cluster_name}"
+  value       = "shared"
+}
\ No newline at end of file
diff --git a/.gitlab-ci/jobs/rke2/dependencies/terraform/main/variables.tf b/.gitlab-ci/jobs/rke2/dependencies/terraform/main/variables.tf
new file mode 100644
index 0000000000000000000000000000000000000000..31327392b6fc7643a3c0c215b8ee11d2833d1e7d
--- /dev/null
+++ b/.gitlab-ci/jobs/rke2/dependencies/terraform/main/variables.tf
@@ -0,0 +1,77 @@
+variable "env" {}
+variable "aws_region" {
+  default = "us-gov-west-1"
+}
+variable "vpc_id" {}
+
+variable "private_subnets" {
+  type = list(string)
+}
+
+variable "public_subnets" {
+  type = list(string)
+}
+
+variable "tags" {
+  type    = map(string)
+  default = {}
+}
+
+#
+# Cluster variables
+#
+variable "controlplane_internal" {
+  default = true
+}
+
+variable "enable_ccm" {
+  default = true
+}
+
+variable "enable_autoscaler" {
+  default = true
+}
+
+variable "ssh_authorized_keys" {
+  type    = list(string)
+  default = []
+}
+
+variable "download" {
+  type    = bool
+  default = true
+  # TODO: Probably makes the most sense to set this to false and just use the ami for everything
+  description = "Toggle dependency downloading"
+}
+
+#
+# Server variables
+#
+variable "server_ami" {
+  default = "ami-57ecd436" # RHEL 8.3
+}
+variable "server_instance_type" {
+  default = "m5a.large"
+}
+variable "servers" {
+  default = 1
+}
+variable "rke2_version" {
+  default = "v1.18.12+rke2r2"
+}
+
+#
+# Generic agent variables
+#
+variable "agent_ami" {
+  default = "ami-57ecd436" # RHEL 8.3
+}
+variable "agent_instance_type" {
+  default = "m5a.4xlarge"
+}
+variable "agent_asg" {
+  default = { min : 2, max : 10, desired : 2 }
+}
+variable "agent_spot" {
+  default = false
+}
diff --git a/.gitlab-ci/templates.yml b/.gitlab-ci/templates.yml
new file mode 100644
index 0000000000000000000000000000000000000000..fa508e91450a3cea40f06e26932f49a6e6c7b201
--- /dev/null
+++ b/.gitlab-ci/templates.yml
@@ -0,0 +1,33 @@
+include:
+  # "Default" AWS Networking
+  - local: '/.gitlab-ci/jobs/networking/aws/.gitlab-ci.yml'
+
+  # K3D Gitlab CI job
+  - local: '/.gitlab-ci/jobs/k3d/.gitlab-ci.yml'
+
+  # RKE2 Gitlab CI jobs
+  - local: '/.gitlab-ci/jobs/rke2/.gitlab-ci.yml'
+
+.terraformer:
+  image:
+    name: registry.dsop.io/platform-one/big-bang/pipeline-templates/pipeline-templates/terraform:0.13.5
+    entrypoint:
+      - /usr/bin/env
+      - "PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin"
+  interruptible: false
+  variables:
+    TF_IN_AUTOMATION: "1"
+    TF_VAR_env: ${CI_COMMIT_REF_SLUG}-${CI_COMMIT_SHORT_SHA}
+  before_script:
+    # Shorten the env name down to 15 characters
+    - export TF_VAR_env=$(echo "${CI_COMMIT_REF_SLUG}"| cut -c 1-7)-$(echo "${CI_COMMIT_SHA}" | cut -c 1-7)
+    - cd ${CI_PROJECT_DIR}/${TF_ROOT}
+    - terraform version
+    - terraform init -input=false
+    - terraform workspace select $TF_VAR_env || terraform workspace new $TF_VAR_env
+    - terraform validate
+
+.terraform destroy workspace:
+  after_script:
+    - cd ${CI_PROJECT_DIR}/${TF_ROOT}
+    - terraform workspace select default && terraform workspace delete "${TF_VAR_env}"
\ No newline at end of file