<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0" xmlns:itunes="http://www.itunes.com/dtds/podcast-1.0.dtd" xmlns:googleplay="http://www.google.com/schemas/play-podcasts/1.0"><channel><title><![CDATA[Software & Stuff]]></title><description><![CDATA[A newsletter about things I find interesting, mainly about programming]]></description><link>https://andriotis.me</link><image><url>https://substackcdn.com/image/fetch/$s_!4yz9!,w_256,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb316b763-ff17-469f-8290-67fb906d732e_460x460.png</url><title>Software &amp; Stuff</title><link>https://andriotis.me</link></image><generator>Substack</generator><lastBuildDate>Wed, 06 May 2026 11:12:09 GMT</lastBuildDate><atom:link href="https://andriotis.me/feed" rel="self" type="application/rss+xml"/><copyright><![CDATA[Nikolaos Andriotis]]></copyright><language><![CDATA[en]]></language><webMaster><![CDATA[softwarenstuff@substack.com]]></webMaster><itunes:owner><itunes:email><![CDATA[softwarenstuff@substack.com]]></itunes:email><itunes:name><![CDATA[Nikos Andriotis]]></itunes:name></itunes:owner><itunes:author><![CDATA[Nikos Andriotis]]></itunes:author><googleplay:owner><![CDATA[softwarenstuff@substack.com]]></googleplay:owner><googleplay:email><![CDATA[softwarenstuff@substack.com]]></googleplay:email><googleplay:author><![CDATA[Nikos Andriotis]]></googleplay:author><itunes:block><![CDATA[Yes]]></itunes:block><item><title><![CDATA[Deploy a PostgreSQL Backup Solution with Docker in 5 Minutes]]></title><description><![CDATA[How to deploy a Postgres continuous backup solution in under 5 minutes using Docker]]></description><link>https://andriotis.me/p/how-to-deploy-a-postgres-backup-solution-in-under-5-minutes-using-docker-8251cb5949b0</link><guid isPermaLink="false">https://andriotis.me/p/how-to-deploy-a-postgres-backup-solution-in-under-5-minutes-using-docker-8251cb5949b0</guid><dc:creator><![CDATA[Nikos Andriotis]]></dc:creator><pubDate>Wed, 16 Apr 2025 16:42:30 GMT</pubDate><enclosure url="https://substackcdn.com/image/fetch/f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fbe22003e-7c1a-468c-b8a3-133921728949_1024x683.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<h3>How to deploy a Postgres continuous backup solution in under 5 minutes using&nbsp;Docker</h3><p>[Song of the day: HELL ON ME&#8202;&#8212;&#8202;Johnny&nbsp;Huynh]</p><p>Hey there! Its&#8230; been a while. I was recently looking to help a collaborator out with backing up a Postgres database and thought it would be a great idea for a blog post. So, <strong>let&#8217;s&nbsp;begin.</strong></p><h3>Table of&nbsp;contents</h3><ul><li><p>Deployment Method</p></li><li><p>General Prerequisites</p></li><li><p>Step 1: Gathering S3-Compatible Bucket Credentials</p></li><li><p>Step 2: Get your schedule in Cron&nbsp;format</p></li><li><p>Step 3: (Optional) Gather Sentry Credentials</p></li><li><p>Step 4: Convert your postgres credentials to a connection URL</p></li><li><p>Step 5: Filling out the&nbsp;.env&nbsp;file</p></li><li><p>Step 6: Deploying</p></li><li><p>Building the image for a version other than 14,15 and&nbsp;16</p></li><li><p>GitHub</p></li><li><p>Regarding stricter permissions for&nbsp;AWS</p></li></ul><h3>Deployment Method</h3><p>There are 2 ways to deploy the backup solution:</p><ul><li><p>Using the <a href="https://railway.com/template/ZJn5OO?referralCode=2VmC2h">Railway&nbsp;Template</a></p></li><li><p>Using Docker on your machine /&nbsp;cloud</p></li></ul><p>We will go over each of the 2 step by step to not miss&nbsp;anything</p><h3>General Prerequisites&#8202;&#8212;&#8202;Required regardless the&nbsp;method</h3><ul><li><p>A <a href="https://cloudflare.com">Cloudflare</a> / <a href="https://backblaze.com">Backblaze</a> / <a href="https://aws.amazon.com">AWS</a>&nbsp;Account</p></li><li><p>An accessible PostgreSQL database, version 16 to&nbsp;14</p></li><li><p>(Optional) A <a href="https://sentry.com">Sentry</a>&nbsp;Account</p></li></ul><h3>Step 1: Gathering S3-Compatible Bucket Credentials</h3><h4>Provider 1:&nbsp;AWS</h4><ol><li><p>Head over to <a href="https://console.aws.amazon.com">console.aws.amazon.com</a> and&nbsp;login</p></li><li><p><strong>Navigate over to the S3 Dashboard</strong> in the region of your&nbsp;choice</p></li></ol><p>3. Create or choose a bucket&#8202;&#8212;&#8202;<strong>Note down the bucket name and its&nbsp;region</strong></p><p>4. Navigate over to <strong>AWS&nbsp;IAM</strong></p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!9I5h!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb5f4e431-7121-4c7b-80d9-ed3d11e77058_1024x612.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!9I5h!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb5f4e431-7121-4c7b-80d9-ed3d11e77058_1024x612.png 424w, https://substackcdn.com/image/fetch/$s_!9I5h!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb5f4e431-7121-4c7b-80d9-ed3d11e77058_1024x612.png 848w, https://substackcdn.com/image/fetch/$s_!9I5h!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb5f4e431-7121-4c7b-80d9-ed3d11e77058_1024x612.png 1272w, https://substackcdn.com/image/fetch/$s_!9I5h!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb5f4e431-7121-4c7b-80d9-ed3d11e77058_1024x612.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!9I5h!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb5f4e431-7121-4c7b-80d9-ed3d11e77058_1024x612.png" width="1024" height="612" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/b5f4e431-7121-4c7b-80d9-ed3d11e77058_1024x612.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:612,&quot;width&quot;:1024,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:null,&quot;alt&quot;:&quot;&quot;,&quot;title&quot;:null,&quot;type&quot;:null,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" title="" srcset="https://substackcdn.com/image/fetch/$s_!9I5h!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb5f4e431-7121-4c7b-80d9-ed3d11e77058_1024x612.png 424w, https://substackcdn.com/image/fetch/$s_!9I5h!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb5f4e431-7121-4c7b-80d9-ed3d11e77058_1024x612.png 848w, https://substackcdn.com/image/fetch/$s_!9I5h!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb5f4e431-7121-4c7b-80d9-ed3d11e77058_1024x612.png 1272w, https://substackcdn.com/image/fetch/$s_!9I5h!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb5f4e431-7121-4c7b-80d9-ed3d11e77058_1024x612.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><p>3. Click on <strong>Users </strong>then &#8220;<strong>Create&nbsp;User</strong>&#8221;</p><p>4. Give it the name &#8220;pg-backup&#8221; or whatever else you&#8217;d&nbsp;like</p><p>5. Assign the permission &#8220;<strong>AmazonS3FullAccess</strong>&#8221;</p><p>(<strong>Note: </strong>As the permission&#8217;s name suggests, this grants the user FULL access to ALL s3 buckets, so a more restricted permission set is advised. Check the end of the post for detailed instructions)</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!moyZ!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F334ee1a5-3946-437d-bee4-67770ec137ae_1024x628.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!moyZ!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F334ee1a5-3946-437d-bee4-67770ec137ae_1024x628.png 424w, https://substackcdn.com/image/fetch/$s_!moyZ!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F334ee1a5-3946-437d-bee4-67770ec137ae_1024x628.png 848w, https://substackcdn.com/image/fetch/$s_!moyZ!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F334ee1a5-3946-437d-bee4-67770ec137ae_1024x628.png 1272w, https://substackcdn.com/image/fetch/$s_!moyZ!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F334ee1a5-3946-437d-bee4-67770ec137ae_1024x628.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!moyZ!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F334ee1a5-3946-437d-bee4-67770ec137ae_1024x628.png" width="1024" height="628" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/334ee1a5-3946-437d-bee4-67770ec137ae_1024x628.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:628,&quot;width&quot;:1024,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:null,&quot;alt&quot;:&quot;&quot;,&quot;title&quot;:null,&quot;type&quot;:null,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" title="" srcset="https://substackcdn.com/image/fetch/$s_!moyZ!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F334ee1a5-3946-437d-bee4-67770ec137ae_1024x628.png 424w, https://substackcdn.com/image/fetch/$s_!moyZ!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F334ee1a5-3946-437d-bee4-67770ec137ae_1024x628.png 848w, https://substackcdn.com/image/fetch/$s_!moyZ!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F334ee1a5-3946-437d-bee4-67770ec137ae_1024x628.png 1272w, https://substackcdn.com/image/fetch/$s_!moyZ!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F334ee1a5-3946-437d-bee4-67770ec137ae_1024x628.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><p>5. Proceed to the next page and confirm the user creation.</p><p>6. You should now be on the &#8220;<strong>Users</strong>&#8221; page. Select the one you just&nbsp;created</p><p>7. Navigate over to &#8220;<strong>Security Credentials</strong>&#8221;</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!AYsu!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F62608c21-bc3e-4160-8540-f17909375191_1024x632.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!AYsu!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F62608c21-bc3e-4160-8540-f17909375191_1024x632.png 424w, https://substackcdn.com/image/fetch/$s_!AYsu!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F62608c21-bc3e-4160-8540-f17909375191_1024x632.png 848w, https://substackcdn.com/image/fetch/$s_!AYsu!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F62608c21-bc3e-4160-8540-f17909375191_1024x632.png 1272w, https://substackcdn.com/image/fetch/$s_!AYsu!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F62608c21-bc3e-4160-8540-f17909375191_1024x632.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!AYsu!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F62608c21-bc3e-4160-8540-f17909375191_1024x632.png" width="1024" height="632" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/62608c21-bc3e-4160-8540-f17909375191_1024x632.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:632,&quot;width&quot;:1024,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:null,&quot;alt&quot;:&quot;&quot;,&quot;title&quot;:null,&quot;type&quot;:null,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" title="" srcset="https://substackcdn.com/image/fetch/$s_!AYsu!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F62608c21-bc3e-4160-8540-f17909375191_1024x632.png 424w, https://substackcdn.com/image/fetch/$s_!AYsu!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F62608c21-bc3e-4160-8540-f17909375191_1024x632.png 848w, https://substackcdn.com/image/fetch/$s_!AYsu!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F62608c21-bc3e-4160-8540-f17909375191_1024x632.png 1272w, https://substackcdn.com/image/fetch/$s_!AYsu!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F62608c21-bc3e-4160-8540-f17909375191_1024x632.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><p>8. Select &#8220;<strong>Create Access Key</strong>&#8221; under &#8220;<strong>Access&nbsp;Keys</strong>&#8221;</p><ul><li><p>Choose &#8220;<strong>Other&#8221; </strong>on the Use&nbsp;Case</p></li><li><p>Skip description (or&nbsp;dont?)</p></li></ul><p>9. Save both the <strong>Access Key </strong>and <strong>Secret Access&nbsp;Key</strong></p><h4>Provider 2: Cloudflare (R2)</h4><ol><li><p>Head over to <a href="https://dash.cloudflare.com">dash.cloudflare.com</a> and&nbsp;login</p></li><li><p>Choose &#8220;<strong>R2 Object Storage</strong>&#8221; from the&nbsp;sidebar</p></li></ol><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!_DFA!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F74f3867e-dafd-4a73-8b5a-18eade1e3f4e_1024x717.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!_DFA!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F74f3867e-dafd-4a73-8b5a-18eade1e3f4e_1024x717.png 424w, https://substackcdn.com/image/fetch/$s_!_DFA!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F74f3867e-dafd-4a73-8b5a-18eade1e3f4e_1024x717.png 848w, https://substackcdn.com/image/fetch/$s_!_DFA!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F74f3867e-dafd-4a73-8b5a-18eade1e3f4e_1024x717.png 1272w, https://substackcdn.com/image/fetch/$s_!_DFA!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F74f3867e-dafd-4a73-8b5a-18eade1e3f4e_1024x717.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!_DFA!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F74f3867e-dafd-4a73-8b5a-18eade1e3f4e_1024x717.png" width="1024" height="717" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/74f3867e-dafd-4a73-8b5a-18eade1e3f4e_1024x717.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:717,&quot;width&quot;:1024,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:null,&quot;alt&quot;:&quot;&quot;,&quot;title&quot;:null,&quot;type&quot;:null,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" title="" srcset="https://substackcdn.com/image/fetch/$s_!_DFA!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F74f3867e-dafd-4a73-8b5a-18eade1e3f4e_1024x717.png 424w, https://substackcdn.com/image/fetch/$s_!_DFA!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F74f3867e-dafd-4a73-8b5a-18eade1e3f4e_1024x717.png 848w, https://substackcdn.com/image/fetch/$s_!_DFA!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F74f3867e-dafd-4a73-8b5a-18eade1e3f4e_1024x717.png 1272w, https://substackcdn.com/image/fetch/$s_!_DFA!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F74f3867e-dafd-4a73-8b5a-18eade1e3f4e_1024x717.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><p>3. Create or choose a bucket and <strong>note down its&nbsp;name</strong></p><p>4. Click on API &gt; Manage API Tokens (See&nbsp;picture)</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!63Wc!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fba827b9f-f74c-4687-bb96-7bcac390a7ad_1024x424.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!63Wc!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fba827b9f-f74c-4687-bb96-7bcac390a7ad_1024x424.png 424w, https://substackcdn.com/image/fetch/$s_!63Wc!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fba827b9f-f74c-4687-bb96-7bcac390a7ad_1024x424.png 848w, https://substackcdn.com/image/fetch/$s_!63Wc!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fba827b9f-f74c-4687-bb96-7bcac390a7ad_1024x424.png 1272w, https://substackcdn.com/image/fetch/$s_!63Wc!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fba827b9f-f74c-4687-bb96-7bcac390a7ad_1024x424.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!63Wc!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fba827b9f-f74c-4687-bb96-7bcac390a7ad_1024x424.png" width="1024" height="424" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/ba827b9f-f74c-4687-bb96-7bcac390a7ad_1024x424.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:424,&quot;width&quot;:1024,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:null,&quot;alt&quot;:&quot;&quot;,&quot;title&quot;:null,&quot;type&quot;:null,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" title="" srcset="https://substackcdn.com/image/fetch/$s_!63Wc!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fba827b9f-f74c-4687-bb96-7bcac390a7ad_1024x424.png 424w, https://substackcdn.com/image/fetch/$s_!63Wc!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fba827b9f-f74c-4687-bb96-7bcac390a7ad_1024x424.png 848w, https://substackcdn.com/image/fetch/$s_!63Wc!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fba827b9f-f74c-4687-bb96-7bcac390a7ad_1024x424.png 1272w, https://substackcdn.com/image/fetch/$s_!63Wc!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fba827b9f-f74c-4687-bb96-7bcac390a7ad_1024x424.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><p>5. Create an &#8220;<strong>Account Token</strong>&#8221; like&nbsp;below:</p><ul><li><p>Set its&nbsp;name</p></li><li><p>Change permissions to &#8220;Object Read &amp;&nbsp;Write&#8221;</p></li><li><p>Specify your backup&nbsp;bucket</p></li><li><p>Click &#8220;<strong>Create</strong>&#8221;</p></li></ul><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!_LHq!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7e800d20-79cc-4127-a358-5905a958c261_1024x793.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!_LHq!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7e800d20-79cc-4127-a358-5905a958c261_1024x793.png 424w, https://substackcdn.com/image/fetch/$s_!_LHq!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7e800d20-79cc-4127-a358-5905a958c261_1024x793.png 848w, https://substackcdn.com/image/fetch/$s_!_LHq!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7e800d20-79cc-4127-a358-5905a958c261_1024x793.png 1272w, https://substackcdn.com/image/fetch/$s_!_LHq!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7e800d20-79cc-4127-a358-5905a958c261_1024x793.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!_LHq!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7e800d20-79cc-4127-a358-5905a958c261_1024x793.png" width="1024" height="793" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/7e800d20-79cc-4127-a358-5905a958c261_1024x793.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:793,&quot;width&quot;:1024,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:null,&quot;alt&quot;:&quot;&quot;,&quot;title&quot;:null,&quot;type&quot;:null,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" title="" srcset="https://substackcdn.com/image/fetch/$s_!_LHq!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7e800d20-79cc-4127-a358-5905a958c261_1024x793.png 424w, https://substackcdn.com/image/fetch/$s_!_LHq!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7e800d20-79cc-4127-a358-5905a958c261_1024x793.png 848w, https://substackcdn.com/image/fetch/$s_!_LHq!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7e800d20-79cc-4127-a358-5905a958c261_1024x793.png 1272w, https://substackcdn.com/image/fetch/$s_!_LHq!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7e800d20-79cc-4127-a358-5905a958c261_1024x793.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><p>6. Of the values shown&nbsp;<strong>Copy:</strong></p><ul><li><p>The <strong>Access Key&nbsp;ID</strong></p></li><li><p>The <strong>Secret Access&nbsp;Key</strong></p></li><li><p>The <strong>Jurisdiction-Specific Endpoint</strong></p></li></ul><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!cW7h!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4f8262ee-9009-4e70-87f9-0c70e6aec2e6_1024x683.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!cW7h!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4f8262ee-9009-4e70-87f9-0c70e6aec2e6_1024x683.png 424w, https://substackcdn.com/image/fetch/$s_!cW7h!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4f8262ee-9009-4e70-87f9-0c70e6aec2e6_1024x683.png 848w, https://substackcdn.com/image/fetch/$s_!cW7h!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4f8262ee-9009-4e70-87f9-0c70e6aec2e6_1024x683.png 1272w, https://substackcdn.com/image/fetch/$s_!cW7h!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4f8262ee-9009-4e70-87f9-0c70e6aec2e6_1024x683.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!cW7h!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4f8262ee-9009-4e70-87f9-0c70e6aec2e6_1024x683.png" width="1024" height="683" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/4f8262ee-9009-4e70-87f9-0c70e6aec2e6_1024x683.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:683,&quot;width&quot;:1024,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:null,&quot;alt&quot;:&quot;&quot;,&quot;title&quot;:null,&quot;type&quot;:null,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" title="" srcset="https://substackcdn.com/image/fetch/$s_!cW7h!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4f8262ee-9009-4e70-87f9-0c70e6aec2e6_1024x683.png 424w, https://substackcdn.com/image/fetch/$s_!cW7h!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4f8262ee-9009-4e70-87f9-0c70e6aec2e6_1024x683.png 848w, https://substackcdn.com/image/fetch/$s_!cW7h!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4f8262ee-9009-4e70-87f9-0c70e6aec2e6_1024x683.png 1272w, https://substackcdn.com/image/fetch/$s_!cW7h!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F4f8262ee-9009-4e70-87f9-0c70e6aec2e6_1024x683.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><h4><strong>Provider 3: Backblaze B2</strong></h4><ol><li><p>Head over to <a href="https://secure.backblaze.com">https://secure.backblaze.com</a> and sign&nbsp;in</p></li><li><p>Click &#8220;<strong>Create a Bucket</strong>&#8221; and choose the following:</p></li></ol><ul><li><p>Private files</p></li><li><p>No encryption</p></li><li><p>No Object&nbsp;Lock</p></li></ul><p>3. From the info of the bucket,&nbsp;<strong>note:</strong></p><ul><li><p>The <strong>Endpoint</strong></p></li><li><p>The <strong>Bucket&nbsp;name</strong></p></li><li><p>The <strong>Region</strong> (found in the endpoint, its first subdomain. For example, the region in the pic is eu-central-003)</p></li></ul><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!7XYG!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F921eca3b-a4f0-4168-b852-c4d396d59d9b_846x476.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!7XYG!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F921eca3b-a4f0-4168-b852-c4d396d59d9b_846x476.png 424w, https://substackcdn.com/image/fetch/$s_!7XYG!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F921eca3b-a4f0-4168-b852-c4d396d59d9b_846x476.png 848w, https://substackcdn.com/image/fetch/$s_!7XYG!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F921eca3b-a4f0-4168-b852-c4d396d59d9b_846x476.png 1272w, https://substackcdn.com/image/fetch/$s_!7XYG!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F921eca3b-a4f0-4168-b852-c4d396d59d9b_846x476.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!7XYG!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F921eca3b-a4f0-4168-b852-c4d396d59d9b_846x476.png" width="846" height="476" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/921eca3b-a4f0-4168-b852-c4d396d59d9b_846x476.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:476,&quot;width&quot;:846,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:null,&quot;alt&quot;:&quot;&quot;,&quot;title&quot;:null,&quot;type&quot;:null,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" title="" srcset="https://substackcdn.com/image/fetch/$s_!7XYG!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F921eca3b-a4f0-4168-b852-c4d396d59d9b_846x476.png 424w, https://substackcdn.com/image/fetch/$s_!7XYG!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F921eca3b-a4f0-4168-b852-c4d396d59d9b_846x476.png 848w, https://substackcdn.com/image/fetch/$s_!7XYG!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F921eca3b-a4f0-4168-b852-c4d396d59d9b_846x476.png 1272w, https://substackcdn.com/image/fetch/$s_!7XYG!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F921eca3b-a4f0-4168-b852-c4d396d59d9b_846x476.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><p>4. Now, head over to <a href="https://secure.backblaze.com/app_keys.htm">https://secure.backblaze.com/app_keys.htm</a></p><p>5. Create an <strong>Application Key </strong>with the following properties</p><ul><li><p>A Name</p></li><li><p>Access to <strong>ONLY </strong>the backup&nbsp;bucket</p></li><li><p>Read &amp; Write&nbsp;scopes</p></li></ul><p>6. Note down the &#8220;<strong>Key ID</strong>&#8221; and &#8220;<strong>Application Key</strong>&#8221; as &#8220;<strong>Access Key ID</strong>&#8221; and &#8220;<strong>Secret Access Key</strong>&#8221; respectively</p><h3>Step 2: Get your schedule in Cron&nbsp;format</h3><p>Backups run on a cron job. So, we need the schedule for example &#8220;Every day at midnight&#8221; to become &#8220;0 0 * *&nbsp;*&#8221;</p><p>Your options&nbsp;are:</p><ul><li><p>Use the prompt &#8220;cron schedule {schedule}&#8221; on&nbsp;ChatGPT</p></li><li><p>Use <a href="https://crontab.guru">crontab.guru</a></p></li></ul><p><strong>To freshen up your memory on&nbsp;Cron:</strong></p><p>It uses the format [second] [minute] [hour] [day_of_month] [month] [day_of_week]&nbsp;,&nbsp;so</p><p>* * * * * * runs every second.&nbsp;Also:</p><ul><li><p>* means &#8220;Every {minutes / hours / days&nbsp;etc}&#8221;</p></li><li><p>*/a (a is a number) means &#8220;Every a {minutes / hours / days&nbsp;etc}&#8221;</p></li></ul><h3>Step 3: (Optional) Gather Sentry Credentials</h3><p>If you want to check the status of your backups, you will need Sentry for monitoring. So let&#8217;s&nbsp;begin.</p><ol><li><p>Head over to <a href="https://sentry.io">sentry.io</a> and&nbsp;login</p></li><li><p>If you haven&#8217;t yet, create a project by going to the top side of your sidebar, selecting &#8220;Projects&#8221; then on the top right, &#8220;Create new&nbsp;project&#8221;</p></li><li><p>Now, head over to &#8220;<strong>Crons</strong>&#8221; then &#8220;<strong>Add&nbsp;Monitor</strong>&#8221;</p></li></ol><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!I1Gg!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7356e3b1-ba3e-49b0-a81f-d005c2e1723c_1024x695.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!I1Gg!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7356e3b1-ba3e-49b0-a81f-d005c2e1723c_1024x695.png 424w, https://substackcdn.com/image/fetch/$s_!I1Gg!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7356e3b1-ba3e-49b0-a81f-d005c2e1723c_1024x695.png 848w, https://substackcdn.com/image/fetch/$s_!I1Gg!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7356e3b1-ba3e-49b0-a81f-d005c2e1723c_1024x695.png 1272w, https://substackcdn.com/image/fetch/$s_!I1Gg!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7356e3b1-ba3e-49b0-a81f-d005c2e1723c_1024x695.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!I1Gg!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7356e3b1-ba3e-49b0-a81f-d005c2e1723c_1024x695.png" width="1024" height="695" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/7356e3b1-ba3e-49b0-a81f-d005c2e1723c_1024x695.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:695,&quot;width&quot;:1024,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:null,&quot;alt&quot;:&quot;&quot;,&quot;title&quot;:null,&quot;type&quot;:null,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" title="" srcset="https://substackcdn.com/image/fetch/$s_!I1Gg!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7356e3b1-ba3e-49b0-a81f-d005c2e1723c_1024x695.png 424w, https://substackcdn.com/image/fetch/$s_!I1Gg!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7356e3b1-ba3e-49b0-a81f-d005c2e1723c_1024x695.png 848w, https://substackcdn.com/image/fetch/$s_!I1Gg!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7356e3b1-ba3e-49b0-a81f-d005c2e1723c_1024x695.png 1272w, https://substackcdn.com/image/fetch/$s_!I1Gg!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7356e3b1-ba3e-49b0-a81f-d005c2e1723c_1024x695.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><p>4. Add a name, set it to your desired project, and add the cron schedule from the previous step. You can, of course, mess around with the other settings as well. Then press&nbsp;<strong>Create.</strong></p><p>5. Copy the <strong>monitor slug</strong> like shown below and store&nbsp;it:</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!J36b!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F49b0ac0e-e599-4e30-9c79-74b0018fea6b_1024x695.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!J36b!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F49b0ac0e-e599-4e30-9c79-74b0018fea6b_1024x695.png 424w, https://substackcdn.com/image/fetch/$s_!J36b!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F49b0ac0e-e599-4e30-9c79-74b0018fea6b_1024x695.png 848w, https://substackcdn.com/image/fetch/$s_!J36b!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F49b0ac0e-e599-4e30-9c79-74b0018fea6b_1024x695.png 1272w, https://substackcdn.com/image/fetch/$s_!J36b!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F49b0ac0e-e599-4e30-9c79-74b0018fea6b_1024x695.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!J36b!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F49b0ac0e-e599-4e30-9c79-74b0018fea6b_1024x695.png" width="1024" height="695" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/49b0ac0e-e599-4e30-9c79-74b0018fea6b_1024x695.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:695,&quot;width&quot;:1024,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:null,&quot;alt&quot;:&quot;&quot;,&quot;title&quot;:null,&quot;type&quot;:null,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" title="" srcset="https://substackcdn.com/image/fetch/$s_!J36b!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F49b0ac0e-e599-4e30-9c79-74b0018fea6b_1024x695.png 424w, https://substackcdn.com/image/fetch/$s_!J36b!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F49b0ac0e-e599-4e30-9c79-74b0018fea6b_1024x695.png 848w, https://substackcdn.com/image/fetch/$s_!J36b!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F49b0ac0e-e599-4e30-9c79-74b0018fea6b_1024x695.png 1272w, https://substackcdn.com/image/fetch/$s_!J36b!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F49b0ac0e-e599-4e30-9c79-74b0018fea6b_1024x695.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><p>6. We now need the Sentry&nbsp;DSN:</p><ul><li><p>Go to&nbsp;<strong>Settings</strong></p></li><li><p>Select <strong>Projects</strong></p></li><li><p>Choose the project you used when creating the&nbsp;monitor</p></li></ul><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!c9ba!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F82a97f41-a8fe-4ea3-a7ec-63ce6d115062_1024x695.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!c9ba!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F82a97f41-a8fe-4ea3-a7ec-63ce6d115062_1024x695.png 424w, https://substackcdn.com/image/fetch/$s_!c9ba!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F82a97f41-a8fe-4ea3-a7ec-63ce6d115062_1024x695.png 848w, https://substackcdn.com/image/fetch/$s_!c9ba!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F82a97f41-a8fe-4ea3-a7ec-63ce6d115062_1024x695.png 1272w, https://substackcdn.com/image/fetch/$s_!c9ba!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F82a97f41-a8fe-4ea3-a7ec-63ce6d115062_1024x695.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!c9ba!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F82a97f41-a8fe-4ea3-a7ec-63ce6d115062_1024x695.png" width="1024" height="695" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/82a97f41-a8fe-4ea3-a7ec-63ce6d115062_1024x695.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:695,&quot;width&quot;:1024,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:null,&quot;alt&quot;:&quot;&quot;,&quot;title&quot;:null,&quot;type&quot;:null,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" title="" srcset="https://substackcdn.com/image/fetch/$s_!c9ba!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F82a97f41-a8fe-4ea3-a7ec-63ce6d115062_1024x695.png 424w, https://substackcdn.com/image/fetch/$s_!c9ba!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F82a97f41-a8fe-4ea3-a7ec-63ce6d115062_1024x695.png 848w, https://substackcdn.com/image/fetch/$s_!c9ba!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F82a97f41-a8fe-4ea3-a7ec-63ce6d115062_1024x695.png 1272w, https://substackcdn.com/image/fetch/$s_!c9ba!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F82a97f41-a8fe-4ea3-a7ec-63ce6d115062_1024x695.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><ul><li><p>Go to <strong>Client&nbsp;Keys</strong></p></li><li><p>Copy and store the&nbsp;<strong>DSN</strong></p></li></ul><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!DFaG!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fcfcd97ec-200e-4457-84c3-efa2fbdd3ea1_1024x695.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!DFaG!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fcfcd97ec-200e-4457-84c3-efa2fbdd3ea1_1024x695.png 424w, https://substackcdn.com/image/fetch/$s_!DFaG!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fcfcd97ec-200e-4457-84c3-efa2fbdd3ea1_1024x695.png 848w, https://substackcdn.com/image/fetch/$s_!DFaG!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fcfcd97ec-200e-4457-84c3-efa2fbdd3ea1_1024x695.png 1272w, https://substackcdn.com/image/fetch/$s_!DFaG!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fcfcd97ec-200e-4457-84c3-efa2fbdd3ea1_1024x695.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!DFaG!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fcfcd97ec-200e-4457-84c3-efa2fbdd3ea1_1024x695.png" width="1024" height="695" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/cfcd97ec-200e-4457-84c3-efa2fbdd3ea1_1024x695.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:695,&quot;width&quot;:1024,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:null,&quot;alt&quot;:&quot;&quot;,&quot;title&quot;:null,&quot;type&quot;:null,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" title="" srcset="https://substackcdn.com/image/fetch/$s_!DFaG!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fcfcd97ec-200e-4457-84c3-efa2fbdd3ea1_1024x695.png 424w, https://substackcdn.com/image/fetch/$s_!DFaG!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fcfcd97ec-200e-4457-84c3-efa2fbdd3ea1_1024x695.png 848w, https://substackcdn.com/image/fetch/$s_!DFaG!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fcfcd97ec-200e-4457-84c3-efa2fbdd3ea1_1024x695.png 1272w, https://substackcdn.com/image/fetch/$s_!DFaG!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fcfcd97ec-200e-4457-84c3-efa2fbdd3ea1_1024x695.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><p>And that&#8217;s all for&nbsp;Sentry.</p><h3>Step 4: Convert your postgres credentials to a connection URL</h3><p>That&#8217;s one of the easy steps. If you already have a connection URL, you can skip this step. Anyway, to convert connection credentials to a URL, use this&nbsp;format:</p><pre><code>postgresql://[username]:[password]@[db-host]:[port]/[database]</code></pre><h4><strong>A note for Supabase&nbsp;users:</strong></h4><p>The image <strong>doesn&#8217;t support IPv6. </strong>So please use the<strong> session pooler&nbsp;</strong>instead<strong>.</strong></p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!erNF!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F1a96656b-c60f-4b8c-9e41-e326942dcf76_1024x692.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!erNF!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F1a96656b-c60f-4b8c-9e41-e326942dcf76_1024x692.png 424w, https://substackcdn.com/image/fetch/$s_!erNF!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F1a96656b-c60f-4b8c-9e41-e326942dcf76_1024x692.png 848w, https://substackcdn.com/image/fetch/$s_!erNF!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F1a96656b-c60f-4b8c-9e41-e326942dcf76_1024x692.png 1272w, https://substackcdn.com/image/fetch/$s_!erNF!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F1a96656b-c60f-4b8c-9e41-e326942dcf76_1024x692.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!erNF!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F1a96656b-c60f-4b8c-9e41-e326942dcf76_1024x692.png" width="1024" height="692" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/1a96656b-c60f-4b8c-9e41-e326942dcf76_1024x692.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:692,&quot;width&quot;:1024,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:null,&quot;alt&quot;:&quot;&quot;,&quot;title&quot;:null,&quot;type&quot;:null,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" title="" srcset="https://substackcdn.com/image/fetch/$s_!erNF!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F1a96656b-c60f-4b8c-9e41-e326942dcf76_1024x692.png 424w, https://substackcdn.com/image/fetch/$s_!erNF!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F1a96656b-c60f-4b8c-9e41-e326942dcf76_1024x692.png 848w, https://substackcdn.com/image/fetch/$s_!erNF!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F1a96656b-c60f-4b8c-9e41-e326942dcf76_1024x692.png 1272w, https://substackcdn.com/image/fetch/$s_!erNF!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F1a96656b-c60f-4b8c-9e41-e326942dcf76_1024x692.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><h3>Step 5: Filling out the&nbsp;.env&nbsp;file</h3><p>You will need to pass the backup config to the container somehow. Here&#8217;s how to do&nbsp;that:</p><ol><li><p>Download the&nbsp;.env.preset from&nbsp;GitHub:</p></li></ol><pre><code>curl -o .env "https://raw.githubusercontent.com/andriotisnikos1/pg-backup/refs/heads/main/.env.preset"</code></pre><p>2. Fill out the env vars. Let&#8217;s go over them one by&nbsp;one:</p><p><strong>S3-Compatible ENVs</strong></p><ul><li><p>S3_REGION Is the S3-API compatible region. Fill it with auto if using <strong>Cloudflare, </strong>or the region that you copied if not using Cloudflare</p></li><li><p>S3_ENDPOINT Is the endpoint to your bucket. Leave empty if using <strong>AWS, </strong>use the &#8220; <strong>Jurisdiction-Specific Endpoint</strong>&#8221; if you are using <strong>Cloudflare </strong>and the bucket &#8220;<strong>Endpoint&#8221; </strong>if using Backblaze</p></li><li><p>S3_AUTH_KEY_ID Is the &#8220;<strong>Access Key&nbsp;ID&#8221;</strong></p></li><li><p>S3_AUTH_KEY_SECRET Is the &#8220;<strong>Secret Access&nbsp;Key</strong>&#8221;</p></li><li><p>S3_BUCKET is the bucket&nbsp;name</p></li></ul><p><strong>Backups Configuration ENVs</strong></p><ul><li><p>BACKUPS_CRON_SCHEDULE Is the schedule from <strong>Step&nbsp;2</strong></p></li><li><p>BACKUPS_MAX_KEEP_COUNT (Optional modification, defaults to 5) Is the amount of newest backups to keep before deleting the old&nbsp;ones</p></li><li><p>BACKUPS_FILE_IDENTIFIER (Optional) Is a string appended to the backup file&#8217;s names to distinguish them from others. For example, a configuration with the identifier set to &#8220;<strong>andriotis&#8221; </strong>will result in files with naming like so: {date}-{random 32 chars}.andriotis.dump&nbsp;. If left unset, the backup files will follow the {date}-{random 32 chars}.dump convention</p></li><li><p>BACKUPS_USE_PG_DUMPALL (Optional, defaults to &#8220;false&#8221;). Activates pg_dumpall instead of pg_dump&nbsp;. Used for bumping entire clusters, instead of a singular DB with its tables and&nbsp;data</p></li></ul><p><strong>Postgres Configuration ENVs</strong></p><ul><li><p>POSTGRES_URL Is the URL constructed at <strong>Step&nbsp;4</strong></p></li></ul><p><strong>(Optional) Sentry Configuration</strong></p><ul><li><p>SENTRY_ENABLED &#8220;true&#8221; or &#8220;false&#8221;, enables Sentry. Defaults to&nbsp;&#8220;false&#8221;</p></li><li><p>SENTRY_DSN Is the DSN of your project, we copied this at <strong>Step&nbsp;3</strong></p></li><li><p>SENTRY_MONITOR_SLUG Is the slug of the monitor we created at <strong>Step&nbsp;3</strong></p></li></ul><h3>Step 6: Deploying</h3><p><strong>A note before deploying:</strong></p><p>Postgres 16 was released in 2023 and Postgres 15 in 2022. So if your DB is recent, you&#8217;re most probably using PG 16. The backup will error out if you&#8217;re using an incompatible version so you should probably check it before deploying. You can check the version of your DB by running the&nbsp;query:</p><pre><code>select version();</code></pre><ol><li><p><strong>Docker</strong></p></li></ol><ul><li><p><strong>For Postgres&nbsp;16:</strong></p></li></ul><pre><code>docker run -d \
    -v "./.env:/app/.env" \
    andriotisnikos1/pg-backup</code></pre><ul><li><p><strong>For Postgres&nbsp;15</strong></p></li></ul><pre><code>docker run -d \
    -v "./.env:/app/.env" \
    andriotisnikos1/pg-backup:pg-15</code></pre><ul><li><p><strong>For Postgres&nbsp;14</strong></p></li></ul><pre><code>docker run -d \
    -v "./.env:/app/.env" \
    andriotisnikos1/pg-backup:pg-14</code></pre><p>2. <strong>Railway</strong></p><ul><li><p>Go to the <strong><a href="https://railway.com/template/ZJn5OO?referralCode=2VmC2h">template</a> </strong>and click <strong>Deploy Now&#8202;&#8212;&#8202;</strong>Postgres 16 is <strong>required!</strong></p></li><li><p>Input the&nbsp;.env file contents from the previous&nbsp;step</p></li><li><p>Click deploy</p></li></ul><p>3. <strong>Paid Deployment (Hire&nbsp;me!)</strong></p><p>If deployment is a hassle, i can do it for you as well as guide you with collecting the right ENV values and answering any of your questions for a coffee (5$). You can find me on fiverr: <a href="https://www.fiverr.com/s/BRadeNz">https://www.fiverr.com/s/BRadeNz</a></p><h3>Building the image for a version other than 14,15 and&nbsp;16</h3><p>If you want to build for another version, first make sure it supports pg_dump and/or pg_dumpall then:</p><ul><li><p>Clone the&nbsp;repo</p></li><li><p>Build the image for your&nbsp;version</p></li></ul><pre><code># clone repo
