diff --git a/changelogs/unreleased/alternative-env-override.yml b/changelogs/unreleased/alternative-env-override.yml
new file mode 100644
index 0000000000000000000000000000000000000000..ebc9148f8ebe8c6b27b0b0537028f24b9b9ab545_Y2hhbmdlbG9ncy91bnJlbGVhc2VkL2FsdGVybmF0aXZlLWVudi1vdmVycmlkZS55bWw=
--- /dev/null
+++ b/changelogs/unreleased/alternative-env-override.yml
@@ -0,0 +1,5 @@
+---
+title: Allow gitlab build remote overrides from the environment
+merge_request: 5067
+author:
+type: added
diff --git a/doc/build/team_member_docs.md b/doc/build/team_member_docs.md
index b17d00cfb841cb5388e1dc6e4a0d6c67b4ff7b39_ZG9jL2J1aWxkL3RlYW1fbWVtYmVyX2RvY3MubWQ=..ebc9148f8ebe8c6b27b0b0537028f24b9b9ab545_ZG9jL2J1aWxkL3RlYW1fbWVtYmVyX2RvY3MubWQ= 100644
--- a/doc/build/team_member_docs.md
+++ b/doc/build/team_member_docs.md
@@ -50,6 +50,24 @@
 while other environment variables, if not specified, will be populated from
 their corresponding files and passed on to the triggered pipeline.
 
