<!DOCTYPE html><html lang="en"><head><meta charSet="utf-8"/><meta name="viewport" content="width=device-width, initial-scale=1"/><link rel="stylesheet" href="/_next/static/chunks/0x8qntyk58kcd.css" data-precedence="next"/><link rel="preload" as="script" fetchPriority="low" href="/_next/static/chunks/0wxe83qkw2zvq.js"/><script src="/_next/static/chunks/18a4h7n5bm98v.js" async=""></script><script src="/_next/static/chunks/0ud0jlaqe6t_m.js" async=""></script><script src="/_next/static/chunks/161y7mlp2mi30.js" async=""></script><script src="/_next/static/chunks/turbopack-09~23s1nzpf_f.js" async=""></script><script src="/_next/static/chunks/01xlw8hd842-c.js" async=""></script><script src="/_next/static/chunks/0g~uuqo4.nt4z.js" async=""></script><script src="/_next/static/chunks/0xt00da9uttik.js" async=""></script><link rel="apple-touch-icon" sizes="180x180" href="/favicon/apple-touch-icon.png"/><link rel="icon" type="image/png" sizes="32x32" href="/favicon/favicon-32x32.png"/><link rel="icon" type="image/png" sizes="16x16" href="/favicon/favicon-16x16.png"/><link rel="manifest" href="/favicon/site.webmanifest"/><link rel="mask-icon" href="/favicon/safari-pinned-tab.svg" color="#5bbad5"/><meta name="msapplication-TileColor" content="#da532c"/><meta name="theme-color" content="#ffffff"/><title>Thomas Bandt</title><link rel="canonical" href="https://thomasbandt.com"/><script defer="" data-domain="thomasbandt.com" src="https://plausible.io/js/plausible.js"></script><script src="/_next/static/chunks/03~yq9q893hmn.js" noModule=""></script></head><body class="mx-auto min-w-[320px] max-w-[720px] px-4 bg-black bg-opacity-[3%] font-serif"><div hidden=""><!--$--><!--/$--></div><header class="font-sans my-8 sm:my-16"><nav class="w-full flex flex-col-reverse sm:flex-row items-center"><div class="flex-1"><div class="text-sm font-bold text-gray-600 mb-4 sm:mb-1 text-center sm:text-left">Thomas Bandt</div><div class="space-x-3"><a title="Home" class="uppercase hover:text-gray-800 text-gray-800" href="/">Home</a><a title="Articles" class="uppercase hover:text-gray-800 text-gray-500" href="/articles">Articles</a><a title="Gedanken" class="uppercase hover:text-gray-800 text-gray-500" href="/gedanken">Gedanken</a><a title="About" class="uppercase hover:text-gray-800 text-gray-500" href="/about">About</a></div></div><div class="flex-none mb-4 sm:m-0"><a title="Home" href="/"><img alt="Thomas Bandt" loading="lazy" width="300" height="300" decoding="async" data-nimg="1" class="w-24" style="color:transparent" srcSet="/_next/image?url=%2Fimages%2Ftb.png&amp;w=384&amp;q=75 1x, /_next/image?url=%2Fimages%2Ftb.png&amp;w=640&amp;q=75 2x" src="/_next/image?url=%2Fimages%2Ftb.png&amp;w=640&amp;q=75"/></a></div></nav></header><div class="prose prose-neutral md:prose-lg max-w-full prose-a:no-underline prose-h2:mb-2"><article><h2><a class="hover:underline font-semibold" href="/self-hosted-docker-registry-watchtower">Self-Hosted Docker Registry: The 15-Minute Setup That Replaced Docker Hub</a></h2><p>Docker Hub works, but for private images you&#x27;re dealing with rate limits, pricing tiers, and an external dependency. A self-hosted Docker Registry can replace all of that. This post walks through the setup and shares a few things I learned the hard way.</p></article><article><h2><a class="hover:underline font-semibold" href="/ide-death-fsharp">The IDE Might Die – Taking My Favorite Programming Language With It</a></h2><p>I&#x27;ve been in love with F# for many years. But as AI changes how I write code, the IDE I depend on may not survive – and F# might not either (at least not in my toolstack).</p></article><article><h2><a class="hover:underline font-semibold" href="/ead-udid-from-iphone-ipad-web-application">Reading The UDID from an iPhone or iPad Through A Web Application</a></h2><p>If you want to provide your app for internal testing purposes on a limited number of devices, you need to know the UDID of those devices. This guide shows you how to read the UDID from an iPhone or iPad through a web application.</p></article><article><h2><a class="hover:underline font-semibold" href="/installing-ios-apps-internally-with-a-manifest">Installing iOS Apps Internally: All You Need Is A Manifest</a></h2><p>This guide briefly shows what is necessary to allow your internal users to install your iOS app on their devices without using the App Store or TestFlight.</p></article><article><h2><a class="hover:underline font-semibold" href="/blue-green-deployments">Blue-Green Deployments: A Practical Guide for Zero-Downtime Updates</a></h2><p>Outlining the implementation of a blue-green deployment setup, this post focuses on web applications that have outgrown their early stages and require a strategy to minimize interruptions, especially during the deployment of new app versions.</p></article></div><!--$--><!--/$--><footer class="text-center my-16 flex flex-col"><div class="flex justify-center pb-1"><img alt="" loading="lazy" width="90" height="53" decoding="async" data-nimg="1" class="w-8" style="color:transparent" srcSet="/_next/image?url=%2Fimages%2Fbrezn.png&amp;w=96&amp;q=75 1x, /_next/image?url=%2Fimages%2Fbrezn.png&amp;w=256&amp;q=75 2x" src="/_next/image?url=%2Fimages%2Fbrezn.png&amp;w=256&amp;q=75"/></div><div><a class="text-sm text-gray-500 italic hover:underline" href="/about">© <!-- -->2026<!-- --> Thomas Bandt, Munich</a></div></footer><script src="/_next/static/chunks/0wxe83qkw2zvq.js" id="_R_" async=""></script><script>(self.__next_f=self.__next_f||[]).push([0])</script><script>self.__next_f.push([1,"1:\"$Sreact.fragment\"\n2:I[39756,[\"/_next/static/chunks/01xlw8hd842-c.js\",\"/_next/static/chunks/0g~uuqo4.nt4z.js\"],\"default\"]\n3:I[37457,[\"/_next/static/chunks/01xlw8hd842-c.js\",\"/_next/static/chunks/0g~uuqo4.nt4z.js\"],\"default\"]\n4:I[73438,[\"/_next/static/chunks/0xt00da9uttik.js\"],\"default\"]\n5:I[64862,[\"/_next/static/chunks/0xt00da9uttik.js\"],\"default\"]\n6:I[22016,[\"/_next/static/chunks/0xt00da9uttik.js\"],\"\"]\n7:I[5500,[\"/_next/static/chunks/0xt00da9uttik.js\"],\"Image\"]\n8:I[86186,[\"/_next/static/chunks/0xt00da9uttik.js\"],\"default\"]\n11:I[68027,[],\"default\",1]\n:HL[\"/_next/static/chunks/0x8qntyk58kcd.css\",\"style\"]\n"])</script><script>self.__next_f.push([1,"0:{\"P\":null,\"c\":[\"\",\"\"],\"q\":\"\",\"i\":false,\"f\":[[[\"\",{\"children\":[\"(blog)\",{\"children\":[\"__PAGE__\",{}]},\"$undefined\",\"$undefined\",16]}],[[\"$\",\"$1\",\"c\",{\"children\":[null,[\"$\",\"$L2\",null,{\"parallelRouterKey\":\"children\",\"error\":\"$undefined\",\"errorStyles\":\"$undefined\",\"errorScripts\":\"$undefined\",\"template\":[\"$\",\"$L3\",null,{}],\"templateStyles\":\"$undefined\",\"templateScripts\":\"$undefined\",\"notFound\":[[[\"$\",\"title\",null,{\"children\":\"404: This page could not be found.\"}],[\"$\",\"div\",null,{\"style\":{\"fontFamily\":\"system-ui,\\\"Segoe UI\\\",Roboto,Helvetica,Arial,sans-serif,\\\"Apple Color Emoji\\\",\\\"Segoe UI Emoji\\\"\",\"height\":\"100vh\",\"textAlign\":\"center\",\"display\":\"flex\",\"flexDirection\":\"column\",\"alignItems\":\"center\",\"justifyContent\":\"center\"},\"children\":[\"$\",\"div\",null,{\"children\":[[\"$\",\"style\",null,{\"dangerouslySetInnerHTML\":{\"__html\":\"body{color:#000;background:#fff;margin:0}.next-error-h1{border-right:1px solid rgba(0,0,0,.3)}@media (prefers-color-scheme:dark){body{color:#fff;background:#000}.next-error-h1{border-right:1px solid rgba(255,255,255,.3)}}\"}}],[\"$\",\"h1\",null,{\"className\":\"next-error-h1\",\"style\":{\"display\":\"inline-block\",\"margin\":\"0 20px 0 0\",\"padding\":\"0 23px 0 0\",\"fontSize\":24,\"fontWeight\":500,\"verticalAlign\":\"top\",\"lineHeight\":\"49px\"},\"children\":404}],[\"$\",\"div\",null,{\"style\":{\"display\":\"inline-block\"},\"children\":[\"$\",\"h2\",null,{\"style\":{\"fontSize\":14,\"fontWeight\":400,\"lineHeight\":\"49px\",\"margin\":0},\"children\":\"This page could not be found.\"}]}]]}]}]],[]],\"forbidden\":\"$undefined\",\"unauthorized\":\"$undefined\"}]]}],{\"children\":[[\"$\",\"$1\",\"c\",{\"children\":[[[\"$\",\"link\",\"0\",{\"rel\":\"stylesheet\",\"href\":\"/_next/static/chunks/0x8qntyk58kcd.css\",\"precedence\":\"next\",\"crossOrigin\":\"$undefined\",\"nonce\":\"$undefined\"}],[\"$\",\"script\",\"script-0\",{\"src\":\"/_next/static/chunks/0xt00da9uttik.js\",\"async\":true,\"nonce\":\"$undefined\"}]],[\"$\",\"html\",null,{\"lang\":\"en\",\"children\":[[\"$\",\"head\",null,{\"children\":[[\"$\",\"script\",null,{\"defer\":true,\"data-domain\":\"thomasbandt.com\",\"src\":\"https://plausible.io/js/plausible.js\"}],[\"$\",\"link\",null,{\"rel\":\"apple-touch-icon\",\"sizes\":\"180x180\",\"href\":\"/favicon/apple-touch-icon.png\"}],[\"$\",\"link\",null,{\"rel\":\"icon\",\"type\":\"image/png\",\"sizes\":\"32x32\",\"href\":\"/favicon/favicon-32x32.png\"}],[\"$\",\"link\",null,{\"rel\":\"icon\",\"type\":\"image/png\",\"sizes\":\"16x16\",\"href\":\"/favicon/favicon-16x16.png\"}],[\"$\",\"link\",null,{\"rel\":\"manifest\",\"href\":\"/favicon/site.webmanifest\"}],[\"$\",\"link\",null,{\"rel\":\"mask-icon\",\"href\":\"/favicon/safari-pinned-tab.svg\",\"color\":\"#5bbad5\"}],[\"$\",\"meta\",null,{\"name\":\"msapplication-TileColor\",\"content\":\"#da532c\"}],[\"$\",\"meta\",null,{\"name\":\"theme-color\",\"content\":\"#ffffff\"}]]}],[\"$\",\"body\",null,{\"className\":\"mx-auto min-w-[320px] max-w-[720px] px-4 bg-black bg-opacity-[3%] font-serif\",\"children\":[[\"$\",\"header\",null,{\"className\":\"font-sans my-8 sm:my-16\",\"children\":[\"$\",\"nav\",null,{\"className\":\"w-full flex flex-col-reverse sm:flex-row items-center\",\"children\":[[\"$\",\"div\",null,{\"className\":\"flex-1\",\"children\":[[\"$\",\"div\",null,{\"className\":\"text-sm font-bold text-gray-600 mb-4 sm:mb-1 text-center sm:text-left\",\"children\":[\"$\",\"$L4\",null,{\"alternativeContent\":\"Thomas Bandt\"}]}],[\"$\",\"div\",null,{\"className\":\"space-x-3\",\"children\":[[\"$\",\"$L5\",null,{\"href\":\"/\",\"text\":\"Home\"}],[\"$\",\"$L5\",null,{\"href\":\"/articles\",\"text\":\"Articles\"}],[\"$\",\"$L5\",null,{\"href\":\"/gedanken\",\"text\":\"Gedanken\"}],[\"$\",\"$L5\",null,{\"href\":\"/about\",\"text\":\"About\"}]]}]]}],[\"$\",\"div\",null,{\"className\":\"flex-none mb-4 sm:m-0\",\"children\":[\"$\",\"$L6\",null,{\"href\":\"/\",\"title\":\"Home\",\"children\":[\"$\",\"$L7\",null,{\"src\":\"/images/tb.png\",\"width\":300,\"height\":300,\"alt\":\"Thomas Bandt\",\"className\":\"w-24\"}]}]}]]}]}],[\"$\",\"$L2\",null,{\"parallelRouterKey\":\"children\",\"error\":\"$undefined\",\"errorStyles\":\"$undefined\",\"errorScripts\":\"$undefined\",\"template\":[\"$\",\"$L3\",null,{}],\"templateStyles\":\"$undefined\",\"templateScripts\":\"$undefined\",\"notFound\":[[[\"$\",\"title\",null,{\"children\":\"404: This page could not be found.\"}],[\"$\",\"div\",null,{\"style\":\"$0:f:0:1:0:props:children:1:props:notFound:0:1:props:style\",\"children\":[\"$\",\"div\",null,{\"children\":[[\"$\",\"style\",null,{\"dangerouslySetInnerHTML\":{\"__html\":\"body{color:#000;background:#fff;margin:0}.next-error-h1{border-right:1px solid rgba(0,0,0,.3)}@media (prefers-color-scheme:dark){body{color:#fff;background:#000}.next-error-h1{border-right:1px solid rgba(255,255,255,.3)}}\"}}],[\"$\",\"h1\",null,{\"className\":\"next-error-h1\",\"style\":\"$0:f:0:1:0:props:children:1:props:notFound:0:1:props:children:props:children:1:props:style\",\"children\":404}],[\"$\",\"div\",null,{\"style\":\"$0:f:0:1:0:props:children:1:props:notFound:0:1:props:children:props:children:2:props:style\",\"children\":[\"$\",\"h2\",null,{\"style\":\"$0:f:0:1:0:props:children:1:props:notFound:0:1:props:children:props:children:2:props:children:props:style\",\"children\":\"This page could not be found.\"}]}]]}]}]],[]],\"forbidden\":\"$undefined\",\"unauthorized\":\"$undefined\"}],[\"$\",\"footer\",null,{\"className\":\"text-center my-16 flex flex-col\",\"children\":[[\"$\",\"div\",null,{\"className\":\"flex justify-center pb-1\",\"children\":[\"$\",\"$L7\",null,{\"src\":\"/images/brezn.png\",\"width\":90,\"height\":53,\"alt\":\"\",\"className\":\"w-8\"}]}],[\"$\",\"$L8\",null,{}]]}]]}]]}]]}],{\"children\":[[\"$\",\"$1\",\"c\",{\"children\":[[\"$\",\"div\",null,{\"className\":\"prose prose-neutral md:prose-lg max-w-full prose-a:no-underline prose-h2:mb-2\",\"children\":[\"$L9\",\"$La\",\"$Lb\",\"$Lc\",\"$Ld\"]}],null,\"$Le\"]}],{},null,false,null]},null,false,null]},null,false,\"$@f\"],\"$L10\",false]],\"m\":\"$undefined\",\"G\":[\"$11\",[]],\"S\":true,\"h\":null,\"s\":\"$undefined\",\"l\":\"$undefined\",\"p\":\"$undefined\",\"d\":\"$undefined\",\"b\":\"LwiX-p2m52cHouOQNFQLw\"}\n"])</script><script>self.__next_f.push([1,"12:I[97367,[\"/_next/static/chunks/01xlw8hd842-c.js\",\"/_next/static/chunks/0g~uuqo4.nt4z.js\"],\"OutletBoundary\"]\n13:\"$Sreact.suspense\"\n16:I[97367,[\"/_next/static/chunks/01xlw8hd842-c.js\",\"/_next/static/chunks/0g~uuqo4.nt4z.js\"],\"ViewportBoundary\"]\n18:I[97367,[\"/_next/static/chunks/01xlw8hd842-c.js\",\"/_next/static/chunks/0g~uuqo4.nt4z.js\"],\"MetadataBoundary\"]\n9:[\"$\",\"article\",\"61\",{\"children\":[[\"$\",\"h2\",null,{\"children\":[\"$\",\"$L6\",null,{\"href\":\"/self-hosted-docker-registry-watchtower\",\"className\":\"hover:underline font-semibold\",\"children\":\"Self-Hosted Docker Registry: The 15-Minute Setup That Replaced Docker Hub\"}]}],[\"$\",\"p\",null,{\"children\":\"Docker Hub works, but for private images you're dealing with rate limits, pricing tiers, and an external dependency. A self-hosted Docker Registry can replace all of that. This post walks through the setup and shares a few things I learned the hard way.\"}]]}]\na:[\"$\",\"article\",\"60\",{\"children\":[[\"$\",\"h2\",null,{\"children\":[\"$\",\"$L6\",null,{\"href\":\"/ide-death-fsharp\",\"className\":\"hover:underline font-semibold\",\"children\":\"The IDE Might Die – Taking My Favorite Programming Language With It\"}]}],[\"$\",\"p\",null,{\"children\":\"I've been in love with F# for many years. But as AI changes how I write code, the IDE I depend on may not survive – and F# might not either (at least not in my toolstack).\"}]]}]\nb:[\"$\",\"article\",\"59\",{\"children\":[[\"$\",\"h2\",null,{\"children\":[\"$\",\"$L6\",null,{\"href\":\"/ead-udid-from-iphone-ipad-web-application\",\"className\":\"hover:underline font-semibold\",\"children\":\"Reading The UDID from an iPhone or iPad Through A Web Application\"}]}],[\"$\",\"p\",null,{\"children\":\"If you want to provide your app for internal testing purposes on a limited number of devices, you need to know the UDID of those devices. This guide shows you how to read the UDID from an iPhone or iPad through a web application.\"}]]}]\nc:[\"$\",\"article\",\"58\",{\"children\":[[\"$\",\"h2\",null,{\"children\":[\"$\",\"$L6\",null,{\"href\":\"/installing-ios-apps-internally-with-a-manifest\",\"className\":\"hover:underline font-semibold\",\"children\":\"Installing iOS Apps Internally: All You Need Is A Manifest\"}]}],[\"$\",\"p\",null,{\"children\":\"This guide briefly shows what is necessary to allow your internal users to install your iOS app on their devices without using the App Store or TestFlight.\"}]]}]\nd:[\"$\",\"article\",\"57\",{\"children\":[[\"$\",\"h2\",null,{\"children\":[\"$\",\"$L6\",null,{\"href\":\"/blue-green-deployments\",\"className\":\"hover:underline font-semibold\",\"children\":\"Blue-Green Deployments: A Practical Guide for Zero-Downtime Updates\"}]}],[\"$\",\"p\",null,{\"children\":\"Outlining the implementation of a blue-green deployment setup, this post focuses on web applications that have outgrown their early stages and require a strategy to minimize interruptions, especially during the deployment of new app versions.\"}]]}]\ne:[\"$\",\"$L12\",null,{\"children\":[\"$\",\"$13\",null,{\"name\":\"Next.MetadataOutlet\",\"children\":\"$@14\"}]}]\n15:[]\nf:\"$W15\"\n10:[\"$\",\"$1\",\"h\",{\"children\":[null,[\"$\",\"$L16\",null,{\"children\":\"$L17\"}],[\"$\",\"div\",null,{\"hidden\":true,\"children\":[\"$\",\"$L18\",null,{\"children\":[\"$\",\"$13\",null,{\"name\":\"Next.Metadata\",\"children\":\"$L19\"}]}]}],null]}]\n"])</script><script>self.__next_f.push([1,"17:[[\"$\",\"meta\",\"0\",{\"charSet\":\"utf-8\"}],[\"$\",\"meta\",\"1\",{\"name\":\"viewport\",\"content\":\"width=device-width, initial-scale=1\"}]]\n"])</script><script>self.__next_f.push([1,"14:null\n19:[[\"$\",\"title\",\"0\",{\"children\":\"Thomas Bandt\"}],[\"$\",\"link\",\"1\",{\"rel\":\"canonical\",\"href\":\"https://thomasbandt.com\"}]]\n"])</script></body></html>