diff --git a/docs/proxy.md b/docs/proxy.md
index ec473324f26202fecdb47631da649b4446041ddf..867b90f4d0f64ac35d6aaf0c7ddff840b8de30bb 100644
--- a/docs/proxy.md
+++ b/docs/proxy.md
@@ -1,6 +1,6 @@
 # Setting up Environment Proxy
 
-If you set http and https proxy, all nodes and loadbalancer will be excluded from proxy with generating no_proxy variable in `roles/kubespray-defaults/defaults/main.yml`, if you have additional resources for exclude add them to `additional_no_proxy` variable. If you want fully override your `no_proxy` setting, then fill in just `no_proxy` and no nodes or loadbalancer addresses will be added to no_proxy.
+If you set http and https proxy, all nodes and loadbalancer will be excluded from proxy with generating no_proxy variable in `roles/kubespray-defaults/tasks/no_proxy.yml`, if you have additional resources for exclude add them to `additional_no_proxy` variable. If you want fully override your `no_proxy` setting, then fill in just `no_proxy` and no nodes or loadbalancer addresses will be added to no_proxy.
 
 ## Set proxy for http and https
 
diff --git a/roles/kubespray-defaults/defaults/main.yaml b/roles/kubespray-defaults/defaults/main.yaml
index 5b8b2f0f7f1535eb61e55576357805f9701a2395..266dc51595e712ba6ab2f84b87c3a90bc3bf78b7 100644
--- a/roles/kubespray-defaults/defaults/main.yaml
+++ b/roles/kubespray-defaults/defaults/main.yaml
@@ -405,38 +405,6 @@ contiv_peer_with_uplink_leaf: false
 contiv_global_as: "65002"
 contiv_global_neighbor_as: "500"
 
