diff --git a/lib/config/presets/__snapshots__/github.spec.ts.snap b/lib/config/presets/__snapshots__/github.spec.ts.snap
new file mode 100644
index 0000000000000000000000000000000000000000..9274f8368d7281ec8ab13cb59201bfc3f9131b20
--- /dev/null
+++ b/lib/config/presets/__snapshots__/github.spec.ts.snap
@@ -0,0 +1,13 @@
+// Jest Snapshot v1, https://goo.gl/fbAQLP
+
+exports[`config/presets/github fetchJSONFile() returns JSON 1`] = `
+Object {
+  "from": "api",
+}
+`;
+
+exports[`config/presets/github fetchJSONFile() returns renovate internal 1`] = `
+Object {
+  "from": "www",
+}
+`;
diff --git a/lib/config/presets/github.spec.ts b/lib/config/presets/github.spec.ts
index 3b3628251f609b64e39c173e24c5d3769390775b..3fd6c664ec7f689fcffe56645a8f14b84d2b08f0 100644
--- a/lib/config/presets/github.spec.ts
+++ b/lib/config/presets/github.spec.ts
@@ -18,6 +18,54 @@ describe('config/presets/github', () => {
     got.mockReset();
     return global.renovateCache.rmAll();
   });
+  describe('setInternalPreset()', () => {
+    it('allows override', () => {
+      github.setInternalPreset({ body: {} });
+    });
+  });
+  describe('fetchJSONFile()', () => {
+    beforeEach(() => {
+      delete global.repoCache.internalPresets;
+    });
+    it('returns JSON', async () => {
+      hostRules.find.mockReturnValueOnce({ token: 'abc' });
+      got.mockImplementationOnce(() => ({
+        body: {
+          content: Buffer.from('{"from":"api"}').toString('base64'),
+        },
+      }));
+      const res = await github.fetchJSONFile(
+        'some/repo',
+        'some-filename',
+        'https://api.github.com'
+      );
+      expect(res).toMatchSnapshot();
+    });
+    it('returns renovate internal', async () => {
+      hostRules.find.mockReturnValueOnce({ token: 'abc' });
+      got.mockImplementationOnce(() => ({
+        body: { from: 'www' },
+      }));
+      const res = await github.fetchJSONFile(
+        'renovatebot/presets',
+        'presets.json',
+        'https://api.github.com/'
+      );
+      expect(res).toMatchSnapshot();
+    });
+    it('throws platform error', async () => {
+      got.mockImplementationOnce(() => {
+        throw new Error();
+      });
+      await expect(
+        github.fetchJSONFile(
+          'renovatebot/presets',
+          'presets.json',
+          'https://api.github.com/'
+        )
+      ).rejects.toThrow(PLATFORM_FAILURE);
+    });
+  });
   describe('getPreset()', () => {
     it('passes up platform-failure', async () => {
       got.mockImplementationOnce(() => {
diff --git a/lib/config/presets/github.ts b/lib/config/presets/github.ts
index 11849e764a42ebcdcdda0853681878871d09fbc1..8bf562be16945006ef3fa8919ba86adb2dd40307 100644
--- a/lib/config/presets/github.ts
+++ b/lib/config/presets/github.ts
@@ -7,12 +7,40 @@ import { PLATFORM_TYPE_GITHUB } from '../../constants/platforms';
 
 const http = new Http(PLATFORM_TYPE_GITHUB);
 
-async function fetchJSONFile(
+export function setInternalPreset(content: { body: Preset }): void {
+  global.repoCache.internalPresets = Promise.resolve(content);
+}
+
+async function fetchInternalPreset(): Promise<Preset> {
+  const res = await http.getJson<Preset>(
+    'https://raw.githubusercontent.com/renovatebot/presets/master/presets.json'
+  );
+  return res.body;
+}
+
+function getInternalPreset(): Promise<Preset> {
+  global.repoCache.internalPresets =
+    global.repoCache.internalPresets || fetchInternalPreset();
+  return global.repoCache.internalPresets;
+}
+
+export async function fetchJSONFile(
   repo: string,
   fileName: string,
   endpoint: string
 ): Promise<Preset> {
   const url = `${endpoint}repos/${repo}/contents/${fileName}`;
+  if (
+    url ===
+    'https://api.github.com/repos/renovatebot/presets/contents/presets.json'
+  ) {
+    try {
+      const res = await getInternalPreset();
+      return res;
+    } catch (err) {
+      throw new Error(PLATFORM_FAILURE);
+    }
+  }
   const opts: HttpOptions = {
     headers: {
       accept: global.appMode