Last updated: 15th October, 2025
Secure Multi-VPC Cloud Architecture with VPC Peering
Building a Secure Jump-Point to Connect Development to Production.
This project was developed within a lab environment that automatically terminates all resources when lab timer lapses. To ensure continuity, I created an Infrastructure as Code (IaC) solution using CloudFormation. This allowed me to quickly redeploy the entire stack when the lab is restarted and pick up from where I left off without any manual reconfiguration.
Introduction: Initial Setup & Prerequisites
This project establishes two separate VPC environments (PROD and DEV) and then connects them securely using VPC Peering.
Below is the architecture of the project, we would build it step by step throughout this document

Prerequisites
- • AWS Account with appropriate IAM users and permissions
- • Familiarity with AWS Management Console
- • A Command Line Interface (CLI) tool
- • Familiarity with basic Linux Commands
- • Familiarity with AWS CloudFormation (optional but recommended)
I will be using a WSL terminal
Step 1: Creating VPC and Subnets
We will first create two isoloated networks for the environments using a VPCTwo public and one private
• From the Management Console got to the VPC Dashboard.
• Create VPC.
• "VPC only" and provide a name ("prod-vpc" for production environment).
I will be using this naming format for the entire project for simplicity, you can use any format that works for you• Set an IPv4 CIDR block of 10.0.0.0/16
• Review and Create VPC

• Create another VPC
• Create VPC.
• "VPC only" and provide a name ("dev-vpc" for development environment).
• Set an IPv4 CIDR block of 192.168.0.0/16
so that the prod and dev CIDRs do not overlap

Now to create subnets, two for PROD and one for DEV,
Expand the VPC Dashboard sidebar and go to Subnets
Create Subnet
Choose the production VPC ("prod-vpc").
We will create a Public Subnet first
• So name it "prod-public-subnet"
• Set the Availability Zone to your preference (e.g., us-west-2a) and note it somewhere
becasue the second subnet must be in a different AZ• Set the IPv4 subnet CIDR block to 10.0.1.0/28
• Review and Create Subnet

We will follow similar procedure to create the private subnet also prod-vpc
• Name: prod-private-subnet
• Different AZ from prod-public-subnet
• CIDR: 10.0.2.0/28

And then create the DEV public subnet
• Must be in the dev-vpc
• Name: dev-public-subnet
• Same AZ as prod-public-subnet
• CIDR: 192.168.1.0/24

Cloudformation Code for Step 1 - (VPC and Subnets)
The part of the Cloudformation code that creates vpc and subnets as we discussed above
AWSTemplateFormatVersion: "2010-09-09"
Description: >-
This template creates a VPC Peering connection for 2 disparate networks
Parameters:
VPCName:
Description: The name of the VPC being created.
Type: String
Default: my-vpc
AL2023AMI:
Type: AWS::SSM::Parameter::Value<AWS::EC2::Image::Id>
Default: /aws/service/ami-amazon-linux-latest/al2023-ami-kernel-default-x86_64
Mappings:
SubnetConfig:
VPC:
CIDR: 10.0.0.0/16
Public1:
CIDR: 10.0.1.0/28
Public2:
CIDR: 10.0.2.0/28
Private:
CIDR: 10.0.3.0/28
Resources:
Step 2: Routing
While still in the VPC Dashboard we'll create and configure three route tables.
The purpose of routing is to control the traffic flow between the subnets, or between the subnets and the internet
What we'll create:
• A Route Table for the Public Subnet in Production with routes to an Internet Gateway to enable internet access.
• Another Route Table for the Public Subnet in Development with routes to it's own Internet Gateway to enable internet access.
• A Route Table for the Private Subnet with a route to the VPC Peering connection
That means the route tables have dependencies on Internet Gateways so let's create them first before we move on
Choose "Internet gateways" from the sidebar and click on Create Internet Gateway.
• Name it "prod-igw"
andCreate internet gateway.
Select Attach to VPC from the green pop-up and select the VPC ("prod-vpc").

Create the second Internet Gateway call it "dev-igw" and attach it to "dev-vpc"
Now that we have both Internet Gateways created, we can create the route tables
Open "Route Tables" from the side menu
• Create Route Table.
• We'll name it "prod-public-rtb" and associate it with the prod-vpc.
• Create route table

You'll be redirected to the dashboard of the just created route table
There, select the "Routes" tab. Click on Edit routes and then Add route.
• Set the destination to 0.0.0.0/0 and the target to the production Internet Gateway("prod-igw")
Save changes