-# Set 127.0.0.1 as fallback IP if we do not have host facts for host
-# ansible_default_ipv4 isn't what you think.
-# Thanks https://medium.com/opsops/ansible-default-ipv4-is-not-what-you-think-edb8ab154b10
-fallback_ips_base: |
-  ---
-  {% for item in groups['k8s-cluster'] + groups['etcd'] + groups['calico-rr']|default([])|unique %}
-  {% set found = hostvars[item].get('ansible_default_ipv4') %}
-  {{ item }}: "{{ found.get('address', '127.0.0.1') }}"
-  {% endfor %}
-fallback_ips: "{{ fallback_ips_base | from_yaml }}"
-
-## Set no_proxy to all assigned cluster IPs and hostnames
-no_proxy: >-
-  {%- if http_proxy is defined or https_proxy is defined %}
-  {%- if loadbalancer_apiserver is defined -%}
-  {{ apiserver_loadbalancer_domain_name| default('') }},
-  {{ loadbalancer_apiserver.address | default('') }},
-  {%- endif -%}
-  {%- for item in (groups['k8s-cluster'] + groups['etcd'] + groups['calico-rr']|default([]))|unique -%}
-  {{ hostvars[item]['access_ip'] | default(hostvars[item]['ip'] | default(fallback_ips[item])) }},
-  {%-   if item != hostvars[item].get('ansible_hostname', '') -%}
-  {{ hostvars[item]['ansible_hostname'] }},
-  {{ hostvars[item]['ansible_hostname'] }}.{{ dns_domain }},
-  {%-   endif -%}
-  {{ item }},{{ item }}.{{ dns_domain }},
-  {%- endfor -%}
-  {%- if additional_no_proxy is defined -%}
-  {{ additional_no_proxy }},
-  {%- endif -%}
-  127.0.0.1,localhost,{{kube_service_addresses}},{{kube_pods_subnet}}
-  {%- endif %}
-
 ssl_ca_dirs: >-
   [
   {% if ansible_os_family in ['CoreOS', 'Container Linux by CoreOS', 'Flatcar', 'Flatcar Container Linux by Kinvolk'] -%}
diff --git a/roles/kubespray-defaults/tasks/fallback_ips.yml b/roles/kubespray-defaults/tasks/fallback_ips.yml
new file mode 100644
index 0000000000000000000000000000000000000000..546ac1e2be76f9bba89fb470c78ba71e3671233e
--- /dev/null
+++ b/roles/kubespray-defaults/tasks/fallback_ips.yml
@@ -0,0 +1,29 @@
+---
+# Set 127.0.0.1 as fallback IP if we do not have host facts for host
+# ansible_default_ipv4 isn't what you think.
+# Thanks https://medium.com/opsops/ansible-default-ipv4-is-not-what-you-think-edb8ab154b10
+
+- name: Gather ansible_default_ipv4 from all hosts
+  include_tasks: fallback_ips_gather.yml
+  when: hostvars[delegate_host_to_gather_facts].ansible_default_ipv4 is not defined
+  loop: "{{ groups['all'] }}"
+  loop_control:
+    loop_var: delegate_host_to_gather_facts
+  run_once: yes
+
+- name: create fallback_ips_base
+  set_fact:
+    fallback_ips_base: |
+      ---
+      {% for item in (groups['k8s-cluster']|default([]) + groups['etcd']|default([]) + groups['calico-rr']|default([]))|unique %}
+      {% set found = hostvars[item].get('ansible_default_ipv4') %}
+      {{ item }}: "{{ found.get('address', '127.0.0.1') }}"
+      {% endfor %}
+  delegate_to: localhost
+  delegate_facts: yes
+  become: no
+  run_once: yes
+
+- name: set fallback_ips
+  set_fact:
+    fallback_ips: "{{ hostvars.localhost.fallback_ips_base | from_yaml }}"
diff --git a/roles/kubespray-defaults/tasks/fallback_ips_gather.yml b/roles/kubespray-defaults/tasks/fallback_ips_gather.yml
new file mode 100644
index 0000000000000000000000000000000000000000..c5f5b74276f453d1dd0677a26e1e527886b9208a
--- /dev/null
+++ b/roles/kubespray-defaults/tasks/fallback_ips_gather.yml
@@ -0,0 +1,10 @@
+---
+# include to workaround mitogen issue
+# https://github.com/dw/mitogen/issues/663
+
+- name: "Gather ansible_default_ipv4 from {{ delegate_host_to_gather_facts }}"
+  setup:
+    gather_subset: '!all,network'
+    filter: "ansible_default_ipv4"
+  delegate_to: "{{ delegate_host_to_gather_facts }}"
+  delegate_facts: yes
diff --git a/roles/kubespray-defaults/tasks/main.yaml b/roles/kubespray-defaults/tasks/main.yaml
index 11b9e36536eccedf020ed236fbfebc7402d5f20e..b27cafc150290bc2779d960e2a61d38e4e7ecc41 100644
--- a/roles/kubespray-defaults/tasks/main.yaml
+++ b/roles/kubespray-defaults/tasks/main.yaml
@@ -4,3 +4,21 @@
     msg: "Check roles/kubespray-defaults/defaults/main.yml"
   tags:
     - always
+
+# do not run gather facts when bootstrap-os in roles
+- name: set fallback_ips
+  include_tasks: fallback_ips.yml
+  when:
+    - "'bootstrap-os' not in ansible_play_role_names"
+    - fallback_ips is not defined
+  tags:
+    - always
+
+- name: set no_proxy
+  include_tasks: no_proxy.yml
+  when:
+    - "'bootstrap-os' not in ansible_play_role_names"
+    - http_proxy is defined or https_proxy is defined
+    - no_proxy is not defined
+  tags:
+    - always
diff --git a/roles/kubespray-defaults/tasks/no_proxy.yml b/roles/kubespray-defaults/tasks/no_proxy.yml
new file mode 100644
index 0000000000000000000000000000000000000000..efff7d3989ad9ac3a19009dbd403576ced93f2de
--- /dev/null
+++ b/roles/kubespray-defaults/tasks/no_proxy.yml
@@ -0,0 +1,28 @@
+---
+- name: Set no_proxy to all assigned cluster IPs and hostnames
+  set_fact:
+    no_proxy_prepare: >-
+      {%- if loadbalancer_apiserver is defined -%}
+      {{ apiserver_loadbalancer_domain_name| default('') }},
+      {{ loadbalancer_apiserver.address | default('') }},
+      {%- endif -%}
+      {%- for item in (groups['k8s-cluster'] + groups['etcd'] + groups['calico-rr']|default([]))|unique -%}
+      {{ hostvars[item]['access_ip'] | default(hostvars[item]['ip'] | default(fallback_ips[item])) }},
+      {%-   if item != hostvars[item].get('ansible_hostname', '') -%}
+      {{ hostvars[item]['ansible_hostname'] }},
+      {{ hostvars[item]['ansible_hostname'] }}.{{ dns_domain }},
+      {%-   endif -%}
+      {{ item }},{{ item }}.{{ dns_domain }},
+      {%- endfor -%}
+      {%- if additional_no_proxy is defined -%}
+      {{ additional_no_proxy }},
+      {%- endif -%}
+      127.0.0.1,localhost,{{ kube_service_addresses }},{{ kube_pods_subnet }}
+  delegate_to: localhost
+  delegate_facts: yes
+  become: no
+  run_once: yes
+
+- name: Populates no_proxy to all hosts
+  set_fact:
+    no_proxy: "{{ hostvars.localhost.no_proxy_prepare }}"