<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Aditya Bhatt</title>
    <description>The latest articles on DEV Community by Aditya Bhatt (@itsadijmbt).</description>
    <link>https://dev.to/itsadijmbt</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F3432819%2F96a7f3b6-c03b-46ff-8b3d-56a856455021.png</url>
      <title>DEV Community: Aditya Bhatt</title>
      <link>https://dev.to/itsadijmbt</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/itsadijmbt"/>
    <language>en</language>
    <item>
      <title>My VPC Journey: Hosting a Website in a Multi-AZ Production Environment</title>
      <dc:creator>Aditya Bhatt</dc:creator>
      <pubDate>Wed, 17 Sep 2025 16:05:01 +0000</pubDate>
      <link>https://dev.to/itsadijmbt/my-vpc-journey-hosting-a-website-in-a-multi-az-production-environment-4830</link>
      <guid>https://dev.to/itsadijmbt/my-vpc-journey-hosting-a-website-in-a-multi-az-production-environment-4830</guid>
      <description>&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Faf0xhljzbx5mtnhjk7a5.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Faf0xhljzbx5mtnhjk7a5.png" alt=" " width="800" height="533"&gt;&lt;/a&gt;&lt;br&gt;
When you’re building something for production, “just launch an EC2” is never the full story. Networking, routing, gateways, and security controls define whether your app is resilient and secure  or completely exposed.  &lt;/p&gt;

&lt;p&gt;I recently set up a &lt;strong&gt;multi-AZ AWS VPC environment&lt;/strong&gt; to host a website, and this process turned into a real-world lesson in cloud networking. Below is a breakdown of the entire journey from subnets and gateways to bastion access and load balancers.  &lt;/p&gt;


&lt;h2&gt;
  
  
  &lt;strong&gt;1. Subnets and Internet Gateway&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;I provisioned a VPC in &lt;em&gt;us-west-1&lt;/em&gt; with CIDR &lt;code&gt;10.0.0.0/16&lt;/code&gt;. Inside it, I created four subnets across two Availability Zones for fault tolerance:  &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;10.0.1.0/24&lt;/code&gt; → Public subnet in AZ1 (us-west-1a)
&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;10.0.2.0/24&lt;/code&gt; → Public subnet in AZ2 (us-west-1c)
&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;10.0.3.0/24&lt;/code&gt; → Private subnet in AZ1
&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;10.0.4.0/24&lt;/code&gt; → Private subnet in AZ2
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;By default, subnets are private (no route to the internet). To make the public subnets truly public:  &lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Attached an &lt;strong&gt;Internet Gateway (IGW)&lt;/strong&gt; to the VPC
&lt;/li&gt;
&lt;li&gt;Created a public route table:
&lt;/li&gt;
&lt;/ol&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Destination   Target
0.0.0.0/0     igw-xxxxxx
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;ol&gt;
&lt;li&gt;Associated this route table with the public subnets
&lt;/li&gt;
&lt;li&gt;Enabled &lt;strong&gt;auto-assign public IP&lt;/strong&gt; in subnet settings
&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;em&gt;Tech Note&lt;/em&gt;: Without enabling auto-assign IP, even a “public subnet” won’t let your EC2 instances reach the internet.  &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Key Points&lt;/strong&gt;  &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Subnets are private until routed to an IGW
&lt;/li&gt;
&lt;li&gt;Public subnet = IGW route + auto public IPs
&lt;/li&gt;
&lt;li&gt;Always allocate Elastic IPs for stability
&lt;/li&gt;
&lt;/ul&gt;


&lt;h2&gt;
  
  
  &lt;strong&gt;2. NAT Gateway – Controlled Outbound Access&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;My private subnets (&lt;code&gt;10.0.3.0/24&lt;/code&gt;, &lt;code&gt;10.0.4.0/24&lt;/code&gt;) needed outbound internet (for updates, patching, yum installs) without being directly reachable. Enter the &lt;strong&gt;NAT Gateway&lt;/strong&gt;.  &lt;/p&gt;

