diff --git a/lib/platform/bitbucket-server/__snapshots__/index.spec.ts.snap b/lib/platform/bitbucket-server/__snapshots__/index.spec.ts.snap
index ee6f150c1344b4308f3e29b453b5ce9a29ce6ea3..1f3af18f51564d1abc46d2051597c12fda212d96 100644
--- a/lib/platform/bitbucket-server/__snapshots__/index.spec.ts.snap
+++ b/lib/platform/bitbucket-server/__snapshots__/index.spec.ts.snap
@@ -2406,14 +2406,14 @@ Object {
 }
 `;
 
-exports[`platform/bitbucket-server/index endpoint with no path initRepo() does not throw 1`] = `
+exports[`platform/bitbucket-server/index endpoint with no path initRepo() generates URL if API does not contain clone links 1`] = `
 Object {
   "defaultBranch": "master",
   "isFork": false,
 }
 `;
 
-exports[`platform/bitbucket-server/index endpoint with no path initRepo() does not throw 2`] = `
+exports[`platform/bitbucket-server/index endpoint with no path initRepo() generates URL if API does not contain clone links 2`] = `
 Array [
   Object {
     "headers": Object {
@@ -2442,7 +2442,79 @@ Array [
 ]
 `;
 
-exports[`platform/bitbucket-server/index endpoint with no path initRepo() throws empty 1`] = `
+exports[`platform/bitbucket-server/index endpoint with no path initRepo() throws REPOSITORY_EMPTY if there is no default branch 1`] = `
+Array [
+  Object {
+    "headers": Object {
+      "accept": "application/json",
+      "accept-encoding": "gzip, deflate",
+      "authorization": "Basic YWJjOjEyMw==",
+      "host": "stash.renovatebot.com",
+      "user-agent": "https://github.com/renovatebot/renovate",
+      "x-atlassian-token": "no-check",
+    },
+    "method": "GET",
+    "url": "https://stash.renovatebot.com/rest/api/1.0/projects/SOME/repos/repo",
+  },
+  Object {
+    "headers": Object {
+      "accept": "application/json",
+      "accept-encoding": "gzip, deflate",
+      "authorization": "Basic YWJjOjEyMw==",
+      "host": "stash.renovatebot.com",
+      "user-agent": "https://github.com/renovatebot/renovate",
+      "x-atlassian-token": "no-check",
+    },
+    "method": "GET",
+    "url": "https://stash.renovatebot.com/rest/api/1.0/projects/SOME/repos/repo/branches/default",
+  },
+]
+`;
+
+exports[`platform/bitbucket-server/index endpoint with no path initRepo() uses http url from API with injected auth if http url in API response 1`] = `
+Object {
+  "defaultBranch": "master",
+  "isFork": false,
+}
+`;
+
+exports[`platform/bitbucket-server/index endpoint with no path initRepo() uses http url from API with injected auth if http url in API response 2`] = `
+Array [
+  Object {
+    "headers": Object {
+      "accept": "application/json",
+      "accept-encoding": "gzip, deflate",
+      "authorization": "Basic YWJjOjEyMw==",
+      "host": "stash.renovatebot.com",
+      "user-agent": "https://github.com/renovatebot/renovate",
+      "x-atlassian-token": "no-check",
+    },
+    "method": "GET",
+    "url": "https://stash.renovatebot.com/rest/api/1.0/projects/SOME/repos/repo",
+  },
+  Object {
+    "headers": Object {
+      "accept": "application/json",
+      "accept-encoding": "gzip, deflate",
+      "authorization": "Basic YWJjOjEyMw==",
+      "host": "stash.renovatebot.com",
+      "user-agent": "https://github.com/renovatebot/renovate",
+      "x-atlassian-token": "no-check",
+    },
+    "method": "GET",
+    "url": "https://stash.renovatebot.com/rest/api/1.0/projects/SOME/repos/repo/branches/default",
+  },
+]
+`;
+
+exports[`platform/bitbucket-server/index endpoint with no path initRepo() uses ssh url from API if http not in API response 1`] = `
+Object {
+  "defaultBranch": "master",
+  "isFork": false,
+}
+`;
+
+exports[`platform/bitbucket-server/index endpoint with no path initRepo() uses ssh url from API if http not in API response 2`] = `
 Array [
   Object {
     "headers": Object {
@@ -6424,14 +6496,14 @@ Object {
 }
 `;
 
-exports[`platform/bitbucket-server/index endpoint with path initRepo() does not throw 1`] = `
+exports[`platform/bitbucket-server/index endpoint with path initRepo() generates URL if API does not contain clone links 1`] = `
 Object {
   "defaultBranch": "master",
   "isFork": false,
 }
 `;
 
-exports[`platform/bitbucket-server/index endpoint with path initRepo() does not throw 2`] = `
+exports[`platform/bitbucket-server/index endpoint with path initRepo() generates URL if API does not contain clone links 2`] = `
 Array [
   Object {
     "headers": Object {
@@ -6460,7 +6532,79 @@ Array [
 ]
 `;
 
-exports[`platform/bitbucket-server/index endpoint with path initRepo() throws empty 1`] = `
+exports[`platform/bitbucket-server/index endpoint with path initRepo() throws REPOSITORY_EMPTY if there is no default branch 1`] = `
+Array [
+  Object {
+    "headers": Object {
+      "accept": "application/json",
+      "accept-encoding": "gzip, deflate",
+      "authorization": "Basic YWJjOjEyMw==",
+      "host": "stash.renovatebot.com",
+      "user-agent": "https://github.com/renovatebot/renovate",
+      "x-atlassian-token": "no-check",
+    },
+    "method": "GET",
+    "url": "https://stash.renovatebot.com/vcs/rest/api/1.0/projects/SOME/repos/repo",
+  },
+  Object {
+    "headers": Object {
+      "accept": "application/json",
+      "accept-encoding": "gzip, deflate",
+      "authorization": "Basic YWJjOjEyMw==",
+      "host": "stash.renovatebot.com",
+      "user-agent": "https://github.com/renovatebot/renovate",
+      "x-atlassian-token": "no-check",
+    },
+    "method": "GET",
+    "url": "https://stash.renovatebot.com/vcs/rest/api/1.0/projects/SOME/repos/repo/branches/default",
+  },
+]
+`;
+
+exports[`platform/bitbucket-server/index endpoint with path initRepo() uses http url from API with injected auth if http url in API response 1`] = `
+Object {
+  "defaultBranch": "master",
+  "isFork": false,
+}
+`;
+
+exports[`platform/bitbucket-server/index endpoint with path initRepo() uses http url from API with injected auth if http url in API response 2`] = `
+Array [
+  Object {
+    "headers": Object {
+      "accept": "application/json",
+      "accept-encoding": "gzip, deflate",
+      "authorization": "Basic YWJjOjEyMw==",
+      "host": "stash.renovatebot.com",
+      "user-agent": "https://github.com/renovatebot/renovate",
+      "x-atlassian-token": "no-check",
+    },
+    "method": "GET",
+    "url": "https://stash.renovatebot.com/vcs/rest/api/1.0/projects/SOME/repos/repo",
+  },
+  Object {
+    "headers": Object {
+      "accept": "application/json",
+      "accept-encoding": "gzip, deflate",
+      "authorization": "Basic YWJjOjEyMw==",
+      "host": "stash.renovatebot.com",
+      "user-agent": "https://github.com/renovatebot/renovate",
+      "x-atlassian-token": "no-check",
+    },
+    "method": "GET",
+    "url": "https://stash.renovatebot.com/vcs/rest/api/1.0/projects/SOME/repos/repo/branches/default",
+  },
+]
+`;
+
+exports[`platform/bitbucket-server/index endpoint with path initRepo() uses ssh url from API if http not in API response 1`] = `
+Object {
+  "defaultBranch": "master",
+  "isFork": false,
+}
+`;
+
+exports[`platform/bitbucket-server/index endpoint with path initRepo() uses ssh url from API if http not in API response 2`] = `
 Array [
   Object {
     "headers": Object {
diff --git a/lib/platform/bitbucket-server/index.spec.ts b/lib/platform/bitbucket-server/index.spec.ts
index 926831e487e7f8567aa96fbc0523312807fe3632..06206b8dbc5865a16144af629eae48bbe9e37934 100644
--- a/lib/platform/bitbucket-server/index.spec.ts
+++ b/lib/platform/bitbucket-server/index.spec.ts
@@ -10,13 +10,57 @@ import { BranchStatus, PrState } from '../../types';
 import * as _git from '../../util/git';
 import { Platform } from '../common';
 
+function sshLink(projectKey: string, repositorySlug: string): string {
+  return `ssh://git@stash.renovatebot.com:7999/${projectKey.toLowerCase()}/${repositorySlug}.git`;
+}
+
+function httpLink(
+  endpointStr: string,
+  projectKey: string,
+  repositorySlug: string
+): string {
+  return `${endpointStr}scm/${projectKey.toLowerCase()}/${repositorySlug}.git`;
+}
+
 function repoMock(
   endpoint: URL | string,
   projectKey: string,
-  repositorySlug: string
+  repositorySlug: string,
+  options: { cloneUrl: { https: boolean; ssh: boolean } } = {
+    cloneUrl: { https: true, ssh: true },
+  }
 ) {
   const endpointStr = endpoint.toString();
-  const projectKeyLower = projectKey.toLowerCase();
+  const links: {
+    self: { href: string }[];
+    clone?: { href: string; name: string }[];
+  } = {
+    self: [
+      {
+        href: `${endpointStr}projects/${projectKey}/repos/${repositorySlug}/browse`,
+      },
+    ],
+  };
+
+  if (options.cloneUrl.https || options.cloneUrl.ssh) {
+    // This mimics the behavior of bb-server which does not include the clone property at all
+    // if ssh and https are both turned off
+    links.clone = [
+      options.cloneUrl.https
+        ? {
+            href: httpLink(endpointStr, projectKey, repositorySlug),
+            name: 'http',
+          }
+        : null,
+      options.cloneUrl.ssh
+        ? {
+            href: sshLink(projectKey, repositorySlug),
+            name: 'ssh',
+          }
+        : null,
+    ].filter(Boolean);
+  }
+
   return {
     slug: repositorySlug,
     id: 13076,
@@ -38,23 +82,7 @@ function repoMock(
       },
     },
     public: false,
-    links: {
-      clone: [
-        {
-          href: `${endpointStr}/scm/${projectKeyLower}/${repositorySlug}.git`,
-          name: 'http',
-        },
-        {
-          href: `ssh://git@stash.renovatebot.com:7999/${projectKeyLower}/${repositorySlug}.git`,
-          name: 'ssh',
-        },
-      ],
-      self: [
-        {
-          href: `${endpointStr}/projects/${projectKey}/repos/${repositorySlug}/browse`,
-        },
-      ],
-    },
+    links,
   };
 }
 
@@ -150,6 +178,8 @@ describe(getName(__filename), () => {
       let bitbucket: Platform;
       let hostRules: jest.Mocked<typeof import('../../util/host-rules')>;
       let git: jest.Mocked<typeof _git>;
+      const username = 'abc';
+      const password = '123';
 
       async function initRepo(config = {}): Promise<nock.Scope> {
         const scope = httpMock
@@ -192,13 +222,13 @@ describe(getName(__filename), () => {
             ? 'https://stash.renovatebot.com/vcs/'
             : 'https://stash.renovatebot.com';
         hostRules.find.mockReturnValue({
-          username: 'abc',
-          password: '123',
+          username,
+          password,
         });
         await bitbucket.initPlatform({
           endpoint,
-          username: 'abc',
-          password: '123',
+          username,
+          password,
         });
       });
 
@@ -266,12 +296,43 @@ describe(getName(__filename), () => {
           ).toMatchSnapshot();
           expect(httpMock.getTrace()).toMatchSnapshot();
         });
-        it('does not throw', async () => {
-          expect.assertions(2);
+
+        it('uses ssh url from API if http not in API response', async () => {
+          expect.assertions(3);
+          const responseMock = repoMock(url, 'SOME', 'repo', {
+            cloneUrl: { https: false, ssh: true },
+          });
           httpMock
             .scope(urlHost)
             .get(`${urlPath}/rest/api/1.0/projects/SOME/repos/repo`)
-            .reply(200, repoMock(url, 'SOME', 'repo'))
+            .reply(200, responseMock)
+            .get(
+              `${urlPath}/rest/api/1.0/projects/SOME/repos/repo/branches/default`
+            )
+            .reply(200, {
+              displayId: 'master',
+            });
+          const res = await bitbucket.initRepo({
+            endpoint: 'https://stash.renovatebot.com/vcs/',
+            repository: 'SOME/repo',
+            localDir: '',
+          });
+          expect(git.initRepo).toHaveBeenCalledWith(
+            expect.objectContaining({ url: sshLink('SOME', 'repo') })
+          );
+          expect(res).toMatchSnapshot();
+          expect(httpMock.getTrace()).toMatchSnapshot();
+        });
+
+        it('uses http url from API with injected auth if http url in API response', async () => {
+          expect.assertions(3);
+          const responseMock = repoMock(url, 'SOME', 'repo', {
+            cloneUrl: { https: true, ssh: true },
+          });
+          httpMock
+            .scope(urlHost)
+            .get(`${urlPath}/rest/api/1.0/projects/SOME/repos/repo`)
+            .reply(200, responseMock)
             .get(
               `${urlPath}/rest/api/1.0/projects/SOME/repos/repo/branches/default`
             )
@@ -283,11 +344,50 @@ describe(getName(__filename), () => {
             repository: 'SOME/repo',
             localDir: '',
           });
+          expect(git.initRepo).toHaveBeenCalledWith(
+            expect.objectContaining({
+              url: httpLink(url.toString(), 'SOME', 'repo').replace(
+                'https://',
+                `https://${username}:${password}@`
+              ),
+            })
+          );
+          expect(res).toMatchSnapshot();
+          expect(httpMock.getTrace()).toMatchSnapshot();
+        });
+
+        it('generates URL if API does not contain clone links', async () => {
+          expect.assertions(3);
+          const link = httpLink(url.toString(), 'SOME', 'repo');
+          const responseMock = repoMock(url, 'SOME', 'repo', {
+            cloneUrl: { https: false, ssh: false },
+          });
+          httpMock
+            .scope(urlHost)
+            .get(`${urlPath}/rest/api/1.0/projects/SOME/repos/repo`)
+            .reply(200, responseMock)
+            .get(
+              `${urlPath}/rest/api/1.0/projects/SOME/repos/repo/branches/default`
+            )
+            .reply(200, {
+              displayId: 'master',
+            });
+          git.getUrl.mockReturnValueOnce(link);
+          const res = await bitbucket.initRepo({
+            endpoint: 'https://stash.renovatebot.com/vcs/',
+            repository: 'SOME/repo',
+            localDir: '',
+          });
+          expect(git.initRepo).toHaveBeenCalledWith(
+            expect.objectContaining({
+              url: link,
+            })
+          );
           expect(res).toMatchSnapshot();
           expect(httpMock.getTrace()).toMatchSnapshot();
         });
 
-        it('throws empty', async () => {
+        it('throws REPOSITORY_EMPTY if there is no default branch', async () => {
           expect.assertions(2);
           httpMock
             .scope(urlHost)
diff --git a/lib/platform/bitbucket-server/index.ts b/lib/platform/bitbucket-server/index.ts
index 609255bf32d702d4c8679815e15ca2c0d1d9ffbc..7123068eadb176a310dcd4daf8d1b61c6d577b86 100644
--- a/lib/platform/bitbucket-server/index.ts
+++ b/lib/platform/bitbucket-server/index.ts
@@ -40,7 +40,14 @@ import {
   VulnerabilityAlert,
 } from '../common';
 import { smartTruncate } from '../utils/pr-body';
-import { BbbsRestPr, BbsConfig, BbsPr, BbsRestUserRef } from './types';
+import {
+  BbsConfig,
+  BbsPr,
+  BbsRestBranch,
+  BbsRestPr,
+  BbsRestRepo,
+  BbsRestUserRef,
+} from './types';
 import * as utils from './utils';
 
 /*
@@ -154,37 +161,15 @@ export async function initRepo({
     ignorePrAuthor,
   } as any;
 
-  const { host, pathname } = url.parse(defaults.endpoint);
-  const gitUrl = git.getUrl({
-    protocol: defaults.endpoint.split(':')[0] as GitProtocol,
-    auth: `${opts.username}:${opts.password}`,
-    host: `${host}${pathname}${
-      pathname.endsWith('/') ? '' : /* istanbul ignore next */ '/'
-    }scm`,
-    repository,
-  });
-
-  await git.initRepo({
-    ...config,
-    localDir,
-    url: gitUrl,
-    gitAuthorName: global.gitAuthor?.name,
-    gitAuthorEmail: global.gitAuthor?.email,
-    cloneSubmodules,
-  });
-
   try {
     const info = (
-      await bitbucketServerHttp.getJson<{
-        project: { key: string };
-        parent: string;
-      }>(
+      await bitbucketServerHttp.getJson<BbsRestRepo>(
         `./rest/api/1.0/projects/${config.projectKey}/repos/${config.repositorySlug}`
       )
     ).body;
     config.owner = info.project.key;
     logger.debug(`${repository} owner = ${config.owner}`);
-    const branchRes = await bitbucketServerHttp.getJson<{ displayId: string }>(
+    const branchRes = await bitbucketServerHttp.getJson<BbsRestBranch>(
       `./rest/api/1.0/projects/${config.projectKey}/repos/${config.repositorySlug}/branches/default`
     );
 
@@ -193,11 +178,49 @@ export async function initRepo({
       throw new Error(REPOSITORY_EMPTY);
     }
 
+    let cloneUrl = info.links.clone?.find(({ name }) => name === 'http');
+    if (!cloneUrl) {
+      // Http access might be disabled, try to find ssh url in this case
+      cloneUrl = info.links.clone?.find(({ name }) => name === 'ssh');
+    }
+
+    let gitUrl: string;
+    if (!cloneUrl) {
+      // Fallback to generating the url if the API didn't give us an URL
+      const { host, pathname } = url.parse(defaults.endpoint);
+      gitUrl = git.getUrl({
+        protocol: defaults.endpoint.split(':')[0] as GitProtocol,
+        auth: `${opts.username}:${opts.password}`,
+        host: `${host}${pathname}${
+          pathname.endsWith('/') ? '' : /* istanbul ignore next */ '/'
+        }scm`,
+        repository,
+      });
+    } else if (cloneUrl.name === 'http') {
+      // Inject auth into the API provided URL
+      const repoUrl = url.parse(cloneUrl.href);
+      repoUrl.auth = `${opts.username}:${opts.password}`;
+      gitUrl = url.format(repoUrl);
+    } else {
+      // SSH urls can be used directly
+      gitUrl = cloneUrl.href;
+    }
+
+    await git.initRepo({
+      ...config,
+      localDir,
+      url: gitUrl,
+      gitAuthorName: global.gitAuthor?.name,
+      gitAuthorEmail: global.gitAuthor?.email,
+      cloneSubmodules,
+    });
+
     config.mergeMethod = 'merge';
     const repoConfig: RepoResult = {
       defaultBranch: branchRes.body.displayId,
       isFork: !!info.parent,
     };
+
     return repoConfig;
   } catch (err) /* istanbul ignore next */ {
     if (err.statusCode === 404) {
@@ -240,7 +263,7 @@ export async function getPr(
     return null;
   }
 
-  const res = await bitbucketServerHttp.getJson<BbbsRestPr>(
+  const res = await bitbucketServerHttp.getJson<BbsRestPr>(
     `./rest/api/1.0/projects/${config.projectKey}/repos/${config.repositorySlug}/pull-requests/${prNo}`,
     { useCache: !refreshCache }
   );
@@ -799,7 +822,7 @@ export async function createPr({
     }));
   }
 
-  const body: PartialDeep<BbbsRestPr> = {
+  const body: PartialDeep<BbsRestPr> = {
     title,
     description,
     fromRef: {
@@ -810,9 +833,9 @@ export async function createPr({
     },
     reviewers,
   };
-  let prInfoRes: HttpResponse<BbbsRestPr>;
+  let prInfoRes: HttpResponse<BbsRestPr>;
   try {
-    prInfoRes = await bitbucketServerHttp.postJson<BbbsRestPr>(
+    prInfoRes = await bitbucketServerHttp.postJson<BbsRestPr>(
       `./rest/api/1.0/projects/${config.projectKey}/repos/${config.repositorySlug}/pull-requests`,
       { body }
     );
diff --git a/lib/platform/bitbucket-server/types.ts b/lib/platform/bitbucket-server/types.ts
index d3e64ae3b3d8182e2317949e4317e3914a9df6d7..5215317429dbc59253e76eaa39678a355067a202 100644
--- a/lib/platform/bitbucket-server/types.ts
+++ b/lib/platform/bitbucket-server/types.ts
@@ -38,7 +38,7 @@ export interface BbsRestUserRef {
   user: BbsRestUser;
 }
 
-export interface BbbsRestPr {
+export interface BbsRestPr {
   createdDate: string;
   description: string;
   fromRef: BbsRestBranchRef;
@@ -49,3 +49,15 @@ export interface BbbsRestPr {
   toRef: BbsRestBranchRef;
   version?: number;
 }
+
+export interface BbsRestRepo {
+  project: { key: string };
+  parent: string;
+  links: {
+    clone: { href: string; name: string }[];
+  };
+}
+
+export interface BbsRestBranch {
+  displayId: string;
+}
diff --git a/lib/platform/bitbucket-server/utils.ts b/lib/platform/bitbucket-server/utils.ts
index 0819ce062cf770b50204eed058b81285d6689f42..0d2eeaf1cdf46c18a3a3c79e478ed7be5d888002 100644
--- a/lib/platform/bitbucket-server/utils.ts
+++ b/lib/platform/bitbucket-server/utils.ts
@@ -4,7 +4,7 @@ import { HTTPError, Response } from 'got';
 import { PrState } from '../../types';
 import { HttpOptions, HttpPostOptions, HttpResponse } from '../../util/http';
 import { BitbucketServerHttp } from '../../util/http/bitbucket-server';
-import { BbbsRestPr, BbsPr } from './types';
+import { BbsPr, BbsRestPr } from './types';
 
 const BITBUCKET_INVALID_REVIEWERS_EXCEPTION =
   'com.atlassian.bitbucket.pull.InvalidPullRequestReviewersException';
@@ -18,7 +18,7 @@ const prStateMapping: any = {
   OPEN: PrState.Open,
 };
 
-export function prInfo(pr: BbbsRestPr): BbsPr {
+export function prInfo(pr: BbsRestPr): BbsPr {
   return {
     version: pr.version,
     number: pr.id,