git clone https://github.com/andriotisnikos1/pg-backup.git

# cd
cd pg-backup

# build
docker build -t pg-backup --build-arg POSTGRES_VERSION=[your-version] .</code></pre><h3>GitHub</h3><p><a href="https://github.com/andriotisnikos1/pg-backup">GitHub - andriotisnikos1/pg-backup</a></p><h3>Regarding stricter permissions for&nbsp;AWS</h3><ol><li><p>Go to the AWS S3 on your desired&nbsp;region</p></li><li><p>Select your bucket, then click on &#8220;<strong>Copy&nbsp;ARN&#8221;</strong></p></li></ol><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!kboJ!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd351d7da-e151-49f3-a4d5-88eb4fef4634_1024x696.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!kboJ!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd351d7da-e151-49f3-a4d5-88eb4fef4634_1024x696.png 424w, https://substackcdn.com/image/fetch/$s_!kboJ!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd351d7da-e151-49f3-a4d5-88eb4fef4634_1024x696.png 848w, https://substackcdn.com/image/fetch/$s_!kboJ!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd351d7da-e151-49f3-a4d5-88eb4fef4634_1024x696.png 1272w, https://substackcdn.com/image/fetch/$s_!kboJ!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd351d7da-e151-49f3-a4d5-88eb4fef4634_1024x696.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!kboJ!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd351d7da-e151-49f3-a4d5-88eb4fef4634_1024x696.png" width="1024" height="696" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/d351d7da-e151-49f3-a4d5-88eb4fef4634_1024x696.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:696,&quot;width&quot;:1024,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:null,&quot;alt&quot;:&quot;&quot;,&quot;title&quot;:null,&quot;type&quot;:null,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" title="" srcset="https://substackcdn.com/image/fetch/$s_!kboJ!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd351d7da-e151-49f3-a4d5-88eb4fef4634_1024x696.png 424w, https://substackcdn.com/image/fetch/$s_!kboJ!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd351d7da-e151-49f3-a4d5-88eb4fef4634_1024x696.png 848w, https://substackcdn.com/image/fetch/$s_!kboJ!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd351d7da-e151-49f3-a4d5-88eb4fef4634_1024x696.png 1272w, https://substackcdn.com/image/fetch/$s_!kboJ!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd351d7da-e151-49f3-a4d5-88eb4fef4634_1024x696.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><p>3. Go back to&nbsp;IAM</p><p>4. Click on <strong>Policies, </strong>then <strong>Create&nbsp;Policy</strong></p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!RD9y!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff193c70c-6f0a-416b-89d9-fd1b6896534a_1024x695.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!RD9y!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff193c70c-6f0a-416b-89d9-fd1b6896534a_1024x695.png 424w, https://substackcdn.com/image/fetch/$s_!RD9y!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff193c70c-6f0a-416b-89d9-fd1b6896534a_1024x695.png 848w, https://substackcdn.com/image/fetch/$s_!RD9y!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff193c70c-6f0a-416b-89d9-fd1b6896534a_1024x695.png 1272w, https://substackcdn.com/image/fetch/$s_!RD9y!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff193c70c-6f0a-416b-89d9-fd1b6896534a_1024x695.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!RD9y!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff193c70c-6f0a-416b-89d9-fd1b6896534a_1024x695.png" width="1024" height="695" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/f193c70c-6f0a-416b-89d9-fd1b6896534a_1024x695.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:695,&quot;width&quot;:1024,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:null,&quot;alt&quot;:&quot;&quot;,&quot;title&quot;:null,&quot;type&quot;:null,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" title="" srcset="https://substackcdn.com/image/fetch/$s_!RD9y!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff193c70c-6f0a-416b-89d9-fd1b6896534a_1024x695.png 424w, https://substackcdn.com/image/fetch/$s_!RD9y!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff193c70c-6f0a-416b-89d9-fd1b6896534a_1024x695.png 848w, https://substackcdn.com/image/fetch/$s_!RD9y!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff193c70c-6f0a-416b-89d9-fd1b6896534a_1024x695.png 1272w, https://substackcdn.com/image/fetch/$s_!RD9y!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Ff193c70c-6f0a-416b-89d9-fd1b6896534a_1024x695.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><p>5. Switch to <strong>JSON mode </strong>and paste in the following:</p><pre><code>{
 "Version": "2012-10-17",
 "Statement": [
  {
   "Sid": "Statement1",
   "Effect": "Allow",
   "Action": [
    "s3:ListBucket",
    "s3:PutObject",
    "s3:GetObject",
    "s3:DeleteObject"
   ],
   "Resource": [
    "[ARN from previously]",
    "[ARN from previously]/*"
   ]
  }
 ]
}</code></pre><p>Don&#8217;t forget to replace your&nbsp;ARN!</p><p>This restricts permissions for your user to just the following on your specified bucket:</p><ul><li><p>Retrieving objects</p></li><li><p>Listing objects</p></li><li><p>Adding objects</p></li><li><p>Deleting objects</p></li></ul><p>5. Click <strong>Continue, </strong>give your policy a name (i named it pg-backup) then click <strong>Create&nbsp;policy.</strong></p><p>6. Now, when creating your user, you can attach the policy to it, giving it just enough permissions to do its&nbsp;job.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!Ng4t!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3a3a800a-3a93-4d89-b68f-17c3ee18f262_1024x648.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!Ng4t!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3a3a800a-3a93-4d89-b68f-17c3ee18f262_1024x648.png 424w, https://substackcdn.com/image/fetch/$s_!Ng4t!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3a3a800a-3a93-4d89-b68f-17c3ee18f262_1024x648.png 848w, https://substackcdn.com/image/fetch/$s_!Ng4t!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3a3a800a-3a93-4d89-b68f-17c3ee18f262_1024x648.png 1272w, https://substackcdn.com/image/fetch/$s_!Ng4t!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3a3a800a-3a93-4d89-b68f-17c3ee18f262_1024x648.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!Ng4t!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3a3a800a-3a93-4d89-b68f-17c3ee18f262_1024x648.png" width="1024" height="648" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/3a3a800a-3a93-4d89-b68f-17c3ee18f262_1024x648.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:648,&quot;width&quot;:1024,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:null,&quot;alt&quot;:&quot;&quot;,&quot;title&quot;:null,&quot;type&quot;:null,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" title="" srcset="https://substackcdn.com/image/fetch/$s_!Ng4t!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3a3a800a-3a93-4d89-b68f-17c3ee18f262_1024x648.png 424w, https://substackcdn.com/image/fetch/$s_!Ng4t!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3a3a800a-3a93-4d89-b68f-17c3ee18f262_1024x648.png 848w, https://substackcdn.com/image/fetch/$s_!Ng4t!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3a3a800a-3a93-4d89-b68f-17c3ee18f262_1024x648.png 1272w, https://substackcdn.com/image/fetch/$s_!Ng4t!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F3a3a800a-3a93-4d89-b68f-17c3ee18f262_1024x648.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div><p>The steps for AWS credentials continue normally for the user creation flow, no need to repeat&nbsp;myself</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!FPtP!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fbe22003e-7c1a-468c-b8a3-133921728949_1024x683.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!FPtP!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fbe22003e-7c1a-468c-b8a3-133921728949_1024x683.png 424w, https://substackcdn.com/image/fetch/$s_!FPtP!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fbe22003e-7c1a-468c-b8a3-133921728949_1024x683.png 848w, https://substackcdn.com/image/fetch/$s_!FPtP!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fbe22003e-7c1a-468c-b8a3-133921728949_1024x683.png 1272w, https://substackcdn.com/image/fetch/$s_!FPtP!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fbe22003e-7c1a-468c-b8a3-133921728949_1024x683.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!FPtP!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fbe22003e-7c1a-468c-b8a3-133921728949_1024x683.png" width="1024" height="683" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/be22003e-7c1a-468c-b8a3-133921728949_1024x683.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:683,&quot;width&quot;:1024,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:null,&quot;alt&quot;:&quot;&quot;,&quot;title&quot;:null,&quot;type&quot;:null,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" title="" srcset="https://substackcdn.com/image/fetch/$s_!FPtP!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fbe22003e-7c1a-468c-b8a3-133921728949_1024x683.png 424w, https://substackcdn.com/image/fetch/$s_!FPtP!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fbe22003e-7c1a-468c-b8a3-133921728949_1024x683.png 848w, https://substackcdn.com/image/fetch/$s_!FPtP!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fbe22003e-7c1a-468c-b8a3-133921728949_1024x683.png 1272w, https://substackcdn.com/image/fetch/$s_!FPtP!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fbe22003e-7c1a-468c-b8a3-133921728949_1024x683.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg role="img" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><title></title><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a></figure></div>]]></content:encoded></item><item><title><![CDATA[Making a simple web scraper with an interface using RapidAPI and Next.js]]></title><description><![CDATA[Wanna scrape?]]></description><link>https://andriotis.me/p/making-a-simple-web-scraper-with-an-interface-using-rapidapi-and-next-js-5f22a1125561</link><guid isPermaLink="false">https://andriotis.me/p/making-a-simple-web-scraper-with-an-interface-using-rapidapi-and-next-js-5f22a1125561</guid><dc:creator><![CDATA[Nikos Andriotis]]></dc:creator><pubDate>Fri, 09 Aug 2024 01:45:23 GMT</pubDate><enclosure url="https://substack-post-media.s3.amazonaws.com/public/images/96ba2a01-a9e5-4faa-9848-fef9e9df21f9_1024x662.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Wanna scrape? You&#8217;ve come to the right&nbsp;place</p><p><strong>The demo is publicly available</strong> @ <a href="http://scraper-demo.andriotis.me">scraper-demo.andriotis.me</a> and <a href="https://github.com/andriotisnikos1/scraper-demo.git">github.com/andriotisnikos1/scraper-demo</a></p><p>So. You want to scrape some websites but don&#8217;t know where to start? Ive got you. I believe you have read the title, so i won&#8217;t repeat&nbsp;myself.</p><p><strong>What you&#8217;re gonna&nbsp;need:</strong></p><ul><li><p>A <a href="https://rapidapi.com">RapidAPI&nbsp;account</a></p></li><li><p><a href="http://rapidapi.com/andriotisnikos1/api/crawl-and-scrape-check">A free subscription to the web scraper</a> and your API&nbsp;Key</p></li><li><p>Node.js and NPM (Who doesn&#8217;t have that&nbsp;IK)</p></li><li><p>20 minutes of your&nbsp;time</p></li></ul><p>Lets get to&nbsp;it!</p><h3><strong>Preparation: Getting the RapidAPI API&nbsp;Key</strong></h3><ul><li><p>Head over to <a href="https://rapidapi.com/developer/dashboard">https://rapidapi.com/developer/dashboard</a></p></li><li><p>On the sidebar under &#8220;My Apps&#8221; select one and head to Authorisation&#8221;. If you don&#8217;t have a project, create&nbsp;one</p></li><li><p>Copy your API Key. If you don&#8217;t have one, create one with the &#8220;RapidAPI&#8221; scope</p></li></ul><h3><strong>Part 1: Initialising the&nbsp;project</strong></h3><p>Navigate to your workspace folder. Mine is &#8220;~/workspace&#8221;</p><ul><li><p>Initialise a project&nbsp;with</p></li></ul><pre><code>npx create-next-app --ts scraper
cd scraper</code></pre><p>or if you&#8217;re feeling&nbsp;cheeky:</p><pre><code>yes | npx create-next-app --ts scraper
cd scraper</code></pre><p>this will answer all prompts with &#8220;y&#8221;, something that we&nbsp;need</p><ul><li><p>Now, <strong>add your API Key to&nbsp;.env</strong>:</p></li></ul><pre><code>echo "RAPIDAPI_KEY=&lt;your key here&gt;" &gt; .env</code></pre><ul><li><p>Dependencies</p></li></ul><pre><code>npm i axios sonner @radix-ui/react-icons</code></pre><h3>Part 2: Server&nbsp;Actions</h3><p>The API currently supports 2 endpoints, <strong>/check</strong> and <strong>/scrape</strong>. Here&#8217;s some info about&nbsp;them:</p><ul><li><p><strong>/check </strong>Checks if a URL can be scraped, according to the URL&#8217;s policies.</p></li><li><p><strong>/scrape </strong>Scrapes a URL, processes it according to the&nbsp;rules</p></li></ul><ol><li><p>Make the actions.ts file</p></li></ol><pre><code>touch app/actions.ts</code></pre><p>2. Add these functions:</p><pre><code>"use server" // initialise as server file