+## I want to use a specific mirror or fork of various GitLab components in my build
+
+The repository sources for most software that Omnibus Builds can be found in
+the `.custom_sources.yml` file in the `omnibus-gitlab` repository. The main
+GitLab components can be overridden via environment variables. Check the table
+below for details:
+
+| Environment Variable                          | Description |
+| --------------------------------------------- | ----------- |
+| ALTERNATIVE_PRIVATE_TOKEN                     | An access token used if needing to pull from private repositories. |
+| GITLAB_ALTERNATIVE_REPO                       | Git repository location for the GitLab Rails application. |
+| GITLAB_SHELL_ALTERNATIVE_REPO                 | Git repository location for [GitLab Shell](https://gitlab.com/gitlab-org/gitlab-shell). |
+| GITLAB_WORKHORSE_ALTERNATIVE_REPO             | Git repository location for [GitLab Workhorse](https://gitlab.com/gitlab-org/gitlab-workhorse). |
+| GITLAB_PAGES_ALTERNATIVE_REPO                 | Git repository location for [GitLab Pages](https://gitlab.com/gitlab-org/gitlab-pages). |
+| GITALY_SERVER_ALTERNATIVE_REPO                | Git repository location for [Gitaly](https://gitlab.com/gitlab-org/gitaly). |
+| GITLAB_ELASTICSEARCH_INDEXER_ALTERNATIVE_REPO | Git repository location for [GitLab Elasticsearch Indexer](https://gitlab.com/gitlab-org/gitlab-elasticsearch-indexer). |
+| GITLAB_KAS_ALTERNATIVE_REPO                   | Git repository location for [GitLab Kubernetes Agent Server](https://gitlab.com/gitlab-org/cluster-integration/gitlab-agent). |
+
 ## Building packages for other OSs
 
 If you specifically want a package for an OS other than Ubuntu 16.04, or want to
diff --git a/lib/gitlab/version.rb b/lib/gitlab/version.rb
index b17d00cfb841cb5388e1dc6e4a0d6c67b4ff7b39_bGliL2dpdGxhYi92ZXJzaW9uLnJi..ebc9148f8ebe8c6b27b0b0537028f24b9b9ab545_bGliL2dpdGxhYi92ZXJzaW9uLnJi 100644
--- a/lib/gitlab/version.rb
+++ b/lib/gitlab/version.rb
@@ -120,10 +120,35 @@
       end
     end
 
-    def remote
+    def read_remote_from_env
+      remote = case @software
+               when "gitlab-rails", "gitlab-rails-ee"
+                 Gitlab::Util.get_env("GITLAB_ALTERNATIVE_REPO")
+               when "gitlab-shell"
+                 Gitlab::Util.get_env("GITLAB_SHELL_ALTERNATIVE_REPO")
+               when "gitlab-workhorse"
+                 Gitlab::Util.get_env("GITLAB_WORKHORSE_ALTERNATIVE_REPO")
+               when "gitlab-pages"
+                 Gitlab::Util.get_env("GITLAB_PAGES_ALTERNATIVE_REPO")
+               when "gitaly"
+                 Gitlab::Util.get_env("GITALY_SERVER_ALTERNATIVE_REPO")
+               when "gitlab-elasticsearch-indexer"
+                 Gitlab::Util.get_env("GITLAB_ELASTICSEARCH_INDEXER_ALTERNATIVE_REPO")
+               when "gitlab-kas"
+                 Gitlab::Util.get_env("GITLAB_KAS_ALTERNATIVE_REPO")
+               end
+
+      if remote && Gitlab::Util.get_env("ALTERNATIVE_PRIVATE_TOKEN")
+        attach_remote_credential(remote, Gitlab::Util.get_env("ALTERNATIVE_PRIVATE_TOKEN"))
+      else
+        remote
+      end
+    end
+
+    def read_remote_from_file
       filepath = File.expand_path(".custom_sources.yml", @project_root)
       sources = YAML.load_file(filepath)[@software]
 
       return "" unless sources
 
       if ::Gitlab::Version.security_channel?
@@ -124,12 +149,12 @@
       filepath = File.expand_path(".custom_sources.yml", @project_root)
       sources = YAML.load_file(filepath)[@software]
 
       return "" unless sources
 
       if ::Gitlab::Version.security_channel?
-        attach_remote_credential(sources[::Gitlab::Version.sources_channel]) || sources[::Gitlab::Version.fallback_sources_channel]
+        attach_remote_credential(sources[::Gitlab::Version.sources_channel], Gitlab::Util.get_env("CI_JOB_TOKEN")) || sources[::Gitlab::Version.fallback_sources_channel]
       else
         sources[::Gitlab::Version.sources_channel]
       end
     end
 
@@ -131,7 +156,11 @@
       else
         sources[::Gitlab::Version.sources_channel]
       end
     end
 
+    def remote
+      read_remote_from_env || read_remote_from_file || ""
+    end
+
     private
 
@@ -136,7 +165,7 @@
     private
 
-    def attach_remote_credential(url)
+    def attach_remote_credential(url, token)
       return unless url
 
       uri = URI.parse(url)
       uri.user = "gitlab-ci-token"
@@ -139,8 +168,8 @@
       return unless url
 
       uri = URI.parse(url)
       uri.user = "gitlab-ci-token"
-      uri.password = Gitlab::Util.get_env("CI_JOB_TOKEN")
+      uri.password = token
       uri.to_s
     rescue URI::InvalidURIError
       # Git may use scp address which is not valid URI. Ignore it
diff --git a/spec/gitlab/build/info_spec.rb b/spec/gitlab/build/info_spec.rb
index b17d00cfb841cb5388e1dc6e4a0d6c67b4ff7b39_c3BlYy9naXRsYWIvYnVpbGQvaW5mb19zcGVjLnJi..ebc9148f8ebe8c6b27b0b0537028f24b9b9ab545_c3BlYy9naXRsYWIvYnVpbGQvaW5mb19zcGVjLnJi 100644
--- a/spec/gitlab/build/info_spec.rb
+++ b/spec/gitlab/build/info_spec.rb
@@ -195,7 +195,7 @@
     describe 'with security sources channel selected' do
       before do
         allow(::Gitlab::Version).to receive(:sources_channel).and_return('security')
-        allow(ENV).to receive(:[]).with('CI_JOB_TOKEN').and_return('CJT')
+        stub_env_var('CI_JOB_TOKEN', 'CJT')
       end
 
       it 'returns security mirror for GitLab CE with attached credential' do
diff --git a/spec/gitlab/version_spec.rb b/spec/gitlab/version_spec.rb
index b17d00cfb841cb5388e1dc6e4a0d6c67b4ff7b39_c3BlYy9naXRsYWIvdmVyc2lvbl9zcGVjLnJi..ebc9148f8ebe8c6b27b0b0537028f24b9b9ab545_c3BlYy9naXRsYWIvdmVyc2lvbl9zcGVjLnJi 100644
--- a/spec/gitlab/version_spec.rb
+++ b/spec/gitlab/version_spec.rb
@@ -2,8 +2,12 @@
 require 'gitlab/version'
 
 RSpec.describe Gitlab::Version do
+  before do
+    allow(ENV).to receive(:[]).and_call_original
+  end
+
   describe '.sources_channel' do
     subject { described_class }
 
     context 'with ALTERNATIVE_SOURCES=true' do
       it 'returns "alternative"' do
@@ -5,10 +9,9 @@
   describe '.sources_channel' do
     subject { described_class }
 
     context 'with ALTERNATIVE_SOURCES=true' do
       it 'returns "alternative"' do
-        allow(ENV).to receive(:[]).and_call_original
-        allow(ENV).to receive(:[]).with('ALTERNATIVE_SOURCES').and_return('true')
+        stub_env_var('ALTERNATIVE_SOURCES', 'true')
 
         expect(subject.sources_channel).to eq('alternative')
       end
@@ -16,10 +19,9 @@
 
     context 'with SECURITY_SOURCES=true' do
       it 'returns "security"' do
-        allow(ENV).to receive(:[]).and_call_original
-        allow(ENV).to receive(:[]).with('SECURITY_SOURCES').and_return('true')
+        stub_env_var('SECURITY_SOURCES', 'true')
 
         expect(subject.sources_channel).to eq('security')
       end
 
       it 'ignores ALTERNATIVE_SOURCES=true and still return "security"' do
@@ -21,11 +23,10 @@
 
         expect(subject.sources_channel).to eq('security')
       end
 
       it 'ignores ALTERNATIVE_SOURCES=true and still return "security"' do
-        allow(ENV).to receive(:[]).and_call_original
-        allow(ENV).to receive(:[]).with('ALTERNATIVE_SOURCES').and_return('true')
-        allow(ENV).to receive(:[]).with('SECURITY_SOURCES').and_return('true')
+        stub_env_var('ALTERNATIVE_SOURCES', 'true')
+        stub_env_var('SECURITY_SOURCES', 'true')
 
         expect(subject.sources_channel).to eq('security')
       end
@@ -33,9 +34,8 @@
 
     context 'with neither ALTERNATIVE_SOURCES or SECURITY_SOURCES set true' do
       it 'returns "remote"' do
-        allow(ENV).to receive(:[]).and_call_original
-        allow(ENV).to receive(:[]).with('ALTERNATIVE_SOURCES').and_return('false')
-        allow(ENV).to receive(:[]).with('SECURITY_SOURCES').and_return('false')
+        stub_env_var('ALTERNATIVE_SOURCES', 'false')
+        stub_env_var('SECURITY_SOURCES', 'false')
 
         expect(subject.sources_channel).to eq('remote')
       end
@@ -47,8 +47,7 @@
 
     context 'with ALTERNATIVE_SOURCES=true' do
       it 'returns "alternative"' do
-        allow(ENV).to receive(:[]).and_call_original
-        allow(ENV).to receive(:[]).with('ALTERNATIVE_SOURCES').and_return('true')
+        stub_env_var('ALTERNATIVE_SOURCES', 'true')
 
         expect(subject.fallback_sources_channel).to eq('alternative')
       end
@@ -56,8 +55,7 @@
 
     context 'with ALTERNATIVE_SOURCES not set true' do
       it 'returns "remote"' do
-        allow(ENV).to receive(:[]).and_call_original
-        allow(ENV).to receive(:[]).with('ALTERNATIVE_SOURCES').and_return('false')
+        stub_env_var('ALTERNATIVE_SOURCES', 'false')
 
         expect(subject.fallback_sources_channel).to eq('remote')
       end
@@ -121,5 +119,22 @@
       end
     end
 
+    context 'with alternative env override' do
+      let(:software) { 'gitlab-rails-ee' }
+
+      it 'returns "alternative" link from the environment whenever present' do
+        stub_env_var('GITLAB_ALTERNATIVE_REPO', 'https://gitlab.example.com/gitlab.git')
+
+        expect(subject.remote).to eq('https://gitlab.example.com/gitlab.git')
+      end
+
+      it 'attaches credentials to alternative env links when present' do
+        stub_env_var('GITLAB_ALTERNATIVE_REPO', 'https://gitlab.example.com/gitlab.git')
+        stub_env_var('ALTERNATIVE_PRIVATE_TOKEN', 'APT')
+
+        expect(subject.remote).to eq('https://gitlab-ci-token:APT@gitlab.example.com/gitlab.git')
+      end
+    end
+
     context 'with security source channel selected' do
       before do
@@ -124,7 +139,6 @@
     context 'with security source channel selected' do
       before do
-        allow(ENV).to receive(:[]).and_call_original
-        allow(ENV).to receive(:[]).with("CI_JOB_TOKEN").and_return("CJT")
+        stub_env_var('CI_JOB_TOKEN', 'CJT')
         mock_sources_channel('security')
       end
 
@@ -281,8 +295,7 @@
       let(:software) { 'gitlab-rails' }
 
       it 'identifies correct version from env variable' do
-        allow(ENV).to receive(:[]).and_call_original
-        allow(ENV).to receive(:[]).with("GITLAB_VERSION").and_return("5.6.7")
+        stub_env_var('GITLAB_VERSION', '5.6.7')
         allow(File).to receive(:read).and_return("1.2.3")
         expect(subject.print).to eq("v5.6.7")
       end