<?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: Samuel Ajisafe</title>
    <description>The latest articles on DEV Community by Samuel Ajisafe (@sammy_cloud).</description>
    <link>https://dev.to/sammy_cloud</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%2F1303355%2F12ebd71c-d63e-452f-9c9b-d8d210b4a980.JPG</url>
      <title>DEV Community: Samuel Ajisafe</title>
      <link>https://dev.to/sammy_cloud</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/sammy_cloud"/>
    <language>en</language>
    <item>
      <title>Beyond the Switchover: Using RDS Snapshots to Safely Test MySQL 8.4 Compatibility Before Your Blue/Green Cutover</title>
      <dc:creator>Samuel Ajisafe</dc:creator>
      <pubDate>Thu, 13 Aug 2026 20:16:53 +0000</pubDate>
      <link>https://dev.to/sammy_cloud/beyond-the-switchover-using-rds-snapshots-to-safely-test-mysql-84-compatibility-before-your-2991</link>
      <guid>https://dev.to/sammy_cloud/beyond-the-switchover-using-rds-snapshots-to-safely-test-mysql-84-compatibility-before-your-2991</guid>
      <description>&lt;h2&gt;
  
  
  AWS RDS Blue/Green deployment is a powerful zero-downtime tool, but its Green environment is read-only by design. Here is how to layer a snapshot-based test instance on top of it to validate application compatibility before committing to the full switchover.
&lt;/h2&gt;

&lt;p&gt;There is a moment every DevOps engineer, DBA, and SRE dreads: a database engine reaches end-of-life, AWS begins billing you for Extended Support, and the upgrade clock is ticking. For MySQL 8.0, that moment arrived in 2026. AWS began charging Extended Support fees for any RDS instance still running 8.0, and teams across the industry started planning migrations to MySQL 8.4, the current Long Term Support (LTS) release.&lt;/p&gt;

&lt;p&gt;AWS provides an excellent managed feature for this exact scenario: &lt;strong&gt;RDS Blue/Green Deployments&lt;/strong&gt;. It is powerful, well-documented, and purpose-built for zero-downtime upgrades. But there is a constraint baked into how it works that trips up a lot of engineers the first time they reach for it, and it becomes a real blocker when you are managing a shared RDS instance across multiple projects with different readiness timelines.&lt;/p&gt;

&lt;p&gt;This post documents exactly what that constraint is, why it exists, what error you will see in your application logs, and how to layer a snapshot-based testing pattern on top of Blue/Green to get the best of both worlds: safe compatibility validation per project, followed by a single zero-downtime cutover for everything.&lt;/p&gt;




&lt;h2&gt;
  
  
  The Context: A Shared RDS Instance Serving Multiple Projects
&lt;/h2&gt;

&lt;p&gt;Picture a common real-world setup. You have one RDS MySQL 8.0 instance - call it &lt;code&gt;proddb&lt;/code&gt; - running in us-east-1. It hosts several logical databases across seven different projects/environments: a SaaS platform in Node.js, several Laravel applications, a portfolio site. Some of these applications have been running for years. The code was written before MySQL 8.4 existed. You have no guarantee that everything will work after the engine upgrade.&lt;/p&gt;

&lt;p&gt;You cannot afford to do a big bang upgrade. If one application breaks on MySQL 8.4, you need the others to continue running on the working engine while you fix it. You need a way to validate each project individually before committing everything.&lt;/p&gt;

&lt;p&gt;This is the scenario where Blue/Green deployments look like the perfect answer - and they are, but not in the way you might initially expect.&lt;/p&gt;




&lt;h2&gt;
  
  
  What AWS RDS Blue/Green Deployment Actually Does
&lt;/h2&gt;

&lt;p&gt;Before getting into the limitation, it is worth being precise about what Blue/Green deployment is and why it exists.&lt;/p&gt;

&lt;p&gt;When you create a Blue/Green deployment in RDS, AWS provisions a &lt;strong&gt;Green environment&lt;/strong&gt; that is an exact replica of your &lt;strong&gt;Blue environment&lt;/strong&gt; (your current production instance). RDS manages the replication between them automatically, using physical replication for MySQL. The Green instance stays continuously synchronised with Blue. Your schema, your data, your parameter groups - everything is mirrored.&lt;/p&gt;

&lt;p&gt;The workflow is designed like this:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Create the Blue/Green deployment&lt;/li&gt;
&lt;li&gt;Upgrade the Green instance to MySQL 8.4 (you do this manually after creation, or configure it during setup)&lt;/li&gt;
&lt;li&gt;Test the Green environment&lt;/li&gt;
&lt;li&gt;Trigger the switchover&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;During switchover, AWS stops writes to Blue, waits for replication lag to reach zero, renames the instances (Green takes the original Blue endpoint, Blue gets an &lt;code&gt;-old1&lt;/code&gt; suffix and is set to read-only), and brings write traffic live on the new MySQL 8.4 instance. Typical downtime for single-region configurations is under five seconds. The old Blue instance is retained so you can roll back if needed.&lt;/p&gt;

&lt;p&gt;This is genuinely excellent engineering. For a planned, coordinated upgrade where all your applications are ready to move at the same time, it is the right tool.&lt;/p&gt;




&lt;h2&gt;
  
  
  The Constraint You Will Hit: Green Is Read-Only by Design
&lt;/h2&gt;

&lt;p&gt;Here is where the trouble starts if your goal is gradual, per-project migration.&lt;/p&gt;

&lt;p&gt;The AWS documentation is explicit about this:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;"During testing, we recommend that you keep your databases in the green environment read only. Enable write operations on the green environment with caution because they can result in replication conflicts. They can also result in unintended data in the production databases after switchover."&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;The Green environment is &lt;strong&gt;read-only by default&lt;/strong&gt;. RDS sets the &lt;code&gt;read_only&lt;/code&gt; parameter to &lt;code&gt;1&lt;/code&gt; on the Green instance to protect replication integrity. If writes reach the Green during the testing phase, they could cause replication conflicts and potentially corrupt data that flows back after switchover.&lt;/p&gt;

&lt;p&gt;There is a technical reason for this. MySQL physical replication works by replaying binary log events from the Blue primary on the Green replica. If you write directly to the Green instance, those writes are not in the Blue binlog. When the switchover happens and the old Blue becomes the replica, those writes have no origin on the Blue side. The replication relationship breaks, or worse, data that was never in production gets silently promoted into what is now your production database.&lt;/p&gt;

&lt;p&gt;AWS therefore makes the protection the default. You can override it with a parameter group change, but the official guidance is to leave it alone.&lt;/p&gt;




&lt;h2&gt;
  
  
  What This Looks Like in Your Application Logs
&lt;/h2&gt;