&lt;p&gt;Steps I followed:  &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Created NAT in a &lt;strong&gt;public subnet&lt;/strong&gt; (important -&amp;gt; NAT itself needs to reach IGW)
&lt;/li&gt;
&lt;li&gt;Allocated an &lt;strong&gt;Elastic IP&lt;/strong&gt; and bound it to NAT
&lt;/li&gt;
&lt;li&gt;Updated private route table:
&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Destination   Target
0.0.0.0/0     nat-xxxxxx
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;ul&gt;
&lt;li&gt;Associated this private route table with the private subnets
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;em&gt;Tech Note&lt;/em&gt;: NAT is stateful. It tracks connections opened by private instances and allows return traffic, but drops unsolicited inbound traffic.  &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Key Points&lt;/strong&gt;  &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;NAT must live in a public subnet
&lt;/li&gt;
&lt;li&gt;Elastic IP is mandatory for consistency
&lt;/li&gt;
&lt;li&gt;Route private subnets through NAT, not IGW
&lt;/li&gt;
&lt;/ul&gt;


&lt;h2&gt;
  
  
  &lt;strong&gt;3. Bastion Host – The Secure Jump Point&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;You don’t expose private EC2s directly for SSH. Instead, you deploy a &lt;strong&gt;bastion host&lt;/strong&gt; in the public subnet to act as a controlled entry point.  &lt;/p&gt;

&lt;p&gt;What I did:  &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Launched a &lt;strong&gt;CIS-hardened Amazon Linux AMI&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;Configured Security Group (SG):

&lt;ul&gt;
&lt;li&gt;Inbound &lt;code&gt;tcp/22&lt;/code&gt; allowed only from my corporate/public IP
&lt;/li&gt;
&lt;li&gt;Outbound &lt;code&gt;tcp/22&lt;/code&gt; allowed to private instances SG
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Used &lt;code&gt;ProxyJump&lt;/code&gt; for SSH chaining:
&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;ssh &lt;span class="nt"&gt;-i&lt;/span&gt; bastion.pem &lt;span class="nt"&gt;-J&lt;/span&gt; ec2-user@bastion-public-ip ec2-user@private-instance
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;ul&gt;
&lt;li&gt;Used &lt;code&gt;scp&lt;/code&gt; with ProxyJump to move SSH keys/files:
&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;scp &lt;span class="nt"&gt;-i&lt;/span&gt; bastion.pem &lt;span class="nt"&gt;-o&lt;/span&gt; &lt;span class="nv"&gt;ProxyJump&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;ec2-user@bastion-public-ip mykey.pem ec2-user@private-instance:/home/ec2-user/
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;ul&gt;
&lt;li&gt;Secured the keys with &lt;code&gt;chmod 400&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Security Practices&lt;/strong&gt;  &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Limit bastion access to known IPs only
&lt;/li&gt;
&lt;li&gt;Use hardened AMIs to avoid zero-day risks
&lt;/li&gt;
&lt;li&gt;Enable monitoring (CloudTrail, GuardDuty) for SSH attempts
&lt;/li&gt;
&lt;/ul&gt;


&lt;h2&gt;
  
  
  &lt;strong&gt;4. Private Instances with Load Balancer&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;My app servers ran inside the &lt;strong&gt;private subnets&lt;/strong&gt;. They needed to serve traffic without being directly exposed. The solution: &lt;strong&gt;Application Load Balancer (ALB)&lt;/strong&gt;.  &lt;/p&gt;

&lt;p&gt;Configuration:  &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Deployed ALB in both public subnets (multi-AZ)
&lt;/li&gt;
&lt;li&gt;Listener: HTTP port 80
&lt;/li&gt;
&lt;li&gt;Target Group: private EC2s on port 8080
&lt;/li&gt;
&lt;li&gt;SGs:

