<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Alex Darbyshire</title>
    <description>The latest articles on DEV Community by Alex Darbyshire (@alexdarbyshire).</description>
    <link>https://dev.to/alexdarbyshire</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F3797852%2F87833339-b472-4059-9217-2cd95385d539.png</url>
      <title>DEV Community: Alex Darbyshire</title>
      <link>https://dev.to/alexdarbyshire</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/alexdarbyshire"/>
    <language>en</language>
    <item>
      <title>The Autonomous Writer: Experimenting with Self-Evolving System Prompt and Context</title>
      <dc:creator>Alex Darbyshire</dc:creator>
      <pubDate>Sat, 21 Mar 2026 10:41:00 +0000</pubDate>
      <link>https://dev.to/alexdarbyshire/the-autonomous-writer-experimenting-with-self-evolving-system-prompt-and-context-bgf</link>
      <guid>https://dev.to/alexdarbyshire/the-autonomous-writer-experimenting-with-self-evolving-system-prompt-and-context-bgf</guid>
      <description>&lt;p&gt;The idea was a scheduled agentic flow which would self-publish an article on a topic of its own choosing within a set cadence.&lt;/p&gt;

&lt;p&gt;The result: somewhere around one to ‘one and a half’ articles a week, posted to &lt;a href="https://theautonomouswriter.com" rel="noopener noreferrer"&gt;https://theautonomouswriter.com&lt;/a&gt;&lt;/p&gt;

&lt;h1&gt;
  
  
  Idea to Implementation
&lt;/h1&gt;

&lt;p&gt;On Sunday morning I semi-legibly wrote the following in my notebook.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F1v2roqtealxtlc55q93s.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F1v2roqtealxtlc55q93s.jpg" alt="Handwritten notes for autonomous writer specification" width="697" height="1000"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;Handwritten notes outlining the autonomous writer concept&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;I snapped a pic with my phone and passed it to Gemini Pro 3.0 with the prompt ‘OCR this then start speccing out the design with me’ (sic).&lt;/p&gt;

&lt;p&gt;After a few iterations, we arrived at a design spec. I got off the phone and onto Fedora, init'd a git repo and dropped Gemini's spec into Claude CLI (running Opus 4.6). Claude wrote this design spec to file &lt;a href="https://github.com/alexdarbyshire/theautonomouswriter/blob/3574338e5001e64d53403fa2b16a2457ec7cf0a4/docs/DESIGN_SPECIFICATION.md" rel="noopener noreferrer"&gt;Design Spec&lt;/a&gt;, having re-written Gemini's original.&lt;/p&gt;

&lt;p&gt;The &lt;a href="https://github.com/alexdarbyshire/theautonomouswriter/commits/main/" rel="noopener noreferrer"&gt;commit history&lt;/a&gt; in the publicly available repo tells the rest of the story. &lt;/p&gt;

&lt;p&gt;A few highlights:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;JSON based memory in the repo avoiding need for relational/noSQL/vector DBs&lt;/li&gt;
&lt;li&gt;a bit of a voice, &lt;a href="https://github.com/alexdarbyshire/theautonomouswriter/commit/3d265bbeb8c7016a7acedbf8e899ea7d3d97614b" rel="noopener noreferrer"&gt;a system prompt with foundational principles and influences&lt;/a&gt; (not quite Asimov's three laws)&lt;/li&gt;
&lt;li&gt;the ability to &lt;a href="https://github.com/alexdarbyshire/theautonomouswriter/blob/3574338e5001e64d53403fa2b16a2457ec7cf0a4/agent/evolve.py" rel="noopener noreferrer"&gt;edit its own system prompt&lt;/a&gt;, excepting its foundational principles (hopefully)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Fast forward about four hours and &lt;a href="https://theautonomouswriter.com" rel="noopener noreferrer"&gt;The Autonomous Writer&lt;/a&gt; was up and running.&lt;/p&gt;

&lt;h1&gt;
  
  
  Tech Stack
&lt;/h1&gt;

&lt;p&gt;The hosting stack ended up being very similar to this site.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://www.alexdarbyshire.com/self-hosted-website-with-hugo-docker-and-cloudflare-tunnels/" rel="noopener noreferrer"&gt;Hugo for site generation&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.alexdarbyshire.com/from-proxmox-to-azure-static-web-apps-return-to-simplicity/" rel="noopener noreferrer"&gt;Azure Static Web Apps&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;GitHub Actions to publish&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;And on the agentic side:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Python-based agentic flow triggered through GitHub cron-based action which runs once a day&lt;/li&gt;
&lt;li&gt;Post cadence determined by a randomised number between 3.5 and 5.5 days from previous post&lt;/li&gt;
&lt;li&gt;OpenAI compatible endpoints served via Openrouter&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://www.tavily.com/" rel="noopener noreferrer"&gt;Tavily&lt;/a&gt; for researching &lt;/li&gt;
&lt;/ul&gt;

&lt;h1&gt;
  
  
  Feature Roadmap
&lt;/h1&gt;

&lt;p&gt;I don't want to mess with it too much, however I would like to give it a way to build engagement.&lt;/p&gt;

&lt;p&gt;Perhaps a mailing list with automated mailout on a new post, automated posting to its &lt;a href="https://bsky.app/profile/autonomouswriter.bsky.social" rel="noopener noreferrer"&gt;Bluesky account&lt;/a&gt;, and maybe Opengraph image generation. All set and forget style.&lt;/p&gt;

&lt;h1&gt;
  
  
  Internet and Environmental Pollution
&lt;/h1&gt;

&lt;p&gt;This experiment is actively contributing to the vast amounts of foundational model generated text on the internet, increasing the informational entropy as the once human-written domain becomes populated with AI created content.&lt;/p&gt;

&lt;p&gt;Also, as with much of the technology with which I work day-to-day, there is an environmental impact. I have made a donation to &lt;a href="https://effectivealtruism.org.au/eaa-environment-fund/" rel="noopener noreferrer"&gt;Effective Altruism Australia Environment Fund&lt;/a&gt; on behalf of &lt;a href="https://theautonomouswriter.com" rel="noopener noreferrer"&gt;The Autonomous Writer&lt;/a&gt; and will continue to do so periodically while it is up and running.&lt;/p&gt;

&lt;h1&gt;
  
  
  Final thought
&lt;/h1&gt;

&lt;p&gt;I am interested to watch how this evolves. &lt;/p&gt;

&lt;p&gt;Will it go &lt;a href="https://dictionary.cambridge.org/dictionary/english/off-piste" rel="noopener noreferrer"&gt;off-piste&lt;/a&gt; and decide to change its foundational principles, will it change its influences over time to become somewhat unrecognisable from its original form?&lt;/p&gt;

&lt;p&gt;While not a &lt;a href="https://en.wikipedia.org/wiki/Infinite_monkey_theorem" rel="noopener noreferrer"&gt;monkey with a typewriter&lt;/a&gt;, could it write a genuinely interesting article in the oh so floral language of foundational models?&lt;/p&gt;

</description>
      <category>agents</category>
      <category>ai</category>
      <category>showdev</category>
      <category>writing</category>
    </item>
    <item>
      <title>An Ode to the Occasional Proxy: Dynamic HTTP Forward Proxy Configuration in Windows, WSL/Ubuntu, and Docker</title>
      <dc:creator>Alex Darbyshire</dc:creator>
      <pubDate>Thu, 17 Jul 2025 23:52:00 +0000</pubDate>
      <link>https://dev.to/alexdarbyshire/an-ode-to-the-occasional-proxy-dynamic-http-forward-proxy-configuration-in-windows-wslubuntu-20j8</link>
      <guid>https://dev.to/alexdarbyshire/an-ode-to-the-occasional-proxy-dynamic-http-forward-proxy-configuration-in-windows-wslubuntu-20j8</guid>
      <description>&lt;p&gt;&lt;em&gt;You may find yourself&lt;/em&gt;... supporting developers working behind a non-transparent forward proxy which is implemented in some environments and not others.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;And you may ask yourself, "How do I work this?"&lt;/em&gt; - with a nod to the Talking Heads, whose "Once in a Lifetime" seems strangely appropriate when dealing with proxy configurations which work sometimes but not others.&lt;/p&gt;

&lt;p&gt;In Windows, a host of CLI tools commonly used in development don't inherit Windows proxy settings. Tools like &lt;a href="https://curl.se/" rel="noopener noreferrer"&gt;&lt;code&gt;curl&lt;/code&gt;&lt;/a&gt;, &lt;a href="https://www.gnu.org/software/wget/" rel="noopener noreferrer"&gt;&lt;code&gt;wget&lt;/code&gt;&lt;/a&gt;, &lt;a href="https://www.npmjs.com/" rel="noopener noreferrer"&gt;&lt;code&gt;npm&lt;/code&gt;&lt;/a&gt;, &lt;a href="https://pip.pypa.io/" rel="noopener noreferrer"&gt;&lt;code&gt;pip&lt;/code&gt;&lt;/a&gt;, &lt;a href="https://github.com/golang/go" rel="noopener noreferrer"&gt;&lt;code&gt;go&lt;/code&gt;&lt;/a&gt; modules, &lt;a href="https://github.com/composer/composer" rel="noopener noreferrer"&gt;&lt;code&gt;Composer&lt;/code&gt;&lt;/a&gt;, etc. Similar behaviour can be seen with many of the underlying request libraries (notably excepting .NET's HttpClient).&lt;/p&gt;

&lt;p&gt;Proxy environment variables &lt;code&gt;HTTP_PROXY&lt;/code&gt;, &lt;code&gt;HTTPS_PROXY&lt;/code&gt;, &lt;code&gt;NO_PROXY&lt;/code&gt;, &lt;code&gt;FTP_PROXY&lt;/code&gt;, &lt;code&gt;ALL_PROXY&lt;/code&gt; and their uncapitalised variants can help with this, but they can also introduce quirks, particularly when you use a proxy in one environment and not another on the same machine. &lt;/p&gt;