&lt;p&gt;If you follow the logical path - "I have a Green instance running MySQL 8.4, let me point my Dev application at it and test" - this is the error you will see immediately:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nb"&gt;Error&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;The&lt;/span&gt; &lt;span class="nx"&gt;MySQL&lt;/span&gt; &lt;span class="nx"&gt;server&lt;/span&gt; &lt;span class="nx"&gt;is&lt;/span&gt; &lt;span class="nx"&gt;running&lt;/span&gt; &lt;span class="kd"&gt;with&lt;/span&gt; &lt;span class="nx"&gt;the&lt;/span&gt; &lt;span class="o"&gt;--&lt;/span&gt;&lt;span class="nx"&gt;read&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;only&lt;/span&gt; &lt;span class="nx"&gt;option&lt;/span&gt;
       &lt;span class="nx"&gt;so&lt;/span&gt; &lt;span class="nx"&gt;it&lt;/span&gt; &lt;span class="nx"&gt;cannot&lt;/span&gt; &lt;span class="nx"&gt;execute&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt; &lt;span class="nx"&gt;statement&lt;/span&gt;
    &lt;span class="nx"&gt;at&lt;/span&gt; &lt;span class="nx"&gt;PromisePool&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;query &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sr"&gt;/app/&lt;/span&gt;&lt;span class="nx"&gt;node_modules&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="nx"&gt;express&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;mysql&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;session&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;
       &lt;span class="nx"&gt;node_modules&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="nx"&gt;mysql2&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="nx"&gt;promise&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;js&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;356&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;22&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="nx"&gt;at&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="nx"&gt;app&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="nx"&gt;node_modules&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="nx"&gt;express&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;mysql&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;session&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="nx"&gt;index&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;js&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;384&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;30&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;code&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;ER_OPTION_PREVENTS_STATEMENT&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;errno&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;1290&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;sql&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;INSERT INTO `sessions` (`session_id`, `expires`, `data`)
        VALUES (&lt;/span&gt;&lt;span class="se"&gt;\'&lt;/span&gt;&lt;span class="s1"&gt;KYzPpAzZpm9vHHp7WI_6W7H0UHkBHnaq&lt;/span&gt;&lt;span class="se"&gt;\'&lt;/span&gt;&lt;span class="s1"&gt;, 1786734753,
        &lt;/span&gt;&lt;span class="se"&gt;\'&lt;/span&gt;&lt;span class="s1"&gt;{"cookie":...}&lt;/span&gt;&lt;span class="se"&gt;\'&lt;/span&gt;&lt;span class="s1"&gt;)
        ON DUPLICATE KEY UPDATE `expires` = VALUES(`expires`),
        `data` = VALUES(`data`)&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;sqlState&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;HY000&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;sqlMessage&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;The MySQL server is running with the --read-only
               option so it cannot execute this statement&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This surfaces immediately on the first write operation - in this case, the session store trying to persist a session record during an ELB health check. The application cannot even initialise properly. The cascade is:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;ELB health checker hits &lt;code&gt;/admin/login&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Application attempts to create or update a session record in MySQL&lt;/li&gt;
&lt;li&gt;Green instance rejects the write with &lt;code&gt;ER_OPTION_PREVENTS_STATEMENT&lt;/code&gt; (errno 1290)&lt;/li&gt;
&lt;li&gt;Application returns HTTP 500&lt;/li&gt;
&lt;li&gt;A secondary error &lt;code&gt;ERR_HTTP_HEADERS_SENT&lt;/code&gt; follows because the error handler tries to write a response after the response has already been partially sent&lt;/li&gt;
&lt;li&gt;Health check fails, ELB marks the target unhealthy
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="err"&gt;API&lt;/span&gt;&lt;span class="p"&gt;][&lt;/span&gt;&lt;span class="err"&gt;/admin/login&lt;/span&gt;&lt;span class="p"&gt;][&lt;/span&gt;&lt;span class="mi"&gt;500&lt;/span&gt;&lt;span class="p"&gt;][&lt;/span&gt;&lt;span class="err"&gt;user_id:-&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"request_id"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="s2"&gt;"msrwaseu-3r7f2m"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"method"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="s2"&gt;"GET"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"duration_ms"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;29&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"headers"&lt;/span&gt;&lt;span class="p"&gt;:{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"host"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="s2"&gt;"172.31.3.155:4000"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"user-agent"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="s2"&gt;"ELB-HealthChecker/2.0"&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="err"&gt;Error&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="err"&gt;ERR_HTTP_HEADERS_SENT&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="err"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;Cannot&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;set&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;headers&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;after&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;they&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;are&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;sent&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;to&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;the&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;client&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="err"&gt;at&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;ServerResponse.setHeader&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;(node:_http_outgoing:&lt;/span&gt;&lt;span class="mi"&gt;655&lt;/span&gt;&lt;span class="err"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;11&lt;/span&gt;&lt;span class="err"&gt;)&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="err"&gt;at&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;ServerResponse.header&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;(/app/node_modules/express/lib/response.js:&lt;/span&gt;&lt;span class="mi"&gt;684&lt;/span&gt;&lt;span class="err"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="err"&gt;)&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The &lt;code&gt;ERR_HTTP_HEADERS_SENT&lt;/code&gt; error is a cascade failure, not the root cause. Fix the MySQL read-only problem and this disappears with it.&lt;/p&gt;

&lt;p&gt;The important thing to understand is that &lt;strong&gt;this is not a misconfiguration on your part&lt;/strong&gt;. The Green instance is behaving exactly as designed. You pointed an application with write operations at a managed replica. The replica correctly refused the writes.&lt;/p&gt;




&lt;h2&gt;
  
  
  Why the Naive Fixes Do Not Work
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;"Can I just set &lt;code&gt;read_only=0&lt;/code&gt; on the Green instance via a parameter group?"&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Technically yes. The &lt;code&gt;read_only&lt;/code&gt; parameter is dynamic in MySQL, meaning you can change it without a reboot. Some community members on AWS rePost have suggested this as a workaround. However, AWS's own guidance explicitly warns against it because it breaks the replication integrity guarantee. If your application writes data to the Green during testing and that data does not exist on Blue, the switchover will either fail guardrail checks or promote inconsistent data. This is not a theoretical risk - it is the exact failure mode the read-only default exists to prevent.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;"Can I just do the switchover now and test on the new production instance?"&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;This defeats the purpose of testing before the switchover. If your application breaks on MySQL 8.4 and you have already cut over, you are now dealing with a production incident. The rollback path (replicating from the new MySQL 8.4 back to the old &lt;code&gt;-old1&lt;/code&gt; MySQL 8.0 instance using binlog position) is complex and time-sensitive.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;"Can I selectively switchover just one project's database?"&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;No. Blue/Green deployment is an instance-level operation, not a database-level operation. When you trigger the switchover, every logical database on the instance moves simultaneously. You cannot switch one logical database while leaving others on Blue.&lt;/p&gt;




&lt;h2&gt;
  
  
  The Solution: Snapshot the Green, Test in Isolation, Switch Everything at Once
&lt;/h2&gt;

&lt;p&gt;This is the pattern that gives you everything:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Per-project compatibility testing against a writable MySQL 8.4 instance&lt;/li&gt;
&lt;li&gt;Replication on the Blue/Green deployment continues uninterrupted throughout&lt;/li&gt;
&lt;li&gt;A single managed switchover when all projects are validated&lt;/li&gt;
&lt;li&gt;No manual dump and restore for any project at cutover time&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Here is how it works.&lt;/p&gt;

&lt;h3&gt;
  
  
  Step 1: Keep your Blue/Green deployment intact and revert your application immediately
&lt;/h3&gt;

&lt;p&gt;If you pointed an application at the Green endpoint and it is throwing 500s, revert &lt;code&gt;DB_HOST&lt;/code&gt; in your secrets manager or SSM Parameter Store back to the Blue endpoint and redeploy. Get the application healthy again first.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;aws ssm put-parameter &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--name&lt;/span&gt; &lt;span class="s2"&gt;"/your-project/dev/DB_HOST"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--value&lt;/span&gt; &lt;span class="s2"&gt;"proddb.xxxxxxxx.us-east-1.rds.amazonaws.com"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--type&lt;/span&gt; &lt;span class="s2"&gt;"String"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--overwrite&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--region&lt;/span&gt; us-east-1
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Do not delete the Blue/Green deployment. It is doing its job. Replication is running, the Green is staying synchronised with Blue, and you will use it for the final switchover.&lt;/p&gt;

&lt;h3&gt;
  
  
  Step 2: Take a snapshot of the Green instance
&lt;/h3&gt;

&lt;p&gt;In the AWS Console, navigate to Databases, select your Green instance (&lt;code&gt;proddb-green-grigwa&lt;/code&gt; in this example), and choose Actions - Take snapshot. Give it a descriptive name like &lt;code&gt;green-84-compat-test-20260813&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Via CLI:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;aws rds create-db-snapshot &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--db-instance-identifier&lt;/span&gt; proddb-green-grigwa &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--db-snapshot-identifier&lt;/span&gt; green-84-compat-test-20260813 &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--region&lt;/span&gt; us-east-1
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Wait for the snapshot status to reach &lt;code&gt;available&lt;/code&gt;. This typically takes a few minutes.&lt;/p&gt;

&lt;h3&gt;
  
  
  Step 3: Restore the snapshot as a standalone MySQL 8.4 instance
&lt;/h3&gt;

&lt;p&gt;Restore the snapshot as a new, independent DB instance. This instance is not part of any Blue/Green deployment, not a replica of anything, and is fully writable from the moment it comes online.&lt;/p&gt;

&lt;p&gt;In the console: RDS - Snapshots - select your snapshot - Actions - Restore snapshot. Set the DB instance identifier to something clear like &lt;code&gt;proddb-84-test&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Via CLI:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;aws rds restore-db-instance-from-db-snapshot &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--db-instance-identifier&lt;/span&gt; proddb-84-test &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--db-snapshot-identifier&lt;/span&gt; green-84-compat-test-20260813 &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--db-instance-class&lt;/span&gt; db.t3.medium &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--vpc-security-group-ids&lt;/span&gt; sg-xxxxxxxxxx &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--db-subnet-group-name&lt;/span&gt; your-subnet-group &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--no-publicly-accessible&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--region&lt;/span&gt; us-east-1
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This instance contains every logical database from your Green snapshot, running on MySQL 8.4. It accepts full read/write operations. It costs the same as any other RDS instance of that class and size, prorated to the hours it runs - typically a few days at most for a dev validation exercise.&lt;/p&gt;

&lt;h3&gt;
  
  
  Step 4: Point your first project at the test instance and validate
&lt;/h3&gt;

&lt;p&gt;Update the &lt;code&gt;DB_HOST&lt;/code&gt; for your first project's dev environment to the test instance endpoint and redeploy.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;aws ssm put-parameter &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--name&lt;/span&gt; &lt;span class="s2"&gt;"/project/dev/DB_HOST"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--value&lt;/span&gt; &lt;span class="s2"&gt;"proddb-84-test.xxxxxxxx.us-east-1.rds.amazonaws.com"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--type&lt;/span&gt; &lt;span class="s2"&gt;"String"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--overwrite&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--region&lt;/span&gt; us-east-1
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now run your application against MySQL 8.4. Exercise every critical path: authentication flows, session management, file uploads, report generation, background jobs - whatever your application does. Check application logs for any MySQL 8.4 compatibility errors. Common ones to watch for include deprecated functions, changes to default values for SQL mode, and authentication plugin changes.&lt;/p&gt;

&lt;p&gt;All other projects remain on the Blue instance throughout this process. Your production workloads are completely unaffected.&lt;/p&gt;

&lt;h3&gt;
  
  
  Step 5: Validate additional projects as they are ready
&lt;/h3&gt;

&lt;p&gt;For each subsequent project, either point it at the same test instance (all logical databases are present since the snapshot captured everything) or repeat the process per environment. The test instance holds a point-in-time copy of every database. For projects that have been running production writes since the snapshot was taken, you may want to do a fresh &lt;code&gt;mysqldump&lt;/code&gt; of just that logical database from Blue and restore it into the test instance to get current data for realistic testing. But for application compatibility validation, the snapshot data is usually sufficient.&lt;/p&gt;

&lt;h3&gt;
  
  
  Step 6: Delete the test instance and trigger the Blue/Green switchover
&lt;/h3&gt;

&lt;p&gt;Once every project that shares the RDS instance is validated on MySQL 8.4, delete the test instance. It has served its purpose and you no longer need to pay for it.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;aws rds delete-db-instance &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--db-instance-identifier&lt;/span&gt; proddb-84-test &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--skip-final-snapshot&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--region&lt;/span&gt; us-east-1
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then trigger the switchover on your Blue/Green deployment. Because replication has been running continuously throughout the entire testing phase, the Green instance is fully synchronised with Blue. The switchover is clean, the downtime is under five seconds, and every project moves to MySQL 8.4 simultaneously with no manual dump or restore required.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;aws rds switchover-blue-green-deployment &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--blue-green-deployment-identifier&lt;/span&gt; bgd-xxxxxxxxxx &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--switchover-timeout&lt;/span&gt; 300 &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--region&lt;/span&gt; us-east-1
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;After switchover, the original Blue endpoint now points to the MySQL 8.4 instance. All your applications that were pointing at the Blue endpoint continue working without any &lt;code&gt;DB_HOST&lt;/code&gt; changes. The old MySQL 8.0 instance is retained with an &lt;code&gt;-old1&lt;/code&gt; suffix. Keep it for at least 24-48 hours as a rollback option, then delete it once you are confident everything is stable.&lt;/p&gt;




&lt;h2&gt;
  
  
  Why This Pattern Works: The SRE Reasoning
&lt;/h2&gt;

&lt;p&gt;This approach is grounded in a core SRE principle: &lt;strong&gt;validate before you commit, not while you commit&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Blue/Green deployment is optimised for the commitment phase - the actual cutover. It gives you replication, endpoint swapping, automatic rollback, and near-zero downtime. What it does not give you is a writable staging environment for compatibility testing, because enabling writes on the Green would compromise the very replication integrity that makes the switchover safe.&lt;/p&gt;

&lt;p&gt;The snapshot test instance fills exactly that gap. It is an isolated sandbox that costs almost nothing for a short-lived validation exercise. It carries no risk to the Blue/Green replication. If the application breaks badly on MySQL 8.4 on the test instance, you simply delete the test instance, fix the code, create a new snapshot from the Green (which has continued replicating and is still current), and restore again. The Blue/Green deployment is completely untouched.&lt;/p&gt;

&lt;p&gt;This is &lt;strong&gt;defence in depth for database migrations&lt;/strong&gt;: one layer for safety (Blue/Green with continuous replication and managed switchover), one layer for confidence (snapshot-based isolated testing with full read/write access).&lt;/p&gt;




&lt;h2&gt;
  
  
  Summary: The Full Migration Sequence
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Phase&lt;/th&gt;
&lt;th&gt;Action&lt;/th&gt;
&lt;th&gt;Blue/Green Replication&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;1&lt;/td&gt;
&lt;td&gt;Create Blue/Green deployment, upgrade Green to MySQL 8.4&lt;/td&gt;
&lt;td&gt;Running&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;2&lt;/td&gt;
&lt;td&gt;Take snapshot of Green instance&lt;/td&gt;
&lt;td&gt;Running&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;3&lt;/td&gt;
&lt;td&gt;Restore snapshot as standalone writable test instance&lt;/td&gt;
&lt;td&gt;Running&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;4&lt;/td&gt;
&lt;td&gt;Point project Dev environment at test instance, validate&lt;/td&gt;
&lt;td&gt;Running&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;5&lt;/td&gt;
&lt;td&gt;Fix any MySQL 8.4 compatibility issues in application code&lt;/td&gt;
&lt;td&gt;Running&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;6&lt;/td&gt;
&lt;td&gt;Repeat for each project and environment as ready&lt;/td&gt;
&lt;td&gt;Running&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;7&lt;/td&gt;
&lt;td&gt;Delete test instance&lt;/td&gt;
&lt;td&gt;Running&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;8&lt;/td&gt;
&lt;td&gt;Trigger Blue/Green switchover - all projects move at once&lt;/td&gt;
&lt;td&gt;Completes&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;9&lt;/td&gt;
&lt;td&gt;Validate production, delete old Blue instance&lt;/td&gt;
&lt;td&gt;Done&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;




&lt;h2&gt;
  
  
  Things to Keep in Mind
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Snapshot data is a point in time.&lt;/strong&gt; The test instance holds data as of the moment you took the snapshot. For high-volume databases, the data on the test instance may be hours or days old by the time you finish testing. This is fine for compatibility validation. If you need realistic load testing with current data volumes, consider scripting a fresh snapshot restore closer to your planned switchover date.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The test instance incurs cost.&lt;/strong&gt; Even a db.t3.micro or db.t3.medium running for three days is a small number, but track it. Delete the test instance as soon as validation is complete. It has no reason to linger.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;MySQL 8.4 changes the default authentication plugin.&lt;/strong&gt; If your application uses &lt;code&gt;mysql_native_password&lt;/code&gt;, check whether your database users are configured correctly on the Green instance. MySQL 8.4 makes &lt;code&gt;caching_sha2_password&lt;/code&gt; the default. Most modern MySQL client libraries handle this transparently, but older applications or direct connection strings may surface authentication errors during testing.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Run the MySQL Shell upgrade checker before any of this.&lt;/strong&gt; The AWS blog post on MySQL 8.0 to 8.4 upgrades recommends restoring a snapshot of your 8.0 Blue instance and running &lt;code&gt;mysqlsh -- util check-for-server-upgrade&lt;/code&gt; against it before you even create the Blue/Green deployment. This catches error-level incompatibilities (corrupted tables, deprecated syntax, partitioning issues) before you spend time on the migration pipeline.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Pre-switchover, monitor ReplicaLag.&lt;/strong&gt; Before triggering the switchover, confirm the &lt;code&gt;ReplicaLag&lt;/code&gt; CloudWatch metric on the Green instance is at or near zero. A switchover with significant lag means a longer write blackout window while RDS waits for the Green to catch up.&lt;/p&gt;




&lt;h2&gt;
  
  
  Closing Thoughts
&lt;/h2&gt;

&lt;p&gt;RDS Blue/Green deployment is not a limitation to work around - it is the right tool for the final mile of a database upgrade. The read-only Green environment is not a bug; it is an intentional protection that keeps your data consistent through the switchover.&lt;/p&gt;

&lt;p&gt;The pattern described here does not replace Blue/Green. It layers a temporary, low-cost, isolated testing environment on top of it so that by the time you press the switchover button, you have already confirmed that every application works correctly on the new engine. The switchover becomes a formality rather than a risk event.&lt;/p&gt;

&lt;p&gt;For any engineering team managing a shared RDS instance across multiple projects with different codebase ages and readiness timelines, this two-layer approach - snapshot test instance for validation, Blue/Green for the cutover - is the pattern that gives you both site reliability and migration confidence.&lt;/p&gt;




&lt;h2&gt;
  
  
  References
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://docs.aws.amazon.com/AmazonRDS/latest/UserGuide/blue-green-deployments-overview.html" rel="noopener noreferrer"&gt;AWS Documentation: Overview of Amazon RDS Blue/Green Deployments&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://docs.aws.amazon.com/AmazonRDS/latest/UserGuide/blue-green-deployments-switching.html" rel="noopener noreferrer"&gt;AWS Documentation: Switching a Blue/Green Deployment in Amazon RDS&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://docs.aws.amazon.com/AmazonRDS/latest/UserGuide/blue-green-deployments-considerations.html" rel="noopener noreferrer"&gt;AWS Documentation: Limitations and Considerations for RDS Blue/Green Deployments&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://aws.amazon.com/blogs/database/best-practices-for-upgrading-amazon-rds-for-mysql-8-0-to-8-4-with-prechecks-blue-green-and-rollback/" rel="noopener noreferrer"&gt;AWS Blog: Best Practices for Upgrading Amazon RDS for MySQL 8.0 to 8.4&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://aws.amazon.com/blogs/database/upgrade-strategies-for-amazon-rds-for-mysql-8-0-to-8-4/" rel="noopener noreferrer"&gt;AWS Blog: Upgrade Strategies for Amazon RDS for MySQL 8.0 to 8.4&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://repost.aws/questions/QUL5Pw6ok1Q9y7tfy8mqxuEg/how-to-enable-write-operations-on-mysql-rds-green-environment" rel="noopener noreferrer"&gt;AWS re:Post: How to Enable Write Operations on MySQL RDS Green Environment&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>aws</category>
      <category>mysql</category>
      <category>devops</category>
      <category>sre</category>
    </item>
    <item>
      <title>Fixing the AWS Amplify “Make SSL Changes and Try Again” Error (Root Cause &amp; Solution)</title>
      <dc:creator>Samuel Ajisafe</dc:creator>
      <pubDate>Fri, 28 Nov 2025 18:36:42 +0000</pubDate>
      <link>https://dev.to/sammy_cloud/fixing-the-aws-amplify-make-ssl-changes-and-try-again-error-root-cause-solution-47l7</link>
      <guid>https://dev.to/sammy_cloud/fixing-the-aws-amplify-make-ssl-changes-and-try-again-error-root-cause-solution-47l7</guid>
      <description>&lt;h2&gt;
  
  
  &lt;strong&gt;Introduction&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;Connecting a custom domain to AWS Amplify should be simple but sometimes you may run into this frustrating error:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Make SSL changes and try again.
Consult the troubleshooting guide, make any necessary changes, and retry activation.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If you’ve spent hours checking DNS records, regenerating SSL certificates, or digging through AWS documentation with no luck—you’re not alone. I recently encountered this issue while supporting a customer, and after extensive troubleshooting, I discovered the real root cause that AWS doesn't clearly point out.&lt;/p&gt;

&lt;p&gt;This post walks you through the exact problem and the simple fix that finally resolved it.&lt;/p&gt;




&lt;h2&gt;
  
  
  ❗️The Error in Amplify
&lt;/h2&gt;

&lt;p&gt;When activating a custom domain in AWS Amplify, you may see:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Make SSL changes and try again.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Amplify advises you to check the SSL configuration, but the real issue is usually &lt;em&gt;not&lt;/em&gt; related to your certificate at all.&lt;/p&gt;




&lt;h2&gt;
  
  
  ⚡ My Troubleshooting Journey
&lt;/h2&gt;

&lt;p&gt;Like most engineers, I started with the standard checks:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Regenerating the SSL certificate&lt;/li&gt;
&lt;li&gt;Ensuring the certificate was issued in &lt;strong&gt;us-east-1&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;Validating domain and subdomain spelling&lt;/li&gt;
&lt;li&gt;Reviewing Route 53 DNS records&lt;/li&gt;
&lt;li&gt;Searching AWS &lt;a href="https://repost.aws/questions/QUphbiu8VLTOKeXAtBf-8ERw/i-get-a-cnamealreadyexistsexception-error" rel="noopener noreferrer"&gt;re:Post&lt;/a&gt;, StackOverflow, and several AI agents&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Nothing worked.&lt;/p&gt;

&lt;p&gt;At that point, I decided to isolate every possible cause manually. That’s when I noticed something that Amplify does not highlight clearly.&lt;/p&gt;




&lt;h2&gt;
  
  
  🧠 Understanding the Real Root Cause
&lt;/h2&gt;

&lt;p&gt;AWS Amplify, although regionally displayed in the console, behaves like a &lt;strong&gt;global service&lt;/strong&gt; when it comes to domain management similar to S3, CloudFront.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;This means:&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;👉 You &lt;strong&gt;cannot map the same domain or subdomain to more than one Amplify app&lt;/strong&gt;, even if the other app is old, inactive, or already deleted from your current workflows.&lt;/p&gt;

&lt;p&gt;If a domain or subdomain is still attached to ANY Amplify or CloudFront project anywhere in AWS Accounts, the new SSL validation will fail silently and repeatedly.&lt;/p&gt;

&lt;p&gt;Also another scenario is the customer already tried using cloudfront and has created the same domain as “Alternate name” for the distribution&lt;/p&gt;

&lt;p&gt;Amplify does not explicitly warn you that the domain is already mapped somewhere else—making the error appear unrelated.&lt;/p&gt;




&lt;h2&gt;
  
  
  ✔️ The Solution That Worked
&lt;/h2&gt;

&lt;p&gt;When I asked the client whether they had an older Amplify app before migrating, they confirmed &lt;em&gt;yes&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;That old app still had the domain attached and was blocking SSL activation.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Fix Steps:&lt;/strong&gt;
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;Go to the previous Amplify app (if deleted, check the Amplify console history).&lt;/li&gt;
&lt;li&gt;Remove any &lt;strong&gt;custom domain mappings&lt;/strong&gt;. If Cloudfront, ensure the Distribution is disabled and deleted&lt;/li&gt;
&lt;li&gt;Return to the new Amplify app.&lt;/li&gt;
&lt;li&gt;Re-add the domain.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;After deleting the old domain mapping, the SSL validation completed instantly.&lt;/p&gt;




&lt;h2&gt;
  
  
  🛠 Code Snippet — Domain Cleanup (If Using CLI)
&lt;/h2&gt;

&lt;p&gt;If you manage Amplify via CLI, you can list and remove domain mappings like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# List domain associations for an Amplify app&lt;/span&gt;
aws amplify list-domain-associations &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--app-id&lt;/span&gt; YOUR_APP_ID

&lt;span class="c"&gt;# Delete an old domain mapping&lt;/span&gt;
aws amplify delete-domain-association &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--app-id&lt;/span&gt; YOUR_APP_ID &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--domain-name&lt;/span&gt; yourdomain.com
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






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

&lt;p&gt;This issue is surprisingly common, and the fix is much simpler than the error message implies.&lt;br&gt;
If you’re stuck on the SSL activation step in AWS Amplify:&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Always check whether your domain or subdomain is mapped to another Amplify app or CloudFront Distribution.&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Removing that mapping is often the key to solving the problem instantly.&lt;/p&gt;

</description>
      <category>aws</category>
      <category>amplify</category>
      <category>cloud</category>
      <category>devops</category>
    </item>
    <item>
      <title>How to Setup Pritunl on Amazon Linux 2023 | Centos | RedHAT</title>
      <dc:creator>Samuel Ajisafe</dc:creator>
      <pubDate>Thu, 21 Aug 2025 22:02:35 +0000</pubDate>
      <link>https://dev.to/sammy_cloud/how-to-setup-pritunl-on-amazon-linux-2023-centos-redhat-2n1l</link>
      <guid>https://dev.to/sammy_cloud/how-to-setup-pritunl-on-amazon-linux-2023-centos-redhat-2n1l</guid>
      <description>&lt;p&gt;Unlock Your Secure Network: A Step-by-Step Guide to Setting up Pritunl VPN on Amazon Linux 2023 🚀&lt;/p&gt;

&lt;p&gt;Welcome back! Following the great feedback on my last guide for setting up Pritunl VPN on &lt;a href="https://dev.to/sammy_cloud/how-to-setup-pritunl-on-ubuntu-server-5g8d"&gt;Ubuntu&lt;/a&gt;, I'm excited to dive into a new environment. This time, we're tackling Amazon Linux 2023, a fantastic choice given its long-term support (EOL is still years away). This guide will get your secure VPN server up and running, and I'll be sure to update it as new versions are released.&lt;/p&gt;

&lt;p&gt;So, let's get started and secure your network! 🔒&lt;/p&gt;

&lt;p&gt;Prerequisites: Setting the Stage 🛠️&lt;br&gt;
Before we dive into the Pritunl setup, we need to ensure our system is ready. This involves installing Docker and Docker Compose, which we'll use to run Pritunl in a containerized environment. This approach is clean, efficient, and avoids conflicts with other software on your server.&lt;/p&gt;

&lt;p&gt;Bash&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# Install Docker
sudo dnf install -y docker

# Start and enable the Docker service
sudo systemctl start docker
sudo systemctl enable docker

# Add your user to the docker group to run Docker commands without sudo
sudo usermod -aG docker $USER

# Install Docker Compose as a plugin for the Docker CLI
sudo curl -SL https://github.com/docker/compose/releases/latest/download/docker-compose-linux-$(uname -m) -o /usr/libexec/docker/cli-plugins/docker-compose
sudo chmod +x /usr/libexec/docker/cli-plugins/docker-compose
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Note: After running the usermod command, it's best to log out and log back in (or run newgrp docker) for the changes to take effect.&lt;/p&gt;

&lt;p&gt;Step 1: Configuring the System for VPN Traffic ⚙️&lt;br&gt;
Pritunl requires specific system settings to handle VPN traffic correctly. We'll set up iptables rules and enable IP forwarding, which are crucial for routing traffic through the VPN tunnel.&lt;/p&gt;

&lt;p&gt;Bash&lt;/p&gt;
&lt;h1&gt;
  
  
  Create a directory for our Pritunl configuration
&lt;/h1&gt;


&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;mkdir pritunl &amp;amp;&amp;amp; cd pritunl
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;h1&gt;
  
  
  Allow traffic to and from the VPN tunnel interface (tun+)
&lt;/h1&gt;


&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;sudo iptables -A FORWARD -i tun+ -j ACCEPT
sudo iptables -A FORWARD -o tun+ -j ACCEPT
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;h1&gt;
  
  
  Install iptables-services to persist the rules
&lt;/h1&gt;


&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;sudo dnf install -y iptables-services
sudo service iptables save
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;h1&gt;
  
  
  Enable IP forwarding, which allows packets to be forwarded between interfaces
&lt;/h1&gt;


&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;sudo sysctl -w net.ipv4.ip_forward=1
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;h1&gt;
  
  
  Make this change permanent
&lt;/h1&gt;


&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;echo 'net.ipv4.ip_forward=1' | sudo tee -a /etc/sysctl.conf
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;h1&gt;
  
  
  Load the TUN module, which is essential for the VPN tunnel
&lt;/h1&gt;


&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;sudo modprobe tun
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;h1&gt;
  
  
  Make the TUN module persistent on reboots
&lt;/h1&gt;


&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;echo 'tun' | sudo tee -a /etc/modules-load.d/tun.conf
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Step 2: Deploying Pritunl with Docker Compose 🐳&lt;br&gt;
Now, let's define our Pritunl container using a docker-compose.yml file. This file simplifies the deployment process, ensuring all dependencies are handled correctly.&lt;/p&gt;

&lt;p&gt;Bash&lt;/p&gt;
&lt;h1&gt;
  
  
  Open a text editor to create the docker-compose.yml file
&lt;/h1&gt;


&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;sudo vi docker-compose.yml
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Paste the following configuration into the file:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;services:
  mongodb:
    image: mongo:latest
    container_name: mongodb
    restart: always
    network_mode: host
    volumes:
      - mongodb_data:/data/db

  pritunl:
    image: jippi/pritunl
    container_name: pritunl
    privileged: true
    restart: always
    network_mode: host
    volumes:
      - pritunl_data:/var/lib/pritunl
    devices:
      - /dev/net/tun:/dev/net/tun
    cap_add:
      - NET_ADMIN
      - SYS_MODULE
      - SYS_ADMIN
    environment:
      - PRITUNL_MONGODB_URI=mongodb://localhost:27017/pritunl
    depends_on:
      - mongodb
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Save the file and exit the editor. Now, launch the container with a single command:&lt;/p&gt;

&lt;p&gt;Bash&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;docker compose up -d
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This command will download the Pritunl image and start the container in the background.&lt;/p&gt;

&lt;p&gt;Step 3: Initial Setup &amp;amp; Configuration ✨&lt;br&gt;
With the container running, we need to retrieve the initial setup key and default credentials to access the web interface.&lt;/p&gt;

&lt;p&gt;Bash&lt;/p&gt;
&lt;h1&gt;
  
  
  Retrieve the Pritunl setup key
&lt;/h1&gt;


&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;docker exec pritunl pritunl setup-key
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;h1&gt;
  
  
  Retrieve the default username and password
&lt;/h1&gt;


&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;docker exec pritunl pritunl default-password
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;Note down these credentials carefully. Now, navigate to your server's public IP address &lt;code&gt;&amp;lt;https://ip-address&amp;gt;&lt;/code&gt; in a web browser. You'll be prompted to enter the setup key and then the default credentials to log in. The Port 443 must be Open on security Group&lt;/p&gt;

&lt;p&gt;Once inside the Pritunl admin console, you can create a new Server, add a User, and start the server. The final step is to create a crucial NAT rule to allow traffic to exit your server.&lt;/p&gt;

&lt;p&gt;While creating the Server, note down 2 things, UDP port and Virtual Network, UDP Port must be open on the EC2 Security Group, and the Virtual Network must be open must be used in the next command&lt;/p&gt;

&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%2F80piqq437l4l708gfgce.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%2F80piqq437l4l708gfgce.png" alt=" " width="602" height="372"&gt;&lt;/a&gt;&lt;/p&gt;

&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%2F5fwx66c3fhwzkwb9vvmc.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%2F5fwx66c3fhwzkwb9vvmc.png" alt=" " width="800" height="195"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This rule ensures VPN traffic can be routed out to the internet&lt;br&gt;
Replace 192.168.248.0/24 with your Pritunl server's network range if you change it&lt;br&gt;
Replace eth0 with your server's primary network interface&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;sudo iptables -t nat -A POSTROUTING -s 192.168.248.0/24 -o eth0 -j MASQUERADE
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Step 4: Final Touches on AWS ☁️&lt;br&gt;
If you're hosting this on AWS, you must open the necessary ports in your security group to allow clients to connect.&lt;/p&gt;

&lt;p&gt;HTTPS (TCP 443): Required for the Pritunl web interface and VPN connection.&lt;/p&gt;

&lt;p&gt;OpenVPN Ports (UDP): Pritunl uses a range of ports for its VPN tunnels. Check your server's configuration and open those specific ports. The default is often UDP 1194, but Pritunl can use others.&lt;/p&gt;

&lt;p&gt;By completing these steps, you've successfully deployed a robust and secure Pritunl VPN server. You can now download the client configuration file from the web interface and connect to your new private network.&lt;/p&gt;

&lt;p&gt;If you have any questions or run into issues, drop a comment below. Happy securing! &lt;/p&gt;

&lt;h1&gt;
  
  
  pritunl #vpn #vpnserver #amazonlinux2023 #centos #redhat #docker #dockercompose #openvpn #devops #linux #cloud #aws #tutorial #security #technology #howto
&lt;/h1&gt;

</description>
    </item>
    <item>
      <title>Access an EC2 Instance Using Session Manager (Even Without SSH Keys</title>
      <dc:creator>Samuel Ajisafe</dc:creator>
      <pubDate>Sat, 07 Jun 2025 15:00:14 +0000</pubDate>
      <link>https://dev.to/sammy_cloud/access-an-ec2-instance-using-session-manager-even-without-ssh-keys-la1</link>
      <guid>https://dev.to/sammy_cloud/access-an-ec2-instance-using-session-manager-even-without-ssh-keys-la1</guid>
      <description>&lt;p&gt;Sometimes you're dropped into an AWS environment where EC2 instances already exist — maybe from a team handover or an inherited project. But here's the issue:&lt;br&gt;
You don't have the SSH key pair to access the instances. It might have been lost, never shared, or never created in the first place.&lt;/p&gt;

&lt;p&gt;Thankfully, there are several ways to regain access:&lt;/p&gt;




&lt;h2&gt;
  
  
  Common Solutions When SSH Access is Lost
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;Use EC2 Instance Connect&lt;/li&gt;
&lt;li&gt;Use AWS Systems Manager Session Manager&lt;/li&gt;
&lt;li&gt;Create an AMI of the instance and launch a new one&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;While each option has its use case, the most secure, scalable, and production-friendly solution is Option 2 — Session Manager.&lt;/p&gt;




&lt;h2&gt;
  
  
  Why Session Manager is the Best Option
&lt;/h2&gt;

&lt;p&gt;Over time, I've seen many clients face this exact issue. In most cases, EC2 Instance Connect either doesn't work due to misconfigurations, or it's blocked by security groups and firewalls.&lt;/p&gt;

&lt;p&gt;Session Manager, on the other hand, works consistently and securely. Plus, it doesn't require any open ports — a huge win for environments with strict compliance requirements.&lt;/p&gt;

&lt;h3&gt;
  
  
  Benefits of Session Manager
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;No SSH keys or bastion hosts required&lt;/li&gt;
&lt;li&gt;No open inbound ports needed&lt;/li&gt;
&lt;li&gt;Works over AWS Systems Manager Agent (SSM Agent)&lt;/li&gt;
&lt;li&gt;Supports centralized logging (CloudWatch, S3)&lt;/li&gt;
&lt;li&gt;Secured via IAM and AWS KMS&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  First: Check if the Instance is Already Registered
&lt;/h2&gt;

&lt;p&gt;Before doing any configuration, verify whether your instance is already registered with Session Manager.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;Go to this link:&lt;br&gt;
&lt;a href="https://058264152527-7vncxtey.us-east-1.console.aws.amazon.com/systems-manager/session-manager/start-session?region=us-east-1#" rel="noopener noreferrer"&gt;Start a Session in AWS Session Manager&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Click "Start session".&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;If your instance is listed, you can connect directly — no further setup needed.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;If no instances appear, follow the steps below to enable access.&lt;/p&gt;

&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%2F0svxzk871lidjnjypt4b.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%2F0svxzk871lidjnjypt4b.png" alt=" " width="800" height="379"&gt;&lt;/a&gt;&lt;/p&gt;

&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%2Fwqegy382qcgsdkjo228r.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%2Fwqegy382qcgsdkjo228r.png" alt=" " width="800" height="413"&gt;&lt;/a&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  Step-by-Step: Enable Session Manager on EC2
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Step 1: Create an IAM Policy for Session Manager
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;Go to the &lt;a href="https://console.aws.amazon.com/iam/" rel="noopener noreferrer"&gt;IAM Console&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;In the sidebar, click "Policies" &amp;gt; "Create Policy".&lt;/li&gt;
&lt;li&gt;Select the &lt;strong&gt;JSON&lt;/strong&gt; tab and replace the contents with the following policy (adjust values as needed):
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"Version"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"2012-10-17"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"Statement"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"Effect"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Allow"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"Action"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="s2"&gt;"ssmmessages:CreateControlChannel"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="s2"&gt;"ssmmessages:CreateDataChannel"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="s2"&gt;"ssmmessages:OpenControlChannel"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="s2"&gt;"ssmmessages:OpenDataChannel"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="s2"&gt;"ssm:UpdateInstanceInformation"&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"Resource"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"*"&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"Effect"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Allow"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"Action"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="s2"&gt;"logs:CreateLogStream"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="s2"&gt;"logs:PutLogEvents"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="s2"&gt;"logs:DescribeLogGroups"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="s2"&gt;"logs:DescribeLogStreams"&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"Resource"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"*"&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"Effect"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Allow"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"Action"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="s2"&gt;"s3:PutObject"&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"Resource"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"arn:aws:s3:::your-bucket-name/s3-prefix/*"&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"Effect"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Allow"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"Action"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="s2"&gt;"s3:GetEncryptionConfiguration"&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"Resource"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"*"&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"Effect"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Allow"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"Action"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="s2"&gt;"kms:Decrypt"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="s2"&gt;"kms:GenerateDataKey"&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"Resource"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"arn:aws:kms:your-region:your-account-id:key/your-key-id"&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ol&gt;
&lt;li&gt;Click "Next: Tags" (optional).&lt;/li&gt;
&lt;li&gt;Click "Next: Review".&lt;/li&gt;
&lt;li&gt;Name the policy something like &lt;code&gt;SessionManagerPermissions&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Click "Create Policy".&lt;/li&gt;
&lt;/ol&gt;

&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%2F9ra1uc92g07g65zxr85d.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%2F9ra1uc92g07g65zxr85d.png" alt=" " width="800" height="403"&gt;&lt;/a&gt;&lt;/p&gt;




&lt;h3&gt;
  
  
  Step 2: Create an IAM Role for EC2 Instances
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;Go to "Roles" &amp;gt; "Create Role" in the IAM console.&lt;/li&gt;
&lt;li&gt;Select &lt;strong&gt;AWS service&lt;/strong&gt; as the trusted entity, and choose &lt;strong&gt;EC2&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;Click "Next".&lt;/li&gt;
&lt;li&gt;Attach the &lt;code&gt;SessionManagerPermissions&lt;/code&gt; policy you just created.&lt;/li&gt;
&lt;li&gt;Name the role something like &lt;code&gt;EC2SessionManagerRole&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Click "Create Role".&lt;/li&gt;
&lt;/ol&gt;

&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%2Fbvab4rcoxu4ns02bhldy.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%2Fbvab4rcoxu4ns02bhldy.png" alt=" " width="800" height="273"&gt;&lt;/a&gt;&lt;/p&gt;




&lt;h3&gt;
  
  
  Step 3: Attach the IAM Role to the EC2 Instance
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;Open the &lt;strong&gt;EC2 Console&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;Select the instance you want to access.&lt;/li&gt;
&lt;li&gt;Choose "Actions &amp;gt; Security &amp;gt; Modify IAM Role".&lt;/li&gt;
&lt;li&gt;Select the role you just created (&lt;code&gt;EC2SessionManagerRole&lt;/code&gt;).&lt;/li&gt;
&lt;li&gt;Click "Update IAM Role".&lt;/li&gt;
&lt;/ol&gt;

&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%2Fiw2nq3b4bsfxc47q47jn.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%2Fiw2nq3b4bsfxc47q47jn.png" alt=" " width="800" height="228"&gt;&lt;/a&gt;&lt;/p&gt;

&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%2Fjf808h4627zcjcgzvx2z.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%2Fjf808h4627zcjcgzvx2z.png" alt=" " width="800" height="273"&gt;&lt;/a&gt;&lt;/p&gt;




&lt;h3&gt;
  
  
  Step 4: Connect via Session Manager
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;Go to &lt;strong&gt;Systems Manager &amp;gt; Session Manager&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;Wait a few minutes — the instance should now appear.&lt;/li&gt;
&lt;li&gt;Click "Start session" and select your instance.&lt;/li&gt;
&lt;li&gt;Click "Connect".&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;You now have shell access to the EC2 instance — without SSH or open ports.&lt;/p&gt;

&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%2Fyv9w5y82d95d5d51alkl.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%2Fyv9w5y82d95d5d51alkl.png" alt=" " width="800" height="267"&gt;&lt;/a&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  Final Notes
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Ensure the &lt;strong&gt;SSM Agent&lt;/strong&gt; is installed and running. Most Amazon Linux, Ubuntu, and Windows AMIs include it by default.&lt;/li&gt;
&lt;li&gt;The instance &lt;strong&gt;must have internet access&lt;/strong&gt; (via a NAT Gateway or Internet Gateway) unless you're using &lt;strong&gt;VPC endpoints&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;Session Manager access is &lt;strong&gt;auditable&lt;/strong&gt;, &lt;strong&gt;secure&lt;/strong&gt;, and great for managing access at scale.&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Summary
&lt;/h2&gt;

&lt;p&gt;Session Manager is the go-to tool for securely accessing EC2 instances when SSH is not an option. Whether you're dealing with lost keys or just want to manage access more securely and efficiently — this is the approach I recommend and use in production environments.&lt;/p&gt;

&lt;p&gt;Let me know in the comments if you’ve used Session Manager or if you ran into any issues while setting it up.&lt;/p&gt;




&lt;h1&gt;
  
  
  AWSCommunityBuilder #Cloud #AWS #Server #Compute #SystemsManager #EC2 #Passwordless #DevOps
&lt;/h1&gt;

</description>
    </item>
    <item>
      <title>Send AWS CloudWatch Alerts to Google Chat Using SNS and Lambda</title>
      <dc:creator>Samuel Ajisafe</dc:creator>
      <pubDate>Wed, 09 Apr 2025 10:00:41 +0000</pubDate>
      <link>https://dev.to/sammy_cloud/aws-sns-integration-with-google-chat-aka-hangout-30na</link>
      <guid>https://dev.to/sammy_cloud/aws-sns-integration-with-google-chat-aka-hangout-30na</guid>
      <description>&lt;p&gt;Monitoring and alerting are key pillars of any production-grade AWS environment. In this guide, I’ll walk you through integrating &lt;strong&gt;AWS CloudWatch Alarms&lt;/strong&gt; with &lt;strong&gt;Google Chat&lt;/strong&gt; using &lt;strong&gt;Amazon SNS&lt;/strong&gt; and a &lt;strong&gt;Lambda function&lt;/strong&gt; ideal for teams using Google Workspace instead of Slack or Microsoft Teams.&lt;/p&gt;

&lt;h3&gt;
  
  
  🎯 Use Case
&lt;/h3&gt;

&lt;p&gt;My &lt;strong&gt;ECS service&lt;/strong&gt; scales up when CPU or memory exceeds 75%. I want real-time alerts in &lt;strong&gt;Google Chat&lt;/strong&gt;—not just email.&lt;/p&gt;

&lt;h2&gt;
  
  
  🚧 The Challenge
&lt;/h2&gt;

&lt;p&gt;While CloudWatch can trigger alarms and send notifications via &lt;strong&gt;SNS&lt;/strong&gt;, Google Chat isn't a native target. SNS supports protocols like email, Lambda, SQS, and HTTP/S—but &lt;strong&gt;not&lt;/strong&gt; Google Chat directly.&lt;/p&gt;

&lt;h3&gt;
  
  
  ✅ The Solution
&lt;/h3&gt;

&lt;p&gt;We can bridge the gap with this flow:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;CloudWatch Alarm → SNS Topic → Lambda Function → Google Chat Webhook
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  🧰 Prerequisites
&lt;/h2&gt;

&lt;p&gt;To complete this integration, you'll need:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;An AWS account with permission to create SNS topics and Lambda functions&lt;/li&gt;
&lt;li&gt;A Google Chat space with an active webhook URL&lt;/li&gt;
&lt;li&gt;Basic Python and AWS Lambda familiarity&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  🔧 Step 1: Set Up a Google Chat Webhook
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;In Google Chat, open or create a &lt;strong&gt;Space&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;Click the arrow next to the space name → &lt;strong&gt;Manage Webhooks&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;Click &lt;strong&gt;Add Webhook&lt;/strong&gt;, name it (e.g., &lt;code&gt;AWS Alerts&lt;/code&gt;), and copy the &lt;strong&gt;Webhook URL&lt;/strong&gt;.&lt;/li&gt;
&lt;/ol&gt;




&lt;h2&gt;
  
  
  🐍 Step 2: Write Your Lambda Function (Python)
&lt;/h2&gt;

&lt;p&gt;Create a simple Lambda function to forward SNS messages to Google Chat using &lt;code&gt;httplib2&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;lambda_function.py&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;httplib2&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;Http&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;json&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;dumps&lt;/span&gt;

&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;lambda_handler&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;event&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;url&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;&amp;lt;WEBHOOK-URL&amp;gt;&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;  &lt;span class="c1"&gt;# Replace with your actual webhook URL
&lt;/span&gt;    &lt;span class="n"&gt;message&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;text&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;event&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;Records&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;][&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;][&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;Sns&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;][&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;Message&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;]}&lt;/span&gt;
    &lt;span class="n"&gt;headers&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;Content-Type&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;application/json; charset=UTF-8&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="n"&gt;http_obj&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Http&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="n"&gt;response&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;http_obj&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;request&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="n"&gt;uri&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;url&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="n"&gt;method&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;POST&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="n"&gt;headers&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;headers&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="n"&gt;body&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nf"&gt;dumps&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;message&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;response&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  📦 Step 3: Package the Lambda Code
&lt;/h2&gt;

&lt;p&gt;On any Linux machine:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;mkdir&lt;/span&gt; &lt;span class="nt"&gt;-p&lt;/span&gt; python/lambda
&lt;span class="nb"&gt;cd &lt;/span&gt;python/lambda

&lt;span class="c"&gt;# Add your lambda_function.py here&lt;/span&gt;
vi lambda_function.py

&lt;span class="c"&gt;# Install dependencies&lt;/span&gt;
pip3 &lt;span class="nb"&gt;install &lt;/span&gt;httplib2 &lt;span class="nt"&gt;-t&lt;/span&gt; &lt;span class="nb"&gt;.&lt;/span&gt;
pip3 &lt;span class="nb"&gt;install &lt;/span&gt;requests &lt;span class="nt"&gt;-t&lt;/span&gt; &lt;span class="nb"&gt;.&lt;/span&gt;

&lt;span class="c"&gt;# Zip the code&lt;/span&gt;
zip &lt;span class="nt"&gt;-r&lt;/span&gt; python_code.zip &lt;span class="nb"&gt;.&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;⚠️ Install pip3 if missing:&lt;br&gt;
Ubuntu/Debian: &lt;code&gt;sudo apt install python3-pip&lt;/code&gt;&lt;br&gt;
RHEL/CentOS: &lt;code&gt;sudo dnf install python3-pip&lt;/code&gt;&lt;/p&gt;
&lt;/blockquote&gt;




&lt;h2&gt;
  
  
  🚀 Step 4: Deploy the Lambda Function
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;Go to &lt;strong&gt;AWS Lambda&lt;/strong&gt; → &lt;strong&gt;Create function&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;Choose &lt;strong&gt;Author from scratch&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;Set &lt;strong&gt;Runtime&lt;/strong&gt; to &lt;strong&gt;Python 3.x&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;Upload &lt;code&gt;python_code.zip&lt;/code&gt; under &lt;strong&gt;Function Code&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;Set the &lt;strong&gt;Handler&lt;/strong&gt; to &lt;code&gt;lambda_function.lambda_handler&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Click &lt;strong&gt;Deploy&lt;/strong&gt;
&lt;/li&gt;
&lt;/ol&gt;




&lt;h2&gt;
  
  
  🧪 Step 5: Test the Integration
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Manual Test (Lambda)
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;In your Lambda function, click &lt;strong&gt;Test&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;Select the &lt;strong&gt;SNS Topic Notification&lt;/strong&gt; template&lt;/li&gt;
&lt;li&gt;Use the default sample event&lt;/li&gt;
&lt;li&gt;Confirm the alert is posted in your &lt;strong&gt;Google Chat room&lt;/strong&gt;
&lt;/li&gt;
&lt;/ol&gt;




&lt;h2&gt;
  
  
  📢 Step 6: Set Up SNS Topic &amp;amp; Subscription
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Create SNS Topic
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;Go to &lt;strong&gt;Amazon SNS&lt;/strong&gt; → &lt;strong&gt;Topics&lt;/strong&gt; → &lt;strong&gt;Create topic&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;Choose &lt;strong&gt;Standard&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;Name it something like &lt;code&gt;alert-notifications&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Click &lt;strong&gt;Create topic&lt;/strong&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  Subscribe Lambda to SNS
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;Go to &lt;strong&gt;Subscriptions&lt;/strong&gt; → &lt;strong&gt;Create subscription&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;Set protocol to &lt;strong&gt;AWS Lambda&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;Select your deployed Lambda function&lt;/li&gt;
&lt;li&gt;Confirm the subscription&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  Manual Test (SNS)
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;In the SNS topic, click &lt;strong&gt;Publish message&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;Add a subject and message body&lt;/li&gt;
&lt;li&gt;Publish and check Google Chat for the alert&lt;/li&gt;
&lt;/ol&gt;




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

&lt;p&gt;With this integration, you can pipe AWS alerts directly into Google Chat—keeping your team informed in real time, even if you're not using Slack or Microsoft Teams.&lt;/p&gt;

&lt;p&gt;You can attach this SNS topic to &lt;strong&gt;any CloudWatch alarm or event&lt;/strong&gt;, including:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;ECS Service scaling&lt;/li&gt;
&lt;li&gt;EC2 high CPU alerts&lt;/li&gt;
&lt;li&gt;ALB 5XX errors&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  🔗 Resources
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://docs.aws.amazon.com/lambda/" rel="noopener noreferrer"&gt;AWS Lambda Docs&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://developers.google.com/chat" rel="noopener noreferrer"&gt;Google Chat Webhooks&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://docs.aws.amazon.com/sns/" rel="noopener noreferrer"&gt;Amazon SNS Developer Guide&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;




&lt;p&gt;If you found this useful, follow me for more practical AWS DevOps content.&lt;/p&gt;

&lt;p&gt;Let’s keep building resilient cloud-native systems—&lt;strong&gt;one alert at a time&lt;/strong&gt;!&lt;/p&gt;




&lt;p&gt;&lt;strong&gt;Tags:&lt;/strong&gt;&lt;br&gt;
#DevOps #CloudEngineer #AWS #GoogleChat #Lambda #SNS #Alerting #Monitoring #CloudWatch #Automation #AWSCommunityBuilders&lt;/p&gt;

</description>
      <category>aws</category>
      <category>googlecloud</category>
      <category>cloud</category>
      <category>devops</category>
    </item>
    <item>
      <title>My one stop for solution open source setup of software on Linux</title>
      <dc:creator>Samuel Ajisafe</dc:creator>
      <pubDate>Sun, 06 Apr 2025 01:22:19 +0000</pubDate>
      <link>https://dev.to/sammy_cloud/my-one-stop-for-solution-open-source-setup-of-software-on-linux-1cmk</link>
      <guid>https://dev.to/sammy_cloud/my-one-stop-for-solution-open-source-setup-of-software-on-linux-1cmk</guid>
      <description>&lt;p&gt;Still Building this post.&lt;/p&gt;

&lt;p&gt;Reference this docs: &lt;a href="https://devtutorial.io/how-to-install-rabbitmq-on-centos-stream-10-p3704.html" rel="noopener noreferrer"&gt;https://devtutorial.io/how-to-install-rabbitmq-on-centos-stream-10-p3704.html&lt;/a&gt;&lt;/p&gt;

</description>
      <category>opensourcedevops</category>
      <category>linux</category>
      <category>softwaredevelopment</category>
      <category>howto</category>
    </item>
    <item>
      <title>Unlocking a Hidden Power of CloudFront: Integrating On-Premise Servers with AWS CloudFront</title>
      <dc:creator>Samuel Ajisafe</dc:creator>
      <pubDate>Wed, 02 Apr 2025 23:13:12 +0000</pubDate>
      <link>https://dev.to/sammy_cloud/unlocking-a-hidden-power-of-cloudfront-integrating-on-premise-servers-with-aws-cloudfront-4fh1</link>
      <guid>https://dev.to/sammy_cloud/unlocking-a-hidden-power-of-cloudfront-integrating-on-premise-servers-with-aws-cloudfront-4fh1</guid>
      <description>&lt;h2&gt;
  
  
  Introduction
&lt;/h2&gt;

&lt;p&gt;AWS CloudFront is widely known for improving web performance, reducing latency for global users, and enhancing security with tight integrations AWS WAF and Shield Advanced. Many AWS Cloud Engineers and DevOps professionals associate it primarily with delivering static content from Amazon S3 websites, but its potential goes far beyond that. &lt;/p&gt;

&lt;p&gt;In this guide, I’ll walk you through an innovative use case—leveraging AWS CloudFront to optimize and secure applications running on-premises. If you manage a hybrid environment or entirely on-premise infrastructure and need to enhance performance for global users or further tighten the security of your application by protecting it against DDOS and Vulnerabilities this solution is for you.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Challenge
&lt;/h2&gt;

&lt;p&gt;If your applications are hosted within your private corporate network, accessing them via HTTPS can be a headache. You might encounter errors like &lt;code&gt;ERR_SSL_VERSION_OR_CIPHER_MISMATCH&lt;/code&gt; due to DNS issues and SSL/TLS misconfigurations.&lt;/p&gt;

&lt;p&gt;For example, I deployed multiple applications within my private network (&lt;code&gt;192.168.10.0/24&lt;/code&gt;) using Nginx as a load balancer. While external users could access the application seamlessly on the secure channel (https), internal users faced SSL-related issues, despite setting up a private DNS. &lt;/p&gt;

&lt;p&gt;After extensive research with many read on AWS Whitepapers, I found an efficient solution:&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;CloudFront with On-Premises Web Servers&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;By integrating AWS CloudFront with an on-premises web server, we can achieve:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Enhanced security&lt;/strong&gt; with CloudFront’s native DDoS protection&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Global performance optimization&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Seamless HTTPS support&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Reduced operational overhead&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Prerequisites
&lt;/h2&gt;

&lt;p&gt;Before you proceed with the setup, ensure the following prerequisites are met:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;SSL Certificate in AWS ACM:&lt;/strong&gt; You must generate an SSL certificate in AWS Certificate Manager (ACM) for your domain in us-east-1.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Public DNS Mapping:&lt;/strong&gt; The origin domain name (&lt;code&gt;analytics-origin.example.com&lt;/code&gt;) should already be mapped and pointing to the public IP of &lt;code&gt;analytics.example.com&lt;/code&gt; in a DNS manager such as AWS Route 53, GoDaddy, Namecheap etc.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Network Configuration:&lt;/strong&gt; Ensure that the firewall and security group rules allow inbound connections from CloudFront IP ranges to your on-premise server.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Step-by-Step Implementation
&lt;/h3&gt;

&lt;p&gt;In my case I have already configured NGINX as Load balancer&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;1. Configure Nginx as a Load Balancer&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;If you are using Nginx to route traffic to an internal application, set up your configuration as follows:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight nginx"&gt;&lt;code&gt;&lt;span class="k"&gt;server&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kn"&gt;listen&lt;/span&gt;       &lt;span class="mi"&gt;443&lt;/span&gt; &lt;span class="s"&gt;ssl&lt;/span&gt; &lt;span class="s"&gt;http2&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="kn"&gt;listen&lt;/span&gt;       &lt;span class="s"&gt;[::]:443&lt;/span&gt; &lt;span class="s"&gt;ssl&lt;/span&gt; &lt;span class="s"&gt;http2&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="kn"&gt;server_name&lt;/span&gt;  &lt;span class="s"&gt;analytics.example.com&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="kn"&gt;ssl_certificate&lt;/span&gt; &lt;span class="s"&gt;"/etc/nginx/ssl/public.example.crt"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="kn"&gt;ssl_certificate_key&lt;/span&gt; &lt;span class="s"&gt;"/etc/nginx/ssl/private.example.com.key"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="kn"&gt;ssl_session_cache&lt;/span&gt; &lt;span class="s"&gt;shared:SSL:5m&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="kn"&gt;ssl_session_timeout&lt;/span&gt;  &lt;span class="mi"&gt;10m&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="kn"&gt;ssl_protocols&lt;/span&gt; &lt;span class="s"&gt;TLSv1.2&lt;/span&gt; &lt;span class="s"&gt;TLSv1.3&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="kn"&gt;ssl_ciphers&lt;/span&gt; &lt;span class="s"&gt;'ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="kn"&gt;ssl_prefer_server_ciphers&lt;/span&gt; &lt;span class="no"&gt;on&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="kn"&gt;add_header&lt;/span&gt; &lt;span class="s"&gt;Strict-Transport-Security&lt;/span&gt; &lt;span class="s"&gt;"max-age=31536000&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="kn"&gt;includeSubDomains"&lt;/span&gt; &lt;span class="s"&gt;always&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="kn"&gt;proxy_set_header&lt;/span&gt; &lt;span class="s"&gt;Host&lt;/span&gt; &lt;span class="nv"&gt;$host&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="kn"&gt;proxy_set_header&lt;/span&gt; &lt;span class="s"&gt;X-Real-IP&lt;/span&gt; &lt;span class="nv"&gt;$remote_addr&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="kn"&gt;proxy_set_header&lt;/span&gt; &lt;span class="s"&gt;X-Forwarded-For&lt;/span&gt; &lt;span class="nv"&gt;$proxy_add_x_forwarded_for&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="kn"&gt;proxy_set_header&lt;/span&gt; &lt;span class="s"&gt;X-Forwarded-Proto&lt;/span&gt; &lt;span class="nv"&gt;$scheme&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="kn"&gt;ignore_invalid_headers&lt;/span&gt; &lt;span class="no"&gt;off&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="kn"&gt;client_max_body_size&lt;/span&gt; &lt;span class="mi"&gt;100m&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="kn"&gt;proxy_buffering&lt;/span&gt; &lt;span class="no"&gt;off&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="kn"&gt;proxy_request_buffering&lt;/span&gt; &lt;span class="no"&gt;off&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="kn"&gt;location&lt;/span&gt; &lt;span class="n"&gt;/&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="kn"&gt;proxy_buffer_size&lt;/span&gt;          &lt;span class="mi"&gt;128k&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="kn"&gt;proxy_buffers&lt;/span&gt;              &lt;span class="mi"&gt;4&lt;/span&gt; &lt;span class="mi"&gt;256k&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="kn"&gt;proxy_busy_buffers_size&lt;/span&gt;    &lt;span class="mi"&gt;256k&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="kn"&gt;client_max_body_size&lt;/span&gt;       &lt;span class="mi"&gt;50M&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="kn"&gt;proxy_pass&lt;/span&gt;  &lt;span class="s"&gt;http://192.168.10.68:3000&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  &lt;strong&gt;2. Configure AWS CloudFront&lt;/strong&gt;
&lt;/h3&gt;

&lt;h4&gt;
  
  
  &lt;strong&gt;Origin Settings&lt;/strong&gt;
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Origin Domain Name:&lt;/strong&gt; &lt;code&gt;analytics-origin.example.com&lt;/code&gt; (must already be mapped and pointing to the public IP of &lt;code&gt;analytics.example.com&lt;/code&gt; in a DNS manager like AWS Route 53, GoDaddy, etc.)&lt;/li&gt;
&lt;/ul&gt;

&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%2Fn4gur7ll9lq7owq8g57o.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%2Fn4gur7ll9lq7owq8g57o.png" alt=" " width="800" height="477"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Origin Protocol Policy:&lt;/strong&gt; HTTPS Only&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Origin Port:&lt;/strong&gt; 443&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Origin Path:&lt;/strong&gt; Leave blank&lt;/li&gt;
&lt;/ul&gt;

&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%2Fqifr0objbcdenj0ya136.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%2Fqifr0objbcdenj0ya136.png" alt=" " width="800" height="528"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h4&gt;
  
  
  &lt;strong&gt;Viewer Settings&lt;/strong&gt;
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Viewer Protocol Policy:&lt;/strong&gt; Redirect HTTP to HTTPS&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Allowed HTTP Methods:&lt;/strong&gt; GET, HEAD, OPTIONS, PUT, POST, PATCH, DELETE&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Cache Policy:&lt;/strong&gt; Use &lt;code&gt;CachingDisabled&lt;/code&gt; (recommended for dynamic content)&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  &lt;strong&gt;Additional Configuration but Compulsory&lt;/strong&gt;
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Alternate Domain Names (CNAMEs):&lt;/strong&gt; &lt;code&gt;analytics.example.com&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;SSL Certificate:&lt;/strong&gt; Use AWS-managed certificate for your domain&lt;/li&gt;
&lt;/ul&gt;

&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%2Fntc0jpzlbhgdwezzfrfk.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%2Fntc0jpzlbhgdwezzfrfk.png" alt=" " width="800" height="482"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;3. Configure DNS Records&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Create a CNAME record in your DNS provider or Alias record in Route53:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Name:&lt;/strong&gt; &lt;code&gt;analytics.example.com&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Value:&lt;/strong&gt; Your CloudFront distribution domain (&lt;code&gt;*.cloudfront.net&lt;/code&gt;)&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;4. Network Considerations&lt;/strong&gt;
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Allow traffic from CloudFront IP ranges in your firewall/security group.&lt;/li&gt;
&lt;li&gt;Restrict direct access to &lt;code&gt;Your Public IP&lt;/code&gt; (your on-prem server's public IP).&lt;/li&gt;
&lt;li&gt;Ensure CloudFront can reach &lt;code&gt;Your Public IP&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;5. Testing and Validation&lt;/strong&gt;
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;✅ Verify DNS resolution for &lt;code&gt;analytics-origin.example.com&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;✅ Check CloudFront distribution status&lt;/li&gt;
&lt;li&gt;✅ Test application access at &lt;code&gt;https://analytics.example.com&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;✅ Validate functionality&lt;/li&gt;
&lt;li&gt;✅ Review Nginx and CloudFront logs&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;Conclusion&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;CloudFront isn’t just for static content—it’s a powerful tool for accelerating and securing on-prem applications. By following this setup, you can:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Improve latency for global users&lt;/li&gt;
&lt;li&gt;Secure on-premise applications using AWS-managed SSL/TLS&lt;/li&gt;
&lt;li&gt;Leverage AWS’s DDoS protection and WAF&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If you found this guide helpful, drop a comment below or share your experience integrating CloudFront with on-premise servers! 🚀&lt;/p&gt;

&lt;h1&gt;
  
  
  AWS #Cloud #DevOps #SRE #AWSCommunityBuilder #s3 #Infrastructure #CloudEngineer #CDN #Security #Nginx #Network
&lt;/h1&gt;

</description>
    </item>
    <item>
      <title>Redirect a Top-Level Domain Hosted on AWS to an External URL</title>
      <dc:creator>Samuel Ajisafe</dc:creator>
      <pubDate>Thu, 30 Jan 2025 00:28:45 +0000</pubDate>
      <link>https://dev.to/sammy_cloud/redirect-a-top-level-domain-hosted-on-aws-to-an-external-url-4mp3</link>
      <guid>https://dev.to/sammy_cloud/redirect-a-top-level-domain-hosted-on-aws-to-an-external-url-4mp3</guid>
      <description>&lt;p&gt;In today’s interconnected digital landscape, businesses often need to redirect traffic from their primary domain to external URLs hosted outside their cloud infrastructure. Whether it’s for rebranding, marketing campaigns, mergers, or compliance, redirecting a top-level domain (TLD) is a common yet critical task.  &lt;/p&gt;

&lt;p&gt;In this article, we’ll explore real-world use cases for domain redirection and walk you through a step-by-step guide to achieve this using AWS services like Route 53, S3, ACM, and CloudFront.  &lt;/p&gt;

&lt;p&gt;*&lt;em&gt;Scenarios Requiring Domain Redirection *&lt;/em&gt; &lt;br&gt;
Here are some common situations where mapping a TLD to an external URL is necessary:  &lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Rebranding or Domain Consolidation&lt;/strong&gt;  &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Example: A company rebrands from &lt;strong&gt;example.com&lt;/strong&gt; to &lt;strong&gt;tester.com/agents/&lt;/strong&gt; and wants legacy traffic to seamlessly redirect to the new site.
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Marketing Campaigns&lt;/strong&gt;  &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Example: A short-term campaign uses a memorable domain (e.g., &lt;strong&gt;promo.example.com&lt;/strong&gt;) to redirect users to a third-party landing page (e.g., &lt;strong&gt;tester.com/summer-sale&lt;/strong&gt;).
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Mergers and Acquisitions&lt;/strong&gt;  &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Example: After acquiring a company, redirect its domain (e.g., &lt;strong&gt;acquired-company.com&lt;/strong&gt;) to a section of the parent company’s site (e.g., &lt;strong&gt;tester.com/partners&lt;/strong&gt;).
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Compliance or Legal Requirements&lt;/strong&gt;  &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Example: Redirecting users from a non-compliant legacy domain to an updated, compliant URL hosted externally.
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;If any of these scenarios sound familiar, this walkthrough is for you!  &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Solution Overview: AWS Architecture for Domain Redirection&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
For the use case &lt;strong&gt;example.com → &lt;a href="http://www.tester.com/agents/dns" rel="noopener noreferrer"&gt;www.tester.com/agents/dns&lt;/a&gt;&lt;/strong&gt;, the following AWS services are leveraged:  &lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;AWS Route 53&lt;/strong&gt;: Managed DNS routing for the TLD.
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Amazon S3&lt;/strong&gt;: Hosts a simple redirect rule.
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;AWS Certificate Manager (ACM)&lt;/strong&gt;: Provides SSL/TLS certificates for secure redirection.
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Amazon CloudFront&lt;/strong&gt;: Ensures HTTPS support and improves performance.
&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;strong&gt;Step-by-Step Walkthrough&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
Here’s how to redirect example.com and &lt;a href="http://www.example.com" rel="noopener noreferrer"&gt;www.example.com&lt;/a&gt; to &lt;a href="http://www.tester.com/agents/dns/" rel="noopener noreferrer"&gt;www.tester.com/agents/dns/&lt;/a&gt; using AWS services:  &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Step 1: Create S3 Buckets for Redirection&lt;/strong&gt;  &lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Create the root domain bucket&lt;/strong&gt;:  &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Go to &lt;a href="https://docs.aws.amazon.com/AmazonS3/latest/userguide/access-bucket-intro.html#accessing-aws-management-console" rel="noopener noreferrer"&gt;AWS S3 Console&lt;/a&gt; → Create bucket.
&lt;/li&gt;
&lt;li&gt;Bucket name: &lt;code&gt;example.com&lt;/code&gt; (must match your domain).
&lt;/li&gt;
&lt;li&gt;Region: Choose a region (e.g., US East (N. Virginia)).
&lt;/li&gt;
&lt;li&gt;Uncheck &lt;strong&gt;Block all public access&lt;/strong&gt; &lt;/li&gt;
&lt;li&gt;Click &lt;strong&gt;Create bucket&lt;/strong&gt;.
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Configure static website hosting for the root domain bucket&lt;/strong&gt;:  &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Open the bucket → &lt;strong&gt;Properties&lt;/strong&gt; tab → &lt;strong&gt;Static website hosting&lt;/strong&gt;.
&lt;/li&gt;
&lt;li&gt;Select Redirect all requests to another host name.
&lt;/li&gt;
&lt;li&gt;Target domain: &lt;code&gt;www.tester.com/agents/dns/&lt;/code&gt;.
&lt;/li&gt;
&lt;li&gt;Protocol: &lt;code&gt;https&lt;/code&gt; (if the target supports HTTPS).
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;strong&gt;Step 2: Request an SSL Certificate (AWS Certificate Manager)&lt;/strong&gt;  &lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Request a certificate&lt;/strong&gt;:  &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Go to &lt;strong&gt;AWS Certificate Manager (ACM)&lt;/strong&gt; → &lt;strong&gt;Request a certificate&lt;/strong&gt;.
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Domain names&lt;/strong&gt;:

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;example.com&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;*.example.com&lt;/code&gt; (covers subdomains like www).
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Validation method&lt;/strong&gt;: &lt;strong&gt;DNS validation&lt;/strong&gt;.
&lt;/li&gt;
&lt;li&gt;Click &lt;strong&gt;Request&lt;/strong&gt;.
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Validate the certificate&lt;/strong&gt;:  &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;ACM will ask you to add CNAME records to your Route 53 hosted zone.
&lt;/li&gt;
&lt;li&gt;Click &lt;strong&gt;Create records in Route 53&lt;/strong&gt; &lt;/li&gt;
&lt;li&gt;Wait for validation (status changes to &lt;strong&gt;Issued&lt;/strong&gt;).
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;strong&gt;Step 3: Create CloudFront Distributions&lt;/strong&gt;  &lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Create a CloudFront distribution for the root domain&lt;/strong&gt;:

&lt;ul&gt;
&lt;li&gt;Go to &lt;strong&gt;CloudFront Console&lt;/strong&gt; → &lt;strong&gt;Create Distribution&lt;/strong&gt;.
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Origin Domain&lt;/strong&gt;: Select the S3 bucket &lt;strong&gt;example.com&lt;/strong&gt; (use the &lt;strong&gt;S3 website endpoint URL&lt;/strong&gt;).
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Origin Path&lt;/strong&gt;: Leave blank.
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Viewer Protocol Policy&lt;/strong&gt;: &lt;strong&gt;Redirect HTTP to HTTPS&lt;/strong&gt;.
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Alternate Domain Names (CNAMEs)&lt;/strong&gt;: &lt;code&gt;example.com&lt;/code&gt; and &lt;a href="http://www.example.com" rel="noopener noreferrer"&gt;www.example.com&lt;/a&gt;.
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;SSL Certificate&lt;/strong&gt;: Select the ACM certificate you created.
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Default Root Object&lt;/strong&gt;: Leave blank.
&lt;/li&gt;
&lt;li&gt;Click &lt;strong&gt;Create Distribution&lt;/strong&gt;.
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;strong&gt;Step 4: Update Route 53 DNS Records&lt;/strong&gt;  &lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Point the root domain to CloudFront&lt;/strong&gt;:  &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Go to &lt;strong&gt;Route 53 Console&lt;/strong&gt; → &lt;strong&gt;Hosted Zones&lt;/strong&gt; → &lt;strong&gt;example.com&lt;/strong&gt;.
&lt;/li&gt;
&lt;li&gt;Edit the &lt;strong&gt;A record&lt;/strong&gt; for the root domain:

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Record name&lt;/strong&gt;: Leave blank.
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Alias&lt;/strong&gt;: &lt;strong&gt;Yes&lt;/strong&gt;.
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Route traffic to&lt;/strong&gt;: &lt;strong&gt;Alias to CloudFront distribution&lt;/strong&gt; → Select the root domain CloudFront distribution.
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Save.
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Point the www subdomain to CloudFront&lt;/strong&gt;:  &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Create/edit the &lt;strong&gt;A record&lt;/strong&gt; for &lt;code&gt;www&lt;/code&gt;:

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Record name&lt;/strong&gt;: &lt;code&gt;www&lt;/code&gt;.
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Alias&lt;/strong&gt;: &lt;strong&gt;Yes&lt;/strong&gt;.
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Route traffic to&lt;/strong&gt;: &lt;strong&gt;Alias to CloudFront distribution&lt;/strong&gt; → Select the root domain CloudFront distribution.
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Save.
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;strong&gt;Step 5: Test the Redirection&lt;/strong&gt;  &lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Wait for DNS propagation&lt;/strong&gt; (up to 48 hours, but usually faster).
&lt;/li&gt;
&lt;li&gt;Test using:

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Browser&lt;/strong&gt;: Visit &lt;code&gt;https://example.com&lt;/code&gt; → Should redirect to &lt;code&gt;https://www.tester.com/agents/dns/&lt;/code&gt;.
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;strong&gt;Troubleshooting Tips&lt;/strong&gt;  &lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;SSL/TLS Errors&lt;/strong&gt;:  &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Ensure the ACM certificate is created in &lt;strong&gt;us-east-1&lt;/strong&gt; (required for CloudFront).
&lt;/li&gt;
&lt;li&gt;Verify the certificate is attached to the CloudFront distribution.
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Infinite Redirect Loops&lt;/strong&gt;:  &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Ensure S3 bucket redirects point directly to the external URL (not to another S3 bucket).
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;DNS Issues&lt;/strong&gt;:  &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Use &lt;code&gt;dig example.com&lt;/code&gt; to confirm DNS resolution.
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;strong&gt;Conclusion&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
Redirecting a top-level domain hosted on AWS to an external URL is a powerful strategy for maintaining brand continuity, complying with legal requirements, or executing marketing campaigns. By leveraging AWS services like &lt;strong&gt;Route 53&lt;/strong&gt;, &lt;strong&gt;S3&lt;/strong&gt;, &lt;strong&gt;ACM&lt;/strong&gt;, and &lt;strong&gt;CloudFront&lt;/strong&gt;, you can achieve seamless, secure, and cost-effective redirection without infrastructure overhead.  &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Call to Action&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
Have you implemented domain redirection on AWS? Share your experience in the comments below! If you have questions, feel free to ask—we’re here to help.  &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Tags&lt;/strong&gt;: #AWS #DomainManagement #Route53 #CloudComputing #WebHosting #HTTPS #DevOps  &lt;/p&gt;

</description>
    </item>
    <item>
      <title>How to Create an IAM User</title>
      <dc:creator>Samuel Ajisafe</dc:creator>
      <pubDate>Mon, 27 Jan 2025 04:30:55 +0000</pubDate>
      <link>https://dev.to/sammy_cloud/how-to-create-an-iam-user-2j15</link>
      <guid>https://dev.to/sammy_cloud/how-to-create-an-iam-user-2j15</guid>
      <description>&lt;p&gt;How to Create an IAM User&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Log in to the AWS Management Console

&lt;ul&gt;
&lt;li&gt;Go to &lt;a href="https://signin.aws.amazon.com/signin?client_id=arn%3Aaws%3Asignin%3A%3A%3Aconsole%2Fcanvas&amp;amp;redirect_uri=https%3A%2F%2Fconsole.aws.amazon.com%2Fconsole%2Fhome%3FhashArgs%3D%2523%26isauthcode%3Dtrue%26nc2%3Dh_ct%26oauthStart%3D1737951342683%26src%3Dheader-signin%26state%3DhashArgsFromTB_eu-north-1_60aedb6c31ab01e8&amp;amp;page=resolve&amp;amp;code_challenge=3ppvEErgW9bFdxMdk9sRi1V9pcqCq48kJjivRjAbX18&amp;amp;code_challenge_method=SHA-256&amp;amp;backwards_compatible=true" rel="noopener noreferrer"&gt;AWS Console&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;Use your root account credentials (the email and password you used to sign up for AWS).&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;

&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%2Fh9k3eoiz4ajxoeb729xr.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%2Fh9k3eoiz4ajxoeb729xr.png" alt=" " width="800" height="1082"&gt;&lt;/a&gt;&lt;/p&gt;

&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%2Fnlqvg9prqwnw718vl41o.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%2Fnlqvg9prqwnw718vl41o.png" alt=" " width="724" height="920"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Access the IAM Dashboard

&lt;ul&gt;
&lt;li&gt;In the search bar at the top of the page, type IAM and click on it.&lt;/li&gt;
&lt;li&gt;This will take you to the IAM (Identity and Access Management) dashboard.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;

&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%2Fiihy4hfo1jp8azl9dvni.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%2Fiihy4hfo1jp8azl9dvni.png" alt=" " width="800" height="248"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Create a New User

&lt;ul&gt;
&lt;li&gt;On the left-hand menu, click on Users.&lt;/li&gt;
&lt;li&gt;Click the Add users button.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;

&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%2F3himu2qj5fsj04eos3ql.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%2F3himu2qj5fsj04eos3ql.png" alt=" " width="800" height="251"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Enter the User Details

&lt;ul&gt;
&lt;li&gt;In the User name field, type the name for the user (e.g., "New-User").&lt;/li&gt;
&lt;li&gt;Under AWS access type, select Management Console access.&lt;/li&gt;
&lt;li&gt;Create a custom password or select the Autogenerated password option.&lt;/li&gt;
&lt;li&gt;(Optional) Enable the "User must create a new password at next sign-in" option.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;

&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%2Fmg4e89vwdoypi9zgj2e5.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%2Fmg4e89vwdoypi9zgj2e5.png" alt=" " width="800" height="460"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Assign Permissions

&lt;ul&gt;
&lt;li&gt;On the next page, under Set permissions, choose Attach policies directly.&lt;/li&gt;
&lt;li&gt;Search for AdministratorAccess in the list.&lt;/li&gt;
&lt;li&gt;Check the box next to AdministratorAccess to assign full admin rights.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;

&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%2Fq0jbbtc592lgn2wafmbd.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%2Fq0jbbtc592lgn2wafmbd.png" alt=" " width="800" height="369"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Review and Create

&lt;ul&gt;
&lt;li&gt;Review the details on the final page to ensure everything is correct.&lt;/li&gt;
&lt;li&gt;Click Create user.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;

&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%2Fwt0ujjeh7rthsm1k1p96.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%2Fwt0ujjeh7rthsm1k1p96.png" alt=" " width="800" height="450"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Share Login Information

&lt;ul&gt;
&lt;li&gt;Once the user is created, AWS will provide a link to the console login page.&lt;/li&gt;
&lt;li&gt;Share the following details with me securely:

&lt;ul&gt;
&lt;li&gt;The login link.&lt;/li&gt;
&lt;li&gt;The username.&lt;/li&gt;
&lt;li&gt;The temporary password (if autogenerated).&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;

&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%2Fyt6dynwwxbhv3mo0blfr.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%2Fyt6dynwwxbhv3mo0blfr.png" alt=" " width="800" height="313"&gt;&lt;/a&gt;&lt;/p&gt;

</description>
    </item>
    <item>
      <title>How to Setup Pritunl on Ubuntu Server</title>
      <dc:creator>Samuel Ajisafe</dc:creator>
      <pubDate>Fri, 24 Jan 2025 07:40:09 +0000</pubDate>
      <link>https://dev.to/sammy_cloud/how-to-setup-pritunl-on-ubuntu-server-5g8d</link>
      <guid>https://dev.to/sammy_cloud/how-to-setup-pritunl-on-ubuntu-server-5g8d</guid>
      <description>&lt;p&gt;In this tutorial, we'll walk through the complete setup of the Pritunl VPN server on Ubuntu 22.04.&lt;/p&gt;

&lt;p&gt;Pritunl is an open-source enterprise VPN server and management platform. With its intuitive web interface and strong security features, it offers a powerful alternative to commercial VPN solutions. Pritunl supports both OpenVPN and WireGuard, and is designed to scale easily to thousands of users—perfect for modern cloud environments.&lt;/p&gt;

&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%2Fh9nlx79rxhiladm2yej2.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%2Fh9nlx79rxhiladm2yej2.png" alt=" " width="800" height="779"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;🌟 Key Features of Pritunl&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;Easy installation and configuration&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Multi-cloud VPN peering support for AWS, Google Cloud, Azure, and Oracle Cloud&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Up to five layers of authentication&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Supports both OpenVPN and WireGuard&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Scales seamlessly to thousands of users with high availability&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Official clients available for all major platforms (compatible with any OpenVPN client)&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Built on MongoDB, with fast and reliable replication support&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;strong&gt;&lt;u&gt;Pritunl Architecture Overview&lt;/u&gt;&lt;/strong&gt;&lt;br&gt;
Pritunl uses a server-client architecture, where VPN servers and users are managed centrally via the web interface. Clients connect using downloaded profiles.&lt;/p&gt;

&lt;p&gt;It is built on top of MongoDB, a scalable NoSQL database. This makes it easy to deploy a Pritunl cluster with built-in database replication and high availability, all without the need for expensive hardware.&lt;/p&gt;

&lt;p&gt;✅ This setup has been fully tested on Ubuntu 22.04. I’ll continue updating this guide if there are any future changes.&lt;/p&gt;

&lt;p&gt;Step 1: Install Required Dependencies&lt;br&gt;
Start by updating your system and installing essential packages:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;sudo apt update &amp;amp;&amp;amp; sudo apt install -y \
  wget vim curl gnupg2 software-properties-common \
  apt-transport-https ca-certificates lsb-release
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Step 2: Install Legacy OpenSSL (Required for MongoDB 6)&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;sudo apt-key adv --keyserver hkp://keyserver.ubuntu.com:80 --recv-keys 7AE645C0CF8E292A
wget http://archive.ubuntu.com/ubuntu/pool/main/o/openssl/libssl1.1_1.1.1f-1ubuntu2_amd64.deb
sudo dpkg -i libssl1.1_1.1.1f-1ubuntu2_amd64.deb
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Step 3: Add MongoDB and Pritunl Repositories&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;wget -qO - https://www.mongodb.org/static/pgp/server-6.0.asc | sudo apt-key add -

echo "deb [ arch=amd64,arm64 ] https://repo.mongodb.org/apt/ubuntu jammy/mongodb-org/6.0 multiverse" \
  | sudo tee /etc/apt/sources.list.d/mongodb-org-6.0.list
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Step 4: Install MongoDB and Pritunl&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;sudo apt update
sudo apt install -y pritunl mongodb-org
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Step 5: Start and Enable Services&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;sudo systemctl start pritunl mongod
sudo systemctl enable pritunl mongod
sudo systemctl status pritunl mongod
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You should see both services running without issues.&lt;/p&gt;

&lt;p&gt;Step 6: Access the Pritunl Web Interface&lt;br&gt;
Now that Pritunl is running, you can access the web interface:&lt;/p&gt;

&lt;p&gt;Open your browser and go to:&lt;br&gt;
http://&lt;/p&gt;

&lt;p&gt;Note: Make sure ports 80 and 443 are open on your server.&lt;/p&gt;

&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%2F0e58ehgf5c3we6l9nib9.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%2F0e58ehgf5c3we6l9nib9.png" alt=" " width="800" height="801"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Generate setup-key by running the command below:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;sudo pritunl setup-key
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Once you enter the setup-key and MongoDB URL, it will prompt you for a username and password.&lt;/p&gt;

&lt;p&gt;The default username and password are obtained with the below command:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;sudo pritunl default-password
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;When you log in with the provided credentials. Set your new password and save and you should be taken to a page to configure organizations, users, and servers.&lt;/p&gt;

&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%2Fn7lbyiy057rjel5dqqzz.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%2Fn7lbyiy057rjel5dqqzz.png" alt=" " width="800" height="552"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Step 8. Create a User&lt;/p&gt;

&lt;p&gt;To add users, click on ‘Users’. This takes you to a window to first add organization.&lt;/p&gt;

&lt;p&gt;Click on ‘Add organization’ then provide it a name then click ‘Add’.&lt;/p&gt;

&lt;p&gt;Your organization should now be added.&lt;/p&gt;

&lt;p&gt;Click on ‘Add user’ to create a user. Provide the required details and click ‘Add’.&lt;/p&gt;

&lt;p&gt;If you want to add many users at once, click on ‘Bulk Add user’.&lt;/p&gt;

&lt;p&gt;Let’s now create a Vpn server. Click on ‘servers’ then ‘Add server’.&lt;/p&gt;

&lt;p&gt;Provide server particulars and click ‘Add’. You should see that the server has successfully been added.&lt;/p&gt;

&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%2F214in9d7vhei53nu5tl4.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%2F214in9d7vhei53nu5tl4.png" alt=" " width="800" height="458"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Your Firewall should mimic the image below:&lt;/p&gt;

&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%2Fyz1a5wckkqo8npbgtqzs.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%2Fyz1a5wckkqo8npbgtqzs.png" alt=" " width="800" height="289"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;🧩 Step 9: Link Server to Organization&lt;br&gt;
Once logged in, create an Organization, User, and Server. Then link the server to the organization to begin assigning user profiles.&lt;/p&gt;

&lt;p&gt;Click on Server, then click on Attach Organisation&lt;/p&gt;

&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%2F80iy1t6x156e5at3j1of.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%2F80iy1t6x156e5at3j1of.png" alt=" " width="800" height="395"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Once Attached Click on Start Server.&lt;/p&gt;

&lt;p&gt;The setup is now completed.&lt;/p&gt;

&lt;p&gt;Here is the guide on how to setup the client side&lt;/p&gt;

&lt;p&gt;Follow this link '&lt;a href="https://client.pritunl.com/" rel="noopener noreferrer"&gt;https://client.pritunl.com/&lt;/a&gt;' to download the Pritunl client, mobile device download OpenVPN from Playstore or Appstore.&lt;/p&gt;

&lt;p&gt;Install client and upload downloaded profile to client and click connect.&lt;/p&gt;

&lt;p&gt;📚 Reference&lt;br&gt;
This guide was inspired by &lt;a href="https://vinayak-s.medium.com/install-and-set-up-the-pritunl-vpn-server-software-on-ubuntu-22-04-9e7ec46e5ce2" rel="noopener noreferrer"&gt;Vinayak's&lt;/a&gt; Pritunl Setup Guide, with updates and improvements based on the latest best practices.&lt;/p&gt;

&lt;p&gt;🚧 Note: The original reference has been updated. I will continue to maintain this documentation as new changes emerge.&lt;/p&gt;

&lt;h1&gt;
  
  
  DevOps #SRE #HybridCloud #Cloud #Security #VPN #PrivateNetwork #Network #OpenVPN #Pritunl
&lt;/h1&gt;

</description>
      <category>linux</category>
      <category>ubuntu</category>
      <category>devops</category>
      <category>security</category>
    </item>
    <item>
      <title>How to disable AWS Route53 Resolver Network Interface</title>
      <dc:creator>Samuel Ajisafe</dc:creator>
      <pubDate>Thu, 09 Jan 2025 11:23:20 +0000</pubDate>
      <link>https://dev.to/sammy_cloud/how-to-disable-aws-route53-resolver-network-interface-1fjn</link>
      <guid>https://dev.to/sammy_cloud/how-to-disable-aws-route53-resolver-network-interface-1fjn</guid>
      <description>&lt;p&gt;How I Tackled Unexpected AWS Route 53 Resolver Costs&lt;/p&gt;

&lt;p&gt;Are you getting unexpected AWS charges for Route 53 Resolver? The costs can quickly become worrisome, especially if you're not actively using the service. As someone managing an AWS account, cost optimization was my primary goal for this project, and I leaned on several AWS tools to help with this analysis.&lt;/p&gt;

&lt;h4&gt;
  
  
  Tools I Used:
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;AWS Compute Optimizer&lt;/li&gt;
&lt;li&gt;Billing Dashboard&lt;/li&gt;
&lt;li&gt;Cost Explorer&lt;/li&gt;
&lt;li&gt;Savings Plan&lt;/li&gt;
&lt;li&gt;Reserved Instances&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Identifying the Problem
&lt;/h3&gt;

&lt;p&gt;While analyzing costs using &lt;strong&gt;Cost Explorer&lt;/strong&gt;, I noticed a line item labeled &lt;strong&gt;EU-ResolverNetworkInterface&lt;/strong&gt;. At first, I couldn't figure out where this cost was coming from. After thoroughly exploring AWS Route 53 via the console, I found no visible resolver endpoints, and searching the web didn’t offer any direct solutions. Ultimately, I realized that resolving this issue would require the &lt;strong&gt;AWS CLI&lt;/strong&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  What is AWS Route 53 Resolver?
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Amazon Route 53 Resolver&lt;/strong&gt; is a DNS service that enables you to manage and route DNS queries between your VPCs, on-premises networks, and the internet. If you have workloads spanning both AWS VPCs and on-premises resources, you'll likely need to resolve DNS records hosted in both environments. &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Route 53 Resolver&lt;/strong&gt; supports this by providing:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Inbound Resolver Endpoints&lt;/strong&gt;: Allow DNS queries to your VPC from on-premises or another VPC.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Outbound Resolver Endpoints&lt;/strong&gt;: Allow DNS queries from your VPC to on-premises resources or another VPC.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Additionally, &lt;strong&gt;Resolver rules&lt;/strong&gt; enable you to create forwarding rules for specific domain names, specifying where to route DNS queries. These rules can be applied to individual VPCs and shared across multiple AWS accounts.&lt;/p&gt;

&lt;h3&gt;
  
  
  How I Resolved the Issue
&lt;/h3&gt;

&lt;p&gt;Once I identified the cost was related to a Resolver in the &lt;strong&gt;EU&lt;/strong&gt; region, I followed these steps to resolve it:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;List the Resolver Endpoints&lt;/strong&gt;:
First, I ran the following CLI command to check for existing resolver endpoints in the &lt;strong&gt;EU West (eu-west-1)&lt;/strong&gt; region:
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;   aws route53resolver list-resolver-endpoints &lt;span class="nt"&gt;--region&lt;/span&gt; eu-west-1
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This showed that a resolver endpoint existed.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;List Resolver Rule Associations&lt;/strong&gt;:
Next, I checked the resolver rule associations to see where the rules were applied:
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;   aws route53resolver list-resolver-rule-associations &lt;span class="nt"&gt;--region&lt;/span&gt; eu-west-1
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This revealed the associated rule and the linked VPC.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Disassociate the Resolver Rule&lt;/strong&gt;:
To unlink the resolver rule from the VPC, I ran the following command:
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;   aws route53resolver disassociate-resolver-rule &lt;span class="nt"&gt;--vpc-id&lt;/span&gt; &amp;lt;vpc-id&amp;gt; &lt;span class="nt"&gt;--resolver-rule-id&lt;/span&gt; rslvr-rr-33c7383d12cb43919 &lt;span class="nt"&gt;--region&lt;/span&gt; eu-west-1
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Delete the Resolver Rule&lt;/strong&gt;:
Once the rule was disassociated, I proceeded to delete it:
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;   aws route53resolver delete-resolver-rule &lt;span class="nt"&gt;--resolver-rule-id&lt;/span&gt; rslvr-rr-33c7383d12cb43919 &lt;span class="nt"&gt;--region&lt;/span&gt; eu-west-1
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Delete the Resolver Endpoint&lt;/strong&gt;:
Finally, I deleted the resolver endpoint using the following command:
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;   aws route53resolver delete-resolver-endpoint &lt;span class="nt"&gt;--resolver-endpoint-id&lt;/span&gt; &amp;lt;resolver-endpoint-id&amp;gt; &lt;span class="nt"&gt;--region&lt;/span&gt; eu-west-1
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Double Check&lt;/strong&gt;:
I ran the &lt;strong&gt;list-resolver-endpoints&lt;/strong&gt; command again to ensure no resolver endpoints remained. If any were still there, I repeated the process.&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  Conclusion
&lt;/h3&gt;

&lt;p&gt;In my case, it was an &lt;strong&gt;Outbound Resolver Endpoint&lt;/strong&gt; causing the issue. Following the steps above helped me clear the associated costs. If you’re seeing similar charges, don’t hesitate to follow these steps and clean up unused resolver endpoints or rules.&lt;/p&gt;

&lt;p&gt;Good luck with your AWS cost optimization!&lt;/p&gt;

&lt;h1&gt;
  
  
  AWS #DevOps #Cloud #Cost_Optimization #Route53 #DNS
&lt;/h1&gt;

</description>
    </item>
    <item>
      <title>AWS CodeDeploy: How to Fix the "Cannot Reach Instance Service" Error</title>
      <dc:creator>Samuel Ajisafe</dc:creator>
      <pubDate>Sat, 16 Nov 2024 11:19:23 +0000</pubDate>
      <link>https://dev.to/sammy_cloud/aws-codedeploy-how-to-fix-the-cannot-reach-instance-service-error-2061</link>
      <guid>https://dev.to/sammy_cloud/aws-codedeploy-how-to-fix-the-cannot-reach-instance-service-error-2061</guid>
      <description>&lt;p&gt;If you're a &lt;strong&gt;DevOps engineer&lt;/strong&gt;, &lt;strong&gt;System engineer&lt;/strong&gt;, or &lt;strong&gt;Cloud engineer&lt;/strong&gt; using &lt;strong&gt;AWS CodePipeline&lt;/strong&gt;, &lt;strong&gt;CodeBuild&lt;/strong&gt;, and &lt;strong&gt;CodeDeploy&lt;/strong&gt; to deploy applications to EC2 instances, you may encounter a deployment failure after a successful build. If the logs from &lt;strong&gt;CodeDeploy&lt;/strong&gt; show the following error:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;CodeDeploy agent was not able to receive the lifecycle event. Check the CodeDeploy agent logs on your host and make sure the agent is running and can connect to the CodeDeploy server.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Don’t panic! This guide will help you troubleshoot and resolve the issue.&lt;/p&gt;

&lt;h3&gt;
  
  
  Step 1: Check the Status of the CodeDeploy Agent on the EC2 Instance
&lt;/h3&gt;

&lt;p&gt;The first step is to verify if the &lt;strong&gt;CodeDeploy agent&lt;/strong&gt; is running on your EC2 instance. To check the status, run the following command:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;sudo &lt;/span&gt;service codedeploy-agent status
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;If the agent is stopped, start it by running:
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;sudo &lt;/span&gt;service codedeploy-agent start
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Step 2: Confirm IAM Role Permissions
&lt;/h3&gt;

&lt;p&gt;Ensure that the EC2 instance has an &lt;strong&gt;IAM role&lt;/strong&gt; attached to it, and this role must have the necessary permissions to interact with AWS CodeDeploy. The policy should include actions for CodeDeploy, S3, and CloudWatch Logs:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"Version"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"2012-10-17"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"Statement"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"Effect"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Allow"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"Action"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="s2"&gt;"codedeploy:*"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="s2"&gt;"s3:GetObject"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="s2"&gt;"s3:ListBucket"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="s2"&gt;"logs:CreateLogStream"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="s2"&gt;"logs:PutLogEvents"&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"Resource"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"*"&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Step 3: Validate IAM Role Trust Relationship
&lt;/h3&gt;

&lt;p&gt;Next, ensure that the IAM role trust relationship is set up correctly. It should allow EC2 instances to assume the role. The trust relationship policy should look like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"Version"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"2012-10-17"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"Statement"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"Effect"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Allow"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"Principal"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"Service"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"ec2.amazonaws.com"&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"Action"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"sts:AssumeRole"&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Step 4: Restart the CodeDeploy Agent
&lt;/h3&gt;

&lt;p&gt;Once you've confirmed that the IAM role is correctly configured, restart the &lt;strong&gt;CodeDeploy agent&lt;/strong&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;sudo &lt;/span&gt;service codedeploy-agent restart
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Step 5: Check the CodeDeploy Agent Logs
&lt;/h3&gt;

&lt;p&gt;If the problem persists, inspect the &lt;strong&gt;CodeDeploy agent logs&lt;/strong&gt; for additional error messages that might provide insight into why the lifecycle event failed. To tail the log file:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;sudo tail&lt;/span&gt; &lt;span class="nt"&gt;-f&lt;/span&gt; /var/log/aws/codedeploy-agent/codedeploy-agent.log
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Look for any errors similar to this one:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;ERROR [codedeploy-agent(3313518)]: InstanceAgent::Plugins::CodeDeployPlugin::CommandPoller: Cannot reach InstanceService: Aws::CodeDeployCommand::Errors::AccessDeniedException - Aws::CodeDeployCommand::Errors::AccessDeniedException
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Step 6: Remove AWS Credentials from the Instance (if applicable)
&lt;/h3&gt;

&lt;p&gt;If the error mentions &lt;strong&gt;AccessDeniedException&lt;/strong&gt;, it's possible that an &lt;strong&gt;AWS credentials file&lt;/strong&gt; exists on the instance (e.g., &lt;code&gt;/root/.aws/credentials&lt;/code&gt; or &lt;code&gt;/home/{user}/.aws/credentials&lt;/code&gt;). If such a file exists, it might be interfering with the CodeDeploy agent’s ability to connect.&lt;/p&gt;

&lt;p&gt;To fix this:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Delete the credentials file:
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;sudo rm&lt;/span&gt; &lt;span class="nt"&gt;-rf&lt;/span&gt; /root/.aws/credentials
&lt;span class="c"&gt;# or for a specific user:&lt;/span&gt;
&lt;span class="nb"&gt;sudo rm&lt;/span&gt; &lt;span class="nt"&gt;-rf&lt;/span&gt; /home/&lt;span class="o"&gt;{&lt;/span&gt;user&lt;span class="o"&gt;}&lt;/span&gt;/.aws/credentials
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ol&gt;
&lt;li&gt;Restart the CodeDeploy agent:
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;sudo &lt;/span&gt;systemctl restart codedeploy-agent
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Conclusion
&lt;/h3&gt;

&lt;p&gt;By following these steps, you should be able to resolve the &lt;strong&gt;"CodeDeploy cannot reach instance service"&lt;/strong&gt; error and get your deployments back on track. If the issue persists, revisit the IAM role permissions and the CodeDeploy agent logs to gather more information.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;References:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://repost.aws/questions/QUUQG8erWXTj6KlQ1Asa4siw/aws-code-deploy-cannot-reach-instance-service" rel="noopener noreferrer"&gt;AWS CodeDeploy: Cannot reach instance service&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://stackoverflow.com/questions/37721601/aws-code-deploy-deployment-failed" rel="noopener noreferrer"&gt;StackOverflow: AWS CodeDeploy Deployment Failed&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h1&gt;
  
  
  Cloud #AWS #DevOps #Automation #CI/CD #System #Engineer #CodeDeploy #CodePipeline #EC2
&lt;/h1&gt;

</description>
    </item>
  </channel>
</rss>
