diff --git a/docs/usage/java.md b/docs/usage/java.md
index 082501663d2d74a85f660524fa1c54db464fe081..e58dbe408117b24f98c7ba75bbeffa9e234dbef2 100644
--- a/docs/usage/java.md
+++ b/docs/usage/java.md
@@ -6,7 +6,7 @@ description: Java versions support in Renovate
 # Java Dependency Updates
 
 Renovate can update Gradle and Maven dependencies.
-This includes libraries and plugins.
+This includes libraries and plugins as well as the Gradle Wrapper.
 
 ## Gradle
 
@@ -23,10 +23,41 @@ Renovate does not support:
 - Android projects that require extra configuration to run (e.g. setting the Android SDK)
 - Gradle versions prior to version 5.0.
 
+## Gradle Wrapper
+
+Renovate can update the [Gradle Wrapper](https://docs.gradle.org/current/userguide/gradle_wrapper.html) of a project.
+
+This includes the source declaration inside the `gradle/wrapper/gradle-wrapper.properties` as well as accompanied files such as `gradlew`, `gradlew.bat`, and `gradle/wrapper/gradle-wrapper.jar`.
+
 ### How It Works
 
-Renovate uses a plugin to search and extract versions from projects.
-Once the Gradle plugin has detected the dependencies, lookups and updating will be performed like usual with datasources and direct patching of files.
+Renovate extracts the Gradle Wrapper version used from the `distributionUrl` inside the `gradle-wrapper.properties`.
+Once the version is determined, Renovate will look for newer versions from the `gradle-version` datasource.
+Renovate will then invoke the Gradle Wrapper to update itself, [as recommended by Gradle](https://docs.gradle.org/current/userguide/gradle_wrapper.html#sec:upgrading_wrapper).
+
+For the extraction to work, the `distributionUrl` must point to a file of type `.zip`, which includes the version in its name, and defines one of the official distribution types (bin, all).
+
+### Support for mirrors and custom distributions
+
+As Renovate takes the `distributionUrl` defined inside the `gradle-wrapper.properties` as basis for its update, source declarations other than to the official Gradle Wrapper are supported.
+
+This can be used for hosting the official distributions with a proxy server, an offline mirror or even providing a custom distribution of the Gradle Wrapper, e.g. to provide a company-wide base configuration for all Gradle projects.
+
+However, the `gradle-version` datasource is used to determine available versions.
+In case the available versions at the defined source differ from those available from Gradle or the [default datasource](https://services.gradle.org/versions/all) cannot be reached, e.g. due to network restrictions, the datasource may be reconfigured via a `packageRule`:
+
+```json
+{
+  "packageRules": [
+    {
+      "matchDatasources": ["gradle-version"],
+      "registryUrls": [
+        "https://domain.tld/repository/custom-gradle-wrapper/versions.json"
+      ]
+    }
+  ]
+}
+```
 
 ## Maven
 
@@ -36,7 +67,12 @@ Renovate can update dependency versions found in Maven `pom.xml` files.
 
 Renovate will search repositories for all `pom.xml` files and processes them independently.
 
-### Custom registry support, and authentication
+## Custom registry support, and authentication
+
+Unless using `deepExtract`, Renovate does not make use of authentication credentials available to Gradle.
+
+The manager for Gradle makes use of the `maven` datasource.
+Renovate can be configured to access additional repositories and access repositories authenticated.
 
 This example shows how you can use a `config.js` file to configure Renovate for use with Artifactory.
 We're using environment variables to pass the Artifactory username and password to Renovate bot.
@@ -53,3 +89,16 @@ module.exports = {
   ],
 };
 ```
+
+You can overwrite the repositories to use for version lookup through configuration.
+
+```js
+module.exports = {
+  packageRules: [
+    {
+      matchDatasources: ['maven'],
+      registryUrls: ['https://repo-a.tld/repo', 'https://repo-b.tld/repo'],
+    },
+  ],
+};
+```
diff --git a/lib/manager/gradle-wrapper/__fixtures__/custom-gradle-wrapper-all.properties b/lib/manager/gradle-wrapper/__fixtures__/custom-gradle-wrapper-all.properties
new file mode 100644
index 0000000000000000000000000000000000000000..691f26185e7824df2b2b4e9af9567245d93d9259
--- /dev/null
+++ b/lib/manager/gradle-wrapper/__fixtures__/custom-gradle-wrapper-all.properties
@@ -0,0 +1,7 @@
+distributionBase=GRADLE_USER_HOME
+distributionPath=wrapper/dists
+zipStoreBase=GRADLE_USER_HOME
+zipStorePath=wrapper/dists
+
+# distributionUrl includes version both in file name and path hierarchy, file name has different prefix
+distributionUrl=https\://domain.tld/repository/maven-releases/tld/domain/gradle-wrapper/custom-gradle-wrapper/6.6.6/custom-gradle-wrapper-6.6.6-all.zip
diff --git a/lib/manager/gradle-wrapper/__fixtures__/custom-gradle-wrapper-bin.properties b/lib/manager/gradle-wrapper/__fixtures__/custom-gradle-wrapper-bin.properties
new file mode 100644
index 0000000000000000000000000000000000000000..909f9745dd90e971c52642a90d0ff304608d4b22
--- /dev/null
+++ b/lib/manager/gradle-wrapper/__fixtures__/custom-gradle-wrapper-bin.properties
@@ -0,0 +1,7 @@
+distributionBase=GRADLE_USER_HOME
+distributionPath=wrapper/dists
+zipStoreBase=GRADLE_USER_HOME
+zipStorePath=wrapper/dists
+
+# distributionUrl includes version both in file name and path hierarchy, file name has different prefix
+distributionUrl=https\://domain.tld/repository/maven-releases/tld/domain/gradle-wrapper/custom-gradle-wrapper/1.3.7/custom-gradle-wrapper-1.3.7-bin.zip
diff --git a/lib/manager/gradle-wrapper/__fixtures__/gradle-wrapper-2.properties b/lib/manager/gradle-wrapper/__fixtures__/gradle-wrapper-all.properties
similarity index 84%
rename from lib/manager/gradle-wrapper/__fixtures__/gradle-wrapper-2.properties
rename to lib/manager/gradle-wrapper/__fixtures__/gradle-wrapper-all.properties
index aa0b761449f4e058d89932e2c635b2c62ea9898c..56482f3365a0b1d116743f8696bdfbf3d19f36b2 100644
--- a/lib/manager/gradle-wrapper/__fixtures__/gradle-wrapper-2.properties
+++ b/lib/manager/gradle-wrapper/__fixtures__/gradle-wrapper-all.properties
@@ -2,6 +2,7 @@ distributionBase=GRADLE_USER_HOME
 distributionPath=wrapper/dists
 zipStoreBase=GRADLE_USER_HOME
 zipStorePath=wrapper/dists
-# @See https://gradle.org/releases/
-distributionUrl=https\://services.gradle.org/distributions/gradle-4.10.3-all.zip
 distributionSha256Sum=336b6898b491f6334502d8074a6b8c2d73ed83b92123106bd4bf837f04111043
+
+# distributionUrl includes distribution type "all"
+distributionUrl=https\://services.gradle.org/distributions/gradle-4.10.3-all.zip
diff --git a/lib/manager/gradle-wrapper/__fixtures__/gradle-wrapper-1.properties b/lib/manager/gradle-wrapper/__fixtures__/gradle-wrapper-bin.properties
similarity index 73%
rename from lib/manager/gradle-wrapper/__fixtures__/gradle-wrapper-1.properties
rename to lib/manager/gradle-wrapper/__fixtures__/gradle-wrapper-bin.properties
index b206624d48d3ecd8a87226a0eef811789c266970..83d5d1c8cb5ca3914dd72832c5865997c1f05c34 100644
--- a/lib/manager/gradle-wrapper/__fixtures__/gradle-wrapper-1.properties
+++ b/lib/manager/gradle-wrapper/__fixtures__/gradle-wrapper-bin.properties
@@ -2,4 +2,6 @@ distributionBase=GRADLE_USER_HOME
 distributionPath=wrapper/dists
 zipStoreBase=GRADLE_USER_HOME
 zipStorePath=wrapper/dists
-distributionUrl=https\://services.gradle.org/distributions/gradle-4.8-bin.zip
\ No newline at end of file
+
+# distributionUrl includes distribution type "bin"
+distributionUrl=https\://services.gradle.org/distributions/gradle-4.8-bin.zip
diff --git a/lib/manager/gradle-wrapper/__fixtures__/gradle-wrapper-custom-distribution-url.properties b/lib/manager/gradle-wrapper/__fixtures__/gradle-wrapper-custom-distribution-url.properties
deleted file mode 100644
index 9953c8e10896085ab3c0e7f90f29d94a868ab1a9..0000000000000000000000000000000000000000
--- a/lib/manager/gradle-wrapper/__fixtures__/gradle-wrapper-custom-distribution-url.properties
+++ /dev/null
@@ -1,7 +0,0 @@
-distributionBase=GRADLE_USER_HOME
-distributionPath=wrapper/dists
-zipStoreBase=GRADLE_USER_HOME
-zipStorePath=wrapper/dists
-# @See https://gradle.org/releases/
-distributionUrl=https\://artifactory/gradle-wrapper-cache/distributions/gradle-4.8-bin.zip
-distributionSha256Sum=336b6898b491f6334502d8074a6b8c2d73ed83b92123106bd4bf837f04111043
diff --git a/lib/manager/gradle-wrapper/__fixtures__/gradle-wrapper-3.properties b/lib/manager/gradle-wrapper/__fixtures__/gradle-wrapper-prerelease.properties
similarity index 82%
rename from lib/manager/gradle-wrapper/__fixtures__/gradle-wrapper-3.properties
rename to lib/manager/gradle-wrapper/__fixtures__/gradle-wrapper-prerelease.properties
index a78c7b6f53f70510ff92aee962643faed7d9deb7..2ce023bdd94c560a36bf481c650e92e0fabbec5d 100644
--- a/lib/manager/gradle-wrapper/__fixtures__/gradle-wrapper-3.properties
+++ b/lib/manager/gradle-wrapper/__fixtures__/gradle-wrapper-prerelease.properties
@@ -2,4 +2,6 @@ distributionBase=GRADLE_USER_HOME
 distributionPath=wrapper/dists
 zipStoreBase=GRADLE_USER_HOME
 zipStorePath=wrapper/dists
+
+# distributionUrl includes prerelase version
 distributionUrl=https\://services.gradle.org/distributions/gradle-7.0-milestone-1-bin.zip
diff --git a/lib/manager/gradle-wrapper/__fixtures__/gradle-wrapper-4.properties b/lib/manager/gradle-wrapper/__fixtures__/gradle-wrapper-unknown-format.properties
similarity index 78%
rename from lib/manager/gradle-wrapper/__fixtures__/gradle-wrapper-4.properties
rename to lib/manager/gradle-wrapper/__fixtures__/gradle-wrapper-unknown-format.properties
index d98eba7fbb009ef80e1f4976d92553a742e64a65..4dc14b6b213bbfdede265a6a96a872eb4e51b8bc 100644
--- a/lib/manager/gradle-wrapper/__fixtures__/gradle-wrapper-4.properties
+++ b/lib/manager/gradle-wrapper/__fixtures__/gradle-wrapper-unknown-format.properties
@@ -2,4 +2,6 @@ distributionBase=GRADLE_USER_HOME
 distributionPath=wrapper/dists
 zipStoreBase=GRADLE_USER_HOME
 zipStorePath=wrapper/dists
+
+# distributionUrl includes unsupported file name format
 distributionUrl=https\://services.gradle.org/distributions/gradle-7-rc-1-bin.zip
diff --git a/lib/manager/gradle-wrapper/__fixtures__/gradle-wrapper-whitespace.properties b/lib/manager/gradle-wrapper/__fixtures__/gradle-wrapper-whitespace.properties
index 0f14bb607411d6a101905178577f84aa243507b4..25fc798d531a94b3f9b0e716a99ab4681e6b291a 100644
--- a/lib/manager/gradle-wrapper/__fixtures__/gradle-wrapper-whitespace.properties
+++ b/lib/manager/gradle-wrapper/__fixtures__/gradle-wrapper-whitespace.properties
@@ -2,6 +2,7 @@ distributionBase=GRADLE_USER_HOME
 distributionPath=wrapper/dists
 zipStoreBase=GRADLE_USER_HOME
 zipStorePath=wrapper/dists
-# @See https://gradle.org/releases/
-distributionUrl = https\://services.gradle.org/distributions/gradle-4.10.3-all.zip
+
+# distributionUrl and distributionSha256Sum include unnecessary whitespace
+distributionUrl    =      https\://services.gradle.org/distributions/gradle-4.10.3-all.zip
 distributionSha256Sum       =    336b6898b491f6334502d8074a6b8c2d73ed83b92123106bd4bf837f04111043
diff --git a/lib/manager/gradle-wrapper/__snapshots__/extract.spec.ts.snap b/lib/manager/gradle-wrapper/__snapshots__/extract.spec.ts.snap
deleted file mode 100644
index a94cb18f3e82cc0836bb6d10d0e6821e7ec33408..0000000000000000000000000000000000000000
--- a/lib/manager/gradle-wrapper/__snapshots__/extract.spec.ts.snap
+++ /dev/null
@@ -1,12 +0,0 @@
-// Jest Snapshot v1, https://goo.gl/fbAQLP
-
-exports[`manager/gradle-wrapper/extract extractPackageFile() extracts prerelease version line 1`] = `
-Array [
-  Object {
-    "currentValue": "7.0-milestone-1",
-    "datasource": "gradle-version",
-    "depName": "gradle",
-    "versioning": "gradle",
-  },
-]
-`;
diff --git a/lib/manager/gradle-wrapper/extract.spec.ts b/lib/manager/gradle-wrapper/extract.spec.ts
index 8e2ecacea001f5b906a1007e0d4487ab777865cf..36fd0ef4b1d9fd60d3dd30ea08e9295dede2c227 100644
--- a/lib/manager/gradle-wrapper/extract.spec.ts
+++ b/lib/manager/gradle-wrapper/extract.spec.ts
@@ -1,25 +1,42 @@
 import { loadFixture } from '../../../test/util';
 import { extractPackageFile } from './extract';
 
-const propertiesFile1 = loadFixture('gradle-wrapper-1.properties');
-const propertiesFile2 = loadFixture('gradle-wrapper-2.properties');
-const propertiesFile3 = loadFixture('gradle-wrapper-3.properties');
-const propertiesFile4 = loadFixture('gradle-wrapper-4.properties');
+const typeBinFileContent = loadFixture('gradle-wrapper-bin.properties');
+const typeAllFileContent = loadFixture('gradle-wrapper-all.properties');
+const prereleaseVersionFileContent = loadFixture(
+  'gradle-wrapper-prerelease.properties'
+);
+const unknownFormatFileContent = loadFixture(
+  'gradle-wrapper-unknown-format.properties'
+);
 const whitespacePropertiesFile = loadFixture(
   'gradle-wrapper-whitespace.properties'
 );
+const customTypeBinFileContent = loadFixture(
+  'custom-gradle-wrapper-bin.properties'
+);
+const customTypeAllFileContent = loadFixture(
+  'custom-gradle-wrapper-all.properties'
+);
 
 describe('manager/gradle-wrapper/extract', () => {
   describe('extractPackageFile()', () => {
-    it('returns null for empty', () => {
+    it('returns null for property file without distributionUrl', () => {
       expect(extractPackageFile('nothing here')).toBeNull();
     });
 
-    it('extracts bin version line', () => {
-      const res = extractPackageFile(propertiesFile1);
+    it('returns null for property file with unsupported distributionUrl format', () => {
+      const res = extractPackageFile(unknownFormatFileContent);
+      expect(res).toBeNull();
+    });
+
+    it('extracts version for property file with distribution type "bin" in distributionUrl', () => {
+      const res = extractPackageFile(typeBinFileContent);
       expect(res.deps).toEqual([
         {
           currentValue: '4.8',
+          replaceString:
+            'https\\://services.gradle.org/distributions/gradle-4.8-bin.zip',
           datasource: 'gradle-version',
           depName: 'gradle',
           versioning: 'gradle',
@@ -27,11 +44,13 @@ describe('manager/gradle-wrapper/extract', () => {
       ]);
     });
 
-    it('extracts all version line', () => {
-      const res = extractPackageFile(propertiesFile2);
+    it('extracts version for property file with distribution type "all" in distributionUrl', () => {
+      const res = extractPackageFile(typeAllFileContent);
       expect(res.deps).toEqual([
         {
           currentValue: '4.10.3',
+          replaceString:
+            'https\\://services.gradle.org/distributions/gradle-4.10.3-all.zip',
           datasource: 'gradle-version',
           depName: 'gradle',
           versioning: 'gradle',
@@ -39,22 +58,55 @@ describe('manager/gradle-wrapper/extract', () => {
       ]);
     });
 
-    it('extracts prerelease version line', () => {
-      const res = extractPackageFile(propertiesFile3);
-      expect(res.deps).toMatchSnapshot();
-      expect(res.deps[0].currentValue).toBe('7.0-milestone-1');
-    });
-
-    it('ignores invalid', () => {
-      const res = extractPackageFile(propertiesFile4);
-      expect(res).toBeNull();
+    it('extracts version for property file with prerelease version in distributionUrl', () => {
+      const res = extractPackageFile(prereleaseVersionFileContent);
+      expect(res.deps).toEqual([
+        {
+          currentValue: '7.0-milestone-1',
+          replaceString:
+            'https\\://services.gradle.org/distributions/gradle-7.0-milestone-1-bin.zip',
+          datasource: 'gradle-version',
+          depName: 'gradle',
+          versioning: 'gradle',
+        },
+      ]);
     });
 
-    it('handles whitespace', () => {
+    it('extracts version for property file with unnecessary whitespace in distributionUrl', () => {
       const res = extractPackageFile(whitespacePropertiesFile);
       expect(res.deps).toEqual([
         {
           currentValue: '4.10.3',
+          replaceString:
+            'https\\://services.gradle.org/distributions/gradle-4.10.3-all.zip',
+          datasource: 'gradle-version',
+          depName: 'gradle',
+          versioning: 'gradle',
+        },
+      ]);
+    });
+
+    it('extracts version for property file with custom distribution of type "bin" in distributionUrl', () => {
+      const res = extractPackageFile(customTypeBinFileContent);
+      expect(res.deps).toEqual([
+        {
+          currentValue: '1.3.7',
+          replaceString:
+            'https\\://domain.tld/repository/maven-releases/tld/domain/gradle-wrapper/custom-gradle-wrapper/1.3.7/custom-gradle-wrapper-1.3.7-bin.zip',
+          datasource: 'gradle-version',
+          depName: 'gradle',
+          versioning: 'gradle',
+        },
+      ]);
+    });
+
+    it('extracts version for property file with custom distribution of type "all" in distributionUrl', () => {
+      const res = extractPackageFile(customTypeAllFileContent);
+      expect(res.deps).toEqual([
+        {
+          currentValue: '6.6.6',
+          replaceString:
+            'https\\://domain.tld/repository/maven-releases/tld/domain/gradle-wrapper/custom-gradle-wrapper/6.6.6/custom-gradle-wrapper-6.6.6-all.zip',
           datasource: 'gradle-version',
           depName: 'gradle',
           versioning: 'gradle',
diff --git a/lib/manager/gradle-wrapper/extract.ts b/lib/manager/gradle-wrapper/extract.ts
index 88383865230e980b598257707de157839ef313fd..fbcdf7f848d959b860310c60a791fe614d283b3d 100644
--- a/lib/manager/gradle-wrapper/extract.ts
+++ b/lib/manager/gradle-wrapper/extract.ts
@@ -6,11 +6,12 @@ import { extractGradleVersion } from './utils';
 
 export function extractPackageFile(fileContent: string): PackageFile | null {
   logger.trace('gradle-wrapper.extractPackageFile()');
-  const currentValue = extractGradleVersion(fileContent);
-  if (currentValue) {
+  const extractResult = extractGradleVersion(fileContent);
+  if (extractResult) {
     const dependency: PackageDependency = {
       depName: 'gradle',
-      currentValue,
+      currentValue: extractResult.version,
+      replaceString: extractResult.url,
       datasource: GradleVersionDatasource.id,
       versioning,
     };
diff --git a/lib/manager/gradle-wrapper/types.ts b/lib/manager/gradle-wrapper/types.ts
new file mode 100644
index 0000000000000000000000000000000000000000..4d9805ab539e238631ae387cde73d3b2ac7b1af0
--- /dev/null
+++ b/lib/manager/gradle-wrapper/types.ts
@@ -0,0 +1,4 @@
+export interface GradleVersionExtract {
+  url: string;
+  version: string;
+}
diff --git a/lib/manager/gradle-wrapper/utils.ts b/lib/manager/gradle-wrapper/utils.ts
index f328ed53e9a6f6230bfab20a5bd549c4008a8746..eb3f75966de5d3f9e2b306c633b99a45bc71590b 100644
--- a/lib/manager/gradle-wrapper/utils.ts
+++ b/lib/manager/gradle-wrapper/utils.ts
@@ -2,10 +2,12 @@ import type { Stats } from 'fs';
 import os from 'os';
 import upath from 'upath';
 import { getGlobalConfig } from '../../config/global';
+import { logger } from '../../logger';
 import { chmod } from '../../util/fs';
 import { regEx } from '../../util/regex';
 import gradleVersioning from '../../versioning/gradle';
 import { id as npmVersioning } from '../../versioning/npm';
+import { GradleVersionExtract } from './types';
 
 export const extraEnv = {
   GRADLE_OPTS:
@@ -72,20 +74,29 @@ export function getJavaVersioning(): string {
   return npmVersioning;
 }
 
-// https://regex101.com/r/1GaQ2X/1
+// https://regex101.com/r/IcOs7P/1
 const DISTRIBUTION_URL_REGEX = regEx(
-  '^(?:distributionUrl\\s*=\\s*)\\S*-(?<version>\\d+\\.\\d+(?:\\.\\d+)?(?:-\\w+)*)-(?<type>bin|all)\\.zip\\s*$'
+  '^(?:distributionUrl\\s*=\\s*)(?<url>\\S*-(?<version>\\d+\\.\\d+(?:\\.\\d+)?(?:-\\w+)*)-(?<type>bin|all)\\.zip)\\s*$'
 );
 
-export function extractGradleVersion(fileContent: string): string | null {
+export function extractGradleVersion(
+  fileContent: string
+): GradleVersionExtract | null {
   const lines = fileContent?.split('\n') ?? [];
 
   for (const line of lines) {
     const distributionUrlMatch = DISTRIBUTION_URL_REGEX.exec(line);
+
     if (distributionUrlMatch) {
-      return distributionUrlMatch.groups.version;
+      return {
+        url: distributionUrlMatch.groups.url,
+        version: distributionUrlMatch.groups.version,
+      };
     }
   }
+  logger.debug(
+    'Gradle wrapper version and url could not be extracted from properties - skipping update'
+  );
 
   return null;
 }
diff --git a/lib/manager/gradle/deep/utils.ts b/lib/manager/gradle/deep/utils.ts
index 4b8aa9e1181eec1c8b322ad5c78038733f4d0294..b984d6c055ab49a17121c38fc8d35e7ebcd66280 100644
--- a/lib/manager/gradle/deep/utils.ts
+++ b/lib/manager/gradle/deep/utils.ts
@@ -21,7 +21,7 @@ export async function getDockerConstraint(
     'utf8'
   );
 
-  const version = extractGradleVersion(fileContent);
+  const version = extractGradleVersion(fileContent)?.version;
 
   return getJavaContraint(version);
 }