<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>AWS on Logan's Nest</title><link>https://blog.han.life/tags/aws/</link><description>Recent content in AWS on Logan's Nest</description><generator>Hugo</generator><language>en-au</language><lastBuildDate>Wed, 20 May 2026 00:00:00 +0000</lastBuildDate><atom:link href="https://blog.han.life/tags/aws/index.xml" rel="self" type="application/rss+xml"/><item><title>Why Sentry events silently vanished from our Fargate Node app</title><link>https://blog.han.life/posts/2026/2026-05-20-sentry-fargate-ipv6-hang/</link><pubDate>Wed, 20 May 2026 00:00:00 +0000</pubDate><guid>https://blog.han.life/posts/2026/2026-05-20-sentry-fargate-ipv6-hang/</guid><description>&lt;h2 id="tldr"&gt;TL;DR&lt;/h2&gt;&#10;&lt;p&gt;Sentry&amp;rsquo;s Node SDK uses Node&amp;rsquo;s native &lt;code&gt;https.Agent&lt;/code&gt;, which in Node 18+ does Happy Eyeballs dual-stack connections by default. When DNS returns AAAA records but the host (e.g. an ECS Fargate ENI) has no IPv6 routing, the IPv6 connect attempts don&amp;rsquo;t fail fast — they hang until the agent&amp;rsquo;s default 2-second timeout, producing &lt;code&gt;AggregateError [ETIMEDOUT]&lt;/code&gt; and silently dropping the event. &lt;code&gt;curl&lt;/code&gt; from the same host works fine because curl falls back to IPv4 in milliseconds. The fix is one line: tell the Sentry transport to force IPv4 via a custom &lt;code&gt;httpModule&lt;/code&gt;.&lt;/p&gt;</description></item><item><title>Bypassing AWS Lambda's 4 KB env var limit</title><link>https://blog.han.life/posts/2026/2026-05-07-lambda-env-4kb-limit/</link><pubDate>Thu, 07 May 2026 00:00:00 +0000</pubDate><guid>https://blog.han.life/posts/2026/2026-05-07-lambda-env-4kb-limit/</guid><description>&lt;h2 id="tldr"&gt;TL;DR&lt;/h2&gt;&#10;&lt;p&gt;Lambda caps the total &lt;code&gt;Environment.Variables&lt;/code&gt; map at 4 KB. There&amp;rsquo;s no AWS feature that auto-hydrates env vars from SSM at runtime. The cleanest way around it is a tiny Go binary wired up as &lt;code&gt;AWS_LAMBDA_EXEC_WRAPPER&lt;/code&gt; that fetches SSM params at cold start and &lt;code&gt;syscall.Exec&lt;/code&gt;s the runtime, so the handler sees &lt;code&gt;process.env.X&lt;/code&gt; exactly as if it had been set inline. Zero application changes; one Lambda layer.&lt;/p&gt;</description></item><item><title>CloudFront Anycast IP</title><link>https://blog.han.life/posts/2025/2025-10-09-cloudfront-anycastp-ip/</link><pubDate>Thu, 09 Oct 2025 00:00:00 +0000</pubDate><guid>https://blog.han.life/posts/2025/2025-10-09-cloudfront-anycastp-ip/</guid><description>&lt;p&gt;I recently worked with a new AWS product called &lt;strong&gt;CloudFront Anycast IP&lt;/strong&gt;, which costs &lt;strong&gt;$3,000/month&lt;/strong&gt;. After testing it, I found the offering to be quite misleading, so I’m sharing my findings here.&lt;/p&gt;</description></item><item><title>CloudFront Functions with Dynamic Origin Pointing to Another CloudFront</title><link>https://blog.han.life/posts/2025/2025-02-05-cf-function-dynamic-origin/</link><pubDate>Wed, 05 Feb 2025 00:00:00 +0000</pubDate><guid>https://blog.han.life/posts/2025/2025-02-05-cf-function-dynamic-origin/</guid><description>&lt;p&gt;At re:Invent 2024, CloudFront Functions introduced new features, including the ability to dynamically change the origin host.&lt;/p&gt;&#10;&lt;p&gt;Previously, this wasn&amp;rsquo;t possible as the Host header was read-only for CloudFront viewer requests.&lt;/p&gt;</description></item><item><title>Lookup CMK for a test in CDK</title><link>https://blog.han.life/posts/2022/2022-09-06-cdk-cmk-test/</link><pubDate>Tue, 06 Sep 2022 00:00:00 +0000</pubDate><guid>https://blog.han.life/posts/2022/2022-09-06-cdk-cmk-test/</guid><description>&lt;p&gt;Add a CMK in CDK was easy, then when I looked into a way to reference the resource using &lt;code&gt;findResources&lt;/code&gt;, faced constant failure as for some reason CDK can&amp;rsquo;t really pickup the key based on the alias.&lt;/p&gt;</description></item><item><title>fargate container healthcheck</title><link>https://blog.han.life/posts/2021/2021-01-18-fargate-healthcheck/</link><pubDate>Mon, 18 Jan 2021 00:00:00 +0000</pubDate><guid>https://blog.han.life/posts/2021/2021-01-18-fargate-healthcheck/</guid><description>&lt;p&gt;Long story in short, unlike what &lt;a href="https://docs.aws.amazon.com/AmazonECS/latest/APIReference/API_HealthCheck.html"&gt;https://docs.aws.amazon.com/AmazonECS/latest/APIReference/API_HealthCheck.html&lt;/a&gt; suggests, fargate doesn&amp;rsquo;t have curl.&lt;/p&gt;&#10;&lt;p&gt;For some reason it does have wget, so &lt;code&gt;&amp;quot;command&amp;quot;: [ &amp;quot;CMD-SHELL&amp;quot;, &amp;quot;wget -q -O - ${healthcheck_endpoint} || exit 1&amp;quot; ]&lt;/code&gt; works as expected.&lt;/p&gt;</description></item><item><title>AWS TGW VPN using Unify UDM</title><link>https://blog.han.life/posts/2020/2020-06-13-aws-tgw-vpn-using-unify-udm/</link><pubDate>Sat, 13 Jun 2020 00:00:00 +0000</pubDate><guid>https://blog.han.life/posts/2020/2020-06-13-aws-tgw-vpn-using-unify-udm/</guid><description>&lt;p&gt;Transit Gateway (TGW) is a managed cloud router service provided by AWS and it supports direct VPN attachment.&lt;/p&gt;&#10;&lt;p&gt;The setup is little bit tricky as UDM doesn&amp;rsquo;t support BGP.&lt;/p&gt;&#10;&lt;p&gt;1. Create a Customer Gateway&lt;br&gt;&#10;Select Dynamic routing and enter your router public IP&lt;/p&gt;</description></item><item><title>Amazon SES with Postfix in Ubuntu</title><link>https://blog.han.life/posts/2020/2020-05-15-amazon-ses-with-postfix-in-ubuntu/</link><pubDate>Fri, 15 May 2020 00:00:00 +0000</pubDate><guid>https://blog.han.life/posts/2020/2020-05-15-amazon-ses-with-postfix-in-ubuntu/</guid><description>&lt;p&gt;Was looking at &lt;a href="https://docs.aws.amazon.com/ses/latest/DeveloperGuide/postfix.html"&gt;https://docs.aws.amazon.com/ses/latest/DeveloperGuide/postfix.html&lt;/a&gt; but it&amp;rsquo;s not really working as it&amp;rsquo;s missing some key commands.&lt;/p&gt;&#10;&lt;p&gt;Install packages &lt;code&gt;apt install -y postfix libsasl2-modules\&lt;/code&gt; select &amp;rsquo;no configuration'&lt;/p&gt;&#10;&lt;p&gt;Config files&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;&#10;&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;&#10;&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt;1&#10;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&#10;&lt;td class="lntd"&gt;&#10;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-sh" data-lang="sh"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;cp /usr/share/postfix/main.cf.debian /etc/postfix/main.cf&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&#10;&lt;/div&gt;&#10;&lt;/div&gt;&lt;p&gt;in &lt;code&gt;/etc/postfix/main.cf&lt;/code&gt;&lt;/p&gt;</description></item><item><title>Salesforce CLI with Docker in AWS</title><link>https://blog.han.life/posts/2019/2019-06-28-salesforce-cli-with-docker-in-aws/</link><pubDate>Fri, 28 Jun 2019 00:00:00 +0000</pubDate><guid>https://blog.han.life/posts/2019/2019-06-28-salesforce-cli-with-docker-in-aws/</guid><description>&lt;p&gt;Auth was the tricky part as the normal auth requires a browser session rather than taking it from the CLI prompt.&lt;/p&gt;&#10;&lt;p&gt;Step 1. Create Dockerfile&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;&#10;&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;&#10;&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt;1&#10;&lt;/span&gt;&lt;span class="lnt"&gt;2&#10;&lt;/span&gt;&lt;span class="lnt"&gt;3&#10;&lt;/span&gt;&lt;span class="lnt"&gt;4&#10;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&#10;&lt;td class="lntd"&gt;&#10;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-sh" data-lang="sh"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;FROM node:9.9.0-alpine &#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;RUN npm install sfdx-cli --global &#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;RUN sfdx --version &#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;RUN sfdx plugins --core&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&#10;&lt;/div&gt;&#10;&lt;/div&gt;&lt;p&gt;Step 2. Generate auth URL from your laptop and push into SSM&lt;/p&gt;</description></item><item><title>AWS KMS - two liners</title><link>https://blog.han.life/posts/2017/2017-05-18-aws-kms-two-liners/</link><pubDate>Thu, 18 May 2017 00:00:00 +0000</pubDate><guid>https://blog.han.life/posts/2017/2017-05-18-aws-kms-two-liners/</guid><description>&lt;p&gt;For binary encrypted output:&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;&#10;&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;&#10;&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt;1&#10;&lt;/span&gt;&lt;span class="lnt"&gt;2&#10;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&#10;&lt;td class="lntd"&gt;&#10;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-sh" data-lang="sh"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;aws kms encrypt --region ap-southeast-2 --key-id alias/blah --plaintext fileb://blah --output text --query CiphertextBlob &lt;span class="p"&gt;|&lt;/span&gt; base64 --decode &amp;gt; blah.enc&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;aws kms decrypt --ciphertext-blob fileb://blah.enc --output text --query Plaintext &lt;span class="p"&gt;|&lt;/span&gt; base64 --decode&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&#10;&lt;/div&gt;&#10;&lt;/div&gt;&lt;p&gt;For base64 encrypted output:&lt;/p&gt;</description></item><item><title>Curl net performance test</title><link>https://blog.han.life/posts/2016/2016-12-15-test-cloudfront-performance-for-support-test/</link><pubDate>Thu, 15 Dec 2016 00:00:00 +0000</pubDate><guid>https://blog.han.life/posts/2016/2016-12-15-test-cloudfront-performance-for-support-test/</guid><description>&lt;p&gt;Print out CloudFront X-Amz-Cf-Id when response time is slower than set threshold.&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;&#10;&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;&#10;&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt; 1&#10;&lt;/span&gt;&lt;span class="lnt"&gt; 2&#10;&lt;/span&gt;&lt;span class="lnt"&gt; 3&#10;&lt;/span&gt;&lt;span class="lnt"&gt; 4&#10;&lt;/span&gt;&lt;span class="lnt"&gt; 5&#10;&lt;/span&gt;&lt;span class="lnt"&gt; 6&#10;&lt;/span&gt;&lt;span class="lnt"&gt; 7&#10;&lt;/span&gt;&lt;span class="lnt"&gt; 8&#10;&lt;/span&gt;&lt;span class="lnt"&gt; 9&#10;&lt;/span&gt;&lt;span class="lnt"&gt;10&#10;&lt;/span&gt;&lt;span class="lnt"&gt;11&#10;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&#10;&lt;td class="lntd"&gt;&#10;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-sh" data-lang="sh"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="cp"&gt;#!/bin/bash&#10;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nv"&gt;output&lt;/span&gt;&lt;span class="o"&gt;=(&lt;/span&gt;&lt;span class="k"&gt;$(&lt;/span&gt;curl -I -s -w &lt;span class="s2"&gt;&amp;#34;Time: %{time_total}\n&amp;#34;&lt;/span&gt; http://cf_url.here grep -e X-Amz-Cf-Id -e Time &lt;span class="p"&gt;|&lt;/span&gt; awk &lt;span class="o"&gt;{&lt;/span&gt;&lt;span class="s1"&gt;&amp;#39;print $2&amp;#39;&lt;/span&gt;&lt;span class="o"&gt;}&lt;/span&gt;&lt;span class="k"&gt;)&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nv"&gt;id&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;output&lt;/span&gt;&lt;span class="p"&gt;[0]&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nv"&gt;time&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="si"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;output&lt;/span&gt;&lt;span class="p"&gt;[1]&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nv"&gt;compare&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;0.01&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;((&lt;/span&gt; &lt;span class="k"&gt;$(&lt;/span&gt;&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;&lt;/span&gt;&lt;span class="nv"&gt;$time&lt;/span&gt;&lt;span class="s2"&gt; &amp;gt; &lt;/span&gt;&lt;span class="nv"&gt;$compare&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;&lt;/span&gt; &lt;span class="p"&gt;|&lt;/span&gt;bc -l&lt;span class="k"&gt;)&lt;/span&gt; &lt;span class="o"&gt;))&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;then&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="nv"&gt;$time&lt;/span&gt; - &lt;span class="nv"&gt;$id&lt;/span&gt; &amp;gt;&amp;gt; test_results.txt&#10;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;fi&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;&#10;&lt;/div&gt;&#10;&lt;/div&gt;&lt;p&gt;Small variation (unrelated to CF)&lt;/p&gt;</description></item><item><title>MongoDB to DynamoDB</title><link>https://blog.han.life/posts/2016/2016-06-08-mongodb-to-dynamodb/</link><pubDate>Wed, 08 Jun 2016 00:00:00 +0000</pubDate><guid>https://blog.han.life/posts/2016/2016-06-08-mongodb-to-dynamodb/</guid><description>&lt;p&gt;Attempted to convert rather large mongo dump to dynamo.&lt;/p&gt;&#10;&lt;p&gt;Seems like AWS data pipeline is most elegant way to do this if one can workaround with dynamo non-standard json format issue.&lt;/p&gt;</description></item></channel></rss>