&lt;ul&gt;
&lt;li&gt;ALB SG allowed inbound port 80 from &lt;code&gt;0.0.0.0/0&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Instance SG allowed inbound port 8080 only from ALB SG
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Health Checks&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Path: /health
Protocol: HTTP
Port: 8080
Healthy threshold: 3
Unhealthy threshold: 2
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;em&gt;Tech Note&lt;/em&gt;: Health checks ensure unhealthy nodes are drained and traffic automatically reroutes to healthy backends.  &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Key Points&lt;/strong&gt;  &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;ALB must live in public subnets
&lt;/li&gt;
&lt;li&gt;Private EC2s never need direct public IPs
&lt;/li&gt;
&lt;li&gt;SG rules enforce controlled traffic paths
&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  &lt;strong&gt;5. DNS and Internal Resolution&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;Networking works better with names than raw IPs. In VPC settings, I:  &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Enabled &lt;strong&gt;DNS hostnames&lt;/strong&gt; and &lt;strong&gt;DNS resolution&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;Allowed private instances to resolve each other as &lt;code&gt;ip-10-0-3-5.ec2.internal&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Mapped a custom domain via Route 53 → ALB DNS name
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Key Points&lt;/strong&gt;  &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Always enable DNS hostnames in VPC
&lt;/li&gt;
&lt;li&gt;Route 53 + ALB = production-ready domain routing
&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  &lt;strong&gt;6. Default VPC&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;Do not delete the Default VPC. AWS services sometimes depend on it in the background.  &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Key Points&lt;/strong&gt;  &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Leave the Default VPC alone — it’s a safety net
&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  &lt;strong&gt;Production-Grade Practices Recap&lt;/strong&gt;
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Multi-AZ subnets for high availability
&lt;/li&gt;
&lt;li&gt;Separate route tables for public and private zones
&lt;/li&gt;
&lt;li&gt;NAT with Elastic IP for outbound-only private access
&lt;/li&gt;
&lt;li&gt;Bastion as a hardened jump server with strict SG rules
&lt;/li&gt;
&lt;li&gt;ALB in public subnets exposing private app servers
&lt;/li&gt;
&lt;li&gt;Route 53 for DNS + ALB hostname mapping
&lt;/li&gt;
&lt;li&gt;Security Groups with least privilege design
&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  &lt;strong&gt;1. Subnets and Internet Gateway&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;I provisioned a VPC in &lt;em&gt;us-west-1&lt;/em&gt; with CIDR &lt;code&gt;10.0.0.0/16&lt;/code&gt;. Inside it, I created four subnets across two Availability Zones for fault tolerance:  &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;10.0.1.0/24&lt;/code&gt; → Public subnet in AZ1 (us-west-1a)
&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;10.0.2.0/24&lt;/code&gt; → Public subnet in AZ2 (us-west-1c)
&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;10.0.3.0/24&lt;/code&gt; → Private subnet in AZ1
&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;10.0.4.0/24&lt;/code&gt; → Private subnet in AZ2
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;By default, subnets are private (no route to the internet). To make the public subnets truly public:  &lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Attached an &lt;strong&gt;Internet Gateway (IGW)&lt;/strong&gt; to the VPC
&lt;/li&gt;
&lt;li&gt;Created a public route table:
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Destination   Target
0.0.0.0/0     igw-xxxxxx
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ol&gt;
&lt;li&gt;Associated this route table with the public subnets
&lt;/li&gt;
&lt;li&gt;Enabled &lt;strong&gt;auto-assign public IP&lt;/strong&gt; in subnet settings
&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;em&gt;Tech Note&lt;/em&gt;: Without enabling auto-assign IP, even a “public subnet” won’t let your EC2 instances reach the internet.  &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Key Points&lt;/strong&gt;  &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Subnets are private until routed to an IGW
&lt;/li&gt;
&lt;li&gt;Public subnet = IGW route + auto public IPs
&lt;/li&gt;
&lt;li&gt;Always allocate Elastic IPs for stability
&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  &lt;strong&gt;2. NAT Gateway – Controlled Outbound Access&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;My private subnets (&lt;code&gt;10.0.3.0/24&lt;/code&gt;, &lt;code&gt;10.0.4.0/24&lt;/code&gt;) needed outbound internet (for updates, patching, yum installs) without being directly reachable. Enter the &lt;strong&gt;NAT Gateway&lt;/strong&gt;.  &lt;/p&gt;

&lt;p&gt;Steps I followed:  &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Created NAT in a &lt;strong&gt;public subnet&lt;/strong&gt; (important — NAT itself needs to reach IGW)
&lt;/li&gt;
&lt;li&gt;Allocated an &lt;strong&gt;Elastic IP&lt;/strong&gt; and bound it to NAT
&lt;/li&gt;
&lt;li&gt;Updated private route table:
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Destination   Target
0.0.0.0/0     nat-xxxxxx
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;Associated this private route table with the private subnets
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;em&gt;Tech Note&lt;/em&gt;: NAT is stateful. It tracks connections opened by private instances and allows return traffic, but drops unsolicited inbound traffic.  &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Key Points&lt;/strong&gt;  &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;NAT must live in a public subnet
&lt;/li&gt;
&lt;li&gt;Elastic IP is mandatory for consistency
&lt;/li&gt;
&lt;li&gt;Route private subnets through NAT, not IGW
&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  &lt;strong&gt;3. Bastion Host – The Secure Jump Point&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;You don’t expose private EC2s directly for SSH. Instead, you deploy a &lt;strong&gt;bastion host&lt;/strong&gt; in the public subnet to act as a controlled entry point.  &lt;/p&gt;