import axios from "axios";

// checks if the input URL can be scraped
export async function scrapeCheck(url: string) {
    try {
        const options = {
            headers: {
                'X-RapidAPI-Key': process.env.RAPIDAPI_KEY,
                'X-RapidAPI-Host': 'crawl-and-scrape-check.p.rapidapi.com'
            }
        };
        // build the request URL
        const builtURL = new URL("https://crawl-and-scrape-check.p.rapidapi.com/check")
        builtURL.searchParams.append('url', url)
        builtURL.searchParams.append('agent', 'ScrapeBot') // you can change the value of this
        const res = await axios.get&lt;{ allowed: boolean }&gt;(builtURL.toString(), { headers: options.headers });
        return res.data.allowed
    } catch (error) {
        console.error(error)
        return false
    }
}

// sends scrape request
export async function scrapeURL(url: string) {
    try {
        const options = {
            headers: {
                'X-RapidAPI-Key': process.env.RAPIDAPI_KEY,
                'X-RapidAPI-Host': 'crawl-and-scrape-check.p.rapidapi.com'
            }
        };
        const builtURL = new URL("https://crawl-and-scrape-check.p.rapidapi.com/scrape")
        builtURL.searchParams.append('url', url)
        // you can change this to an element name
        builtURL.searchParams.append('selector', 'body')
        // you can change this to comma-seperated element names
        builtURL.searchParams.append('unwantedFields', 'link,script,head')
        const res = await axios.get&lt;{
            content: string
        }&gt;(builtURL.toString(), { headers: options.headers });
        return res.data.content
    } catch (error) {
        console.error(error)
        return null
    }
}</code></pre><h3>Part 3: layout.tsx</h3><p>We are starting to approach the HTML part of this demo. <strong>Add these styles to your &lt;body&gt; tag in layout.tsx&nbsp;:</strong></p><pre><code>min-h-full flex flex-col w-full items-center justify-center space-y-20</code></pre><p>This should be the JSX in layout.tsx&nbsp;:</p><pre><code> &lt;html lang="en" className="h-screen"&gt;
      &lt;body className={inter.className + " min-h-full flex flex-col w-full items-center justify-center space-y-20"}&gt;{children}&lt;/body&gt; // change this line
   &lt;/html&gt;</code></pre><h3>Part 4: Form&nbsp;Actions</h3><p>In this part, we add the form actions that will run when we press the &#8220;Check&#8221; and &#8220;Scrape&#8221;&nbsp;buttons</p><ul><li><p>In your page.tsx file, remove all imports and add&nbsp;this:</p></li></ul><pre><code>"use client"