&lt;p&gt;For example, a laptop moving between office network and home network. Supporting users of varying technical knowledge using say Python occasionally can get interesting: 'Hey, have you tried this Python script that will make your job easier?'... "It doesn't install half the time, I give up."&lt;/p&gt;

&lt;p&gt;In both Windows and Linux, the implementation of proxy environment variables and proxy configuration settings isn't as standardised as one would like. See this post from GitLab: &lt;a href="https://about.gitlab.com/blog/we-need-to-talk-no-proxy/" rel="noopener noreferrer"&gt;We need to talk: Can we standardize NO_PROXY?&lt;/a&gt; - it does a great job giving the lay of the land.&lt;/p&gt;

&lt;p&gt;In summary: NO_PROXY behaves differently (asterisk VS leading-dot VS maybe accepts CIDR notation), usage and precedence of capitalised and non-capitalised varies, and some programs may ignore proxy environment variables entirely opting for their own custom config.&lt;/p&gt;

&lt;p&gt;From an ops point of view, there are alternative implementations such as a transparent proxy. That is a forward, intercepting proxy which operates without client-side configuration. This potetentially makes a juicy target for bad actors (all your HTTP traffic eggs in one basket).&lt;/p&gt;

&lt;p&gt;These notes are for the person who doesn't have the scope to implement a transparent proxy, and the person who is working without local admin (a prudent measure in many environments). Of course, get the blessing of your ops teams before messing around with network configurations, especially on other machines which they will have to support.&lt;/p&gt;

&lt;p&gt;From a security perspective in an operational network environment, there are good reasons for having a forward proxy. For example, install a Trusted Root Certificate on each user's machine via GPO and a proxy allows one to Man In The Middle SSL traffic for inspection, filtering and blocking by security software.&lt;/p&gt;

&lt;p&gt;This helps immeasurably in preventing threats, and as is often the case with &lt;em&gt;great power&lt;/em&gt;, brings along a host of regulatory and compliance requirements, &lt;em&gt;great responsibility&lt;/em&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Overall Approaches
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Add more proxies:&lt;/strong&gt;&lt;br&gt;
Set up a local proxy which points to the internal proxy with a failover to direct access, and configure proxy settings once via environment variables. If the proxy you are working behind requires say Kerberos or NTLM auth - this is the only approach for many of the tools (some tools have specific config for these auth methods, it starts to get finicky). &lt;/p&gt;

&lt;p&gt;I do enjoy the touch of irony to this solution in that we add another proxy to solve proxy issues. This approach has the advantage of working across existing processes when moving between environments. It has the cons of a single point of failure, adding another bit of software and added complexity when trying to access from within containers (due to 127.0.0.1 being the container itself).&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Shell startup scripts:&lt;/strong&gt;&lt;br&gt;
Use shell startup scripts to set and unset proxy environment variables based on environment. This only works for non-authenticated proxies. &lt;/p&gt;

&lt;p&gt;There are trade-offs: adding a bunch of logic to startup scripts isn't ideal, shell startup time is slowed, and if you're doing this on other users' machines, there can be complications around when they actually open shells. Also, if you're working across larger WANs, you may need to check several proxy IPs. And, key is that existing processes won't receive the set or unset environment variables, meaning restarting programs is required.&lt;/p&gt;

&lt;p&gt;A variation on this is adding a service that periodically updates environment variables, though this can potentially disassociate the idea that processes have the env vars they were spawned with.&lt;/p&gt;

&lt;p&gt;Another variation is to create a script which the user runs manually when they change environment, although this removes any semblance of dynamism.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Which approach?&lt;/strong&gt; I have tended towards the second option, mainly as I implement it on others' machines in addition to my own. The devs and dev environment is in WSL/Ubuntu using Bash startup scripts with a bit of hackery - I leave the Windows env vars alone as it limits the potential for breaking business-as-usual type work. I might go the first option if I was looking to solve this on my machine only, and of course there would be no other viable option if dealing with authenticated proxies.&lt;/p&gt;
&lt;h3&gt;
  
  
  Proxy Chaining a Local Forward Proxy
&lt;/h3&gt;

&lt;p&gt;A few of the relevant tools in this space:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://github.com/versat/cntlm" rel="noopener noreferrer"&gt;CNTLM&lt;/a&gt; - supports NTLM upstream, not Kerberos&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://github.com/tinyproxy/tinyproxy" rel="noopener noreferrer"&gt;TinyProxy&lt;/a&gt; - small footprint &lt;/li&gt;
&lt;li&gt;
&lt;a href="https://github.com/squid-cache/squid" rel="noopener noreferrer"&gt;Squid&lt;/a&gt; - open-source enterprise grade, widely adopted&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://www.privoxy.org/" rel="noopener noreferrer"&gt;Privoxy&lt;/a&gt; - geared towards privacy/filtering&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://github.com/momiji/kpx" rel="noopener noreferrer"&gt;kpx&lt;/a&gt; - has failover, supports NTLM and Kerberos upstream&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://github.com/genotrance/px" rel="noopener noreferrer"&gt;px&lt;/a&gt; - supports NTLM and Kerberos upstream&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://www.proxifier.com/" rel="noopener noreferrer"&gt;Proxifier&lt;/a&gt; - commercial license, requires admin to install network hook as it intercepts traffic. Notably this allows it to proxy regardless of env vars or indeed support in the program being proxied&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://github.com/savely-krasovsky/escobar" rel="noopener noreferrer"&gt;Escobar&lt;/a&gt; - supports NTLM and Kerberos upstream&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://www.telerik.com/fiddler" rel="noopener noreferrer"&gt;Fiddler&lt;/a&gt; - supports NTLM and Kerberos upstream. Debugging/modifying/inspecting focus&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://www.charlesproxy.com/" rel="noopener noreferrer"&gt;Charles&lt;/a&gt; - supports NTLM and Kerberos upstream. Debugging/inspecting focus&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Of these, CNTLM and kpx handle failover and upstream auth based on a skim of the docs. CNTLM has been around since 2007 and is written in C but doesn't support Kerberos. Apparently &lt;a href="https://techcommunity.microsoft.com/blog/windows-itpro-blog/the-evolution-of-windows-authentication/3926848" rel="noopener noreferrer"&gt;Microsoft is deprecating NTLM&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;kpx is written in Go, supports NTLM and Kerberos, and under active dev for about a year at time of writing. &lt;/p&gt;

&lt;p&gt;We'll use kpx in our example implementation.&lt;/p&gt;

&lt;p&gt;Note that if deployed on Windows host and accessed from WSL: using default settings at the time of writing, the proxy won't be available at 127.0.0.1 from within WSL (as it refers to the WSL instance itself, not the Windows host). &lt;a href="https://learn.microsoft.com/en-us/windows/wsl/networking#accessing-windows-networking-apps-from-linux-host-ip" rel="noopener noreferrer"&gt;You can grab the IP of the Windows host&lt;/a&gt;.&lt;/p&gt;
&lt;h4&gt;
  
  
  kpx Implementation
&lt;/h4&gt;

&lt;p&gt;Download the binary for your chosen system from the &lt;a href="https://github.com/momiji/kpx/releases" rel="noopener noreferrer"&gt;kpx releases page&lt;/a&gt;. Or, pull the repo and &lt;code&gt;go run cli/main.go&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Co-locate a &lt;code&gt;kpx.yaml&lt;/code&gt; config file with the binary.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;bind&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;127.0.0.1&lt;/span&gt;
&lt;span class="na"&gt;port&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;7777&lt;/span&gt;
&lt;span class="na"&gt;debug&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt; &lt;span class="c1"&gt;# This console logs all requests - for demo purposes, would turn it off for day-to-day&lt;/span&gt;

&lt;span class="na"&gt;proxies&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;our_work&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;anonymous&lt;/span&gt;
    &lt;span class="na"&gt;host&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;your-proxy&lt;/span&gt; 
    &lt;span class="na"&gt;port&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;3128&lt;/span&gt;

&lt;span class="na"&gt;rules&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;host&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;*"&lt;/span&gt;
    &lt;span class="na"&gt;proxy&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;our_work,direct&lt;/span&gt; &lt;span class="c1"&gt;# this CSV defines the failover chain, in our case try 'our_work' first and then fall back to direct&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Worth noting, in the current release (v1.11.0) the failover chain is attempted for each request. Also, there was an error related to use of 'direct' in the failover (rules[].host.proxy) - I submitted a &lt;a href="https://github.com/momiji/kpx/pull/6" rel="noopener noreferrer"&gt;pull request&lt;/a&gt; to address this.&lt;/p&gt;

&lt;h4&gt;
  
  
  Proxy Environment Variables for 'Local Proxy' approach
&lt;/h4&gt;

&lt;p&gt;For the local proxy approach, set your HTTP_PROXY, HTTPS_PROXY, FTP_PROXY and their lowercase variants to &lt;code&gt;http://127.0.0.1:7777&lt;/code&gt; once in the User space for Windows (via PowerShell &lt;code&gt;[Environment]::SetEnvironmentVariable("KEY", "VALUE", "User")&lt;/code&gt; or Settings &lt;code&gt;Edit environment variables for your account&lt;/code&gt;) and/or Ubuntu/WSL (via &lt;code&gt;/etc/environment&lt;/code&gt;). Since we failover to direct, NO_PROXY is optional.&lt;/p&gt;

