Introduction
When you update proxy settings in your Ansible Tower/AWX environment or modify mirror URLs in your infrastructure, playbooks may continue downloading artifacts from the old mirror location. This occurs because Ansible's get_url and uri modules inherit environment variables from the controller process, and those variables persist across playbook runs unless explicitly refreshed. Additionally, package managers like pip and npm maintain their own cached configurations that override environment-level proxy settings.
This issue manifests when you've updated /etc/environment, modified your ansible.cfg proxy settings, or changed mirror URLs in your organization's infrastructure, but get_url tasks still hit the old endpoints. The problem is particularly common in containerized Tower deployments where environment variables are set at container startup and persist until the container is recreated.
Symptoms
Your playbook fails with connection timeout or certificate errors when trying to reach the old mirror:
TASK [Download application artifact] *******************************************
fatal: [app-server-01]: FAILED! => {"changed": false, "msg": "Request failed", "status_code": -1, "url": "https://old-mirror.internal:8080/artifacts/app-v2.3.1.tar.gz", "elapsed": 30}Or you see SSL certificate validation failures because the old mirror URL is hardcoded somewhere:
TASK [Fetch package from mirror] ***********************************************
fatal: [web-server-02]: FAILED! => {"changed": false, "msg": "Failed to validate the SSL certificate for old-mirror.company.local:443. The certificate issuer is unknown. make sure your managed hosts trust the certificate authority."}When checking the actual URL being accessed, you find it differs from what you configured:
```bash $ ansible app-server-01 -m debug -a "msg={{ ansible_env.http_proxy }}" app-server-01 | SUCCESS => { "msg": "http://old-proxy.internal:3128" }
$ grep -r "proxy" /etc/ansible/ansible.cfg proxy_env = {"http_proxy": "http://new-proxy.internal:8080", "https_proxy": "http://new-proxy.internal:8080"} ```
Tower/AWX job output shows the old URL despite your changes:
TASK [Download from artifact repository] ***************************************
<app-server-01> ESTABLISH SSH CONNECTION FOR USER: ansible
<app-server-01> EXEC: curl -s -o /tmp/artifact.tar.gz https://old-mirror.internal:8443/releases/app.tar.gzCommon Causes
1. Persistent Environment Variables in Tower Workers
Ansible Tower worker processes inherit environment variables at startup. When you update proxy settings in Tower's settings or system configuration, existing worker processes don't automatically reload. The workers retain the old http_proxy, https_proxy, and no_proxy values until the process is restarted or the container is recreated.
# Check what environment the Tower worker sees
$ docker exec tower_task cat /etc/environment
http_proxy=http://old-proxy.internal:3128
https_proxy=http://old-proxy.internal:31282. pip and npm Cached Mirror URLs
Package managers maintain their own configuration that can override environment variables:
```bash # pip stores mirror URLs in per-user and global configs $ cat ~/.config/pip/pip.conf [global] index-url = https://old-pypi-mirror.company.local/simple
# npm has its own registry configuration $ npm config get registry https://old-npm-mirror.company.local/ ```
3. Ansible Fact Caching Old Proxy Values
When fact caching is enabled, Ansible may cache host-specific environment variables including proxy settings:
$ cat /tmp/ansible_facts/app-server-01
{"ansible_env": {"http_proxy": "http://old-proxy.internal:3128"}}4. URL-Hardcoded in Group Variables
The mirror URL might be defined in multiple places with different precedence:
```yaml # group_vars/all.yml (old value) artifact_mirror: "https://old-mirror.internal:8443"
# group_vars/production.yml (new value - but all.yml takes precedence due to load order) artifact_mirror: "https://new-mirror.company.com/artifacts" ```
Step-by-Step Fix
Step 1: Identify Where the Old Mirror URL Is Configured
Search across all configuration locations:
```bash # Search Ansible configurations grep -r "old-mirror" /etc/ansible/ /etc/tower/ /var/lib/awx/ 2>/dev/null
# Check group_vars and host_vars grep -r "old-mirror|proxy" inventory/group_vars/ inventory/host_vars/
# Check environment variables in Tower docker exec tower_task env | grep -i proxy
# Check pip configuration pip config list cat ~/.pip/pip.conf 2>/dev/null cat /etc/pip.conf 2>/dev/null
# Check npm configuration npm config list ```
Step 2: Clear Cached Environment Variables
For Ansible Tower/AWX, restart the task container to pick up new environment variables:
```bash # Restart Tower task containers (Tower installed via Docker) docker restart tower_task
# For AWX deployed on Kubernetes kubectl rollout restart deployment/awx-task -n awx
# For standalone Ansible controller sudo systemctl restart ansible-runner ```
Clear Ansible fact cache:
```bash # Clear JSON file cache rm -rf /tmp/ansible_facts/*
# Or use the meta task in a playbook ansible all -m meta -a "clear_facts=true" ```
Step 3: Update Package Manager Configurations
Update pip to use the new mirror:
```bash # Update pip configuration globally pip config set global.index-url https://new-pypi.company.com/simple pip config set global.trusted-host new-pypi.company.com
# Or update the config file directly cat > ~/.pip/pip.conf << 'EOF' [global] index-url = https://new-pypi.company.com/simple trusted-host = new-pypi.company.com timeout = 120 EOF ```
Update npm registry:
```bash # Set new npm registry npm config set registry https://new-npm.company.com/
# Verify the change npm config get registry ```
Step 4: Update Playbook to Use Dynamic Mirror URLs
Modify your playbooks to use explicitly set environment variables rather than inherited ones:
```yaml # playbook.yml - Explicit environment configuration - name: Download artifacts with updated proxy hosts: application_servers vars: # Define these in group_vars or pass via --extra-vars artifact_mirror: "https://new-mirror.company.com/artifacts" proxy_server: "http://new-proxy.internal:8080"
environment: http_proxy: "{{ proxy_server }}" https_proxy: "{{ proxy_server }}" no_proxy: "localhost,127.0.0.1,.internal"
tasks: - name: Download application artifact get_url: url: "{{ artifact_mirror }}/app-{{ app_version }}.tar.gz" dest: "/opt/app/artifact.tar.gz" timeout: 120 validate_certs: yes register: download_result
- name: Verify artifact downloaded
- stat:
- path: "/opt/app/artifact.tar.gz"
- register: artifact_stat
- name: Assert artifact exists
- assert:
- that:
- - artifact_stat.stat.exists
- - artifact_stat.stat.size > 0
- fail_msg: "Artifact download failed or file is empty"
`
Step 5: Force Environment Refresh in Tower Job Templates
In Ansible Tower/AWX, configure job templates to explicitly set environment variables:
# extra_vars passed to job template
---
proxy_env:
http_proxy: "http://new-proxy.internal:8080"
https_proxy: "http://new-proxy.internal:8080"
artifact_base_url: "https://new-mirror.company.com/artifacts"Or configure at the Organization level in Tower settings under "Environment Variables".
Verification
Run diagnostic commands to confirm the new mirror is being used:
```bash # Test direct connectivity to new mirror curl -I -x http://new-proxy.internal:8080 https://new-mirror.company.com/artifacts/
# Run playbook with verbose output to see actual URLs ansible-playbook deploy.yml -v --tags "download" 2>&1 | grep -i "url|mirror"
# Verify pip uses new index pip config list | grep index-url # Expected: index-url='https://new-pypi.company.com/simple'
# Check Tower job output for correct URLs # Navigate to Tower -> Jobs -> [Job ID] -> Details # Verify the URL in the task output matches the new mirror ```
Run a test playbook that outputs the effective environment:
```yaml # test-env.yml - name: Test environment configuration hosts: localhost tasks: - name: Display current proxy settings debug: msg: - "http_proxy: {{ ansible_env.http_proxy | default('not set') }}" - "https_proxy: {{ ansible_env.https_proxy | default('not set') }}" - "Artifact URL: {{ artifact_mirror }}"
- name: Test connectivity to new mirror
- uri:
- url: "{{ artifact_mirror }}/health"
- method: GET
- status_code: 200
- register: health_check
- name: Confirm mirror is reachable
- debug:
- msg: "Mirror health check passed - {{ health_check.status }}"
`
Related Issues
- [ansible-cache-serves-old-data-after-deployment](/articles/ansible-cache-serves-old-data-after-deployment) - Fact caching causes stale configuration
- [ansible-environment-variable-prefix-change-leaves-workers-on-legacy-settings](/articles/ansible-environment-variable-prefix-change-leaves-workers-on-legacy-settings) - Environment variable persistence in workers
- [ansible-private-artifact-download-denied-after-token-scope-change](/articles/ansible-private-artifact-download-denied-after-token-scope-change) - Authentication issues with artifact downloads
Related Articles
- [WordPress troubleshooting: Ansible Audit Trail Misses Events Under ](ansible-audit-trail-misses-events-under-burst-load)
- [WordPress troubleshooting: Ansible Background Worker Gets Stuck in ](ansible-background-worker-stuck-in-a-retry-loop)
- [WordPress troubleshooting: Ansible Backup Completes but Restore Fai](ansible-backup-completes-but-restore-fails-checksum-validation)
- [WordPress troubleshooting: Ansible Batch Importer Duplicates Rows A](ansible-batch-importer-duplicates-rows-after-a-retry)
- [WordPress troubleshooting: Ansible Batch Writer Commits Partial Res](ansible-batch-writer-commits-partial-results-before-final-validation)
<script type="application/ld+json"> { "@context": "https://schema.org", "@type": "TechArticle", "headline": "WordPress troubleshooting: Ansible Artifact Download Uses an Old Mi", "description": "Learn how to fix Ansible Artifact Download Uses an Old Mirror After a Proxy Change. Professional WordPress troubleshooting solutions with step-by-step guidance. WP error fix, WordPress optimization, WP security, WordPress performance.", "url": "https://www.fixwikihub.com/ansible-artifact-download-uses-an-old-mirror-after-proxy-change", "publisher": { "@type": "Organization", "name": "FixWikiHub", "url": "https://www.fixwikihub.com" }, "author": { "@type": "Person", "name": "FixWikiHub Editorial Team" }, "datePublished": "2026-02-12T09:34:08.496Z", "dateModified": "2026-02-12T09:34:08.496Z" } </script>