import { Link2Icon } from "@radix-ui/react-icons";
import React, { useState } from "react";
import { toast, Toaster } from "sonner";
import { scrapeCheck, scrapeURL } from "./actions";

// check url scraping
async function checkURL(f: FormData) {
  // get url
  const inputUrl = f.get("url")
  if (!inputUrl) return toast.error("Please enter a URL", {duration: 5000});
  // scrape check
  toast.loading("Checking if scraping is allowed...", { duration: 5000 });
  const res = await scrapeCheck(inputUrl as string);
  // result
  if (res) toast.success("Scraping is allowed", {duration: 5000});
  else toast.error("Scraping is not allowed", {duration: 5000});
}

// scrape URL
async function scrape(f: FormData) {
  // get url
  const inputUrl = f.get("url");
  if (!inputUrl) return toast.error("Please enter a URL", {duration: 5000});
  // scrape
  toast.loading(`Scraping ${inputUrl} ...`, {duration: 5000});
  const res = await scrapeURL(inputUrl as string);
  if (!res) return toast.error("Failed to scrape the URL", {duration: 5000});
  // download
  const blob = new Blob([res], { type: "text/plain" });
  const url = URL.createObjectURL(blob);
  const a = document.createElement("a");
  a.href = url;
  a.download = `scraped-${f.get("url")!}.html`
  document.body.appendChild(a);
  a.click();
  window.URL.revokeObjectURL(url);
}</code></pre><p>Lets talk a bit about these&nbsp;actions:</p><ul><li><p>checkURL takes the URL from the form and outputs the result of the check as a&nbsp;toast</p></li><li><p>scrape is a bit more interesting. It sends a request for a file scrape then checks if it was successful. In case that&#8217;s true, it creates a file and sends it for download!</p></li></ul><h3>Part 4:&nbsp;JSX</h3><p>Finally, replace the JSX part of your page.tsx with this simple&nbsp;form:</p><pre><code>export default function Home() {
  const [url, setUrl] = useState("");
  return (
    &lt;React.Fragment&gt;
      {/* Title */}
      &lt;h1 className="md:text-[60px] text-[30px] font-bold"&gt;Scrape Check Demo&lt;/h1&gt;
      &lt;div className="flex flex-col w-full items-center justify-center gap-2"&gt;
        {/* Main Input */}
        &lt;div className="flex w-11/12 md:w-2/5 items-center space-x-2 p-4 bg-slate-100 rounded-lg"&gt;
          &lt;Link2Icon className="h-5 w-5" /&gt;
          &lt;input type="text" placeholder="Enter a URL....." className="outline-none bg-transparent w-4/5" onChange={(e) =&gt; setUrl(e.target.value)} /&gt;
        &lt;/div&gt;
        &lt;div className="flex items-center gap-2 px-2 flex-col md:flex-row "&gt;
          {/* Check Button */}
          &lt;form action={checkURL}&gt;
            &lt;input type="text" name="url" hidden readOnly value={url} required /&gt;
            &lt;button type="submit" className="w-[250px] p-2 text-sm bg-slate-100 rounded-md "&gt;Can i scrape that?&lt;/button&gt;
          &lt;/form&gt;
          {/* Scrape Button */}
          &lt;form action={scrape}&gt;
            &lt;input type="text" name="url" hidden readOnly value={url} required /&gt;
            &lt;button type="submit" className="w-[250px] p-2 text-sm bg-slate-100 rounded-md "&gt;Scrape URL&lt;/button&gt;
          &lt;/form&gt;
        &lt;/div&gt;
      &lt;/div&gt;
      &lt;Toaster /&gt;
    &lt;/React.Fragment&gt;
  );
}</code></pre><p><strong>Your page.tsx should look like&nbsp;this:</strong></p><pre><code>"use client"
import { Link2Icon } from "@radix-ui/react-icons";
import React, { useState } from "react";
import { toast, Toaster } from "sonner";
import { scrapeCheck, scrapeURL } from "./actions";