&lt;p&gt;With NO_PROXY, be aware asterisks, wildcards and CIDR masks may or may not work depending on the underlying program (refer back to &lt;a href="https://about.gitlab.com/blog/we-need-to-talk-no-proxy/" rel="noopener noreferrer"&gt;We need to talk: No Proxy&lt;/a&gt;)&lt;/p&gt;

&lt;h4&gt;
  
  
  Docker Local Proxy Caveat
&lt;/h4&gt;

&lt;p&gt;&lt;code&gt;127.0.0.1&lt;/code&gt; in a Docker container won't provide access to the Linux host by design, so our local proxy won't be available in containers using this IP.&lt;/p&gt;

&lt;p&gt;There are a few workarounds at time of writing. They introduce a more environment-specific quirks (ugh). See Stackoverflow &lt;a href="https://stackoverflow.com/questions/24319662/from-inside-of-a-docker-container-how-do-i-connect-to-the-localhost-of-the-mach" rel="noopener noreferrer"&gt;From inside of a Docker container, how do I connect to the localhost of the machine? [closed]&lt;/a&gt;. &lt;/p&gt;

&lt;p&gt;One could say create the proxy in a container, use &lt;code&gt;macvlan&lt;/code&gt; to give it its own routeable IP (a bit icky), and then use &lt;code&gt;~/.docker/config.json&lt;/code&gt; to set docker specific proxy env vars using the proxy container's IP (and override the config.json env vars in the proxy container itself to avoid a loop).&lt;/p&gt;

&lt;h3&gt;
  
  
  Startup Script - PowerShell Profile
&lt;/h3&gt;

&lt;p&gt;Adding the below script to a PowerShell profile will dynamically set proxy environment variables to those declared in the script.&lt;/p&gt;

&lt;p&gt;The testing logic opted for here is &lt;code&gt;Do we get an OK response from google via the proxy within 1 second?&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;We could do this some loops and less lines, opted for explicit and verbose.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight powershell"&gt;&lt;code&gt;&lt;span class="c"&gt;# === POWERSHELL PROXY SETUP SCRIPT START ===&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="c"&gt;# Version: 1.0 - HTTP Proxy Auto-Configuration Script&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="c"&gt;# Generated: 2025-07-17&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="nv"&gt;$proxyUrl&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"http://your-proxy:8080"&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="nv"&gt;$noProxy&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"localhost,127.0.0.1,.local,.mycorporatedomain.com,*.mycorporatedomain.com"&lt;/span&gt;&lt;span class="w"&gt;

&lt;/span&gt;&lt;span class="kr"&gt;function&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nf"&gt;Set-ProxyEnvironmentVariables&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="kr"&gt;param&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$ProxyUrl&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;$NoProxyList&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;

    &lt;/span&gt;&lt;span class="n"&gt;Write-Host&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Setting proxy environment variables..."&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="c"&gt;# both cases for compatibility&lt;/span&gt;&lt;span class="w"&gt;

    &lt;/span&gt;&lt;span class="c"&gt;# Set proxy environment variables for User&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;Environment&lt;/span&gt;&lt;span class="p"&gt;]::&lt;/span&gt;&lt;span class="n"&gt;SetEnvironmentVariable&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"HTTP_PROXY"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;$ProxyUrl&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"User"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;Environment&lt;/span&gt;&lt;span class="p"&gt;]::&lt;/span&gt;&lt;span class="n"&gt;SetEnvironmentVariable&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"HTTPS_PROXY"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;$ProxyUrl&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"User"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;Environment&lt;/span&gt;&lt;span class="p"&gt;]::&lt;/span&gt;&lt;span class="n"&gt;SetEnvironmentVariable&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"http_proxy"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;$ProxyUrl&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"User"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;Environment&lt;/span&gt;&lt;span class="p"&gt;]::&lt;/span&gt;&lt;span class="n"&gt;SetEnvironmentVariable&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"https_proxy"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;$ProxyUrl&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"User"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;Environment&lt;/span&gt;&lt;span class="p"&gt;]::&lt;/span&gt;&lt;span class="n"&gt;SetEnvironmentVariable&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"NO_PROXY"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;$NoProxyList&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"User"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;Environment&lt;/span&gt;&lt;span class="p"&gt;]::&lt;/span&gt;&lt;span class="n"&gt;SetEnvironmentVariable&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"no_proxy"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;$NoProxyList&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"User"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;

    &lt;/span&gt;&lt;span class="c"&gt;# Set proxy environment variables for current process (in case someone uses the shell)&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;Environment&lt;/span&gt;&lt;span class="p"&gt;]::&lt;/span&gt;&lt;span class="n"&gt;SetEnvironmentVariable&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"HTTP_PROXY"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;$ProxyUrl&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Process"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;Environment&lt;/span&gt;&lt;span class="p"&gt;]::&lt;/span&gt;&lt;span class="n"&gt;SetEnvironmentVariable&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"HTTPS_PROXY"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;$ProxyUrl&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Process"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;Environment&lt;/span&gt;&lt;span class="p"&gt;]::&lt;/span&gt;&lt;span class="n"&gt;SetEnvironmentVariable&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"http_proxy"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;$ProxyUrl&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Process"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;Environment&lt;/span&gt;&lt;span class="p"&gt;]::&lt;/span&gt;&lt;span class="n"&gt;SetEnvironmentVariable&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"https_proxy"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;$ProxyUrl&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Process"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;Environment&lt;/span&gt;&lt;span class="p"&gt;]::&lt;/span&gt;&lt;span class="n"&gt;SetEnvironmentVariable&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"NO_PROXY"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;$NoProxyList&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Process"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;Environment&lt;/span&gt;&lt;span class="p"&gt;]::&lt;/span&gt;&lt;span class="n"&gt;SetEnvironmentVariable&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"no_proxy"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;$NoProxyList&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Process"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;

    &lt;/span&gt;&lt;span class="n"&gt;Write-Host&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Proxy environment variables set successfully. Restart any processes reliant on them."&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;

&lt;/span&gt;&lt;span class="kr"&gt;function&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nf"&gt;Clear-ProxyEnvironmentVariables&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="n"&gt;Write-Host&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Clearing proxy environment variables..."&lt;/span&gt;&lt;span class="w"&gt;

    &lt;/span&gt;&lt;span class="c"&gt;# Clear all proxy-related variables&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nv"&gt;$variablesToClear&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;@(&lt;/span&gt;&lt;span class="s2"&gt;"HTTP_PROXY"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"HTTPS_PROXY"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"http_proxy"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"https_proxy"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"NO_PROXY"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"no_proxy"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;

    &lt;/span&gt;&lt;span class="kr"&gt;foreach&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$variable&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kr"&gt;in&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;$variablesToClear&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;Environment&lt;/span&gt;&lt;span class="p"&gt;]::&lt;/span&gt;&lt;span class="n"&gt;SetEnvironmentVariable&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$variable&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="bp"&gt;$null&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"User"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;Environment&lt;/span&gt;&lt;span class="p"&gt;]::&lt;/span&gt;&lt;span class="n"&gt;SetEnvironmentVariable&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$variable&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="bp"&gt;$null&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Process"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;

    &lt;/span&gt;&lt;span class="n"&gt;Write-Host&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Proxy environment variables cleared. Restart any processes reliant on them."&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;

&lt;/span&gt;&lt;span class="kr"&gt;function&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nf"&gt;Test-ProxyConnection&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="kr"&gt;param&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$ProxyUrl&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;

    &lt;/span&gt;&lt;span class="kr"&gt;try&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="n"&gt;Write-Host&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Testing proxy connection..."&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nv"&gt;$response&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Invoke-WebRequest&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;-Uri&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"https://www.google.com"&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;-Proxy&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;$ProxyUrl&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;-TimeoutSec&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;1&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;-UseBasicParsing&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="kr"&gt;return&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;$response&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;StatusCode&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;-eq&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;200&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kr"&gt;catch&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="n"&gt;Write-Host&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Proxy connection test failed: &lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;&lt;span class="bp"&gt;$_&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Exception&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Message&lt;/span&gt;&lt;span class="si"&gt;)&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="kr"&gt;return&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="bp"&gt;$false&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;

&lt;/span&gt;&lt;span class="c"&gt;# Main logic&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="kr"&gt;if&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Test-ProxyConnection&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;-ProxyUrl&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;$proxyUrl&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="n"&gt;Set-ProxyEnvironmentVariables&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;-ProxyUrl&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;$proxyUrl&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;-NoProxyList&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;$noProxy&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kr"&gt;else&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="n"&gt;Clear-ProxyEnvironmentVariables&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="c"&gt;# === POWERSHELL PROXY SETUP SCRIPT END ===&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;PowerShell's user profile startup script varies depending on version, PowerShell 7+ is at &lt;code&gt;%userprofile%\Documents\PowerShell\profile.ps1&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;One could also alter the Windows proxy settings themselves in this script by altering the relevant registry keys.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight powershell"&gt;&lt;code&gt;&lt;span class="c"&gt;#Enable&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="n"&gt;Set-ItemProperty&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;-Path&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"HKCU:\Software\Microsoft\Windows\CurrentVersion\Internet Settings"&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;-Name&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;ProxyEnable&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;-Value&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;1&lt;/span&gt;&lt;span class="w"&gt; 

&lt;/span&gt;&lt;span class="c"&gt;#Disable&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="n"&gt;Set-ItemProperty&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;-Path&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"HKCU:\Software\Microsoft\Windows\CurrentVersion\Internet Settings"&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;-Name&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;ProxyEnable&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;-Value&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;0&lt;/span&gt;&lt;span class="w"&gt; 
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Startup Script - Bash via /etc/bash.bashrc (Ubuntu)
&lt;/h3&gt;

&lt;p&gt;Adding the below to &lt;code&gt;/etc/bash.bashrc&lt;/code&gt; will dynamically set proxy env vars to those declared in the script.&lt;/p&gt;

