diff --git a/lib/config/cli.js b/lib/config/cli.js
index e2145f0edfa19f14acde728070c5b580e37209f2..e8edc40c9549860c43d70c85d331dca6a227c5bd 100644
--- a/lib/config/cli.js
+++ b/lib/config/cli.js
@@ -23,6 +23,7 @@ function getConfig(input) {
       .replace('--expose-env=true', '--trust-level=high')
       .replace('--expose-env', '--trust-level=high')
       .replace('--renovate-fork', '--include-forks')
+      .replace('"platform":"', '"hostType":"')
   );
   const options = configDefinitions.getOptions();
 
diff --git a/lib/config/definitions.js b/lib/config/definitions.js
index 677aeda4c380f29af0935143e91659907b55310f..2fccee6f5f55a92e4ca770d78216be019484ed5d 100644
--- a/lib/config/definitions.js
+++ b/lib/config/definitions.js
@@ -1687,6 +1687,16 @@ const options = [
     cli: true,
     mergeable: true,
   },
+  {
+    name: 'hostType',
+    description:
+      'hostType for a package rule. Can be a platform name or a datasource name',
+    type: 'string',
+    stage: 'repository',
+    parent: 'hostRules',
+    cli: false,
+    env: false,
+  },
   {
     name: 'prBodyDefinitions',
     description: 'Table column definitions for use in PR tables',
diff --git a/lib/config/env.js b/lib/config/env.js
index a86d32403b481f85135a52d063aaf182be8b0e2c..5fc7f9e017086c4f77ec5e1e20b86f88699bdcc4 100644
--- a/lib/config/env.js
+++ b/lib/config/env.js
@@ -42,14 +42,14 @@ function getConfig(env) {
   if (env.GITHUB_COM_TOKEN) {
     config.hostRules.push({
       endpoint: 'https://api.github.com/',
-      platform: 'github',
+      hostType: 'github',
       token: env.GITHUB_COM_TOKEN,
     });
   }
 
   if (env.DOCKER_USERNAME && env.DOCKER_PASSWORD) {
     config.hostRules.push({
-      platform: 'docker',
+      hostType: 'docker',
       username: env.DOCKER_USERNAME,
       password: env.DOCKER_PASSWORD,
     });
diff --git a/lib/config/migration.js b/lib/config/migration.js
index 1a6b49bb21593a263a243e65e95c61685be79329..33b4c009c0617930dfdff9fef3c0184b780280d3 100644
--- a/lib/config/migration.js
+++ b/lib/config/migration.js
@@ -25,7 +25,7 @@ const removedOptions = [
 ];
 
 // Returns a migrated config
-function migrateConfig(config) {
+function migrateConfig(config, parentKey) {
   try {
     if (!optionTypes) {
       optionTypes = {};
@@ -50,7 +50,7 @@ function migrateConfig(config) {
         if (is.array(val)) {
           migratedConfig.packageRules = migratedConfig.packageRules || [];
           const migratedPathRules = migratedConfig.pathRules.map(
-            p => migrateConfig(p).migratedConfig
+            p => migrateConfig(p, key).migratedConfig
           );
           migratedConfig.packageRules = migratedPathRules.concat(
             migratedConfig.packageRules
@@ -74,6 +74,10 @@ function migrateConfig(config) {
           isMigrated = true;
           migratedConfig.gitFs = 'https';
         }
+      } else if (parentKey === 'hostRules' && key === 'platform') {
+        isMigrated = true;
+        migratedConfig.hostType = val;
+        delete migratedConfig.platform;
       } else if (key === 'packageFiles' && is.array(val)) {
         isMigrated = true;
         const fileList = [];
@@ -82,7 +86,7 @@ function migrateConfig(config) {
             fileList.push(packageFile.packageFile);
             if (Object.keys(packageFile).length > 1) {
               migratedConfig.packageRules = migratedConfig.packageRules || [];
-              const payload = migrateConfig(packageFile).migratedConfig;
+              const payload = migrateConfig(packageFile, key).migratedConfig;
               for (const subrule of payload.packageRules || []) {
                 subrule.paths = [packageFile.packageFile];
                 migratedConfig.packageRules.push(subrule);
@@ -105,7 +109,7 @@ function migrateConfig(config) {
       } else if (depTypes.includes(key)) {
         isMigrated = true;
         migratedConfig.packageRules = migratedConfig.packageRules || [];
-        const depTypePackageRule = migrateConfig(val).migratedConfig;
+        const depTypePackageRule = migrateConfig(val, key).migratedConfig;
         depTypePackageRule.depTypeList = [key];
         delete depTypePackageRule.packageRules;
         migratedConfig.packageRules.push(depTypePackageRule);
@@ -229,7 +233,7 @@ function migrateConfig(config) {
         isMigrated = true;
         migratedConfig.packageRules = migratedConfig.packageRules || [];
         migratedConfig.packageRules = migratedConfig.packageRules.concat(
-          migratedConfig.packages.map(p => migrateConfig(p).migratedConfig)
+          migratedConfig.packages.map(p => migrateConfig(p, key).migratedConfig)
         );
         delete migratedConfig.packages;
       } else if (key === 'excludedPackageNames') {
@@ -340,7 +344,7 @@ function migrateConfig(config) {
             const depTypeName = depType.depType;
             if (depTypeName) {
               migratedConfig.packageRules = migratedConfig.packageRules || [];
-              const newPackageRule = migrateConfig(depType).migratedConfig;
+              const newPackageRule = migrateConfig(depType, key).migratedConfig;
               delete newPackageRule.depType;
               newPackageRule.depTypeList = [depTypeName];
               migratedConfig.packageRules.push(newPackageRule);
@@ -372,14 +376,14 @@ function migrateConfig(config) {
         if (!Object.keys(migratedConfig.node).length) {
           delete migratedConfig.node;
         } else {
-          const subMigrate = migrateConfig(migratedConfig.node);
+          const subMigrate = migrateConfig(migratedConfig.node, key);
           migratedConfig.node = subMigrate.migratedConfig;
         }
       } else if (is.array(val)) {
         const newArray = [];
         for (const item of migratedConfig[key]) {
           if (is.object(item) && !is.array(item)) {
-            const arrMigrate = migrateConfig(item);
+            const arrMigrate = migrateConfig(item, key);
             newArray.push(arrMigrate.migratedConfig);
             if (arrMigrate.isMigrated) {
               isMigrated = true;
@@ -390,7 +394,7 @@ function migrateConfig(config) {
         }
         migratedConfig[key] = newArray;
       } else if (is.object(val)) {
-        const subMigrate = migrateConfig(migratedConfig[key]);
+        const subMigrate = migrateConfig(migratedConfig[key], key);
         if (subMigrate.isMigrated) {
           isMigrated = true;
           migratedConfig[key] = subMigrate.migratedConfig;
diff --git a/lib/datasource/cargo/index.js b/lib/datasource/cargo/index.js
index 47a74f1fb5866ff61a218df24986256868523728..f23a15cc64e48ef573cf0a1578036929b384968e 100644
--- a/lib/datasource/cargo/index.js
+++ b/lib/datasource/cargo/index.js
@@ -36,7 +36,7 @@ async function getPkgReleases({ lookupName }) {
   const crateUrl = baseUrl + path;
   try {
     let res = await got(crateUrl, {
-      platform: 'cargo',
+      hostType: 'cargo',
     });
     if (!res || !res.body) {
       logger.warn(
diff --git a/lib/datasource/docker/index.js b/lib/datasource/docker/index.js
index d67add841482f17c245affca40a3bb3de35f358a..e5ccc6acc6cae271b9b6ff7eb82e4052131969df 100644
--- a/lib/datasource/docker/index.js
+++ b/lib/datasource/docker/index.js
@@ -51,7 +51,7 @@ async function getAuthHeaders(registry, repository) {
     );
 
     const { host } = URL.parse(registry);
-    const opts = hostRules.find({ platform: 'docker', host }, { json: true });
+    const opts = hostRules.find({ hostType: 'docker', host }, { json: true });
     if (opts.username && opts.password) {
       const auth = Buffer.from(`${opts.username}:${opts.password}`).toString(
         'base64'
diff --git a/lib/datasource/github/index.js b/lib/datasource/github/index.js
index bc345a7bd57577c83f96aa804deebd3695f0d776..4fcde592aa531de2adf59f49cbf8ce7c12917f9f 100644
--- a/lib/datasource/github/index.js
+++ b/lib/datasource/github/index.js
@@ -16,7 +16,7 @@ async function fetchJSONFile(repo, fileName) {
         : 'application/vnd.github.v3+json',
     },
     json: true,
-    platform: 'github',
+    hostType: 'github',
   };
   let res;
   try {
diff --git a/lib/datasource/go/index.js b/lib/datasource/go/index.js
index f76ad4bac56c94e92c78133610f33fd30b4112cf..c1d541a0261c4b0ba2b90d09e30f0ee10525f20f 100644
--- a/lib/datasource/go/index.js
+++ b/lib/datasource/go/index.js
@@ -25,7 +25,7 @@ async function getDatasource(name) {
   const pkgUrl = `https://${name}?go-get=1`;
   try {
     const res = (await got(pkgUrl, {
-      platform: 'go',
+      hostType: 'go',
     })).body;
     const sourceMatch = res.match(
       new RegExp(`<meta name="go-source" content="${name}\\s+([^\\s]+)`)
diff --git a/lib/datasource/hex/index.js b/lib/datasource/hex/index.js
index fc78696fe8e60c8b9e87e527bba60740313d3014..96f3d6cd7cef337d6b249bc2b1d11844841e4fc1 100644
--- a/lib/datasource/hex/index.js
+++ b/lib/datasource/hex/index.js
@@ -7,7 +7,7 @@ module.exports = {
 function getHostOpts() {
   return {
     json: true,
-    platform: 'hex',
+    hostType: 'hex',
   };
 }
 
diff --git a/lib/datasource/maven/index.js b/lib/datasource/maven/index.js
index 1b1e2d0547c85d0bf966b3812f899ac13b293001..f1c66efd3ea4eff384f43c90232882e62364f322 100644
--- a/lib/datasource/maven/index.js
+++ b/lib/datasource/maven/index.js
@@ -136,7 +136,7 @@ async function downloadFileProtocol(pkgUrl) {
 async function downloadHttpProtocol(pkgUrl) {
   let raw;
   try {
-    raw = await got(pkgUrl, { platform: 'maven' });
+    raw = await got(pkgUrl, { hostType: 'maven' });
   } catch (err) {
     if (isNotFoundError(err)) {
       logger.debug(`Url not found ${pkgUrl}`);
diff --git a/lib/datasource/npm/get.js b/lib/datasource/npm/get.js
index c2de3834862b5868b025556141dbd8382d161eca..be2c2794b98733070531c4c4313b2626ce9eff66 100644
--- a/lib/datasource/npm/get.js
+++ b/lib/datasource/npm/get.js
@@ -132,7 +132,7 @@ async function getDependency(name) {
     if (res.repository && res.repository.url) {
       const extraBaseUrls = [];
       // istanbul ignore next
-      hostRules.hosts({ platform: 'github' }).forEach(host => {
+      hostRules.hosts({ hostType: 'github' }).forEach(host => {
         extraBaseUrls.push(host, `gist.${host}`);
       });
       // Massage www out of github URL
diff --git a/lib/datasource/nuget/v2.js b/lib/datasource/nuget/v2.js
index 7021db5f7dde74c30f967ff0471aba974634d409..d959e1a4e37f43ee13c67e34165fbf8cd1ca2ee3 100644
--- a/lib/datasource/nuget/v2.js
+++ b/lib/datasource/nuget/v2.js
@@ -15,7 +15,7 @@ async function getPkgReleases(feedUrl, pkgName) {
 
     let pkgUrlList = `${feedUrl}/FindPackagesById()?id=%27${pkgName}%27&$select=Version,IsLatestVersion,ProjectUrl`;
     do {
-      const pkgVersionsListRaw = await got(pkgUrlList, { platform: 'nuget' });
+      const pkgVersionsListRaw = await got(pkgUrlList, { hostType: 'nuget' });
       if (pkgVersionsListRaw.statusCode !== 200) {
         logger.debug(
           { dependency: pkgName, pkgVersionsListRaw },
diff --git a/lib/datasource/nuget/v3.js b/lib/datasource/nuget/v3.js
index a43313f53a3f6fa7b2f5ab6f974c5af2723afe52..6068ab200950d43b8f8aeefbafda89284f865beb 100644
--- a/lib/datasource/nuget/v3.js
+++ b/lib/datasource/nuget/v3.js
@@ -29,7 +29,7 @@ async function getQueryUrl(url) {
   }
 
   try {
-    const servicesIndexRaw = await got(url, { json: true, platform: 'nuget' });
+    const servicesIndexRaw = await got(url, { json: true, hostType: 'nuget' });
     if (servicesIndexRaw.statusCode !== 200) {
       logger.debug(
         { dependency: url, servicesIndexRaw },
@@ -72,7 +72,7 @@ async function getPkgReleases(registryUrl, feedUrl, pkgName) {
   try {
     const pkgUrlListRaw = await got(queryUrl, {
       json: true,
-      platform: 'nuget',
+      hostType: 'nuget',
     });
     if (pkgUrlListRaw.statusCode !== 200) {
       logger.debug(
@@ -112,7 +112,7 @@ async function getPkgReleases(registryUrl, feedUrl, pkgName) {
         const nugetOrgApi = `https://api.nuget.org/v3-flatcontainer/${pkgName.toLowerCase()}/${lastVersion}/${pkgName.toLowerCase()}.nuspec`;
         let metaresult;
         try {
-          metaresult = await got(nugetOrgApi, { platform: 'nuget' });
+          metaresult = await got(nugetOrgApi, { hostType: 'nuget' });
         } catch (err) /* istanbul ignore next */ {
           logger.debug(
             `Cannot fetch metadata for ${pkgName} using popped version ${lastVersion}`
diff --git a/lib/datasource/packagist/index.js b/lib/datasource/packagist/index.js
index b6ff94a387d3cc00db79f698615f8fda9d6f2e13..a6a3a980691922aef8708b9f17c51dc7f1fea139 100644
--- a/lib/datasource/packagist/index.js
+++ b/lib/datasource/packagist/index.js
@@ -13,7 +13,7 @@ module.exports = {
 
 function getHostOpts(url) {
   const { host } = URL.parse(url);
-  const opts = hostRules.find({ platform: 'packagist', host }, { json: true });
+  const opts = hostRules.find({ hostType: 'packagist', host }, { json: true });
   if (opts && opts.username && opts.password) {
     const auth = Buffer.from(`${opts.username}:${opts.password}`).toString(
       'base64'
diff --git a/lib/datasource/pypi/index.js b/lib/datasource/pypi/index.js
index 8520ce123941dcbbe238e6888dd94346ce99f1e5..e4ad3117909e541a21a295ef00a5374602b446b1 100644
--- a/lib/datasource/pypi/index.js
+++ b/lib/datasource/pypi/index.js
@@ -56,7 +56,7 @@ async function getDependency(depName, hostUrl, compatibility) {
     const dependency = {};
     const rep = await got(url.parse(lookupUrl), {
       json: true,
-      platform: 'pypi',
+      hostType: 'pypi',
     });
     const dep = rep && rep.body;
     if (!dep) {
@@ -105,7 +105,7 @@ async function getSimpleDependency(depName, hostUrl) {
     const dependency = {};
     const response = await got(url.parse(lookupUrl), {
       json: false,
-      platform: 'pypi',
+      hostType: 'pypi',
     });
     const dep = response && response.body;
     if (!dep) {
diff --git a/lib/datasource/rubygems/get.js b/lib/datasource/rubygems/get.js
index ca25bc202bc92c080d554fbeda7992f8db706b42..efce81718527dfebbe06b01516668f04b0f3cbf9 100644
--- a/lib/datasource/rubygems/get.js
+++ b/lib/datasource/rubygems/get.js
@@ -31,7 +31,7 @@ const processError = ({ err, ...rest }) => {
 };
 
 const getHeaders = () => {
-  return { platform: 'rubygems' };
+  return { hostType: 'rubygems' };
 };
 
 const fetch = async ({ dependency, registry, path }) => {
diff --git a/lib/datasource/terraform/index.js b/lib/datasource/terraform/index.js
index 1603303fff78b5884f920352300cf783916e5a9a..b9c7b83bc4d659b3ec80786073be8e0e90003899 100644
--- a/lib/datasource/terraform/index.js
+++ b/lib/datasource/terraform/index.js
@@ -52,7 +52,7 @@ async function getPkgReleases({ lookupName, registryUrls }) {
   try {
     const res = (await got(pkgUrl, {
       json: true,
-      platform: 'terraform',
+      hostType: 'terraform',
     })).body;
     const returnedName = res.namespace + '/' + res.name + '/' + res.provider;
     if (returnedName !== repository) {
diff --git a/lib/manager/composer/artifacts.js b/lib/manager/composer/artifacts.js
index 7fad82bdc27a7f3efa8a543716809a6602bdf3b6..fccb140f05366612840514415139a344f5fb4e14 100644
--- a/lib/manager/composer/artifacts.js
+++ b/lib/manager/composer/artifacts.js
@@ -40,7 +40,7 @@ async function getArtifacts(
     }
     let authJson = {};
     let credentials = hostRules.find({
-      platform: 'github',
+      hostType: 'github',
       host: 'api.github.com',
     });
     // istanbul ignore if
@@ -50,7 +50,7 @@ async function getArtifacts(
       };
     }
     credentials = hostRules.find({
-      platform: 'gitlab',
+      hostType: 'gitlab',
       host: 'gitlab.com',
     });
     // istanbul ignore if
@@ -66,7 +66,7 @@ async function getArtifacts(
           if (regUrl.url) {
             const { host } = URL.parse(regUrl.url);
             const hostRule = hostRules.find({
-              platform: 'packagist',
+              hostType: 'packagist',
               host,
             });
             // istanbul ignore else
diff --git a/lib/manager/gomod/artifacts.js b/lib/manager/gomod/artifacts.js
index cfdbe02b2a1cd8b9dfc0c20a1d2f83f3336dcb50..3407eecfa94433cb5f7050bc224d10a3b4757bf0 100644
--- a/lib/manager/gomod/artifacts.js
+++ b/lib/manager/gomod/artifacts.js
@@ -62,7 +62,7 @@ async function getArtifacts(
       cmd += `-w ${cwd} `;
       cmd += `renovate/go `;
       const credentials = hostRules.find({
-        platform: 'github',
+        hostType: 'github',
         host: 'api.github.com',
       });
       if (credentials && credentials.token) {
diff --git a/lib/manager/npm/post-update/index.js b/lib/manager/npm/post-update/index.js
index b0b12c7b2e3f57ea02a5e98ecefb3c33f1fca523..a466b4b905eb1d21818ad7cfc8b22b1732087573 100644
--- a/lib/manager/npm/post-update/index.js
+++ b/lib/manager/npm/post-update/index.js
@@ -304,7 +304,7 @@ async function writeUpdatedPackageFiles(config) {
     delete massagedFile.engines;
     delete massagedFile.scripts;
     try {
-      const { token } = hostRules.find({ platform: config.platform });
+      const { token } = hostRules.find({ hostType: config.platform });
       for (const upgrade of config.upgrades) {
         if (upgrade.gitRef && upgrade.packageFile === packageFile.name) {
           massagedFile[upgrade.depType][upgrade.depName] = massagedFile[
@@ -377,7 +377,7 @@ async function getAdditionalFiles(config, packageFiles) {
 
   let token = '';
   try {
-    ({ token } = hostRules.find({ platform: config.platform }));
+    ({ token } = hostRules.find({ hostType: config.platform }));
     token += '@';
   } catch (err) {
     logger.warn({ err }, 'Error getting token for packageFile');
diff --git a/lib/platform/azure/azure-got-wrapper.js b/lib/platform/azure/azure-got-wrapper.js
index 10733e9978d433a73d7548cb5d4dc2836ae9f616..24ee067a3a23f1469fc5d21f1d22cce4e805a181 100644
--- a/lib/platform/azure/azure-got-wrapper.js
+++ b/lib/platform/azure/azure-got-wrapper.js
@@ -1,7 +1,7 @@
 const azure = require('azure-devops-node-api');
 const hostRules = require('../../util/host-rules');
 
-const platform = 'azure';
+const hostType = 'azure';
 let endpoint;
 
 module.exports = {
@@ -12,7 +12,7 @@ module.exports = {
 };
 
 function azureObj() {
-  const config = hostRules.find({ platform, endpoint });
+  const config = hostRules.find({ hostType, endpoint });
   if (!(config && config.token)) {
     throw new Error(`No token found for azure`);
   }
diff --git a/lib/platform/azure/index.js b/lib/platform/azure/index.js
index 70dd1cc8b21c4ace39de80a1aa49e44b3d2c7e45..68da0559a1d54bb8d62c2e7183ccc0ad10dd2876 100644
--- a/lib/platform/azure/index.js
+++ b/lib/platform/azure/index.js
@@ -8,7 +8,7 @@ const GitStorage = require('../git/storage');
 let config = {};
 
 const defaults = {
-  platform: 'azure',
+  hostType: 'azure',
 };
 
 module.exports = {
diff --git a/lib/platform/bitbucket-server/bb-got-wrapper.ts b/lib/platform/bitbucket-server/bb-got-wrapper.ts
index 066de5393cbeb7f6bfdd2089167aaf4e1a03facd..9e6f04d5ecda5052f943399f53b04e251316b432 100644
--- a/lib/platform/bitbucket-server/bb-got-wrapper.ts
+++ b/lib/platform/bitbucket-server/bb-got-wrapper.ts
@@ -5,7 +5,7 @@ import { IGotApiOptions, IGotApi } from '../common';
 
 let cache: Renovate.IDict<got.Response<any>> = {};
 
-const platform = 'bitbucket-server';
+const hostType = 'bitbucket-server';
 let endpoint: string;
 
 async function get(path: string, options: IGotApiOptions & got.GotJSONOptions) {
@@ -17,7 +17,7 @@ async function get(path: string, options: IGotApiOptions & got.GotJSONOptions) {
     timeout: 60 * 1000,
     json: true,
     basic: false,
-    ...hostRules.find({ platform, host }),
+    ...hostRules.find({ hostType, host }),
     ...options,
   };
   const url = URL.resolve(endpoint, path);
diff --git a/lib/platform/bitbucket-server/index.ts b/lib/platform/bitbucket-server/index.ts
index 8adea7fc0cf5f375550268ed0fa51878139dd288..7ca97a5b8cb00e7e41d27b76a050bf784d245d6b 100644
--- a/lib/platform/bitbucket-server/index.ts
+++ b/lib/platform/bitbucket-server/index.ts
@@ -6,8 +6,6 @@ import * as utils from './utils';
 import * as hostRules from '../../util/host-rules';
 import GitStorage from '../git/storage';
 
-const platform = 'bitbucket-server';
-
 interface BbsConfig {
   baseBranch: string;
   bbUseDefaultReviewers: boolean;
@@ -25,7 +23,7 @@ interface BbsConfig {
 let config: BbsConfig = {} as any;
 
 const defaults: any = {
-  platform: 'bitbucket-server',
+  hostType: 'bitbucket-server',
 };
 
 export function initPlatform({
@@ -105,7 +103,7 @@ export async function initRepo({
       2
     )}")`
   );
-  const opts = hostRules.find({ platform }, { endpoint });
+  const opts = hostRules.find({ hostType: defaults.hostType, endpoint });
   api.reset();
 
   const [projectKey, repositorySlug] = repository.split('/');
diff --git a/lib/platform/bitbucket/bb-got-wrapper.ts b/lib/platform/bitbucket/bb-got-wrapper.ts
index bf816eb83ee6dd9f3cf35bb9a60b0d40757f9af0..11690713812f9a3b0c14b6640700e78a81908130 100644
--- a/lib/platform/bitbucket/bb-got-wrapper.ts
+++ b/lib/platform/bitbucket/bb-got-wrapper.ts
@@ -16,7 +16,7 @@ async function get(path: string, options: IGotApiOptions & got.GotJSONOptions) {
     timeout: 60 * 1000,
     json: true,
     basic: false,
-    ...hostRules.find({ platform: 'bitbucket', host }),
+    ...hostRules.find({ hostType: 'bitbucket', host }),
     ...options,
   };
   const url = URL.resolve(endpoint, path);
diff --git a/lib/platform/bitbucket/index.ts b/lib/platform/bitbucket/index.ts
index 578187bd8c9cfd2f1fe84262c150f09ffc694159..78aba1a215f642add7578444a1c1387523abf093 100644
--- a/lib/platform/bitbucket/index.ts
+++ b/lib/platform/bitbucket/index.ts
@@ -70,7 +70,7 @@ export async function initRepo({
   localDir: string;
 }) {
   logger.debug(`initRepo("${repository}")`);
-  const opts = hostRules.find({ platform: 'bitbucket' });
+  const opts = hostRules.find({ hostType: 'bitbucket' });
   api.reset();
   config = {} as any;
   // TODO: get in touch with @rarkins about lifting up the caching into the app layer
diff --git a/lib/platform/github/gh-got-wrapper.js b/lib/platform/github/gh-got-wrapper.js
index 64f33f85c4fb334031a5197a1c6b9de0bf65ebe4..0b0705f5b748d43902914923433732d294bc6dc3 100644
--- a/lib/platform/github/gh-got-wrapper.js
+++ b/lib/platform/github/gh-got-wrapper.js
@@ -17,7 +17,7 @@ async function get(path, options, retries = 5) {
   const opts = {
     // TODO: Move to configurable host rules, or use utils/got
     timeout: 60 * 1000,
-    ...hostRules.find({ platform: 'github', host }),
+    ...hostRules.find({ hostType: 'github', host }),
     ...options,
   };
   delete opts.endpoint;
diff --git a/lib/platform/github/index.js b/lib/platform/github/index.js
index e3373ecfcebe2153c972cbdd738aa672e82adc40..3040d3b20f6c8cf118fbb0731a7996b52f1f8cec 100644
--- a/lib/platform/github/index.js
+++ b/lib/platform/github/index.js
@@ -19,7 +19,7 @@ const defaultConfigFile = configFileNames[0];
 let config = {};
 
 const defaults = {
-  platform: 'github',
+  hostType: 'github',
   endpoint: 'https://api.github.com/',
 };
 
@@ -138,13 +138,12 @@ async function initRepo({
   // config is used by the platform api itself, not necessary for the app layer to know
   cleanRepo();
   const opts = hostRules.find({
-    platform: 'github',
+    hostType: 'github',
   });
   config.isGhe =
     opts.endpoint && !opts.endpoint.startsWith('https://api.github.com');
   config.renovateUsername = renovateUsername;
   config.localDir = localDir;
-  config.platform = 'github';
   config.repository = repository;
   [config.repositoryOwner, config.repositoryName] = repository.split('/');
   config.gitPrivateKey = gitPrivateKey;
diff --git a/lib/platform/gitlab/gl-got-wrapper.js b/lib/platform/gitlab/gl-got-wrapper.js
index 9d4a90add78a8aa7b726edd716f682a7fc407560..2090b391232e4b506aa101f2ca830803d7762ed5 100644
--- a/lib/platform/gitlab/gl-got-wrapper.js
+++ b/lib/platform/gitlab/gl-got-wrapper.js
@@ -13,7 +13,7 @@ async function get(path, options, retries = 5) {
   const opts = {
     // TODO: Move to configurable host rules, or use utils/got
     timeout: 60 * 1000,
-    ...hostRules.find({ platform: 'gitlab', host }),
+    ...hostRules.find({ hostType: 'gitlab', host }),
     ...options,
   };
   const url = URL.resolve(endpoint, path);
diff --git a/lib/platform/gitlab/index.js b/lib/platform/gitlab/index.js
index 837efc11b080146ec21d58f9993ce8493f667971..2d08910cc9b66fad7760a47d32f5d16dcdd9d022 100644
--- a/lib/platform/gitlab/index.js
+++ b/lib/platform/gitlab/index.js
@@ -7,7 +7,7 @@ const GitStorage = require('../git/storage');
 
 let config = {};
 const defaults = {
-  platform: 'gitlab',
+  hostType: 'gitlab',
   endpoint: 'https://gitlab.com/api/v4/',
 };
 
@@ -72,8 +72,8 @@ function initPlatform({ endpoint, token }) {
     get.setEndpoint(res.endpoint);
     defaults.endpoint = res.endpoint;
   } else {
-    logger.info('Using default GitLab endpoint: ' + res.endpoint);
     res.endpoint = defaults.endpoint;
+    logger.info('Using default GitLab endpoint: ' + res.endpoint);
   }
   // TODO: Add a connection check that endpoint/token combination are valid
   return res;
@@ -139,7 +139,7 @@ async function initRepo({ repository, gitFs, localDir }) {
     logger.debug('Enabling Git FS');
     const { host, protocol } = URL.parse(defaults.endpoint);
     const opts = hostRules.find({
-      platform: 'gitlab',
+      hostType: 'gitlab',
       host,
     });
     const url = GitStorage.getUrl({
diff --git a/lib/platform/index.js b/lib/platform/index.js
index 884f446b4585fc7b9c40154456b88a86d7fee065..5ffa7708c5a3bfa0e44e9aab80178d11a6c92b11 100644
--- a/lib/platform/index.js
+++ b/lib/platform/index.js
@@ -37,7 +37,7 @@ async function initPlatform(config) {
     token = base64(`${config.username}:${config.password}`);
   }
   const platformRule = {
-    platform: returnConfig.platform,
+    hostType: returnConfig.platform,
     endpoint: returnConfig.endpoint,
     token,
     username: returnConfig.username,
diff --git a/lib/util/got/host-rules.js b/lib/util/got/host-rules.js
index 0586916e70957c9b25e05c8abe3b47255b4988b8..9afc87f47f5f090c183901e0f9a38799781fcc1e 100644
--- a/lib/util/got/host-rules.js
+++ b/lib/util/got/host-rules.js
@@ -10,13 +10,13 @@ module.exports = got.create({
     timeout: 60 * 1000,
   },
   handler: (options, next) => {
-    const { platform, ...opts } = options;
+    const { hostType, ...opts } = options;
     if (!options.hostname) {
       return next(opts);
     }
     const hostRule = hostRules.find({
       host: options.hostname,
-      platform,
+      hostType,
     });
     if (!hostRule) {
       return next(opts);
diff --git a/lib/util/host-rules.ts b/lib/util/host-rules.ts
index 44b3624f42dd5206cfb1d9952d9737b028b6e3f2..86427874b1184eab5b628c70e59193cad1357e2c 100644
--- a/lib/util/host-rules.ts
+++ b/lib/util/host-rules.ts
@@ -1,13 +1,5 @@
 import URL from 'url';
 
-export const defaults: IDict<IPlatformConfig> = {
-  bitbucket: { name: 'Bitbucket', endpoint: 'https://api.bitbucket.org/' },
-  'bitbucket-server': { name: 'Bitbucket Server' },
-  github: { name: 'GitHub', endpoint: 'https://api.github.com/' },
-  gitlab: { name: 'GitLab', endpoint: 'https://gitlab.com/api/v4/' },
-  azure: { name: 'Azure DevOps' },
-};
-
 // TODO: add known properties
 export interface IPlatformConfig {
   [prop: string]: any;
@@ -19,31 +11,31 @@ export interface IPlatformConfig {
 interface IDict<T> {
   [key: string]: T;
 }
-const platforms: IDict<IPlatformConfig> = {};
+const hostTypes: IDict<IPlatformConfig> = {};
 const hostsOnly: IDict<IPlatformConfig> = {};
 
 export function update(params: IPlatformConfig) {
-  const { platform } = params;
-  if (!platform) {
+  const { hostType } = params;
+  if (!hostType) {
     if (params.endpoint) {
       const { host } = URL.parse(params.endpoint);
       hostsOnly[host!] = params;
       return true;
     }
     throw new Error(
-      'Failed to set configuration: no platform or endpoint specified'
+      'Failed to set configuration: no hostType or endpoint specified'
     );
   }
   const config = { ...params };
   const { endpoint } = config;
   if (!endpoint) {
     // istanbul ignore if
-    if (platform === 'docker') {
-      platforms.docker = params;
+    if (hostType === 'docker') {
+      hostTypes.docker = params;
       return true;
     }
     throw new Error(
-      `Failed to configure platform '${platform}': no endpoint defined`
+      `Failed to configure hostType '${hostType}': no endpoint defined`
     );
   }
   config.endpoint = endpoint.replace(/[^/]$/, '$&/');
@@ -54,42 +46,42 @@ export function update(params: IPlatformConfig) {
   host = host || (endpoint && URL.parse('http://' + endpoint).host);
   if (!host) {
     throw new Error(
-      `Failed to configure platform '${platform}': no host for endpoint '${endpoint}'`
+      `Failed to configure hostType '${hostType}': no host for endpoint '${endpoint}'`
     );
   }
-  platforms[platform] = { ...platforms[platform] };
+  hostTypes[hostType] = { ...hostTypes[hostType] };
   logger.debug({ config }, 'Setting hostRule');
-  platforms[platform][host] = { ...platforms[platform][host], ...config };
+  hostTypes[hostType][host] = { ...hostTypes[hostType][host], ...config };
   return true;
 }
 
 export function find(
   {
-    platform,
+    hostType,
     host,
     endpoint,
-  }: { platform: string; host?: string; endpoint?: string },
+  }: { hostType: string; host?: string; endpoint?: string },
   overrides?: IPlatformConfig
 ) {
   const massagedHost =
     host || (endpoint ? URL.parse(endpoint).host : undefined);
-  if (!platforms[platform]) {
+  if (!hostTypes[hostType]) {
     if (massagedHost && hostsOnly[massagedHost]) {
       return merge(hostsOnly[massagedHost], overrides);
     }
     return merge(null, overrides);
   }
   // istanbul ignore if
-  if (platform === 'docker') {
-    if (platforms.docker.platform === 'docker') {
-      return merge(platforms.docker, overrides);
+  if (hostType === 'docker') {
+    if (hostTypes.docker.hostType === 'docker') {
+      return merge(hostTypes.docker, overrides);
     }
-    return merge(platforms.docker[massagedHost!], overrides);
+    return merge(hostTypes.docker[massagedHost!], overrides);
   }
   if (massagedHost) {
-    return merge(platforms[platform][massagedHost], overrides);
+    return merge(hostTypes[hostType][massagedHost], overrides);
   }
-  const configs = Object.values(platforms[platform]);
+  const configs = Object.values(hostTypes[hostType]);
   let config;
   if (configs.length === 1) {
     [config] = configs;
@@ -97,8 +89,8 @@ export function find(
   return merge(config, overrides);
 }
 
-export function hosts({ platform }: { platform: string }) {
-  return Object.keys({ ...platforms[platform] });
+export function hosts({ hostType }: { hostType: string }) {
+  return Object.keys({ ...hostTypes[hostType] });
 }
 
 function merge(config: IPlatformConfig | null, overrides?: IPlatformConfig) {
@@ -115,5 +107,5 @@ function merge(config: IPlatformConfig | null, overrides?: IPlatformConfig) {
 }
 
 export function clear() {
-  Object.keys(platforms).forEach(key => delete platforms[key]);
+  Object.keys(hostTypes).forEach(key => delete hostTypes[key]);
 }
diff --git a/lib/workers/pr/changelog/source-github.js b/lib/workers/pr/changelog/source-github.js
index a9870c86caf0e855e058974501f8f4e8905f1102..f5f7488787f6f2f8bb50838400002bb8471fbbe5 100644
--- a/lib/workers/pr/changelog/source-github.js
+++ b/lib/workers/pr/changelog/source-github.js
@@ -56,7 +56,7 @@ async function getChangeLogJSON({
   const { protocol, host, pathname } = URL.parse(sourceUrl);
   const githubBaseURL = `${protocol}//${host}/`;
   const config = hostRules.find({
-    platform: 'github',
+    hostType: 'github',
     host: host === 'github.com' ? 'api.github.com' : host,
   });
   if (!config) {
diff --git a/renovate-schema.json b/renovate-schema.json
index eecf5bb8bcfc789ef0b255b93d9466985e780927..89af15ae9079108b0cfce7d95d49444d1f4d753c 100644
--- a/renovate-schema.json
+++ b/renovate-schema.json
@@ -1159,7 +1159,20 @@
     },
     "hostRules": {
       "description": "Host rules/configuration including credentials",
-      "type": "array"
+      "type": "array",
+      "items": {
+        "allOf": [
+          {
+            "type": "object",
+            "properties": {
+              "hostType": {
+                "description": "hostType for a package rule. Can be a platform name or a datasource name",
+                "type": "string"
+              }
+            }
+          }
+        ]
+      }
     },
     "prBodyDefinitions": {
       "description": "Table column definitions for use in PR tables",
diff --git a/test/config/__snapshots__/env.spec.js.snap b/test/config/__snapshots__/env.spec.js.snap
index 035f17cdf4805bb65615192e8350b2ad82f0aea3..aa4282aec6a8f8560284294f1540eecebe14a003 100644
--- a/test/config/__snapshots__/env.spec.js.snap
+++ b/test/config/__snapshots__/env.spec.js.snap
@@ -42,7 +42,7 @@ Object {
   "hostRules": Array [
     Object {
       "endpoint": "https://api.github.com/",
-      "platform": "github",
+      "hostType": "github",
       "token": "a github.com token",
     },
   ],
@@ -78,8 +78,8 @@ exports[`config/env .getConfig(env) supports docker username/password 1`] = `
 Object {
   "hostRules": Array [
     Object {
+      "hostType": "docker",
       "password": "some-password",
-      "platform": "docker",
       "username": "some-username",
     },
   ],
diff --git a/test/config/__snapshots__/migration.spec.js.snap b/test/config/__snapshots__/migration.spec.js.snap
index 762ab39e601f01c616b638a349319c9fa5a4e81b..e1cca575cd0f21a5c9b9b8db30efc22ee407dedd 100644
--- a/test/config/__snapshots__/migration.spec.js.snap
+++ b/test/config/__snapshots__/migration.spec.js.snap
@@ -121,6 +121,7 @@ Object {
   "patch": Object {
     "automerge": true,
   },
+  "platform": "github",
   "postUpdateOptions": Array [
     "gomodTidy",
   ],
diff --git a/test/config/cli.spec.js b/test/config/cli.spec.js
index 57862e79797678de20a72f2d86878740d304264c..9f59b361f71479045929742c2fd2fd4d772cd5a8 100644
--- a/test/config/cli.spec.js
+++ b/test/config/cli.spec.js
@@ -76,13 +76,13 @@ describe('config/cli', () => {
     });
     it('parses json lists correctly', () => {
       argv.push(
-        `--host-rules=[{"host":"docker.io","platform":"docker","username":"user","password":"password"}]`
+        `--host-rules=[{"host":"docker.io","hostType":"docker","username":"user","password":"password"}]`
       );
       cli.getConfig(argv).should.deep.equal({
         hostRules: [
           {
             host: 'docker.io',
-            platform: 'docker',
+            hostType: 'docker',
             username: 'user',
             password: 'password',
           },
diff --git a/test/config/migration.spec.js b/test/config/migration.spec.js
index 58bb1bab37354d7d652301b24c49c2fc4e4080a9..3a9f8d60cbc9f6fb1b0bdedbb9e2527d70373abe 100644
--- a/test/config/migration.spec.js
+++ b/test/config/migration.spec.js
@@ -7,6 +7,14 @@ describe('config/migration', () => {
       const config = {
         endpoints: [{}],
         enabled: true,
+        platform: 'github',
+        hostRules: [
+          {
+            platform: 'docker',
+            username: 'some-username',
+            password: 'some-password',
+          },
+        ],
         extends: [':js-app', 'config:library'],
         maintainYarnLock: true,
         onboarding: 'false',
@@ -99,6 +107,7 @@ describe('config/migration', () => {
       expect(migratedConfig.depTypes).not.toBeDefined();
       expect(migratedConfig.automerge).toEqual(false);
       expect(migratedConfig.packageRules).toHaveLength(7);
+      expect(migratedConfig.hostRules).toHaveLength(1);
     });
     it('migrates before and after schedules', () => {
       const config = {
diff --git a/test/datasource/__snapshots__/pypi.spec.js.snap b/test/datasource/__snapshots__/pypi.spec.js.snap
index 607b5894e6b9925f0de97e813ebb8f512a497842..af721ded899838eaa9ec25119a18ea1b9f762cd9 100644
--- a/test/datasource/__snapshots__/pypi.spec.js.snap
+++ b/test/datasource/__snapshots__/pypi.spec.js.snap
@@ -180,8 +180,8 @@ Array [
       "slashes": true,
     },
     Object {
+      "hostType": "pypi",
       "json": true,
-      "platform": "pypi",
     },
   ],
 ]
@@ -205,8 +205,8 @@ Array [
       "slashes": true,
     },
     Object {
+      "hostType": "pypi",
       "json": true,
-      "platform": "pypi",
     },
   ],
 ]
@@ -230,8 +230,8 @@ Array [
       "slashes": true,
     },
     Object {
+      "hostType": "pypi",
       "json": true,
-      "platform": "pypi",
     },
   ],
   Array [
@@ -250,8 +250,8 @@ Array [
       "slashes": true,
     },
     Object {
+      "hostType": "pypi",
       "json": true,
-      "platform": "pypi",
     },
   ],
 ]
diff --git a/test/platform/__snapshots__/index.spec.js.snap b/test/platform/__snapshots__/index.spec.js.snap
index 3bb3dbf79f743fb80cc913f2a01be086ac36315c..8a1a81343a78da72bef3940cf384018d2c7ff74b 100644
--- a/test/platform/__snapshots__/index.spec.js.snap
+++ b/test/platform/__snapshots__/index.spec.js.snap
@@ -141,8 +141,8 @@ Object {
   "hostRules": Array [
     Object {
       "endpoint": "https://api.bitbucket.org/",
+      "hostType": "bitbucket",
       "password": "123",
-      "platform": "bitbucket",
       "token": "YWJjOjEyMw==",
       "username": "abc",
     },
diff --git a/test/platform/azure/azure-got-wrapper.spec.js b/test/platform/azure/azure-got-wrapper.spec.js
index 6e414c202244e3c96cac0031447ae5262a2fb7a3..780284ab24c3d6d8be75a089ea4d5ab9e5f65234 100644
--- a/test/platform/azure/azure-got-wrapper.spec.js
+++ b/test/platform/azure/azure-got-wrapper.spec.js
@@ -15,7 +15,7 @@ describe('platform/azure/azure-got-wrapper', () => {
     });
     it('should set token and endpoint', async () => {
       hostRules.update({
-        platform: 'azure',
+        hostType: 'azure',
         token: 'token',
         endpoint: 'https://dev.azure.com/renovate12345',
       });
diff --git a/test/platform/bitbucket-server/index.spec.ts b/test/platform/bitbucket-server/index.spec.ts
index 30cbb322b787a4c373a6b2daa81b302007d1f773..f8992eade78794ab8938f50fe33826948c2fd47c 100644
--- a/test/platform/bitbucket-server/index.spec.ts
+++ b/test/platform/bitbucket-server/index.spec.ts
@@ -66,7 +66,7 @@ describe('platform/bitbucket-server', () => {
             ? 'https://stash.renovatebot.com/vcs/'
             : 'https://stash.renovatebot.com';
         hostRules.find.mockReturnValue({
-          platform: 'bitbucket-server',
+          hostType: 'bitbucket-server',
           endpoint,
           username: 'abc',
           password: '123',
diff --git a/test/platform/bitbucket/bb-got-wrapper.spec.ts b/test/platform/bitbucket/bb-got-wrapper.spec.ts
index cd62ebd78447d3228154a2078b1420f81ab28ba1..4e337fc8ea61d18a9363dabd789ef4c49bbc6d41 100644
--- a/test/platform/bitbucket/bb-got-wrapper.spec.ts
+++ b/test/platform/bitbucket/bb-got-wrapper.spec.ts
@@ -15,7 +15,7 @@ describe('platform/gl-got-wrapper', () => {
     // clean up hostRules
     hostRules.clear();
     hostRules.update({
-      platform: 'bitbucket',
+      hostType: 'bitbucket',
       endpoint: 'https://api.bitbucket.org',
       token: 'token',
     });
diff --git a/test/platform/bitbucket/index.spec.ts b/test/platform/bitbucket/index.spec.ts
index d61ce742c65fc20bc92dfc044f66e96198b078dc..5edb826614a2bf377af668c41e9a4777fffbbfb2 100644
--- a/test/platform/bitbucket/index.spec.ts
+++ b/test/platform/bitbucket/index.spec.ts
@@ -40,7 +40,7 @@ describe('platform/bitbucket', () => {
     // clean up hostRules
     hostRules.clear();
     hostRules.find.mockReturnValue({
-      platform: 'bitbucket',
+      hostType: 'bitbucket',
       endpoint: 'https://bitbucket.org',
       username: 'abc',
       password: '123',
diff --git a/test/platform/github/index.spec.js b/test/platform/github/index.spec.js
index 76206b1133c53f0d3b412e476275b55cb2f50322..3dd49e202a5388eeaf58921dee2230956d10d759 100644
--- a/test/platform/github/index.spec.js
+++ b/test/platform/github/index.spec.js
@@ -15,7 +15,7 @@ describe('platform/github', () => {
     hostRules = require('../../../lib/util/host-rules');
     delete global.gitAuthor;
     hostRules.find.mockReturnValue({
-      platform: 'github',
+      hostType: 'github',
       endpoint: 'https://api.github.com',
       token: 'abc123',
     });
@@ -1673,7 +1673,7 @@ describe('platform/github', () => {
     });
     it('returns not-updated pr body for GHE', async () => {
       hostRules.find.mockReturnValue({
-        platform: 'github',
+        hostType: 'github',
         endpoint: 'https://github.company.com',
         token: 'abc123',
       });
diff --git a/test/util/__snapshots__/host-rules.spec.js.snap b/test/util/__snapshots__/host-rules.spec.js.snap
index 03060ad866bc7e47e0d6bd1b49b0cf4ecfb81ef2..89d0a5b35e3835a8eaec33fff98893538e1627f3 100644
--- a/test/util/__snapshots__/host-rules.spec.js.snap
+++ b/test/util/__snapshots__/host-rules.spec.js.snap
@@ -3,8 +3,8 @@
 exports[`util/host-rules find() allows overrides 1`] = `
 Object {
   "endpoint": "endpoint/",
+  "hostType": "github",
   "other": "data",
-  "platform": "github",
   "token": "secret",
 }
 `;
@@ -24,7 +24,7 @@ Object {
 exports[`util/host-rules find() matches on endpoint 1`] = `
 Object {
   "endpoint": "https://nuget.local/api/",
-  "platform": "nuget",
+  "hostType": "nuget",
   "token": "abc",
 }
 `;
@@ -32,7 +32,7 @@ Object {
 exports[`util/host-rules find() matches on endpoint subresource 1`] = `
 Object {
   "endpoint": "https://nuget.local/api/",
-  "platform": "nuget",
+  "hostType": "nuget",
   "token": "abc",
 }
 `;
@@ -41,8 +41,8 @@ exports[`util/host-rules find() needs exact host matches 1`] = `
 Object {
   "endpoint": "endpoint/",
   "host": "nuget.org",
+  "hostType": "nuget",
   "password": "p4$$w0rd",
-  "platform": "nuget",
   "username": "root",
 }
 `;
diff --git a/test/util/host-rules.spec.js b/test/util/host-rules.spec.js
index 1b9118711c588b3801c9504a39df6f9276abc27a..8fd2c6cba6b38cf84e972e332b2f869b14e6c5c7 100644
--- a/test/util/host-rules.spec.js
+++ b/test/util/host-rules.spec.js
@@ -5,22 +5,22 @@ describe('util/host-rules', () => {
     clear();
   });
   describe('update()', () => {
-    it('throws if no platform ', () => {
+    it('throws if no hostType ', () => {
       expect(() => update({})).toThrow(
-        'Failed to set configuration: no platform or endpoint specified'
+        'Failed to set configuration: no hostType or endpoint specified'
       );
     });
     it('throws if no endpoint ', () => {
-      expect(() => update({ platform: 'azure' })).toThrow(
-        `Failed to configure platform 'azure': no endpoint defined`
+      expect(() => update({ hostType: 'azure' })).toThrow(
+        `Failed to configure hostType 'azure': no endpoint defined`
       );
     });
 
     it('throws if invalid endpoint ', () => {
       expect(() =>
-        update({ platform: 'azure', endpoint: '/some/path' })
+        update({ hostType: 'azure', endpoint: '/some/path' })
       ).toThrow(
-        `Failed to configure platform 'azure': no host for endpoint '/some/path'`
+        `Failed to configure hostType 'azure': no host for endpoint '/some/path'`
       );
     });
     it('supports endpoint-only', () => {
@@ -35,7 +35,7 @@ describe('util/host-rules', () => {
   describe('find()', () => {
     it('allows overrides', () => {
       update({
-        platform: 'github',
+        hostType: 'github',
         endpoint: 'endpoint',
         token: 'token',
         other: 'data',
@@ -45,49 +45,49 @@ describe('util/host-rules', () => {
         other: null,
         foo: undefined,
       };
-      expect(find({ platform: 'github' }, overrides)).toMatchSnapshot();
+      expect(find({ hostType: 'github' }, overrides)).toMatchSnapshot();
       expect(
-        find({ platform: 'github', host: 'api.github.com' }, overrides)
+        find({ hostType: 'github', host: 'api.github.com' }, overrides)
       ).toMatchSnapshot();
       expect(
-        find({ platform: 'github', host: 'example.com' }, overrides)
+        find({ hostType: 'github', host: 'example.com' }, overrides)
       ).toMatchSnapshot();
     });
     it('needs exact host matches', () => {
       update({
-        platform: 'nuget',
+        hostType: 'nuget',
         endpoint: 'endpoint',
         host: 'nuget.org',
         username: 'root',
         password: 'p4$$w0rd',
       });
-      expect(find({ platform: 'nuget', host: 'nuget.org' })).toMatchSnapshot();
+      expect(find({ hostType: 'nuget', host: 'nuget.org' })).toMatchSnapshot();
       expect(
-        find({ platform: 'nuget', host: 'not.nuget.org' })
+        find({ hostType: 'nuget', host: 'not.nuget.org' })
       ).toMatchSnapshot();
       expect(
-        find({ platform: 'nuget', host: 'not-nuget.org' })
+        find({ hostType: 'nuget', host: 'not-nuget.org' })
       ).toMatchSnapshot();
     });
     it('matches on endpoint', () => {
       update({
-        platform: 'nuget',
+        hostType: 'nuget',
         endpoint: 'https://nuget.local/api',
         token: 'abc',
       });
       expect(
-        find({ platform: 'nuget', endpoint: 'https://nuget.local/api' })
+        find({ hostType: 'nuget', endpoint: 'https://nuget.local/api' })
       ).toMatchSnapshot();
     });
     it('matches on endpoint subresource', () => {
       update({
-        platform: 'nuget',
+        hostType: 'nuget',
         endpoint: 'https://nuget.local/api',
         token: 'abc',
       });
       expect(
         find({
-          platform: 'nuget',
+          hostType: 'nuget',
           endpoint: 'https://nuget.local/api/sub-resource',
         })
       ).toMatchSnapshot();
diff --git a/test/workers/global/index.spec.js b/test/workers/global/index.spec.js
index 040d745c7a78044af6be83fc174c3504b7cc64cb..d2299cc21efb8212f40b8ca599b304bdda30b727 100644
--- a/test/workers/global/index.spec.js
+++ b/test/workers/global/index.spec.js
@@ -36,7 +36,7 @@ describe('lib/workers/global', () => {
       repositories: ['a', 'b'],
       hostRules: [
         {
-          platform: 'docker',
+          hostType: 'docker',
           host: 'docker.io',
           username: 'some-user',
           password: 'some-password',
diff --git a/test/workers/pr/changelog/index.spec.js b/test/workers/pr/changelog/index.spec.js
index 845dda2fa97a750facd0c83513b4aed70cbd852a..3be01f79bda3d24002a4d4e1b6a833191c831a1b 100644
--- a/test/workers/pr/changelog/index.spec.js
+++ b/test/workers/pr/changelog/index.spec.js
@@ -36,7 +36,7 @@ describe('workers/pr/changelog', () => {
       ghGot.mockClear();
       hostRules.clear();
       hostRules.update({
-        platform: 'github',
+        hostType: 'github',
         endpoint: 'https://api.github.com/',
       });
       await global.renovateCache.rmAll();
@@ -156,7 +156,7 @@ describe('workers/pr/changelog', () => {
     });
     it('supports github enterprise and github.com changelog', async () => {
       hostRules.update({
-        platform: 'github',
+        hostType: 'github',
         token: 'super_secret',
         endpoint: 'https://github-enterprise.example.com/',
       });
@@ -168,7 +168,7 @@ describe('workers/pr/changelog', () => {
     });
     it('supports github enterprise and github enterprise changelog', async () => {
       hostRules.update({
-        platform: 'github',
+        hostType: 'github',
         endpoint: 'https://github-enterprise.example.com/',
       });
       process.env.GITHUB_ENDPOINT = '';
diff --git a/website/docs/configuration-options.md b/website/docs/configuration-options.md
index f3e52b0c07a69c41190e3570e8603bd98ae276d2..4be7d8c9973c40c8a9879e7284cd5ae2c4226550 100644
--- a/website/docs/configuration-options.md
+++ b/website/docs/configuration-options.md
@@ -325,7 +325,7 @@ Example for configuring `docker` auth:
 {
   "hostRules": [
     {
-      "platform": "docker",
+      "hostType": "docker",
       "username": "<some-username>",
       "password": "<some-password>"
     }
@@ -333,6 +333,8 @@ Example for configuring `docker` auth:
 }
 ```
 
+### hostType
+
 ## ignoreDeprecated
 
 By default, Renovate won't update any packages to deprecated versions unless the package version was _already_ deprecated. The goal of this is to make sure you don't upgrade from a non-deprecated version to a deprecated one just because it's higher than the current version. If for some reason you wish to _force_ deprecated updates on Renovate, you can set `ignoreDeprecated` to `false`, but this is not recommended for most situations.
diff --git a/website/docs/docker.md b/website/docs/docker.md
index 5eb574d364bacf6dfb20fea564cebc2382463619..45d1939bb6839356ff3abcdb51133ae6f319f963 100644
--- a/website/docs/docker.md
+++ b/website/docs/docker.md
@@ -99,7 +99,7 @@ If you are running your own Renovate bot, add this to your `config.js`:
 module.exports = {
   hostRules: [
     {
-      platform: 'docker',
+      hostType: 'docker',
       username: '<your-username>',
       password: '<your-password>',
     },
diff --git a/website/docs/java.md b/website/docs/java.md
index 2828d228ebf46844707994047290d0ef21276b64..6e32ddc3cee863b518bbb5b2bf2ecebb35669acf 100644
--- a/website/docs/java.md
+++ b/website/docs/java.md
@@ -44,12 +44,12 @@ Here is an example configuration to work with custom Artifactory servers using a
 	    "enabled": true
 	},
 	"hostRules": [{
-	    "platform": "maven",
+	    "hostType": "maven",
         "endpoint": "https://artifactoryurl1/",
 	    "username": "artifactoryusername",
 	    "password": "artifactorypassword"
 	}, {
-	    "platform": "maven",
+	    "hostType": "maven",
         "endpoint": "https://artifactoryurl2/",
 	    "username": "artifactoryusername",
 	    "password": "artifactorypassword"
diff --git a/website/docs/nuget.md b/website/docs/nuget.md
index 42e28032760a09511bac3e3c65d9e8499a4a92c9..e8fa1b9224df822508f5f9d0e22724974be9250b 100644
--- a/website/docs/nuget.md
+++ b/website/docs/nuget.md
@@ -47,7 +47,7 @@ Credentials for authenticated/private feeds can be provided via host rules in th
 ```json
 "hostRules": [
   {
-    "platform": "nuget",
+    "hostType": "nuget",
     "endpoint": "http://example1.com/nuget",
     "username": "root",
     "password": "p4$$w0rd"