// check url scraping
async function checkURL(f: FormData) {
  // get url
  const inputUrl = f.get("url")
  if (!inputUrl) return toast.error("Please enter a URL", {duration: 5000});
  // scrape check
  toast.loading("Checking if scraping is allowed...", { duration: 5000 });
  const res = await scrapeCheck(inputUrl as string);
  // result
  if (res) toast.success("Scraping is allowed", {duration: 5000});
  else toast.error("Scraping is not allowed", {duration: 5000});
}

// scrape URL
async function scrape(f: FormData) {
  // get url
  const inputUrl = f.get("url");
  if (!inputUrl) return toast.error("Please enter a URL", {duration: 5000});
  // scrape
  toast.loading(`Scraping ${inputUrl} ...`, {duration: 5000});
  const res = await scrapeURL(inputUrl as string);
  if (!res) return toast.error("Failed to scrape the URL", {duration: 5000});
  // download
  const blob = new Blob([res], { type: "text/plain" });
  const url = URL.createObjectURL(blob);
  const a = document.createElement("a");
  a.href = url;
  a.download = `scraped-${f.get("url")!}.html`
  document.body.appendChild(a);
  a.click();
  window.URL.revokeObjectURL(url);
}

export default function Home() {
  const [url, setUrl] = useState("");
  return (
    &lt;React.Fragment&gt;
      {/* Title */}
      &lt;h1 className="md:text-[60px] text-[30px] font-bold"&gt;Scrape Check Demo&lt;/h1&gt;
      &lt;div className="flex flex-col w-full items-center justify-center gap-2"&gt;
        {/* Main Input */}
        &lt;div className="flex w-11/12 md:w-2/5 items-center space-x-2 p-4 bg-slate-100 rounded-lg"&gt;
          &lt;Link2Icon className="h-5 w-5" /&gt;
          &lt;input type="text" placeholder="Enter a URL....." className="outline-none bg-transparent w-4/5" onChange={(e) =&gt; setUrl(e.target.value)} /&gt;
        &lt;/div&gt;
        &lt;div className="flex items-center gap-2 px-2 flex-col md:flex-row "&gt;
          {/* Check Button */}
          &lt;form action={checkURL}&gt;
            &lt;input type="text" name="url" hidden readOnly value={url} required /&gt;
            &lt;button type="submit" className="w-[250px] p-2 text-sm bg-slate-100 rounded-md "&gt;Can i scrape that?&lt;/button&gt;
          &lt;/form&gt;
          {/* Scrape Button */}
          &lt;form action={scrape}&gt;
            &lt;input type="text" name="url" hidden readOnly value={url} required /&gt;
            &lt;button type="submit" className="w-[250px] p-2 text-sm bg-slate-100 rounded-md "&gt;Scrape URL&lt;/button&gt;
          &lt;/form&gt;
        &lt;/div&gt;
      &lt;/div&gt;
      &lt;Toaster /&gt;
    &lt;/React.Fragment&gt;
  );
}</code></pre><p>This should be the output when you visit localhost:3000:</p><div class="captioned-image-container"><figure><a class="image-link image2" target="_blank" href="https://substackcdn.com/image/fetch/$s_!jKoj!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F1250849b-d303-4960-b37f-1f820770d9ee_1024x662.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!jKoj!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F1250849b-d303-4960-b37f-1f820770d9ee_1024x662.png 424w, https://substackcdn.com/image/fetch/$s_!jKoj!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F1250849b-d303-4960-b37f-1f820770d9ee_1024x662.png 848w, https://substackcdn.com/image/fetch/$s_!jKoj!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F1250849b-d303-4960-b37f-1f820770d9ee_1024x662.png 1272w, https://substackcdn.com/image/fetch/$s_!jKoj!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F1250849b-d303-4960-b37f-1f820770d9ee_1024x662.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!jKoj!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F1250849b-d303-4960-b37f-1f820770d9ee_1024x662.png" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/1250849b-d303-4960-b37f-1f820770d9ee_1024x662.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:null,&quot;width&quot;:null,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:null,&quot;alt&quot;:&quot;&quot;,&quot;title&quot;:null,&quot;type&quot;:null,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" title="" srcset="https://substackcdn.com/image/fetch/$s_!jKoj!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F1250849b-d303-4960-b37f-1f820770d9ee_1024x662.png 424w, https://substackcdn.com/image/fetch/$s_!jKoj!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F1250849b-d303-4960-b37f-1f820770d9ee_1024x662.png 848w, https://substackcdn.com/image/fetch/$s_!jKoj!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F1250849b-d303-4960-b37f-1f820770d9ee_1024x662.png 1272w, https://substackcdn.com/image/fetch/$s_!jKoj!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F1250849b-d303-4960-b37f-1f820770d9ee_1024x662.png 1456w" sizes="100vw" loading="lazy"></picture><div></div></div></a></figure></div><p><strong>Reminder: You can also visit </strong><a href="https://scraper-demo.andriotis.me">scraper-demo.andriotis.me</a></p><h3>Now for the last part:&nbsp;Usage</h3><ol><li><p>Enter a URL on the&nbsp;field</p></li><li><p>Click either &#8220;Can i scrape that?&#8221; or &#8220;Scrape&nbsp;URL&#8221;</p></li></ol><p>You&#8217;ll get your response via&nbsp;toast!</p><p><em><strong>Thanks for&nbsp;reading!</strong></em></p>]]></content:encoded></item><item><title><![CDATA[Flexible file chunking for Node.js applications with a mini-sdk]]></title><description><![CDATA[Introducing Triple Dot]]></description><link>https://andriotis.me/p/flexible-file-chunking-for-node-js-applications-with-a-mini-sdk-4dc0b36e80ce</link><guid isPermaLink="false">https://andriotis.me/p/flexible-file-chunking-for-node-js-applications-with-a-mini-sdk-4dc0b36e80ce</guid><dc:creator><![CDATA[Nikos Andriotis]]></dc:creator><pubDate>Sat, 23 Mar 2024 02:35:40 GMT</pubDate><enclosure url="https://substack-post-media.s3.amazonaws.com/public/images/e399279e-6ef7-49d2-936c-0787ed614e0b_1024x512.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Introducing Triple&nbsp;Dot</p><p>If you&#8217;ve happened to see any of my recent tweets, im working on an OSS personal file system that can be controlled by the&nbsp;terminal</p><p>So, in order to be able to chunk my files into many, smaller files to upload them progressively and without causing a memory overflow.</p><p>We already know that node programs arent the most momory efficient ones and i dont want to make mine a nightmare. Soooooooo i had to build a file&nbsp;chunker.</p><p><strong>This is where i built Trple Dot </strong>(or &#8220;&#8230;&#8221; or the chunking of a&nbsp;line)</p><p>Lets chunk a file together!</p><h4><strong>Installation</strong></h4><pre><code>bun install @andriotis/triple-dot</code></pre><h4>Usage method 1: File System&nbsp;Chunks</h4><pre><code>import td from "@andriotis/triple-dot";

await td({
    // chunk size in KB
    chunkSize: 1024,
    filePath: "./bun.lockb",
    outputDir: ".triple-dot"
})</code></pre><p>after a bit,&nbsp;.triple-dot will contain files with the format #.chunk where # is the number of the&nbsp;chunk</p><p>Before we move on to the second method, id like to mention the function getFileChunkStats that allows you to predict the behaviour of triple dot by providing you with the chunk amount it will generate for a given file as well as its stats from&nbsp;fs.</p><p><strong>Usage</strong></p><pre><code>import { getFileChunkStats } from "@andriotis/triple-dot";

const stats = await getFileChunkStats("bun.lockb", 1024);
console.log(stats);</code></pre><p>Output</p><pre><code>{
  "chunks": 1 (or another number),
  "stats": ... (typeof fs.Stats)
}</code></pre><h4>Usage method 2: Callback Function&nbsp;Chunks</h4><p>Triple Dot has the option to pass the chunk buffer to an onProgress function instead of writing to the file system. Lets see how this&nbsp;works</p><pre><code>import td from "@andriotis/triple-dot";

const outputToProgress = true;