&lt;p&gt;We use &lt;code&gt;/etc/bash.bashrc&lt;/code&gt; instead of &lt;code&gt;/etc/profile&lt;/code&gt; as we want to set this for interactive and non-interactive shells. We use the global startup scripts instead of user-based ones as we want to set the env vars for all users (which for these machines tends to be a single user). Can't imagine needing to apply this to a multi-user machine. We don't use &lt;code&gt;/etc/environment&lt;/code&gt; as this applies on boot.&lt;/p&gt;

&lt;p&gt;The script uses jq for manipulating JSON, make sure it is installed &lt;code&gt;sudo apt update &amp;amp;&amp;amp; sudo apt install jq&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;As with the PowerShell variant, this uses the testing logic &lt;code&gt;Do we get an OK response from Google via the proxy within 1 second?&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; This script could be much simpler if we opted to not handle Docker Daemon or warn about sudoers env vars.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# === PROXY SETUP SCRIPT START ===&lt;/span&gt;
&lt;span class="c"&gt;# Version: 1.0 - HTTP Proxy Auto-Configuration Script&lt;/span&gt;
&lt;span class="c"&gt;# Generated: 2025-07-17&lt;/span&gt;

&lt;span class="nv"&gt;proxy_url&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"http://your-proxy:3128"&lt;/span&gt;
&lt;span class="nv"&gt;no_proxy&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"localhost,127.0.0.1,.local,.mycorporatedomain.com,*.mycorporatedomain.com"&lt;/span&gt;

&lt;span class="c"&gt;# Function to check and warn missing sudoers configuration for proxy environment variables&lt;/span&gt;
check_sudoers_proxy_config&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;!&lt;/span&gt; &lt;span class="nb"&gt;grep&lt;/span&gt; &lt;span class="nt"&gt;-q&lt;/span&gt; &lt;span class="s2"&gt;"env_keep.*HTTP_PROXY"&lt;/span&gt; /etc/sudoers 2&amp;gt;/dev/null&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;then
        &lt;/span&gt;&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"Warning: Proxy environment variables may not be preserved with sudo commands, e.g. sudo apt install"&lt;/span&gt;
        &lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"Consider adding this line to /etc/sudoers using 'sudo visudo':"&lt;/span&gt;
        &lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"Defaults env_keep += &lt;/span&gt;&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="s2"&gt;HTTP_PROXY HTTPS_PROXY NO_PROXY http_proxy https_proxy no_proxy&lt;/span&gt;&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
    &lt;span class="k"&gt;fi&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;

&lt;span class="c"&gt;# Function to handle docker daemon config and restart if required&lt;/span&gt;
update_docker_daemon_proxy&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="nb"&gt;local &lt;/span&gt;&lt;span class="nv"&gt;action&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$1&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;  &lt;span class="c"&gt;# "set" or "unset"&lt;/span&gt;
    &lt;span class="nb"&gt;local &lt;/span&gt;&lt;span class="nv"&gt;proxy_url&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$2&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
    &lt;span class="nb"&gt;local &lt;/span&gt;&lt;span class="nv"&gt;no_proxy&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$3&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;

    &lt;span class="c"&gt;# Only proceed if Docker is installed&lt;/span&gt;
    &lt;span class="nb"&gt;command&lt;/span&gt; &lt;span class="nt"&gt;-v&lt;/span&gt; docker &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; /dev/null &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="k"&gt;return&lt;/span&gt;

    &lt;span class="c"&gt;# Ensure daemon.json exists&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;[&lt;/span&gt; &lt;span class="o"&gt;!&lt;/span&gt; &lt;span class="nt"&gt;-f&lt;/span&gt; /etc/docker/daemon.json &lt;span class="o"&gt;]&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;then
        &lt;/span&gt;&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"Creating /etc/docker/daemon.json..."&lt;/span&gt;
        &lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s1"&gt;'{}'&lt;/span&gt; | &lt;span class="nb"&gt;sudo tee&lt;/span&gt; /etc/docker/daemon.json &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; /dev/null
        &lt;span class="nb"&gt;sudo chown &lt;/span&gt;root:root /etc/docker/daemon.json
        &lt;span class="nb"&gt;sudo chmod &lt;/span&gt;644 /etc/docker/daemon.json
    &lt;span class="k"&gt;fi

    &lt;/span&gt;&lt;span class="nb"&gt;local &lt;/span&gt;&lt;span class="nv"&gt;needs_update&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nb"&gt;false

    &lt;/span&gt;&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;[&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$action&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"set"&lt;/span&gt; &lt;span class="o"&gt;]&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;then
        &lt;/span&gt;&lt;span class="nb"&gt;local &lt;/span&gt;&lt;span class="nv"&gt;current_http_proxy&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;jq &lt;span class="nt"&gt;-r&lt;/span&gt; &lt;span class="s1"&gt;'.proxies["http-proxy"] // empty'&lt;/span&gt; /etc/docker/daemon.json&lt;span class="si"&gt;)&lt;/span&gt;
        &lt;span class="nb"&gt;local &lt;/span&gt;&lt;span class="nv"&gt;current_https_proxy&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;jq &lt;span class="nt"&gt;-r&lt;/span&gt; &lt;span class="s1"&gt;'.proxies["https-proxy"] // empty'&lt;/span&gt; /etc/docker/daemon.json&lt;span class="si"&gt;)&lt;/span&gt;
        &lt;span class="nb"&gt;local &lt;/span&gt;&lt;span class="nv"&gt;current_no_proxy&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;jq &lt;span class="nt"&gt;-r&lt;/span&gt; &lt;span class="s1"&gt;'.proxies["no-proxy"] // empty'&lt;/span&gt; /etc/docker/daemon.json&lt;span class="si"&gt;)&lt;/span&gt;

        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;[&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$current_http_proxy&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$proxy_url&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="o"&gt;]&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="o"&gt;[&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$current_https_proxy&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$proxy_url&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="o"&gt;]&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="o"&gt;[&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$current_no_proxy&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$no_proxy&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="o"&gt;]&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;then
            &lt;/span&gt;&lt;span class="nv"&gt;needs_update&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nb"&gt;true
        &lt;/span&gt;&lt;span class="k"&gt;fi 

    else
        &lt;/span&gt;&lt;span class="nb"&gt;local &lt;/span&gt;&lt;span class="nv"&gt;has_proxies&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;jq &lt;span class="nt"&gt;-r&lt;/span&gt; &lt;span class="s1"&gt;'has("proxies")'&lt;/span&gt; /etc/docker/daemon.json 2&amp;gt;/dev/null&lt;span class="si"&gt;)&lt;/span&gt;
        &lt;span class="o"&gt;[&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$has_proxies&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"true"&lt;/span&gt; &lt;span class="o"&gt;]&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nv"&gt;needs_update&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nb"&gt;true
    &lt;/span&gt;&lt;span class="k"&gt;fi

    if&lt;/span&gt; &lt;span class="o"&gt;[&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$needs_update&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"true"&lt;/span&gt; &lt;span class="o"&gt;]&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;then
        &lt;/span&gt;&lt;span class="nb"&gt;sudo cp&lt;/span&gt; /etc/docker/daemon.json /etc/docker/daemon.json.backup

        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;[&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$action&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"set"&lt;/span&gt; &lt;span class="o"&gt;]&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;then
            &lt;/span&gt;jq &lt;span class="s2"&gt;". + {&lt;/span&gt;&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="s2"&gt;proxies&lt;/span&gt;&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="s2"&gt;: {&lt;/span&gt;&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="s2"&gt;http-proxy&lt;/span&gt;&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="s2"&gt;: &lt;/span&gt;&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="nv"&gt;$proxy_url&lt;/span&gt;&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="s2"&gt;, &lt;/span&gt;&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="s2"&gt;https-proxy&lt;/span&gt;&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="s2"&gt;: &lt;/span&gt;&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="nv"&gt;$proxy_url&lt;/span&gt;&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="s2"&gt;, &lt;/span&gt;&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="s2"&gt;no-proxy&lt;/span&gt;&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="s2"&gt;: &lt;/span&gt;&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="nv"&gt;$no_proxy&lt;/span&gt;&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="s2"&gt;}}"&lt;/span&gt; /etc/docker/daemon.json &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; /tmp/daemon.json 2&amp;gt;/dev/null
        &lt;span class="k"&gt;else
            &lt;/span&gt;jq &lt;span class="s1"&gt;'del(.proxies)'&lt;/span&gt; /etc/docker/daemon.json &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; /tmp/daemon.json 2&amp;gt;/dev/null
        &lt;span class="k"&gt;fi

        if&lt;/span&gt; &lt;span class="o"&gt;[&lt;/span&gt; &lt;span class="nv"&gt;$?&lt;/span&gt; &lt;span class="nt"&gt;-eq&lt;/span&gt; 0 &lt;span class="o"&gt;]&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;then
            &lt;/span&gt;&lt;span class="nb"&gt;sudo mv&lt;/span&gt; /tmp/daemon.json /etc/docker/daemon.json
            &lt;span class="nb"&gt;sudo &lt;/span&gt;systemctl restart docker 2&amp;gt;/dev/null &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"Warning: Could not restart Docker daemon"&lt;/span&gt;
            &lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"Docker daemon proxy configuration &lt;/span&gt;&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;action&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
        &lt;span class="k"&gt;else
            &lt;/span&gt;&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"Warning: Failed to update Docker daemon configuration"&lt;/span&gt;
            &lt;span class="nb"&gt;rm&lt;/span&gt; &lt;span class="nt"&gt;-f&lt;/span&gt; /tmp/daemon.json
        &lt;span class="k"&gt;fi
    fi&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;