&lt;p&gt;What I did:  &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Launched a &lt;strong&gt;CIS-hardened Amazon Linux AMI&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;Configured Security Group (SG):

&lt;ul&gt;
&lt;li&gt;Inbound &lt;code&gt;tcp/22&lt;/code&gt; allowed only from my corporate/public IP
&lt;/li&gt;
&lt;li&gt;Outbound &lt;code&gt;tcp/22&lt;/code&gt; allowed to private instances SG
&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;Used &lt;code&gt;ProxyJump&lt;/code&gt; for SSH chaining:
&lt;/li&gt;

&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;ssh &lt;span class="nt"&gt;-i&lt;/span&gt; bastion.pem &lt;span class="nt"&gt;-J&lt;/span&gt; ec2-user@bastion-public-ip ec2-user@private-instance
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;Used &lt;code&gt;scp&lt;/code&gt; with ProxyJump to move SSH keys/files:
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;scp &lt;span class="nt"&gt;-i&lt;/span&gt; bastion.pem &lt;span class="nt"&gt;-o&lt;/span&gt; &lt;span class="nv"&gt;ProxyJump&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;ec2-user@bastion-public-ip mykey.pem ec2-user@private-instance:/home/ec2-user/
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;Secured the keys with &lt;code&gt;chmod 400&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Security Practices&lt;/strong&gt;  &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Limit bastion access to known IPs only
&lt;/li&gt;
&lt;li&gt;Use hardened AMIs to avoid zero-day risks
&lt;/li&gt;
&lt;li&gt;Enable monitoring (CloudTrail, GuardDuty) for SSH attempts
&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  &lt;strong&gt;4. Private Instances with Load Balancer&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;My app servers ran inside the &lt;strong&gt;private subnets&lt;/strong&gt;. They needed to serve traffic without being directly exposed. The solution: &lt;strong&gt;Application Load Balancer (ALB)&lt;/strong&gt;.  &lt;/p&gt;

&lt;p&gt;Configuration:  &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Deployed ALB in both public subnets (multi-AZ)
&lt;/li&gt;
&lt;li&gt;Listener: HTTP port 80
&lt;/li&gt;
&lt;li&gt;Target Group: private EC2s on port 8080
&lt;/li&gt;
&lt;li&gt;SGs:

&lt;ul&gt;
&lt;li&gt;ALB SG allowed inbound port 80 from &lt;code&gt;0.0.0.0/0&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Instance SG allowed inbound port 8080 only from ALB SG
&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Health Checks&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Path: /health
Protocol: HTTP
Port: 8080
Healthy threshold: 3
Unhealthy threshold: 2
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;em&gt;Tech Note&lt;/em&gt;: Health checks ensure unhealthy nodes are drained and traffic automatically reroutes to healthy backends.  &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Key Points&lt;/strong&gt;  &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;ALB must live in public subnets
&lt;/li&gt;
&lt;li&gt;Private EC2s never need direct public IPs
&lt;/li&gt;
&lt;li&gt;SG rules enforce controlled traffic paths
&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  &lt;strong&gt;5. DNS and Internal Resolution&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;Networking works better with names than raw IPs. In VPC settings, I:  &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Enabled &lt;strong&gt;DNS hostnames&lt;/strong&gt; and &lt;strong&gt;DNS resolution&lt;/strong&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Key Points&lt;/strong&gt;  &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Always enable DNS hostnames in VPC
&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  &lt;strong&gt;6. Default VPC&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;Do not delete the Default VPC. AWS services sometimes depend on it in the background.  &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Key Points&lt;/strong&gt;  &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Leave the Default VPC alone ,it’s a safety net &lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  &lt;strong&gt;Production-Grade Practices Recap&lt;/strong&gt;
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Multi-AZ subnets for high availability
&lt;/li&gt;
&lt;li&gt;Separate route tables for public and private zones
&lt;/li&gt;
&lt;li&gt;NAT with Elastic IP for outbound-only private access
&lt;/li&gt;
&lt;li&gt;Bastion as a hardened jump server with strict SG rules
&lt;/li&gt;
&lt;li&gt;ALB in public subnets exposing private app servers
&lt;/li&gt;
&lt;li&gt;Route 53 for DNS + ALB hostname mapping
&lt;/li&gt;
&lt;li&gt;Security Groups with least privilege design
&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  &lt;strong&gt;Final Thoughts&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;This wasn’t about launching a single EC2 instance. It was about designing a &lt;strong&gt;network fabric&lt;/strong&gt;:  &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;IGW handled ingress
&lt;/li&gt;
&lt;li&gt;NAT secured egress
&lt;/li&gt;
&lt;li&gt;Bastion managed SSH
&lt;/li&gt;
&lt;li&gt;ALB distributed web traffic
&lt;/li&gt;
&lt;li&gt;SGs enforced boundaries
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The result: a &lt;strong&gt;resilient, secure, production-grade VPC environment&lt;/strong&gt; where every resource plays a defined role.  &lt;/p&gt;