await td({
  chunkSize: 1024,
  filePath: "bun.lockb",
  outputDir: ".chunks",
  passChunkToCallback: outputToProgress,
  onProgress: (chunkNumber, totalChunks, buffer) =&gt; {
    // do stuff with the buffer....
    return;
  },
});</code></pre><p>And that&#8217;s how you can chunk a file with triple dot! If you have any questions, feel free to email me at medium@andriotis.me</p><p>Oh, i almost forgot. Triple dot is OSS. You can check it out here: <a href="https://github.com/andriotisnikos1/file-chunker">https://github.com/andriotisnikos1/file-chunker</a></p><p>thats all for today.&nbsp;adios!</p><div class="captioned-image-container"><figure><a class="image-link image2" target="_blank" href="https://substackcdn.com/image/fetch/$s_!WPz3!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F1779d95d-40a2-4a86-9ca9-2287b3c481b3_1024x512.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!WPz3!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F1779d95d-40a2-4a86-9ca9-2287b3c481b3_1024x512.png 424w, https://substackcdn.com/image/fetch/$s_!WPz3!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F1779d95d-40a2-4a86-9ca9-2287b3c481b3_1024x512.png 848w, https://substackcdn.com/image/fetch/$s_!WPz3!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F1779d95d-40a2-4a86-9ca9-2287b3c481b3_1024x512.png 1272w, https://substackcdn.com/image/fetch/$s_!WPz3!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F1779d95d-40a2-4a86-9ca9-2287b3c481b3_1024x512.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!WPz3!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F1779d95d-40a2-4a86-9ca9-2287b3c481b3_1024x512.png" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/1779d95d-40a2-4a86-9ca9-2287b3c481b3_1024x512.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:null,&quot;width&quot;:null,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:null,&quot;alt&quot;:&quot;&quot;,&quot;title&quot;:null,&quot;type&quot;:null,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" title="" srcset="https://substackcdn.com/image/fetch/$s_!WPz3!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F1779d95d-40a2-4a86-9ca9-2287b3c481b3_1024x512.png 424w, https://substackcdn.com/image/fetch/$s_!WPz3!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F1779d95d-40a2-4a86-9ca9-2287b3c481b3_1024x512.png 848w, https://substackcdn.com/image/fetch/$s_!WPz3!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F1779d95d-40a2-4a86-9ca9-2287b3c481b3_1024x512.png 1272w, https://substackcdn.com/image/fetch/$s_!WPz3!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F1779d95d-40a2-4a86-9ca9-2287b3c481b3_1024x512.png 1456w" sizes="100vw" loading="lazy"></picture><div></div></div></a></figure></div>]]></content:encoded></item><item><title><![CDATA[Polyhook Product Hunt launch report.]]></title><description><![CDATA[TLDR of the good stuff, the bad stuff and the lessons]]></description><link>https://andriotis.me/p/polyhook-product-hunt-release-report-2d975d404f89</link><guid isPermaLink="false">https://andriotis.me/p/polyhook-product-hunt-release-report-2d975d404f89</guid><dc:creator><![CDATA[Nikos Andriotis]]></dc:creator><pubDate>Fri, 16 Feb 2024 21:51:42 GMT</pubDate><enclosure url="https://substack-post-media.s3.amazonaws.com/public/images/3efe3c09-84ba-4fa9-8c11-c0773702861b_1024x512.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>TLDR of the good stuff, the bad stuff and the&nbsp;lessons</p><p>Launching a product or tool on PH is always something that makes you anxious, and I was no exception. In summary, the tool generated little to no attention getting 23 upvotes in 13&nbsp;hours.</p><p><strong>The good&nbsp;things:</strong></p><ul><li><p>i got back into development.</p></li><li><p>i got some, although little, traffic from&nbsp;twitter</p></li><li><p>5 people signed&nbsp;up.</p></li><li><p>20 projects were&nbsp;created.</p></li></ul><p><strong>The bad&nbsp;stuff:</strong></p><ul><li><p>Polyhook wasnt mobile friendly (I KNOW, i&nbsp;know)</p></li><li><p>I only had github as method of oauth. i cringe every time i think of&nbsp;this</p></li><li><p>Signup rate was very low&nbsp;(2%)</p></li></ul><p><strong>Lessons:</strong></p><ul><li><p>Even if you&#8217;re targeting developers. Google OAuth is still a popular choice among them. Don&#8217;t just go with GitHub. Otherwise, add Email&nbsp;signin</p></li><li><p>Make the app mobile friendly by design and from the first edition. Its not something dark mode. responsiveness is necessary. fun fact: roughly 3/5 user agents were indicating a mobile device. take advantage of&nbsp;that.</p></li><li><p>The fact that you&#8217;re solving a problem, doesn&#8217;t mean that it needs solving. sure, some people will want to use a webhook invoker. invoking webhooks is a trivial matter though. the 2% signup rate is more than justified.</p></li><li><p>Product Hunt isnt the first and/or last place you should launch. It requires a small existing audience to support you. I suggest listing your product in directories first. after that, go for the big&nbsp;bucks.</p></li></ul><p>That&#8217;s all. Have a nice&nbsp;day!</p><p>PS. song recommendation: &#8220;Goodbye&#8221;&#8202;&#8212;&#8202;Ramsey</p><div class="captioned-image-container"><figure><a class="image-link image2" target="_blank" href="https://substackcdn.com/image/fetch/$s_!J1Ng!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F36380a4e-87c2-43bc-b880-24a3eec1f5b0_1024x512.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!J1Ng!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F36380a4e-87c2-43bc-b880-24a3eec1f5b0_1024x512.png 424w, https://substackcdn.com/image/fetch/$s_!J1Ng!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F36380a4e-87c2-43bc-b880-24a3eec1f5b0_1024x512.png 848w, https://substackcdn.com/image/fetch/$s_!J1Ng!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F36380a4e-87c2-43bc-b880-24a3eec1f5b0_1024x512.png 1272w, https://substackcdn.com/image/fetch/$s_!J1Ng!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F36380a4e-87c2-43bc-b880-24a3eec1f5b0_1024x512.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!J1Ng!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F36380a4e-87c2-43bc-b880-24a3eec1f5b0_1024x512.png" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/36380a4e-87c2-43bc-b880-24a3eec1f5b0_1024x512.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:null,&quot;width&quot;:null,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:null,&quot;alt&quot;:&quot;&quot;,&quot;title&quot;:null,&quot;type&quot;:null,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" title="" srcset="https://substackcdn.com/image/fetch/$s_!J1Ng!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F36380a4e-87c2-43bc-b880-24a3eec1f5b0_1024x512.png 424w, https://substackcdn.com/image/fetch/$s_!J1Ng!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F36380a4e-87c2-43bc-b880-24a3eec1f5b0_1024x512.png 848w, https://substackcdn.com/image/fetch/$s_!J1Ng!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F36380a4e-87c2-43bc-b880-24a3eec1f5b0_1024x512.png 1272w, https://substackcdn.com/image/fetch/$s_!J1Ng!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F36380a4e-87c2-43bc-b880-24a3eec1f5b0_1024x512.png 1456w" sizes="100vw" loading="lazy"></picture><div></div></div></a></figure></div>]]></content:encoded></item><item><title><![CDATA[Instantly share files and code, with anyone from your terminal.]]></title><description><![CDATA[No joke.]]></description><link>https://andriotis.me/p/instantly-share-files-and-code-with-anyone-from-your-terminal-380c59e5cbd7</link><guid isPermaLink="false">https://andriotis.me/p/instantly-share-files-and-code-with-anyone-from-your-terminal-380c59e5cbd7</guid><dc:creator><![CDATA[Nikos Andriotis]]></dc:creator><pubDate>Fri, 13 Oct 2023 14:06:11 GMT</pubDate><enclosure url="https://substack-post-media.s3.amazonaws.com/public/images/c45d02e4-26d5-49b8-aba8-2326f881df24_978x376.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>No joke. Its name is&nbsp;ICS.</p><p>&#8220;<strong>Hey Nikos, can you send me hello.c?</strong>&#8221; That was the question a friend asked me that caused the discovery of this dev&nbsp;tool.</p><p><strong>No need</strong> for Discord, Dropbox, Drive, permissions, share links and browser&nbsp;tabs.</p><p>Amazing, isn&#8217;t it? Lets see how this&nbsp;works:</p><p>Before we begin, <a href="https://www.npmjs.com/package/ics-cli">here is the npm link</a> to the&nbsp;package</p><h3>1. Installation</h3><pre><code>npm i -g ics-cli</code></pre><h3>2. Username reservation</h3><p>This will allow you to use ICS. otherwise, shares were gonna be a&nbsp;mess.</p><pre><code>ics username reserve &lt;Desired_Username&gt;</code></pre><p>Aaaaand thats it lmao. now, lets create a&nbsp;share</p><h3>3. Create a&nbsp;share</h3><h4>a. Preparation: a temporary file</h4><pre><code>cd ~/Downloads
echo "hello there" &gt; hello.txt</code></pre><h4>b. Publish</h4><pre><code>ics share create</code></pre><p>Follow the instructions given to you by the CLI. The output will look something like&nbsp;this:</p><div class="captioned-image-container"><figure><a class="image-link image2" target="_blank" href="https://substackcdn.com/image/fetch/$s_!Soh2!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7cd71a19-f14c-4d05-9cbc-7d57d994f33a_978x376.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!Soh2!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7cd71a19-f14c-4d05-9cbc-7d57d994f33a_978x376.png 424w, https://substackcdn.com/image/fetch/$s_!Soh2!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7cd71a19-f14c-4d05-9cbc-7d57d994f33a_978x376.png 848w, https://substackcdn.com/image/fetch/$s_!Soh2!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7cd71a19-f14c-4d05-9cbc-7d57d994f33a_978x376.png 1272w, https://substackcdn.com/image/fetch/$s_!Soh2!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7cd71a19-f14c-4d05-9cbc-7d57d994f33a_978x376.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!Soh2!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7cd71a19-f14c-4d05-9cbc-7d57d994f33a_978x376.png" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/7cd71a19-f14c-4d05-9cbc-7d57d994f33a_978x376.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:null,&quot;width&quot;:null,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:null,&quot;alt&quot;:&quot;&quot;,&quot;title&quot;:null,&quot;type&quot;:null,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" title="" srcset="https://substackcdn.com/image/fetch/$s_!Soh2!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7cd71a19-f14c-4d05-9cbc-7d57d994f33a_978x376.png 424w, https://substackcdn.com/image/fetch/$s_!Soh2!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7cd71a19-f14c-4d05-9cbc-7d57d994f33a_978x376.png 848w, https://substackcdn.com/image/fetch/$s_!Soh2!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7cd71a19-f14c-4d05-9cbc-7d57d994f33a_978x376.png 1272w, https://substackcdn.com/image/fetch/$s_!Soh2!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F7cd71a19-f14c-4d05-9cbc-7d57d994f33a_978x376.png 1456w" sizes="100vw" loading="lazy"></picture><div></div></div></a></figure></div><p>As you can see, i now have a single use share called test on my username nikos-medium&nbsp;. For multi-use shares, use thepermanent flag. For other commands look no further&nbsp;than</p><pre><code>ics teachme
#OR
ics getting_started
#OR
ics &lt;command&gt; --help</code></pre><h3>4. Accessing Shares</h3><p>If you have sufficient permissions, no matter your username, you can access an ICS Share&nbsp;via</p><pre><code>ics share get USERNAME/SHARE_NAME
#Example
ics share get nikos-medium/test</code></pre><h3>5. Deleting&nbsp;Shares</h3><pre><code>ics share delete &lt;name of your share&gt;</code></pre><h3>6. Small video&nbsp;demo</h3><p>&lt;a href="https://medium.com/media/b5a136fe3aad394bca4025be1a19932e/href"&gt;https://medium.com/media/b5a136fe3aad394bca4025be1a19932e/href&lt;/a&gt;</p><p>Consider following me on Twitter: <a href="https://twitter.com/andriotisnikos1">https://twitter.com/andriotisnikos1</a></p><div class="captioned-image-container"><figure><a class="image-link image2" target="_blank" href="https://substackcdn.com/image/fetch/$s_!Yzot!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd1cb7a04-f6f5-4acf-b85c-34620f32dfac_1024x393.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!Yzot!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd1cb7a04-f6f5-4acf-b85c-34620f32dfac_1024x393.png 424w, https://substackcdn.com/image/fetch/$s_!Yzot!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd1cb7a04-f6f5-4acf-b85c-34620f32dfac_1024x393.png 848w, https://substackcdn.com/image/fetch/$s_!Yzot!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd1cb7a04-f6f5-4acf-b85c-34620f32dfac_1024x393.png 1272w, https://substackcdn.com/image/fetch/$s_!Yzot!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd1cb7a04-f6f5-4acf-b85c-34620f32dfac_1024x393.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!Yzot!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd1cb7a04-f6f5-4acf-b85c-34620f32dfac_1024x393.png" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/d1cb7a04-f6f5-4acf-b85c-34620f32dfac_1024x393.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:null,&quot;width&quot;:null,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:null,&quot;alt&quot;:&quot;&quot;,&quot;title&quot;:null,&quot;type&quot;:null,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" title="" srcset="https://substackcdn.com/image/fetch/$s_!Yzot!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd1cb7a04-f6f5-4acf-b85c-34620f32dfac_1024x393.png 424w, https://substackcdn.com/image/fetch/$s_!Yzot!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd1cb7a04-f6f5-4acf-b85c-34620f32dfac_1024x393.png 848w, https://substackcdn.com/image/fetch/$s_!Yzot!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd1cb7a04-f6f5-4acf-b85c-34620f32dfac_1024x393.png 1272w, https://substackcdn.com/image/fetch/$s_!Yzot!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd1cb7a04-f6f5-4acf-b85c-34620f32dfac_1024x393.png 1456w" sizes="100vw" loading="lazy"></picture><div></div></div></a></figure></div>]]></content:encoded></item><item><title><![CDATA[Save up to 216$/y/domain on your GCP bill by connecting Cloud Run to Firebase]]></title><description><![CDATA[No bs.]]></description><link>https://andriotis.me/p/save-up-to-216-y-domain-on-your-gcp-bill-by-connecting-cloud-run-to-firebase-9d16d5be00e9</link><guid isPermaLink="false">https://andriotis.me/p/save-up-to-216-y-domain-on-your-gcp-bill-by-connecting-cloud-run-to-firebase-9d16d5be00e9</guid><dc:creator><![CDATA[Nikos Andriotis]]></dc:creator><pubDate>Sat, 09 Sep 2023 22:10:50 GMT</pubDate><enclosure url="https://substack-post-media.s3.amazonaws.com/public/images/e6c9694e-be57-402f-a922-39aff14dca71_1024x512.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>No bs. &#917;xplanation included.</p><p><strong>Note: See at the end of post for savings breakdown.</strong></p><p>Let&#8217;s connect firebase with Cloud&nbsp;Run!</p><p><strong>Requirements</strong></p><ul><li><p>Node.js @&nbsp;latest</p></li></ul><p><strong>Step 1: Install the firebase&nbsp;CLI</strong></p><pre><code>npm i -g firebase-tools</code></pre><p><strong>Step 2: Ensure you are logged in to google via&nbsp;browser.</strong></p><p><strong>Step 3: Create a Firebase&nbsp;project</strong></p><ul><li><p>Go to <a href="http://console.firebase.google.com/">http://console.firebase.google.com/</a></p></li><li><p>Click Add&nbsp;Project</p></li><li><p>Enter a name and click&nbsp;Continue</p></li><li><p>Keep Google Analytics enabled and click&nbsp;Continue</p></li><li><p>Choose or create a Google Analytics account or select an existing&nbsp;one.</p></li><li><p>Click Create&nbsp;Project</p></li><li><p>Wait for the process to finish and click Continue. You&#8217;ll be redirected to the project dashboard</p></li></ul><p><strong>Step 4: Enable Pay-as-you-go</strong></p><p>We need to enable Pay-as-you-go, so our custom domains don&#8217;t shut down! See more on the cost breakdown below!</p><ul><li><p>Go to the bottom left corner of the dashboard. Click Upgrade&nbsp;, next to&nbsp;Spark</p></li><li><p>Select or create a GCP billing account. Its easy to create if you don&#8217;t already have&nbsp;one</p></li><li><p>Click Continue then&nbsp;Purchase</p></li></ul><p>Pay as you go is now&nbsp;enabled!</p><p><strong>Step 5: Deploy your apps to Cloud&nbsp;Run</strong></p><p>For help, you can refer to <a href="https://medium.com/@andriotisnikos1/deploy-a-ts-server-client-using-cloud-run-and-cloudflare-fa07da87e48b">a similar tutorial I made</a>, up until step&nbsp;7</p><p><strong>Step 6: Get your firebase project&nbsp;ID</strong></p><p>On the firebase dashboard:</p><ul><li><p>click the Gear Icon on the top left, on the right of Project&nbsp;Overview</p></li><li><p>go to Project Settings &gt; General &gt; Your&nbsp;Project</p></li><li><p><strong>Copy the Project ID value and store it somewhere.</strong></p></li></ul><p><strong>Step 8: Create hosting&nbsp;sites</strong></p><p>On the firebase dashboard:</p><ul><li><p>click Hosting on the top left, under Project Shortcuts</p></li><li><p>For each of your apps you want to deploy, click the Add another site button on the right of your screen, and give it a Unique Name (unique_name.web.app)</p></li><li><p><strong>Copy each Unique Name and store it somewhere</strong></p></li></ul><p><strong>Step 8: firebase.json</strong></p><p>Go somewhere in your desktop (eg downloads/temp) and create a firebase.json file with the following</p><pre><code>{
    "$schema": "https://raw.githubusercontent.com/mainrs/vscode-firebase-configuration-schema-plugin/master/schemas/firebase.schema.json",
    "hosting": []
}</code></pre><p>We&#8217;re gonna fill out the hosting&nbsp;array</p><p><strong>Step 9: Login to firebase via the&nbsp;CLI</strong></p><pre><code>firebase login</code></pre><p><strong>Step 10: Create hosting targets for the unique&nbsp;names</strong></p><p>For each of the Unique Names you created, apply a hosting target alias by&nbsp;running:</p><pre><code>firebase target:apply hosting &lt;alias&gt; &lt;unique_name&gt;</code></pre><p><strong>Step 11: Fill the hosting&nbsp;array</strong></p><ul><li><p>Head over to <a href="https://console.cloud.google.com/run">https://console.cloud.google.com/run</a></p></li><li><p>Use this page as a reference to the names and regions of your Cloud Run&nbsp;services</p></li></ul><p>The schema for a hosting&nbsp;element</p><pre><code>{
  "target": "&lt;hosting target alias (step 9)&gt;",
  "rewrites": [
    {
      "source": "/*",
      "run": {
        "serviceId": "&lt;name of cloud run service&gt;",
        "region": "&lt;region of cloud run service&gt;",
        "pinTag": true
      }
    }
  ]
}</code></pre><p>Example</p><ul><li><p>Cloud Run Service Name:&nbsp;api</p></li><li><p>Cloud Run Service Region: us-central1 (Iowa)</p></li><li><p>Firebase Hosting Site Unique Name: api-ybbe34t3</p></li></ul><p>I run:</p><pre><code>firebase target:apply hosting cr-api api-ybbe34t3</code></pre><p>Then the&nbsp;schema:</p><pre><code>{
  "target": "cr-api",
  "rewrites": [
    {
      "source": "/*",
      "run": {
        "serviceId": "api",
        "region": "us-central1",
        "pinTag": true
      }
    }
  ]
}</code></pre><p><strong>Step 12:&nbsp;Deploy!</strong></p><pre><code>firebase deploy --only hosting --project &lt;project ID from step 6&gt;</code></pre><p><strong>Step 13: The custom&nbsp;domains.</strong></p><ul><li><p>head over to the firebase&nbsp;console</p></li><li><p>look top-left on the sidebar &gt; &#8220;Hosting&#8221;</p></li><li><p>click &#8220;View&#8221; on one of your&nbsp;sites</p></li><li><p>in the middle of the screen, you will see a &#8220;Add custom domain&#8221; button. Click&nbsp;it</p></li><li><p>Insert the domain you want to use, click&nbsp;Continue</p></li><li><p>Change the DNS records of your domain accordingly</p></li></ul><p>That's it!</p><p>&#8212;&#8202;&#8212;&#8202;&#8212;&#8202;&#8212;&#8202;&#8212;&#8202;&#8212;&#8202;&#8212;&#8202;&#8212;&#8202;&#8212;&#8202;&#8212;&#8202;&#8212;&#8202;&#8212;&#8202;&#8212;&#8202;&#8212;&#8202;&#8212;&#8202;&#8212;&#8202;&#8212;&#8202;&#8212;&#8202;&#8212;&#8202;&#8212;&#8202;&#8212;&#8202;&#8212;&#8202;&#8212;&#8202;&#8212;&#8202;&#8212;&#8202;&#8212;&#8202;&#8212;&#8202;&#8212;&#8202;&#8212;&#8202;&#8212;&#8202;&#8212;&#8202;&#8212;&#8202;&#8212;&#8202;&#8212;&#8202;&#8212;&#8202;&#8212;&#8202;&#8212;</p><p><strong>Cost Breakdown</strong></p><p>Load Balancing on GCP&nbsp;costs:</p><ul><li><p>261$/y for the first 5 rules (0.025$/hr)</p></li><li><p>86,4$/y for every other one (0.01$/hr)</p></li></ul><p>There is no cost for Networking</p><p>Hosting on Firebase&nbsp;costs:</p><ul><li><p>15 cents / GB of Ingress/Egress</p></li><li><p>Some other costs that don&#8217;t apply (BC of Cloud&nbsp;Run)</p></li></ul><p>For a small company with 1TB Networking and 5 Cloud Run services, in a&nbsp;year:</p><ul><li><p>5 * 261$ = 1305$ for&nbsp;GCP</p></li><li><p>1024 * 0,15$ = 130,6$ for Firebase!</p></li></ul><p><strong>When should I move to&nbsp;GCP?</strong></p><p>When your cost of Networking/ hr exceeds your GCP LB&nbsp;costs/hr</p><div class="captioned-image-container"><figure><a class="image-link image2" target="_blank" href="https://substackcdn.com/image/fetch/$s_!iS-1!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F410219e5-985f-4ee0-b530-ac284e24dfd8_1024x512.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!iS-1!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F410219e5-985f-4ee0-b530-ac284e24dfd8_1024x512.png 424w, https://substackcdn.com/image/fetch/$s_!iS-1!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F410219e5-985f-4ee0-b530-ac284e24dfd8_1024x512.png 848w, https://substackcdn.com/image/fetch/$s_!iS-1!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F410219e5-985f-4ee0-b530-ac284e24dfd8_1024x512.png 1272w, https://substackcdn.com/image/fetch/$s_!iS-1!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F410219e5-985f-4ee0-b530-ac284e24dfd8_1024x512.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!iS-1!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F410219e5-985f-4ee0-b530-ac284e24dfd8_1024x512.png" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/410219e5-985f-4ee0-b530-ac284e24dfd8_1024x512.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:null,&quot;width&quot;:null,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:null,&quot;alt&quot;:&quot;&quot;,&quot;title&quot;:null,&quot;type&quot;:null,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" title="" srcset="https://substackcdn.com/image/fetch/$s_!iS-1!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F410219e5-985f-4ee0-b530-ac284e24dfd8_1024x512.png 424w, https://substackcdn.com/image/fetch/$s_!iS-1!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F410219e5-985f-4ee0-b530-ac284e24dfd8_1024x512.png 848w, https://substackcdn.com/image/fetch/$s_!iS-1!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F410219e5-985f-4ee0-b530-ac284e24dfd8_1024x512.png 1272w, https://substackcdn.com/image/fetch/$s_!iS-1!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F410219e5-985f-4ee0-b530-ac284e24dfd8_1024x512.png 1456w" sizes="100vw" loading="lazy"></picture><div></div></div></a></figure></div>]]></content:encoded></item><item><title><![CDATA[Deploy to GCP Cloud Run using GitHub Actions Workflows.]]></title><description><![CDATA[No bs.]]></description><link>https://andriotis.me/p/deploy-to-gcp-cloud-run-using-github-actions-workflows-c2f4ee702104</link><guid isPermaLink="false">https://andriotis.me/p/deploy-to-gcp-cloud-run-using-github-actions-workflows-c2f4ee702104</guid><dc:creator><![CDATA[Nikos Andriotis]]></dc:creator><pubDate>Wed, 06 Sep 2023 18:59:15 GMT</pubDate><enclosure url="https://substackcdn.com/image/fetch/f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F63a09f6f-a8f6-4cf3-b731-25b6e5391c0d_1024x512.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>No bs. TLDR included.</p><p>Lets get started. Requirements for today&nbsp;are:</p><ul><li><p>GitHub repo page to your&nbsp;repo</p></li><li><p><a href="https://console.cloud.google.com/iam-admin/serviceaccounts">https://console.cloud.google.com/iam-admin/serviceaccounts</a></p></li><li><p>your repo open in your preferred editor</p></li><li><p>a Dockerfile in your repo with build instructions</p></li></ul><p><strong>Note: Anything marked with &#8220;&lt; &gt;&#8221;(eg &lt;value&gt;) must be changed to reflect your repo/choice</strong></p><p><strong>Step 1: Create the workflow&nbsp;file</strong></p><ul><li><p>Head over to your repo in your&nbsp;editor</p></li><li><p>create a file under&nbsp;.github/workflows called &lt;workflow name&gt;.yml. the&nbsp;.github/workflows directory must be in the root of your&nbsp;project</p></li></ul><p>example:&nbsp;.github/workflows/cloud_run.yml</p><p><strong>Step 2: start editing your&nbsp;file</strong></p><p><strong>Step 3: paste the following code in your&nbsp;file</strong></p><p>This code was created based on <a href="https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions">this page</a> and the gcp auth workflow&nbsp;repo</p><pre><code>on:
    pull_request: #you can also setup your own triggers
        branches: 
            - main