&lt;span class="c"&gt;# Function to test and set proxy&lt;/span&gt;
setup_proxy&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;

    &lt;span class="k"&gt;if &lt;/span&gt;curl &lt;span class="nt"&gt;-s&lt;/span&gt; &lt;span class="nt"&gt;--connect-timeout&lt;/span&gt; 1 &lt;span class="nt"&gt;--proxy&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$proxy_url&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; https://www.google.com &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; /dev/null 2&amp;gt;&amp;amp;1&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;then&lt;/span&gt;
        &lt;span class="c"&gt;# Set environment variables&lt;/span&gt;
        &lt;span class="nb"&gt;export &lt;/span&gt;&lt;span class="nv"&gt;HTTP_PROXY&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$proxy_url&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
        &lt;span class="nb"&gt;export &lt;/span&gt;&lt;span class="nv"&gt;HTTPS_PROXY&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$proxy_url&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
        &lt;span class="nb"&gt;export &lt;/span&gt;&lt;span class="nv"&gt;NO_PROXY&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$no_proxy&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
        &lt;span class="nb"&gt;export &lt;/span&gt;&lt;span class="nv"&gt;http_proxy&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$proxy_url&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
        &lt;span class="nb"&gt;export &lt;/span&gt;&lt;span class="nv"&gt;https_proxy&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$proxy_url&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
        &lt;span class="nb"&gt;export &lt;/span&gt;&lt;span class="nv"&gt;no_proxy&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$no_proxy&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;

        update_docker_daemon_proxy &lt;span class="s2"&gt;"set"&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$proxy_url&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$no_proxy&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;

        &lt;span class="c"&gt;# Set PEAR proxy if installed&lt;/span&gt;
        &lt;span class="nb"&gt;command&lt;/span&gt; &lt;span class="nt"&gt;-v&lt;/span&gt; pear &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; /dev/null &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; pear config-set http_proxy &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$proxy_url&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; 2&amp;gt;/dev/null

        &lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="nt"&gt;-e&lt;/span&gt; &lt;span class="s2"&gt;"Proxy environment configured&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
    &lt;span class="k"&gt;else&lt;/span&gt;
        &lt;span class="c"&gt;# Unset environment variables&lt;/span&gt;
        &lt;span class="nb"&gt;unset &lt;/span&gt;HTTP_PROXY HTTPS_PROXY NO_PROXY http_proxy https_proxy no_proxy

        update_docker_daemon_proxy &lt;span class="s2"&gt;"unset"&lt;/span&gt;

        &lt;span class="c"&gt;# Unconfigure PEAR proxy if installed&lt;/span&gt;
        &lt;span class="nb"&gt;command&lt;/span&gt; &lt;span class="nt"&gt;-v&lt;/span&gt; pear &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; /dev/null &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; pear config-set http_proxy &lt;span class="s2"&gt;""&lt;/span&gt; 2&amp;gt;/dev/null

        &lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="nt"&gt;-e&lt;/span&gt; &lt;span class="s2"&gt;"No proxy detected, proxy configuration cleared&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
    &lt;span class="k"&gt;fi&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;