We need to associate this route table with the public subnet so that it's reachable from the internet.
• Select the "Subnet associations" tab and Edit subnet associations.
• Select the public subnet ("prod-public-subnet)
Save associations

We repeat the process to create route tables for the prod private subnet and dev public subnet
Prod Private Route Table:
• Name: "prod-private-rtb" and associate it with the prod-vpc as well
• Don't set any routes yet as this subnet is private and can only relate with other subnets internally
we'll come back to add a route to the VPC Peering Connection later• In the "Subnet associations" tab, associate the prod private subnet ("prod-private-subnet) with this route table.
Dev Public Route Table:
• Name: "dev-public-rtb" and associate it with the dev-vpc.
• Set a route with destination 0.0.0.0/0 and target to the development Internet Gateway("dev-igw")
• In the "Subnet associations" tab, associate the dev public subnet ("dev-public-subnet) with this route table.
Key Points / Best Practices
- Private subnets should not have a direct route to the Internet Gateway, they only interact with the internet for their needs through the NAT Gateway
- Ensure that the route tables are correctly associated with their respective subnets
- Double-check the CIDR blocks to avoid overlaps and ensure proper segmentation
Cloudformation Code for Step 2 - (Routing)
The part of the Cloudformation code that creates the IGWs and Route Tables as discussed above
Uploading only this part to Cloudformation will fail to create unless the VPC and Subnets from Step 1 are already created
Append this code to the code from Step 1 to make it work, and ensure the indentations are correct
# Resources: ...
# VPC and Subnets section
# ....
# Routing section
Step 3: VPC Peering
In this section we are going to a create a peering connection between the two VPCs we created in Step 1
Go to Peering connections in the VPC side menu
• Click on Create peering connection
• Assign it a name, "peer-con-interface"
• We'll make the prod-vpc make the peering request to dev-vpc
required in VPC peering to establish the connection• Review andCreate peering connection


You'll see a alert at the top of the page asking to accept the connection request
you need to accept the connection request made by prod-vpc to dev-vpc since they're both managed in the same account
-Go to "Actions" and accept the request

Now we can go and modify "prod-private-rtb"
-You can select "Modify route tables now" from the green popup or go to the Route tables from the sidebar
Set a new route to the dev-public-subnet CIDR 192.168.1.0/24 and target the Peering Connection
- Update "dev-public-rtb" with a route to the prod-private-subnet CIDR10.0.2.0/28 and target the Peering Connection
now both subnets know the route to communicate with each other is through the Peering Connection


Cloudformation Code for Step 3 - (VPC Peering)
The part of the Cloudformation code that creates the Load Balancer dicussed above
Uploading only this part to Cloudformation will fail to create unless the VPC and Subnets from Step 1 are already created
Append this code to the code from Step 1 and step 2 to make it work, and ensure the indentations are correct
# Resources: ...
# VPC and Subnets section
# ....
# Routing section
# ....
# VPC Peering
Step 4: Security Groups
In this step we will set up Security Groups to control access to the Instances we will create in the next step
We will create a Secuity Group for an Elastic Network Interface (ENI)
Security Groups act as virtual firewalls that regulate inbound and outbound traffic. We will create rules to allow only necessary traffic, ensuring a robust architecture.
What we'll create:
• A Security Groups for the Bastion Hosts in both VPCs to allow ssh connection from anywhere.
• A Security Group for the ENI to allow ssh from the bastion in dev-vpc
possible, thanks to VPC Peering!
We'll start with the Bastion Security Groups
• Go to Security Groups in the VPC Dashboard.
• Create Security Group.
• We'll name it "ProdBastionSG"
• Add a description
• Select VPC (prod-vpc)
For Inbound rules:
• Add a rule for SSH access from anywhere

• Create another one with name "DevBastionSG"
• Add a description
• Select VPC (dev-vpc)
• Set ssh inbound rule from anywhere

• We also need a security group for the private instance
a secondary network interface (ENI) will be governed by the ENI security group
- We'll create the ENI and attach it to the private instance in the next step
• Let's name it "PrivateInstanceSG"
• Add a description
• Select VPC (prod-vpc)
• Set ssh inbound rule from "ProdBastionSG" (search "sg" from the dropdown and choose ProdBationSG )

For ENI Security Group.
• We'll name it "ENISG"
• Will be in the prod-vpc
• Add inbound rule:
SSH - Source: Custom 192.168.1.0/24 from dev bastion's subnet

Key Points / Best Practices
- The instances security should allow traffic from only the load balancer security group
- Ensure to use descriptive names and comments for rules to make management easier
Cloudformation Code for Step 4 - (Security Groups)
The part of the Cloudformation code that creates the Security Groups as dicussed above
Uploading only this part to Cloudformation will fail to create unless the VPC and Subnets from Step 1 are already created
Append this code to the code from Step 1 and 2 to make it work, and ensure the indentations are correct
# Resources: ...
# VPC and Subnets section
# ....
# Routing section
# ....
# VPC Peering
# ....
# Security groups
ENISecurityGroup:
Type: AWS::EC2::SecurityGroup
Properties:
GroupDescription: Enable SSH from dev bastion
VpcId: !Ref VPC
SecurityGroupIngress:
- IpProtocol: tcp
FromPort: 22
ToPort: 22
CidrIp: 192.168.1.0/24
Tags:
- Key: Name
Value: ENISG
DevBastionSecurityGroup:
Type: AWS::EC2::SecurityGroup
Properties:
GroupDescription: Enable SSH access from anywhere
VpcId: !Ref VPC
SecurityGroupIngress:
- IpProtocol: tcp
FromPort: 22
ToPort: 22
CidrIp: 0.0.0.0/0
Tags:
- Key: Name
Value: DevBastionSG
ProdBastionSecurityGroup:
Type: AWS::EC2::SecurityGroup
Properties:
GroupDescription: Enable SSH access from anywhere
VpcId: !Ref VPC
SecurityGroupIngress:
- IpProtocol: tcp
FromPort: 22
ToPort: 22
CidrIp: 0.0.0.0/0
Tags:
- Key: Name
Value: ProdBastionSG
PrivateInstanceSecurityGroup:
Type: AWS::EC2::SecurityGroup
Properties:
GroupDescription: Enable SSH access from prod bastion security group
VpcId: !Ref VPC
SecurityGroupIngress:
- IpProtocol: tcp
FromPort: 22
ToPort: 22
SourceSecurityGroupId: !Ref ProdBastionSecurityGroup
Tags:
- Key: Name
Value: PrivateInstanceSG
Step 5: ENI & EC2 Instances
In this step, we will launch three EC2 instances and attach a Network Interface to one of them, and configure them with their appropriate security groups created in the previous step
• Search for "EC2" in the Search bar and open the EC2 Dashboard.
• Go to "Network Interfaces".
• Create a new network interface
• Add a description
• Select prod-private-subnet, so that it will be assigned a private ip form this subnet
• Check the "ENISG" security group andCreate network interface


Now create the private instance first: • Go "Instances" and create a new instance.
• We'll name it "PrivateInstance".
• Leave the next sections as default go to Key Pair
• Select a key pair for SSH access. If you don't have one, create a new key pair and download the ".pem" file
will be required to connect to the instances later when we test ssh access.
Edit Network Settings:
- Select the VPC (prod-vpc)
- Select the the subnet (prod-private-subnet)
- Disable Auto-assign Public IP
the instance is private and doesn't require a public IP.- Under Security Group, "Select an existing security group" and choose the "PrivateInstanceSG" security

• Leave everything else untouched and review
Launch instance when done.
Lauch two more instance for bastion hosts:
For "ProdBastion Server":
In the network settings select "prod-vpc" and the "prod-public-subnet"
Enable auto-assign IP
- And then select the ProdBastionSG security group
For "DevBastion Server":
In the network settings select "dev-vpc" and the "dev-public-subnet"
Enable auto-assign IP
- And then select the DevBastionSG security group
One last thing to seal it all,
Go to Network Interfaces select the ENI we created
Select "Attach" from "Actions"
Choose the "prod-vpc"
And then choose the instance to attach the interface,i.e "Private Instance"
Check if everything is correct and hitAttach

Cloudformation Code for Step 5 - (ENI & EC2 Instances)
The part of the Cloudformation code that creates the EC2 Instances as dicussed above
Uploading only this part to Cloudformation will fail to create unless you combine with the codes from the previous steps, and ensure the indentations are correct
# Resources: ...
# VPC and Subnets section
# ....
# Routing section
# ....
# VPC Peering
# ....
# Security groups
# ....
# ENI & EC2 Instances
Step 6: Testing
In this final step, we will test the entire setup to ensure that all components are functioning correctly. We will verify that the Bastion in the development environment can ssh into the private instance in the production environment
Make sure your key pair file has the right permissions set.
Run this command to do so:
Upload your Key Pair .pem file to the dev bastion so you can use it to ssh into the prod private instance
Run the command below to do that(make sure the key pair file is in the current working directory):
scp -i YOUR-KEY-PAIR.pem YOUR-KEY-PAIR.pem ec2-user@DEV-BASTION-PUBLIC-IP:~/Note that the repetition of "YOUR-KEY-PAIR.pem" isn't a mistake
Let's try to ssh into the private instance from the dev bastion
ssh -i YOUR-KEY-PAIR.pem ec2-user@ENI-PRIVATE-IP
We have confirmed the whole setup is working as expected!
You can run further tests on your own to verify if the security groups are working as intended
Congratulations!
That's all about it, we've been able to successfully complete the design
Thank You
Thank you for following this project on establishing a connection between two VPCs, using VPC Peering. I hope you found it informative and helpful. If you have any questions or need further assistance, feel free to reach out!
Get In Touch
Have questions about this project or want to collaborate? I'd love to hear from you!

Dickson Ankamah
Cloud Practitioner
I'm always open to discussing new opportunities, interesting projects, or just having a chat about technology. Feel free to reach out through any of the channels above!