jobs:
    gc-cloud_run:
        name: 'cloud_run'
        runs-on: ubuntu-latest

        permissions:
            contents: 'read'
            deployments: 'write'
            id-token: 'write'

        steps:
            - uses: 'actions/checkout@v3'

            - id: 'auth'
              name: 'Gcloud Auth'
              uses: 'google-github-actions/auth@v1'
              with:
                credentials_json: '${{secrets.GCLOUD_AUTH}}'
  
            #you can replace "us-central1" with your preferred region
            - run: |-
                gcloud run deploy &lt;service name&gt; --platform managed --source &lt;path to deployment dir&gt; --region us-central1; 
                </code></pre><p><strong>Step 4: Publish your changes to&nbsp;GitHub</strong></p><p><strong>Step 5: IAM service&nbsp;account</strong></p><ul><li><p>head over to <a href="https://console.cloud.google.com/iam-admin/serviceaccounts">https://console.cloud.google.com/iam-admin/serviceaccounts</a></p></li><li><p>click create service account at the top of the&nbsp;page</p></li></ul><div class="captioned-image-container"><figure><a class="image-link image2" target="_blank" href="https://substackcdn.com/image/fetch/$s_!KGv1!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe3dce186-61e2-4f2a-a154-22a0a05fe31c_1024x129.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!KGv1!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe3dce186-61e2-4f2a-a154-22a0a05fe31c_1024x129.png 424w, https://substackcdn.com/image/fetch/$s_!KGv1!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe3dce186-61e2-4f2a-a154-22a0a05fe31c_1024x129.png 848w, https://substackcdn.com/image/fetch/$s_!KGv1!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe3dce186-61e2-4f2a-a154-22a0a05fe31c_1024x129.png 1272w, https://substackcdn.com/image/fetch/$s_!KGv1!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe3dce186-61e2-4f2a-a154-22a0a05fe31c_1024x129.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!KGv1!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe3dce186-61e2-4f2a-a154-22a0a05fe31c_1024x129.png" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/e3dce186-61e2-4f2a-a154-22a0a05fe31c_1024x129.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:null,&quot;width&quot;:null,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:null,&quot;alt&quot;:&quot;&quot;,&quot;title&quot;:null,&quot;type&quot;:null,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" title="" srcset="https://substackcdn.com/image/fetch/$s_!KGv1!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe3dce186-61e2-4f2a-a154-22a0a05fe31c_1024x129.png 424w, https://substackcdn.com/image/fetch/$s_!KGv1!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe3dce186-61e2-4f2a-a154-22a0a05fe31c_1024x129.png 848w, https://substackcdn.com/image/fetch/$s_!KGv1!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe3dce186-61e2-4f2a-a154-22a0a05fe31c_1024x129.png 1272w, https://substackcdn.com/image/fetch/$s_!KGv1!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe3dce186-61e2-4f2a-a154-22a0a05fe31c_1024x129.png 1456w" sizes="100vw" loading="lazy"></picture><div></div></div></a></figure></div><ul><li><p>add a service account name, let the account ID be generated automatically</p></li><li><p>press create and continue&nbsp;. <strong>Dont skip step the other&nbsp;steps</strong></p></li><li><p>click the dropdown: select a&nbsp;role</p></li><li><p>find &#8220;Editor&#8221; under Quick Access &gt; Basic &gt;&nbsp;Editor</p></li><li><p>click continue</p></li><li><p>click done</p></li></ul><p><strong>Step 6: Service account credentials</strong></p><ul><li><p>head back to <a href="https://console.cloud.google.com/iam-admin/serviceaccounts">https://console.cloud.google.com/iam-admin/serviceaccounts</a></p></li><li><p>click on your service&nbsp;account</p></li><li><p>navigate to the KEYS&nbsp;tab</p></li><li><p>click &#8220;Add Key&#8221; &gt; &#8220;Create new&nbsp;Key&#8221;</p></li><li><p>select JSON format and Create&nbsp;. a key file will be downloaded</p></li><li><p>go to your downloads and copy the contents of the key&nbsp;file</p></li></ul><p><strong>Step 7: create the `GCLOUD_AUTH` env</strong></p><ul><li><p>go to your github repo&nbsp;page</p></li><li><p>navigate to the &#8220;Settings&#8221; tab</p></li><li><p>on the sidebar, look under &#8220;Security&#8221; to find &#8220;Secrets and Variables&#8221; &gt; &#8220;Actions&#8221;</p></li><li><p>click on &#8220;New repository secret&#8221;</p></li><li><p>name it &#8220;GCLOUD_AUTH&#8221;</p></li><li><p>paste in the contents of the key&nbsp;file</p></li></ul><p>You're done! Now, if the correct conditions are met, the action will be triggered, deploying your app to cloud&nbsp;run!</p><p>&#8212;&#8202;&#8212;&#8202;&#8212;&#8202;&#8212;&#8202;&#8212;&#8202;&#8212;&#8202;&#8212;&#8202;&#8212;&#8202;&#8212;&#8202;&#8212;&#8202;&#8212;&#8202;&#8212;&#8202;&#8212;&#8202;&#8212;&#8202;&#8212;&#8202;&#8212;&#8202;&#8212;&#8202;&#8212;&#8202;&#8212;&#8202;&#8212;&#8202;&#8212;&#8202;&#8212;&#8202;&#8212;&#8202;&#8212;&#8202;&#8212;&#8202;&#8212;&#8202;&#8212;&#8202;&#8212;&#8202;&#8212;&#8202;&#8212;&#8202;&#8212;&#8202;&#8212;&#8202;&#8212;&#8202;&#8212;&#8202;&#8212;&#8202;&#8212;&#8202;&#8212;</p><h3><strong>TLDR</strong></h3><ul><li><p>create a new workflow file with the contents of <strong>Step 3, </strong>replacing the required&nbsp;values</p></li><li><p>create a new GCP service account with &#8216;Editor&#8217; permissions</p></li><li><p>get json credentials for service&nbsp;account</p></li><li><p>create an env GCLOUD_AUTH with the json credentials as&nbsp;contents</p></li></ul><div class="captioned-image-container"><figure><a class="image-link image2" target="_blank" href="https://substackcdn.com/image/fetch/$s_!JqSX!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F63a09f6f-a8f6-4cf3-b731-25b6e5391c0d_1024x512.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!JqSX!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F63a09f6f-a8f6-4cf3-b731-25b6e5391c0d_1024x512.png 424w, https://substackcdn.com/image/fetch/$s_!JqSX!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F63a09f6f-a8f6-4cf3-b731-25b6e5391c0d_1024x512.png 848w, https://substackcdn.com/image/fetch/$s_!JqSX!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F63a09f6f-a8f6-4cf3-b731-25b6e5391c0d_1024x512.png 1272w, https://substackcdn.com/image/fetch/$s_!JqSX!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F63a09f6f-a8f6-4cf3-b731-25b6e5391c0d_1024x512.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!JqSX!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F63a09f6f-a8f6-4cf3-b731-25b6e5391c0d_1024x512.png" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/63a09f6f-a8f6-4cf3-b731-25b6e5391c0d_1024x512.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:null,&quot;width&quot;:null,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:null,&quot;alt&quot;:&quot;&quot;,&quot;title&quot;:null,&quot;type&quot;:null,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" title="" srcset="https://substackcdn.com/image/fetch/$s_!JqSX!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F63a09f6f-a8f6-4cf3-b731-25b6e5391c0d_1024x512.png 424w, https://substackcdn.com/image/fetch/$s_!JqSX!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F63a09f6f-a8f6-4cf3-b731-25b6e5391c0d_1024x512.png 848w, https://substackcdn.com/image/fetch/$s_!JqSX!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F63a09f6f-a8f6-4cf3-b731-25b6e5391c0d_1024x512.png 1272w, https://substackcdn.com/image/fetch/$s_!JqSX!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F63a09f6f-a8f6-4cf3-b731-25b6e5391c0d_1024x512.png 1456w" sizes="100vw" loading="lazy"></picture><div></div></div></a></figure></div>]]></content:encoded></item><item><title><![CDATA[Deploy a TS server/client using Cloud Run and Cloudflare]]></title><description><![CDATA[No BS.]]></description><link>https://andriotis.me/p/deploy-a-ts-server-client-using-cloud-run-and-cloudflare-fa07da87e48b</link><guid isPermaLink="false">https://andriotis.me/p/deploy-a-ts-server-client-using-cloud-run-and-cloudflare-fa07da87e48b</guid><dc:creator><![CDATA[Nikos Andriotis]]></dc:creator><pubDate>Mon, 04 Sep 2023 18:44:44 GMT</pubDate><enclosure url="https://substackcdn.com/image/fetch/f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc7055366-1ca0-40af-8280-33cbb5e3920d_1024x512.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>No BS. The&nbsp;sauce.</p><p><strong>Reference: My package.json scripts</strong></p><pre><code>"scripts": {
    "dev": "nodemon --watch 'src/**/*.ts' --exec 'node --loader ts-node/esm' src/index.ts",
    "start": "node --loader ts-node/esm ./src/index.ts"
 }</code></pre><p><strong>Step 1: Confirm you&#8217;re logged in to Google from your&nbsp;browser.</strong></p><p><strong>Step 2: Make sure` gcloud` CLI is installed</strong></p><ul><li><p>brew:</p></li></ul><pre><code>brew install google-cloud-sdk --cask</code></pre><ul><li><p>scoop</p></li></ul><pre><code>scoop bucket add extras