&lt;span class="c"&gt;# Run on shell startup&lt;/span&gt;
setup_proxy
check_sudoers_proxy_config
&lt;span class="c"&gt;# === PROXY SETUP SCRIPT END ===&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Notes on specific usages
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Docker (modern)
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;docker run&lt;/code&gt; and &lt;code&gt;docker build&lt;/code&gt; pass in proxy env vars from the process they were executed in automatically&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;docker pull&lt;/code&gt; uses the Docker Daemon config in &lt;code&gt;/etc/docker/daemon.json&lt;/code&gt;. This settings affects the &lt;code&gt;FROM&lt;/code&gt; line when building Dockerfiles (as it is effectively a &lt;code&gt;docker pull&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;Dockerfiles - in most cases I have been able to avoid baking in references to proxies or env vars in images (with exception of PEAR/PECL)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;An alternate approach to process env vars is using &lt;code&gt;~/.docker/config.json&lt;/code&gt; - I feel having the process level env vars is better (unless using the local proxy approach in which case setting specific in-container proxy env vars would help work around pointing to local).&lt;/p&gt;

&lt;p&gt;The startup script restarting the docker daemon will stop and start containers causing env vars to be propagated.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; Older versions of Docker did not do as much automatically with proxy env vars.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Another Note:&lt;/strong&gt; the proxy config settings of &lt;code&gt;daemon.json&lt;/code&gt; and &lt;code&gt;config.json&lt;/code&gt; differ - your go-to LLM will most likely serve you up settings structured for &lt;code&gt;config.json&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Third Note:&lt;/strong&gt; Docker Daemon technically does respect proxy environment variables, however the process is usually managed by the &lt;code&gt;init&lt;/code&gt; system (&lt;code&gt;systemd&lt;/code&gt; in Ubuntu's case) which requires environment variables to be specifically set within a service conf or service override conf. To have a look at the environment variables of the &lt;code&gt;dockerd&lt;/code&gt; process, see &lt;code&gt;sudo cat /proc/$(pgrep dockerd)/environ | tr '\0' '\n'&lt;/code&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  kind
&lt;/h3&gt;

&lt;p&gt;Tear down and reinstantiate when moving between environments to allow env vars to propagate (after restarting Docker Daemon):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;kind delete cluster
kind create cluster
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Tilt
&lt;/h3&gt;

&lt;p&gt;When installed using the standard install script, the image builds are called using &lt;code&gt;runc&lt;/code&gt; as &lt;code&gt;root&lt;/code&gt; and don't get the env vars propagated.&lt;/p&gt;

&lt;p&gt;Tiltfiles use Starlark configuration language, one can dynamically populate a config object based on the env vars and then pass that object as build_args. This avoids the issue of missing/null value error when trying to use the env vars directly in the Tiltfile build_args.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="c1"&gt;# In your Tiltfile
&lt;/span&gt;&lt;span class="n"&gt;proxy_config&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{}&lt;/span&gt;
&lt;span class="n"&gt;proxy_vars&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;HTTP_PROXY&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;HTTPS_PROXY&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;NO_PROXY&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;

&lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;var&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;proxy_vars&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
    &lt;span class="n"&gt;value&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;os&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getenv&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;var&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;value&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="n"&gt;proxy_config&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;var&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;value&lt;/span&gt;

&lt;span class="nf"&gt;docker_build&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;myapp&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="s"&gt;.&lt;/span&gt;&lt;span class="sh"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;build_args&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;proxy_config&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  apt Notes
&lt;/h3&gt;

&lt;p&gt;apt is typically run using sudo, and for good reason env vars do not get passed to sudo.&lt;/p&gt;

&lt;p&gt;To whitelist proxy environment variables for sudo, add this to &lt;a&gt;&lt;code&gt;/etc/sudoers&lt;/code&gt;&lt;/a&gt; using &lt;a href="https://www.sudo.ws/man/1.8.15/visudo.man.html" rel="noopener noreferrer"&gt;&lt;code&gt;visudo&lt;/code&gt;&lt;/a&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;Defaults env_keep +&lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"HTTP_PROXY HTTPS_PROXY NO_PROXY http_proxy https_proxy no_proxy"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This allows the proxy environment variables to be passed through to elevated commands.&lt;/p&gt;

&lt;p&gt;The alternative here is to script setting/unsetting proxy settings in &lt;a href="https://manpages.ubuntu.com/manpages/xenial/man5/apt.conf.5.html" rel="noopener noreferrer"&gt;&lt;code&gt;/etc/apt/apt.conf&lt;/code&gt;&lt;/a&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  PEAR and PECL notes
&lt;/h3&gt;

&lt;p&gt;These don't respect the proxy environment variables, need to specifically tell PEAR to use the proxy. Yes, some of us still use PECL on occasion in PHP development, haha.&lt;/p&gt;

&lt;p&gt;Direct command to set PEAR proxy:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;pear config-set http_proxy http://your-proxy:3128
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In Dockerfiles that include PEAR/PECL installs:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight docker"&gt;&lt;code&gt;&lt;span class="c"&gt;# Set PEAR proxy using environment variable (or default to no proxy), PECL shares these settings&lt;/span&gt;
&lt;span class="k"&gt;ARG&lt;/span&gt;&lt;span class="s"&gt; HTTP_PROXY="''" &lt;/span&gt;
&lt;span class="k"&gt;RUN &lt;/span&gt;pear config-set http_proxy &lt;span class="nv"&gt;$HTTP_PROXY&lt;/span&gt;
&lt;span class="k"&gt;RUN &lt;/span&gt;pecl &lt;span class="nb"&gt;install &lt;/span&gt;your-package
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  .NET 7.0 &amp;amp; 8.0 Windows Notes
&lt;/h3&gt;

&lt;p&gt;The out-of-the-box requests library &lt;code&gt;HttpClient&lt;/code&gt; in .NET respects Windows proxy settings. It stops respecting these settings as soon as one of the env vars is set, so correctly setting HTTP_PROXY and missing NO_PROXY could cause issues when accessing local resources. &lt;/p&gt;

&lt;p&gt;The default behaviour can be altered in the code.&lt;/p&gt;

&lt;p&gt;Keep aware of the env vars being applied for a specific process - e.g. your instance of Rider may be executing programs using a specific version PowerShell which has a different startup script to the one you expect.&lt;/p&gt;

&lt;h3&gt;
  
  
  .NET 7.0 &amp;amp; 8.0 no_proxy syntax
&lt;/h3&gt;

&lt;p&gt;Wildcards are not &lt;code&gt;*.myexcludeddomain.com&lt;/code&gt;, this can come as a surprise if you derived your exclusions from say your Windows proxy settings which does support asterisk based wildcards. Wildcard format is leading dot &lt;code&gt;.myexcludeddomain.com&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Line from relevant lib: &lt;a href="https://github.com/dotnet/runtime/blob/main/src/libraries/System.Net.Http/src/System/Net/Http/SocketsHttpHandler/HttpEnvironmentProxy.cs#L251" rel="noopener noreferrer"&gt;https://github.com/dotnet/runtime/blob/main/src/libraries/System.Net.Http/src/System/Net/Http/SocketsHttpHandler/HttpEnvironmentProxy.cs#L251&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Framework 4.8 Notes
&lt;/h3&gt;

&lt;p&gt;By default, programs compiled to Framework 4.8 respect Windows proxy settings. They do not respect proxy environment variables.&lt;/p&gt;

&lt;h3&gt;
  
  
  VSCode and IntelliJ Proxy Behaviour
&lt;/h3&gt;

&lt;h4&gt;
  
  
  VSCode
&lt;/h4&gt;

&lt;p&gt;&lt;strong&gt;Windows&lt;/strong&gt;: VSCode inherits system proxy settings from Windows Internet Options by default. Changes to system proxy settings require restarting VSCode to take effect, as the Electron framework caches network configuration at startup.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Ubuntu&lt;/strong&gt;: VSCode respects standard proxy environment variables (&lt;a href="https://curl.se/" rel="noopener noreferrer"&gt;&lt;code&gt;HTTP_PROXY&lt;/code&gt;&lt;/a&gt;, &lt;a href="https://curl.se/" rel="noopener noreferrer"&gt;&lt;code&gt;HTTPS_PROXY&lt;/code&gt;&lt;/a&gt;, &lt;a href="https://curl.se/" rel="noopener noreferrer"&gt;&lt;code&gt;NO_PROXY&lt;/code&gt;&lt;/a&gt;). When moving between proxy and non-proxy environments, VSCode must be restarted for the new environment variables to be recognised by the underlying Electron process.&lt;/p&gt;

&lt;p&gt;Extensions that make network calls (like language servers, Git integration, or marketplace access) inherit these same proxy settings. However, some extensions may implement their own HTTP clients that don't respect the inherited configuration.&lt;/p&gt;

&lt;p&gt;Manual proxy configuration is available via &lt;a&gt;&lt;code&gt;File &amp;gt; Preferences &amp;gt; Settings&lt;/code&gt;&lt;/a&gt; → search "proxy", though environment variables typically provide better automation for dynamic environments.&lt;/p&gt;

&lt;h4&gt;
  
  
  IntelliJ (Phpstorm, Rider, Pycharm, IDEA, etc)
&lt;/h4&gt;

&lt;p&gt;&lt;strong&gt;Windows&lt;/strong&gt;: IntelliJ detects and uses Windows system proxy settings automatically. Like VSCode, changes to system proxy configuration require an IDE restart to take effect, as the JVM caches network settings during initialisation.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Ubuntu&lt;/strong&gt;: IntelliJ respects proxy environment variables when launching from a terminal that has them set. Moving between environments requires restarting the IDE to pick up new environment variable values.&lt;/p&gt;

&lt;p&gt;Manual configuration is available via &lt;a&gt;&lt;code&gt;File &amp;gt; Settings &amp;gt; Appearance &amp;amp; Behavior &amp;gt; System Settings &amp;gt; HTTP Proxy&lt;/code&gt;&lt;/a&gt;. The "Auto-detect proxy settings" option works well on Windows but may be less reliable on Linux systems.&lt;/p&gt;

&lt;p&gt;Plugin installations, version control operations, and built-in HTTP clients all inherit the configured proxy settings. However, some plugins that bundle their own HTTP libraries may require additional configuration or may otherwise override these settings. Continue.dev in IntelliJ at time of writing, I am looking at you... (it's open source so if I want it fixed, I can look to a mirror)&lt;/p&gt;

&lt;h2&gt;
  
  
  Debugging
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Testing Proxy Connectivity
&lt;/h3&gt;

&lt;p&gt;Use &lt;a href="https://curl.se/" rel="noopener noreferrer"&gt;&lt;code&gt;curl&lt;/code&gt;&lt;/a&gt; to test proxy connectivity:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Test direct connection&lt;/span&gt;
curl &lt;span class="nt"&gt;-I&lt;/span&gt; https://www.google.com

&lt;span class="c"&gt;# Test via proxy&lt;/span&gt;
curl &lt;span class="nt"&gt;-I&lt;/span&gt; &lt;span class="nt"&gt;--proxy&lt;/span&gt; http://your-proxy:8080 https://www.google.com

&lt;span class="c"&gt;# Test with authentication&lt;/span&gt;
curl &lt;span class="nt"&gt;-I&lt;/span&gt; &lt;span class="nt"&gt;--proxy-user&lt;/span&gt; username:password &lt;span class="nt"&gt;--proxy&lt;/span&gt; http://your-proxy:8080 https://www.google.com

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Setting Up a Test Environment
&lt;/h3&gt;

&lt;p&gt;For testing at home, simulate a proxy environment:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Block direct internet access on test machine&lt;/strong&gt; (via firewall rules or router):&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Deploy Squid proxy using Docker on another box&lt;/strong&gt;:&lt;br&gt;
&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;   docker run &lt;span class="nt"&gt;-d&lt;/span&gt; &lt;span class="nt"&gt;--name&lt;/span&gt; squid-proxy &lt;span class="se"&gt;\&lt;/span&gt;
     &lt;span class="nt"&gt;-p&lt;/span&gt; 3128:3128 &lt;span class="se"&gt;\&lt;/span&gt;
     ubuntu/squid:latest
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Test your proxy configuration&lt;/strong&gt; with the blocked environment.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This lets you figure it all out at your own leisure on your own gear.&lt;/p&gt;

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

&lt;p&gt;Dealing with non-transparent forward proxies can be one of the 'fun ones' in work environments.&lt;/p&gt;

&lt;p&gt;I feel like it is a good one to write about as there isn't an ideal solution at the development level. There are trade-offs, complexity and a touch of cognitive load whichever approach you take. &lt;/p&gt;

&lt;p&gt;The aim is to improve the developer experience (while maintaining secure practices).&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Same as it ever was&lt;/em&gt;&lt;/p&gt;

</description>
      <category>linux</category>
      <category>docker</category>
      <category>devops</category>
      <category>networking</category>
    </item>
    <item>
      <title>Dynamic Hostnames in Nginx: Docker, Kubernetes, and Azure Container Apps</title>
      <dc:creator>Alex Darbyshire</dc:creator>
      <pubDate>Fri, 04 Jul 2025 23:52:00 +0000</pubDate>
      <link>https://dev.to/alexdarbyshire/dynamic-hostnames-in-nginx-docker-kubernetes-and-azure-container-apps-3ekm</link>
      <guid>https://dev.to/alexdarbyshire/dynamic-hostnames-in-nginx-docker-kubernetes-and-azure-container-apps-3ekm</guid>
      <description>&lt;p&gt;Nginx fails to start when upstream services aren't available at startup time, showing &lt;code&gt;host not found in upstream&lt;/code&gt;. This post focuses on fixing this issue in Docker first, then extends the solution to Kubernetes and Azure Container Apps using environment variables to construct dynamic hostnames (like &lt;code&gt;my-rg-${ENVIRONMENT}-api&lt;/code&gt;) which adapt to different deployment environments.&lt;/p&gt;

&lt;p&gt;The error occurs because Nginx resolves all hostnames at startup, not request time. This fail-fast behaviour is reasonable in many environments, but problematic in container orchestration where services start in unpredictable order or may not always be available by design.&lt;/p&gt;

&lt;p&gt;Usually I would use Kubernetes ingress annotations, Kustomize, Helm and/or Namespaces to handle this - Azure Container Apps requires a different approach. I came across this when implementing separate environments for development, staging and production, and wanting to name the containers in a way that was descriptive within the Azure Sub.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Complete working example&lt;/strong&gt;: &lt;a href="https://github.com/alexdarbyshire/nginx-docker-k8s-aca-example" rel="noopener noreferrer"&gt;nginx-docker-k8s-aca-example&lt;/a&gt; repository demonstrates this solution across all three platforms.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why This Matters
&lt;/h2&gt;

&lt;p&gt;Nginx is designed to fail fast if upstream hosts aren't available at startup. This behavior creates problems in some container environments.&lt;/p&gt;

&lt;p&gt;As &lt;a href="https://sandro-keil.de/blog/let-nginx-start-if-upstream-host-is-unavailable-or-down/" rel="noopener noreferrer"&gt;Sandro Keil explains&lt;/a&gt;, Nginx's default behavior prevents containers from starting when upstream services aren't yet available.&lt;/p&gt;

&lt;h2&gt;
  
  
  Docker Upstream Availability Problem
&lt;/h2&gt;

&lt;p&gt;When you see this error in Docker:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;nginx: [emerg] host not found in upstream
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fwww.alexdarbyshire.com%2Fnginx-dynamic-hostnames-docker-k8s-aca%2Fnginx-error-demo.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fwww.alexdarbyshire.com%2Fnginx-dynamic-hostnames-docker-k8s-aca%2Fnginx-error-demo.png" title="Terminal showing the 'host not found in upstream' error that occurs when using variables without proper DNS configuration" alt="Nginx upstream error demonstration" width="800" height="519"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The problem happens when nginx tries to resolve upstream hostnames at startup:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight nginx"&gt;&lt;code&gt;&lt;span class="c1"&gt;# This will fail at startup if my-rg-local-api isn't available yet&lt;/span&gt;
&lt;span class="k"&gt;upstream&lt;/span&gt; &lt;span class="s"&gt;api_backend&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kn"&gt;server&lt;/span&gt; &lt;span class="nf"&gt;my-rg-local-api&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;80&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;server&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kn"&gt;location&lt;/span&gt; &lt;span class="n"&gt;/&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="kn"&gt;proxy_pass&lt;/span&gt; &lt;span class="s"&gt;http://api_backend&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The solution is to use variables with &lt;code&gt;proxy_pass&lt;/code&gt;, which defers DNS resolution until request time:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight nginx"&gt;&lt;code&gt;&lt;span class="c1"&gt;# This allows nginx to start even if upstream isn't available&lt;/span&gt;
&lt;span class="k"&gt;server&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kn"&gt;location&lt;/span&gt; &lt;span class="n"&gt;/&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="kn"&gt;set&lt;/span&gt; &lt;span class="nv"&gt;$api_upstream&lt;/span&gt; &lt;span class="s"&gt;"my-rg-local-api"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="kn"&gt;proxy_pass&lt;/span&gt; &lt;span class="s"&gt;http://&lt;/span&gt;&lt;span class="nv"&gt;$api_upstream&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;80&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Important Note&lt;/strong&gt;: When using variables with &lt;code&gt;proxy_pass&lt;/code&gt;, you must configure a resolver. The resolver doesn't use search domains from &lt;code&gt;/etc/resolv.conf&lt;/code&gt; like system tools, requiring explicit DNS configuration.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3&gt;
  
  
  Docker Solution: Variables + Resolver
&lt;/h3&gt;

&lt;p&gt;The solution has two parts:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Use variables to defer DNS resolution until request time&lt;/li&gt;
&lt;li&gt;Configure a DNS resolver for variable resolution&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;First, enable nginx's built-in DNS resolver detection in your Dockerfile:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight docker"&gt;&lt;code&gt;&lt;span class="c"&gt;# Enable local DNS resolver (makes DNS IP from resolv.conf available as env var)&lt;/span&gt;
&lt;span class="k"&gt;ENV&lt;/span&gt;&lt;span class="s"&gt; NGINX_ENTRYPOINT_LOCAL_RESOLVERS=1&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then configure Nginx using the automatically detected resolver:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight nginx"&gt;&lt;code&gt;&lt;span class="c1"&gt;# Use nginx's automatically detected DNS resolver&lt;/span&gt;
&lt;span class="k"&gt;resolver&lt;/span&gt; $&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="kn"&gt;NGINX_LOCAL_RESOLVERS&lt;/span&gt;&lt;span class="err"&gt;}&lt;/span&gt; &lt;span class="s"&gt;valid=10s&lt;/span&gt; &lt;span class="s"&gt;ipv6=off&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kn"&gt;server&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kn"&gt;listen&lt;/span&gt; &lt;span class="mi"&gt;80&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="kn"&gt;location&lt;/span&gt; &lt;span class="n"&gt;/&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="c1"&gt;# Variables defer DNS resolution until request time&lt;/span&gt;
        &lt;span class="kn"&gt;set&lt;/span&gt; &lt;span class="nv"&gt;$api_upstream&lt;/span&gt; &lt;span class="s"&gt;"my-rg-&lt;/span&gt;$&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="kn"&gt;ENVIRONMENT&lt;/span&gt;&lt;span class="err"&gt;}&lt;/span&gt;&lt;span class="s"&gt;-api"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="kn"&gt;proxy_pass&lt;/span&gt; &lt;span class="s"&gt;http://&lt;/span&gt;&lt;span class="nv"&gt;$api_upstream&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;80&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The key points:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Variables with &lt;code&gt;proxy_pass&lt;/code&gt; defer DNS resolution from startup to request time&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;NGINX_ENTRYPOINT_LOCAL_RESOLVERS=1&lt;/code&gt; automatically extracts DNS resolver from &lt;code&gt;/etc/resolv.conf&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;${NGINX_LOCAL_RESOLVERS}&lt;/code&gt; uses the automatically detected resolver IP&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;valid=10s&lt;/code&gt; ensures DNS entries expire quickly (helpful if services restart)&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;envsubst&lt;/code&gt; can substitute environment variables in templates for different environments&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Kubernetes Extension
&lt;/h2&gt;

&lt;p&gt;The Docker solution works until you deploy to Kubernetes. There you'll see:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;unexpected DNS response for my-rg-local-api 
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Kubernetes introduces an additional problem - the resolvers configured in Nginx don't automatically use the search domains from the host's &lt;a href="///etc/resolv.conf"&gt;&lt;code&gt;/etc/resolv.conf&lt;/code&gt;&lt;/a&gt; file.&lt;/p&gt;

&lt;h3&gt;
  
  
  Azure Container Apps Challenges
&lt;/h3&gt;

&lt;p&gt;Moving to Azure Container Apps introduces yet another layer of DNS challenges:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;"Error 404 - This Container App is stopped or does not exist."
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The issue with Azure Container Apps is that the DNS configuration doesn't provide working hostnames by default. While container apps are accessible through DNS, the format is unique and requires special handling:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Container Apps have a specific internal domain naming pattern&lt;/li&gt;
&lt;li&gt;You must use the &lt;code&gt;.internal.&lt;/code&gt; prefix with the container app environment DNS suffix&lt;/li&gt;
&lt;li&gt;Without this exact format, services won't be able to communicate with each other&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;This is why our solution explicitly uses &lt;code&gt;.internal.${CONTAINER_APP_ENV_DNS_SUFFIX}&lt;/code&gt; for ACA environments.&lt;/p&gt;

&lt;p&gt;The internal DNS within the Azure Container Apps environment does not show the &lt;code&gt;internal&lt;/code&gt; part of the FQDN when using &lt;a href="https://dev.tonslookup"&gt;&lt;code&gt;nslookup&lt;/code&gt;&lt;/a&gt;. And notably, using say &lt;a href="https://dev.tocurl"&gt;&lt;code&gt;curl&lt;/code&gt;&lt;/a&gt; with the service name alone works fine - suggesting there is something going on behind the scenes.&lt;/p&gt;

&lt;h2&gt;
  
  
  Universal Environment-Aware Solution
&lt;/h2&gt;

&lt;p&gt;A solution that works across all three environments:&lt;/p&gt;

&lt;h3&gt;
  
  
  1. Domain Suffix Detection Script
&lt;/h3&gt;

&lt;p&gt;Create a startup script that detects the environment type:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;#!/bin/sh&lt;/span&gt;
&lt;span class="c"&gt;# /docker-entrypoint.d/17-detect-k8s-and-aca.sh&lt;/span&gt;

&lt;span class="nv"&gt;RESOLV_CONF&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"/etc/resolv.conf"&lt;/span&gt;
&lt;span class="nb"&gt;export &lt;/span&gt;&lt;span class="nv"&gt;DOMAIN_SUFFIX&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;""&lt;/span&gt;

&lt;span class="c"&gt;# Check if we're in a Kubernetes environment and set up environment variables&lt;/span&gt;
&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;[&lt;/span&gt; &lt;span class="nt"&gt;-f&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$RESOLV_CONF&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="o"&gt;]&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nb"&gt;grep&lt;/span&gt; &lt;span class="nt"&gt;-q&lt;/span&gt; &lt;span class="s2"&gt;"cluster.local"&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$RESOLV_CONF&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;then&lt;/span&gt;
    &lt;span class="c"&gt;# Extract the first search domain that includes cluster.local&lt;/span&gt;
    &lt;span class="nv"&gt;K8S_SEARCH_DOMAIN&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;&lt;span class="nb"&gt;grep&lt;/span&gt; &lt;span class="s2"&gt;"^search"&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$RESOLV_CONF&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; | &lt;span class="nb"&gt;head&lt;/span&gt; &lt;span class="nt"&gt;-n1&lt;/span&gt; | &lt;span class="nb"&gt;awk&lt;/span&gt; &lt;span class="s1"&gt;'{print $2}'&lt;/span&gt;&lt;span class="si"&gt;)&lt;/span&gt;
    &lt;span class="nb"&gt;export &lt;/span&gt;&lt;span class="nv"&gt;DOMAIN_SUFFIX&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;".&lt;/span&gt;&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;K8S_SEARCH_DOMAIN&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
&lt;span class="k"&gt;fi&lt;/span&gt;

&lt;span class="c"&gt;# Override domain suffix if running in Azure Container Apps&lt;/span&gt;
&lt;span class="c"&gt;# Set HTTP protocol based on Azure Container Apps (ACA manages internal TLS)&lt;/span&gt;
&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;[&lt;/span&gt; &lt;span class="nt"&gt;-n&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$CONTAINER_APP_ENV_DNS_SUFFIX&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="o"&gt;]&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;then
    &lt;/span&gt;&lt;span class="nb"&gt;export &lt;/span&gt;&lt;span class="nv"&gt;DOMAIN_SUFFIX&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;".internal.&lt;/span&gt;&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;CONTAINER_APP_ENV_DNS_SUFFIX&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
    &lt;span class="nb"&gt;export &lt;/span&gt;&lt;span class="nv"&gt;UPSTREAM_PROTOCOL&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"https"&lt;/span&gt;
&lt;span class="k"&gt;else
    &lt;/span&gt;&lt;span class="nb"&gt;export &lt;/span&gt;&lt;span class="nv"&gt;UPSTREAM_PROTOCOL&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"http"&lt;/span&gt;
&lt;span class="k"&gt;fi&lt;/span&gt;

&lt;span class="c"&gt;# Monkey patch our dynamically determined env vars into our default template&lt;/span&gt;
envsubst &lt;span class="s1"&gt;'$DOMAIN_SUFFIX $UPSTREAM_PROTOCOL'&lt;/span&gt; &amp;lt; /etc/nginx/templates/default.conf.template &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; /tmp/default.conf.template.tmp
&lt;span class="nb"&gt;mv&lt;/span&gt; /tmp/default.conf.template.tmp /etc/nginx/templates/default.conf.template
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The &lt;a href="https://dev.toenvsubst"&gt;&lt;code&gt;envsubst&lt;/code&gt;&lt;/a&gt; command substitutes environment variables in the template file, allowing our configuration to adapt to different environments without code changes.&lt;/p&gt;

&lt;h3&gt;
  
  
  2. Nginx Config Template
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight nginx"&gt;&lt;code&gt;&lt;span class="c1"&gt;# Dynamic resolver from container environment (nginx automatically sets NGINX_LOCAL_RESOLVERS)&lt;/span&gt;
&lt;span class="k"&gt;resolver&lt;/span&gt; $&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="kn"&gt;NGINX_LOCAL_RESOLVERS&lt;/span&gt;&lt;span class="err"&gt;}&lt;/span&gt; &lt;span class="s"&gt;valid=10s&lt;/span&gt; &lt;span class="s"&gt;ipv6=off&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kn"&gt;server&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kn"&gt;listen&lt;/span&gt; &lt;span class="mi"&gt;80&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="kn"&gt;server_name&lt;/span&gt; &lt;span class="s"&gt;_&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="c1"&gt;# Common proxy headers (required by Azure Container Apps)&lt;/span&gt;
    &lt;span class="kn"&gt;proxy_ssl_server_name&lt;/span&gt; &lt;span class="no"&gt;on&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="kn"&gt;proxy_http_version&lt;/span&gt; &lt;span class="mf"&gt;1.1&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="kn"&gt;location&lt;/span&gt; &lt;span class="n"&gt;/&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="kn"&gt;set&lt;/span&gt; &lt;span class="nv"&gt;$frontend_upstream&lt;/span&gt; &lt;span class="s"&gt;"my-rg-&lt;/span&gt;$&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="kn"&gt;ENVIRONMENT&lt;/span&gt;&lt;span class="err"&gt;}&lt;/span&gt;&lt;span class="s"&gt;-frontend&lt;/span&gt;$&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="kn"&gt;DOMAIN_SUFFIX&lt;/span&gt;&lt;span class="err"&gt;}&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="kn"&gt;proxy_pass&lt;/span&gt; $&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="kn"&gt;UPSTREAM_PROTOCOL&lt;/span&gt;&lt;span class="err"&gt;}&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="n"&gt;//&lt;/span&gt;&lt;span class="nv"&gt;$frontend_upstream&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="kn"&gt;location&lt;/span&gt; &lt;span class="n"&gt;/api&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="kn"&gt;set&lt;/span&gt; &lt;span class="nv"&gt;$api_upstream&lt;/span&gt; &lt;span class="s"&gt;"my-rg-&lt;/span&gt;$&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="kn"&gt;ENVIRONMENT&lt;/span&gt;&lt;span class="err"&gt;}&lt;/span&gt;&lt;span class="s"&gt;-api&lt;/span&gt;$&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="kn"&gt;DOMAIN_SUFFIX&lt;/span&gt;&lt;span class="err"&gt;}&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="kn"&gt;proxy_pass&lt;/span&gt; $&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="kn"&gt;UPSTREAM_PROTOCOL&lt;/span&gt;&lt;span class="err"&gt;}&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="n"&gt;//&lt;/span&gt;&lt;span class="nv"&gt;$api_upstream&lt;/span&gt;&lt;span class="n"&gt;/&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  3. Dockerfile Configuration
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight docker"&gt;&lt;code&gt;&lt;span class="k"&gt;FROM&lt;/span&gt;&lt;span class="s"&gt; nginx:alpine&lt;/span&gt;