&lt;p&gt;Think of it like plumbing. Subnets are pipes, IGW is the tap, NAT is the filter, bastion is the access gate, and ALB is the pressure valve. Get the flow wrong, nothing works. Get it right, and your users sip your website seamlessly.  &lt;/p&gt;




&lt;p&gt;&lt;strong&gt;Pro Checklist&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
 Public subnets → IGW + auto IP&lt;br&gt;&lt;br&gt;
 Private subnets → NAT for outbound&lt;br&gt;&lt;br&gt;
 Bastion with restricted IP SSH&lt;br&gt;&lt;br&gt;
 ALB for private instance exposure&lt;br&gt;&lt;br&gt;
 Default VPC untouched  &lt;/p&gt;

</description>
    </item>
    <item>
      <title>How I Manually Set Up the VProfile Stack — Lessons I Wish Someone Told Me</title>
      <dc:creator>Aditya Bhatt</dc:creator>
      <pubDate>Wed, 13 Aug 2025 15:06:16 +0000</pubDate>
      <link>https://dev.to/itsadijmbt/how-i-manually-set-up-the-vprofile-stack-lessons-i-wish-someone-told-me-5do4</link>
      <guid>https://dev.to/itsadijmbt/how-i-manually-set-up-the-vprofile-stack-lessons-i-wish-someone-told-me-5do4</guid>
      <description>&lt;p&gt;&lt;strong&gt;Nginx&lt;/strong&gt;&lt;br&gt;
Always run nginx -t before restarting,it’s your safety net.&lt;br&gt;
&lt;em&gt;Only open the ports you actually use (80/443).&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Apache Tomcat&lt;/strong&gt;&lt;br&gt;
Create a separate user to run it, don’t use root!!!!!!.&lt;br&gt;
Set JAVA_HOME and CATALINA_HOME early,missing these will waste hours.&lt;br&gt;
Critical tip: After making a systemd service, run:&lt;br&gt;
&lt;em&gt;I lost so much time because I didn’t know this refreshes systemd’s brain.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;RabbitMQ&lt;/strong&gt;&lt;br&gt;
Change the default username/password immediately.&lt;br&gt;
&lt;em&gt;By default, it only listens on 127.0.0.1. If you need remote access, switch it to 0.0.0.0, but lock it down with a firewall.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Memcached&lt;/strong&gt;&lt;br&gt;
&lt;em&gt;If you must allow remote access, change it to 0.0.0.0 and secure it immediately.&lt;/em&gt;&lt;br&gt;
Give it enough memory but leave room for the other services to breathe.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;SQL Server&lt;/strong&gt;&lt;br&gt;
Create separate DB users with only the permissions they actually need.&lt;br&gt;
Final takeaway: Doing it manually forces you to understand not just what to install, but why each part is there, how they talk to each other, and where things break.&lt;br&gt;
&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F17zkmmnt6rxtun7zl8n4.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F17zkmmnt6rxtun7zl8n4.png" alt=" " width="389" height="635"&gt;&lt;/a&gt;&lt;/p&gt;

</description>
      <category>devops</category>
      <category>linux</category>
    </item>
  </channel>
</rss>