scoop install extras/gcloud</code></pre><p><strong>Step 3: Login with gcloud&nbsp;CLI</strong></p><pre><code>gcloud auth login</code></pre><p>Navigate to the given URL and login with your Google&nbsp;Account</p><p>Note: find all your projectIDs here, top left corner, to the right of the logo: <a href="https://console.cloud.google.com/welcome?project=hello-390809">https://console.cloud.google.com/welcome</a></p><p><strong>Step 4: navigate to your project&nbsp;locally</strong></p><pre><code>cd path/to/project</code></pre><p><strong>Step 5: tsconfig.json</strong></p><p>You need rootDir and outDir&nbsp;. Other than that, do as you wish. Here is&nbsp;mine:</p><pre><code>{
  "compilerOptions": {
    "target": "ES2022",
    "module": "ES2022",
    "rootDir": "./src",
    "moduleResolution": "node",
    "outDir": "./dist",
    "esModuleInterop": true,
    "forceConsistentCasingInFileNames": true,
    "strict": true,
    "skipLibCheck": true
  }
}</code></pre><p><strong>Step 6: Dockerfile</strong></p><p>Customise it as you wish. Here is&nbsp;mine:</p><pre><code>FROM node:20.5.1-alpine

WORKDIR /app

COPY package.json .

RUN npm install

COPY . .

run npx tsc

CMD node ./dist</code></pre><p><strong>Step 7:&nbsp;Launch</strong></p><p>From your root project&nbsp;dir:</p><pre><code>gcloud run deploy --platform managed --set-env-vars NODE_ENV=production</code></pre><p>After that, configure your deployment settings as you wish. Here are&nbsp;mine:</p><pre><code>Allow Unauthenticated Invocations: true
Data Center: lowa (number 30 on the list)</code></pre><p><strong>Step 8: Custom domain setup:&nbsp;GCP</strong></p><ul><li><p>head over to <a href="https://console.cloud.google.com/run/">https://console.cloud.google.com/run/</a></p></li><li><p>click on your deployed&nbsp;app</p></li><li><p>go to Integrations</p></li></ul><div class="captioned-image-container"><figure><a class="image-link image2" target="_blank" href="https://substackcdn.com/image/fetch/$s_!NOlx!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb904948d-11c6-44a3-ba4c-d8f38e89a535_1024x63.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!NOlx!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb904948d-11c6-44a3-ba4c-d8f38e89a535_1024x63.png 424w, https://substackcdn.com/image/fetch/$s_!NOlx!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb904948d-11c6-44a3-ba4c-d8f38e89a535_1024x63.png 848w, https://substackcdn.com/image/fetch/$s_!NOlx!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb904948d-11c6-44a3-ba4c-d8f38e89a535_1024x63.png 1272w, https://substackcdn.com/image/fetch/$s_!NOlx!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb904948d-11c6-44a3-ba4c-d8f38e89a535_1024x63.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!NOlx!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb904948d-11c6-44a3-ba4c-d8f38e89a535_1024x63.png" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/b904948d-11c6-44a3-ba4c-d8f38e89a535_1024x63.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:null,&quot;width&quot;:null,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:null,&quot;alt&quot;:&quot;&quot;,&quot;title&quot;:null,&quot;type&quot;:null,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" title="" srcset="https://substackcdn.com/image/fetch/$s_!NOlx!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb904948d-11c6-44a3-ba4c-d8f38e89a535_1024x63.png 424w, https://substackcdn.com/image/fetch/$s_!NOlx!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb904948d-11c6-44a3-ba4c-d8f38e89a535_1024x63.png 848w, https://substackcdn.com/image/fetch/$s_!NOlx!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb904948d-11c6-44a3-ba4c-d8f38e89a535_1024x63.png 1272w, https://substackcdn.com/image/fetch/$s_!NOlx!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fb904948d-11c6-44a3-ba4c-d8f38e89a535_1024x63.png 1456w" sizes="100vw" loading="lazy"></picture><div></div></div></a></figure></div><ul><li><p>click Add Intgration</p></li><li><p>select <em>Custom Domains&#8202;&#8212;&#8202;Google Cloud Load Balancing</em></p></li><li><p>under Routes replace Domain 1 with your custom domain eg. hello.example.com</p></li><li><p>scroll to page bottom and click Deploy&nbsp;.</p></li></ul><p><strong>Step 9: Get the Load Balancer&nbsp;IP</strong></p><ul><li><p>wait for 2&#8211;5&nbsp;minutes</p></li><li><p>refresh the GCP page and click View Details on the integration.</p></li></ul><div class="captioned-image-container"><figure><a class="image-link image2" target="_blank" href="https://substackcdn.com/image/fetch/$s_!a0xr!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Febb2fb0a-db94-4c59-a6d1-0b43bcc923d1_506x516.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!a0xr!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Febb2fb0a-db94-4c59-a6d1-0b43bcc923d1_506x516.png 424w, https://substackcdn.com/image/fetch/$s_!a0xr!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Febb2fb0a-db94-4c59-a6d1-0b43bcc923d1_506x516.png 848w, https://substackcdn.com/image/fetch/$s_!a0xr!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Febb2fb0a-db94-4c59-a6d1-0b43bcc923d1_506x516.png 1272w, https://substackcdn.com/image/fetch/$s_!a0xr!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Febb2fb0a-db94-4c59-a6d1-0b43bcc923d1_506x516.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!a0xr!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Febb2fb0a-db94-4c59-a6d1-0b43bcc923d1_506x516.png" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/ebb2fb0a-db94-4c59-a6d1-0b43bcc923d1_506x516.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:null,&quot;width&quot;:null,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:null,&quot;alt&quot;:&quot;&quot;,&quot;title&quot;:null,&quot;type&quot;:null,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" title="" srcset="https://substackcdn.com/image/fetch/$s_!a0xr!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Febb2fb0a-db94-4c59-a6d1-0b43bcc923d1_506x516.png 424w, https://substackcdn.com/image/fetch/$s_!a0xr!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Febb2fb0a-db94-4c59-a6d1-0b43bcc923d1_506x516.png 848w, https://substackcdn.com/image/fetch/$s_!a0xr!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Febb2fb0a-db94-4c59-a6d1-0b43bcc923d1_506x516.png 1272w, https://substackcdn.com/image/fetch/$s_!a0xr!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Febb2fb0a-db94-4c59-a6d1-0b43bcc923d1_506x516.png 1456w" sizes="100vw" loading="lazy"></picture><div></div></div></a></figure></div><ul><li><p>scroll to the&nbsp;bottom</p></li><li><p>you should now see the details for an A DNS Record. copy the IP/ record&nbsp;value</p></li></ul><p><strong>Step 10: Cloudflare</strong></p><ul><li><p>head over to the <a href="https://dash.cloudflare.com">Cloudflare Dashboard</a></p></li><li><p>login</p></li><li><p>go to your&nbsp;website</p></li><li><p>add a DNS record of type A and paste the IP of the Load Balancer you copied on step&nbsp;9.</p></li><li><p>set the record type to&nbsp;proxied</p></li></ul><p>You&#8217;re done. Now, wait for the Google CA to issue your SSL cert and you&#8217;ll be good to&nbsp;go!</p><p>&#8212;&#8202;&#8212;&#8202;&#8212;&#8202;&#8212;&#8202;&#8212;&#8202;&#8212;&#8202;&#8212;&#8202;&#8212;&#8202;&#8212;&#8202;&#8212;&#8202;&#8212;&#8202;&#8212;&#8202;&#8212;&#8202;&#8212;&#8202;&#8212;&#8202;&#8212;&#8202;&#8212;&#8202;&#8212;&#8202;&#8212;&#8202;&#8212;&#8202;&#8212;&#8202;&#8212;&#8202;&#8212;&#8202;&#8212;&#8202;&#8212;&#8202;&#8212;&#8202;&#8212;&#8202;&#8212;&#8202;&#8212;&#8202;&#8212;&#8202;&#8212;&#8202;&#8212;&#8202;&#8212;&#8202;&#8212;&#8202;&#8212;&#8202;&#8212;&#8202;&#8212;</p><h3><strong>Deleting the integration</strong></h3><p>GCP does not allow you to delete the integration (error, idk). Here is a&nbsp;bypass:</p><p><strong>Method 1: delete the cloud run&nbsp;app</strong></p><p><strong>Method 2: delete all integration resources</strong></p><ul><li><p>head over to <a href="https://console.cloud.google.com/run/">https://console.cloud.google.com/run/</a></p></li><li><p>click on your deployed&nbsp;app</p></li><li><p>go to Integrations</p></li></ul><div class="captioned-image-container"><figure><a class="image-link image2" target="_blank" href="https://substackcdn.com/image/fetch/$s_!70rO!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe9b769e2-788f-4d96-a85a-0d527c67530d_1024x63.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!70rO!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe9b769e2-788f-4d96-a85a-0d527c67530d_1024x63.png 424w, https://substackcdn.com/image/fetch/$s_!70rO!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe9b769e2-788f-4d96-a85a-0d527c67530d_1024x63.png 848w, https://substackcdn.com/image/fetch/$s_!70rO!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe9b769e2-788f-4d96-a85a-0d527c67530d_1024x63.png 1272w, https://substackcdn.com/image/fetch/$s_!70rO!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe9b769e2-788f-4d96-a85a-0d527c67530d_1024x63.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!70rO!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe9b769e2-788f-4d96-a85a-0d527c67530d_1024x63.png" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/e9b769e2-788f-4d96-a85a-0d527c67530d_1024x63.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:null,&quot;width&quot;:null,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:null,&quot;alt&quot;:&quot;&quot;,&quot;title&quot;:null,&quot;type&quot;:null,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" title="" srcset="https://substackcdn.com/image/fetch/$s_!70rO!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe9b769e2-788f-4d96-a85a-0d527c67530d_1024x63.png 424w, https://substackcdn.com/image/fetch/$s_!70rO!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe9b769e2-788f-4d96-a85a-0d527c67530d_1024x63.png 848w, https://substackcdn.com/image/fetch/$s_!70rO!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe9b769e2-788f-4d96-a85a-0d527c67530d_1024x63.png 1272w, https://substackcdn.com/image/fetch/$s_!70rO!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fe9b769e2-788f-4d96-a85a-0d527c67530d_1024x63.png 1456w" sizes="100vw" loading="lazy"></picture><div></div></div></a></figure></div><ul><li><p>click View Details on the integration</p></li><li><p>scroll down to Resources</p></li><li><p>go one-by-one and delete everything</p></li></ul><p>After you&#8217;re done, just delete the DNS record from Cloudflare and that's&nbsp;it!</p><div class="captioned-image-container"><figure><a class="image-link image2" target="_blank" href="https://substackcdn.com/image/fetch/$s_!1-Uc!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc7055366-1ca0-40af-8280-33cbb5e3920d_1024x512.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!1-Uc!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc7055366-1ca0-40af-8280-33cbb5e3920d_1024x512.png 424w, https://substackcdn.com/image/fetch/$s_!1-Uc!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc7055366-1ca0-40af-8280-33cbb5e3920d_1024x512.png 848w, https://substackcdn.com/image/fetch/$s_!1-Uc!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc7055366-1ca0-40af-8280-33cbb5e3920d_1024x512.png 1272w, https://substackcdn.com/image/fetch/$s_!1-Uc!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc7055366-1ca0-40af-8280-33cbb5e3920d_1024x512.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!1-Uc!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc7055366-1ca0-40af-8280-33cbb5e3920d_1024x512.png" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/c7055366-1ca0-40af-8280-33cbb5e3920d_1024x512.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:null,&quot;width&quot;:null,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:null,&quot;alt&quot;:&quot;&quot;,&quot;title&quot;:null,&quot;type&quot;:null,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" title="" srcset="https://substackcdn.com/image/fetch/$s_!1-Uc!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc7055366-1ca0-40af-8280-33cbb5e3920d_1024x512.png 424w, https://substackcdn.com/image/fetch/$s_!1-Uc!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc7055366-1ca0-40af-8280-33cbb5e3920d_1024x512.png 848w, https://substackcdn.com/image/fetch/$s_!1-Uc!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc7055366-1ca0-40af-8280-33cbb5e3920d_1024x512.png 1272w, https://substackcdn.com/image/fetch/$s_!1-Uc!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fc7055366-1ca0-40af-8280-33cbb5e3920d_1024x512.png 1456w" sizes="100vw" loading="lazy"></picture><div></div></div></a></figure></div>]]></content:encoded></item></channel></rss>