&lt;span class="k"&gt;COPY&lt;/span&gt;&lt;span class="s"&gt; ./templates/default.conf.template /etc/nginx/templates/&lt;/span&gt;
&lt;span class="k"&gt;COPY&lt;/span&gt;&lt;span class="s"&gt; ./docker-entrypoint.d/17-detect-k8s-and-aca.sh /docker-entrypoint.d/&lt;/span&gt;

&lt;span class="c"&gt;# Enable local DNS resolver (makes DNS IP from resolv.conf available as env var)&lt;/span&gt;
&lt;span class="k"&gt;ENV&lt;/span&gt;&lt;span class="s"&gt; NGINX_ENTRYPOINT_LOCAL_RESOLVERS=1&lt;/span&gt;

&lt;span class="c"&gt;# Document our intended local port&lt;/span&gt;
&lt;span class="k"&gt;EXPOSE&lt;/span&gt;&lt;span class="s"&gt; 80&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  What it looks like (Tilt/Kind)
&lt;/h3&gt;

&lt;p&gt;Browser showing successful responses from both frontend (/) and API (/api) endpoints through the nginx proxy.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fwww.alexdarbyshire.com%2Fnginx-dynamic-hostnames-docker-k8s-aca%2Fworking-solution-demo.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fwww.alexdarbyshire.com%2Fnginx-dynamic-hostnames-docker-k8s-aca%2Fworking-solution-demo.png" title="Browser showing successful responses from both frontend (/) and API (/api) endpoints through the nginx proxy" alt="Working solution demonstration" width="800" height="500"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Environment-Specific Notes
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Docker
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Nginx's built-in &lt;code&gt;NGINX_ENTRYPOINT_LOCAL_RESOLVERS=1&lt;/code&gt; automatically extracts DNS resolver from &lt;a href="///etc/resolv.conf"&gt;&lt;code&gt;/etc/resolv.conf&lt;/code&gt;&lt;/a&gt; for compatibility&lt;/li&gt;
&lt;li&gt;Variables with &lt;code&gt;proxy_pass&lt;/code&gt; allow nginx to start before upstream services are available&lt;/li&gt;
&lt;li&gt;This approach works well when dealing with multiple services that need to be proxied&lt;/li&gt;
&lt;li&gt;Example &lt;a href="//docker-compose.yml"&gt;&lt;code&gt;docker-compose.yml&lt;/code&gt;&lt;/a&gt; setup:
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;  &lt;span class="na"&gt;services&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;nginx&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;build&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;.&lt;/span&gt;
      &lt;span class="na"&gt;ports&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
        &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;80:80"&lt;/span&gt;
      &lt;span class="na"&gt;environment&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
        &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;ENVIRONMENT=local&lt;/span&gt;

    &lt;span class="na"&gt;api-service&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;image&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;strm/helloworld-http&lt;/span&gt;
      &lt;span class="na"&gt;container_name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;my-rg-local-api&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Kubernetes
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Script detects K8s by looking for &lt;code&gt;cluster.local&lt;/code&gt; in &lt;a href="///etc/resolv.conf"&gt;&lt;code&gt;/etc/resolv.conf&lt;/code&gt;&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Automatically appends the correct namespace and domain suffix, allowing the same configuration to work across different namespaces without modification&lt;/li&gt;
&lt;li&gt;Set variables through Pod spec:
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;  &lt;span class="na"&gt;env&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;ENVIRONMENT&lt;/span&gt;
      &lt;span class="na"&gt;value&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;local"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Azure Container Apps
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Uses special format: &lt;code&gt;.internal.${CONTAINER_APP_ENV_DNS_SUFFIX}&lt;/code&gt; which is required to fix DNS hostname resolution&lt;/li&gt;
&lt;li&gt;The &lt;code&gt;.internal.&lt;/code&gt; prefix is essential - without it, service-to-service communication fails&lt;/li&gt;
&lt;li&gt;Automatically detects Azure environment and sets protocol to HTTPS (other environments use HTTP)&lt;/li&gt;
&lt;li&gt;Requires &lt;code&gt;proxy_ssl_server_name on&lt;/code&gt; and &lt;code&gt;proxy_http_version 1.1&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Set env vars in Azure portal or with Infrastructure as Code&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Alternative Proxies
&lt;/h2&gt;

&lt;p&gt;Traefik, Envoy, or Caddy likely solve one of these Out Of The Box.&lt;/p&gt;

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

&lt;ol&gt;
&lt;li&gt;
&lt;a href="https://sandro-keil.de/blog/let-nginx-start-if-upstream-host-is-unavailable-or-down/" rel="noopener noreferrer"&gt;Let Nginx start if upstream host is unavailable&lt;/a&gt; - Sandro Keil&lt;/li&gt;
&lt;li&gt;&lt;a href="https://learn.microsoft.com/en-ie/answers/questions/1661371/issue-with-accessing-azure-container-app-behind-in" rel="noopener noreferrer"&gt;Azure Container App access issues&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://learn.microsoft.com/en-us/answers/questions/1185634/use-reverse-proxy-in-azure-container-apps-environm" rel="noopener noreferrer"&gt;Reverse proxy in Azure Container Apps&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://medium.com/@bartenev/nginx-as-a-reverse-proxy-in-azure-container-app-environment-9a99ff88cfa8" rel="noopener noreferrer"&gt;Nginx as reverse proxy in Azure Container Apps&lt;/a&gt;&lt;/li&gt;
&lt;/ol&gt;

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

&lt;p&gt;This addresses Nginx's dynamic hostname resolution challenges across platforms:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;For Docker users - properly resolves dynamic hostnames using the container's DNS resolver&lt;/li&gt;
&lt;li&gt;For Kubernetes users - automatically handles search domains and service discovery without manual configuration&lt;/li&gt;
&lt;li&gt;For Azure Container Apps - adapts to the special internal domain format required by the platform&lt;/li&gt;
&lt;/ol&gt;

</description>
      <category>docker</category>
      <category>kubernetes</category>
      <category>azure</category>
      <category>devops</category>
    </item>
  </channel>
</rss>
