diff --git a/lib/modules/manager/terraform/__fixtures__/azureDevOpsModules.tf b/lib/modules/manager/terraform/__fixtures__/azureDevOpsModules.tf
new file mode 100644
index 0000000000000000000000000000000000000000..106bfdda44104a4f15b423adaa901169fbe61309
--- /dev/null
+++ b/lib/modules/manager/terraform/__fixtures__/azureDevOpsModules.tf
@@ -0,0 +1,11 @@
+module "foobar" {
+  source = "git@ssh.dev.azure.com:v3/MyOrg/MyProject/MyRepository?ref=v1.0.0"
+}
+
+module "gittags" {
+  source = "git::git@ssh.dev.azure.com:v3/MyOrg/MyProject/MyRepository?ref=v1.0.0"
+}
+
+module "gittags_subdir" {
+  source = "git::git@ssh.dev.azure.com:v3/MyOrg/MyProject/MyRepository//some-module/path?ref=v1.0.0"
+}
diff --git a/lib/modules/manager/terraform/extract.spec.ts b/lib/modules/manager/terraform/extract.spec.ts
index ff8c7001d5497af3230a63e47fc4ebd807ffa6cb..d1d82d8556787a9edf81d2a4b35f94e9befac82a 100644
--- a/lib/modules/manager/terraform/extract.spec.ts
+++ b/lib/modules/manager/terraform/extract.spec.ts
@@ -1,23 +1,25 @@
 import { join } from 'upath';
-import { fs, loadFixture } from '../../../../test/util';
+import { Fixtures } from '../../../../test/fixtures';
+import { fs } from '../../../../test/util';
 import { GlobalConfig } from '../../../config/global';
 import type { RepoGlobalConfig } from '../../../config/types';
 import { extractPackageFile } from '.';
 
-const modules = loadFixture('modules.tf');
-const bitbucketModules = loadFixture('bitbucketModules.tf');
-const providers = loadFixture('providers.tf');
-const docker = loadFixture('docker.tf');
+const modules = Fixtures.get('modules.tf');
+const bitbucketModules = Fixtures.get('bitbucketModules.tf');
+const azureDevOpsModules = Fixtures.get('azureDevOpsModules.tf');
+const providers = Fixtures.get('providers.tf');
+const docker = Fixtures.get('docker.tf');
 
 const tf2 = `module "relative" {
   source = "../fe"
 }
 `;
-const helm = loadFixture('helm.tf');
-const lockedVersion = loadFixture('lockedVersion.tf');
-const lockedVersionLockfile = loadFixture('rangeStrategy.hcl');
-const terraformBlock = loadFixture('terraformBlock.tf');
-const tfeWorkspaceBlock = loadFixture('tfeWorkspace.tf');
+const helm = Fixtures.get('helm.tf');
+const lockedVersion = Fixtures.get('lockedVersion.tf');
+const lockedVersionLockfile = Fixtures.get('rangeStrategy.hcl');
+const terraformBlock = Fixtures.get('terraformBlock.tf');
+const tfeWorkspaceBlock = Fixtures.get('tfeWorkspace.tf');
 
 const adminConfig: RepoGlobalConfig = {
   // `join` fixes Windows CI
@@ -52,6 +54,42 @@ describe('modules/manager/terraform/extract', () => {
       expect(res).toMatchSnapshot();
     });
 
+    it('extracts azureDevOps modules', async () => {
+      const res = await extractPackageFile(
+        azureDevOpsModules,
+        'modules.tf',
+        {}
+      );
+      expect(res).toEqual({
+        deps: [
+          {
+            currentValue: 'v1.0.0',
+            datasource: 'git-tags',
+            depName: 'MyOrg/MyProject/MyRepository',
+            depType: 'module',
+            packageName:
+              'git@ssh.dev.azure.com:v3/MyOrg/MyProject/MyRepository',
+          },
+          {
+            currentValue: 'v1.0.0',
+            datasource: 'git-tags',
+            depName: 'MyOrg/MyProject/MyRepository',
+            depType: 'module',
+            packageName:
+              'git@ssh.dev.azure.com:v3/MyOrg/MyProject/MyRepository',
+          },
+          {
+            currentValue: 'v1.0.0',
+            datasource: 'git-tags',
+            depName: 'MyOrg/MyProject/MyRepository//some-module/path',
+            depType: 'module',
+            packageName:
+              'git@ssh.dev.azure.com:v3/MyOrg/MyProject/MyRepository',
+          },
+        ],
+      });
+    });
+
     it('extracts providers', async () => {
       const res = await extractPackageFile(providers, 'providers.tf', {});
       expect(res.deps).toHaveLength(14);
diff --git a/lib/modules/manager/terraform/modules.spec.ts b/lib/modules/manager/terraform/modules.spec.ts
index 984b8189297818b601d8ed20ec0201451d8a6134..53b8d43bb1651c3a86cc5a74acfb61263b4b9ee8 100644
--- a/lib/modules/manager/terraform/modules.spec.ts
+++ b/lib/modules/manager/terraform/modules.spec.ts
@@ -1,4 +1,5 @@
 import {
+  azureDevOpsSshRefMatchRegex,
   bitbucketRefMatchRegex,
   gitTagsRefMatchRegex,
   githubRefMatchRegex,
@@ -115,4 +116,66 @@ describe('modules/manager/terraform/modules', () => {
       expect(dots.tag).toBe('v1.0.0');
     });
   });
+
+  describe('azureDevOpsSshRefMatchRegex', () => {
+    it('should split organization, project, repository and tag from source url', () => {
+      const ssh = azureDevOpsSshRefMatchRegex.exec(
+        'git@ssh.dev.azure.com:v3/MyOrg/MyProject/MyRepository?ref=1.0.0'
+      )?.groups;
+
+      expect(ssh).toEqual({
+        modulepath: '',
+        organization: 'MyOrg',
+        project: 'MyProject',
+        repository: 'MyRepository',
+        tag: '1.0.0',
+        url: 'git@ssh.dev.azure.com:v3/MyOrg/MyProject/MyRepository',
+      });
+    });
+
+    it('should split organization, project, repository and tag from source url with git prefix', () => {
+      const sshGit = azureDevOpsSshRefMatchRegex.exec(
+        'git::git@ssh.dev.azure.com:v3/MyOrg/MyProject/MyRepository?ref=1.0.0'
+      )?.groups;
+
+      expect(sshGit).toEqual({
+        modulepath: '',
+        organization: 'MyOrg',
+        project: 'MyProject',
+        repository: 'MyRepository',
+        tag: '1.0.0',
+        url: 'git@ssh.dev.azure.com:v3/MyOrg/MyProject/MyRepository',
+      });
+    });
+
+    it('should split organization, project, repository and tag from source url with subfolder', () => {
+      const subfolder = azureDevOpsSshRefMatchRegex.exec(
+        'git::git@ssh.dev.azure.com:v3/MyOrg/MyProject/MyRepository//some-module/path?ref=1.0.0'
+      )?.groups;
+
+      expect(subfolder).toEqual({
+        modulepath: '//some-module/path',
+        organization: 'MyOrg',
+        project: 'MyProject',
+        repository: 'MyRepository',
+        tag: '1.0.0',
+        url: 'git@ssh.dev.azure.com:v3/MyOrg/MyProject/MyRepository',
+      });
+    });
+
+    it('should parse alpha-numeric characters as well as dots, underscores, and dashes in repo names', () => {
+      const dots = azureDevOpsSshRefMatchRegex.exec(
+        'git::git@ssh.dev.azure.com:v3/MyOrg/MyProject/MyRepository//some-module/path?ref=v1.0.0'
+      )?.groups;
+
+      expect(dots).toEqual({
+        modulepath: '//some-module/path',
+        organization: 'MyOrg',
+        project: 'MyProject',
+        repository: 'MyRepository',
+        tag: 'v1.0.0',
+        url: 'git@ssh.dev.azure.com:v3/MyOrg/MyProject/MyRepository',
+      });
+    });
+  });
 });
diff --git a/lib/modules/manager/terraform/modules.ts b/lib/modules/manager/terraform/modules.ts
index cbb41c017f2367d5c7ba52aea7aabfd2f11c0f85..b90073a5d0a9e0a7a81e9f2fd48f7479d246cd17 100644
--- a/lib/modules/manager/terraform/modules.ts
+++ b/lib/modules/manager/terraform/modules.ts
@@ -18,6 +18,9 @@ export const bitbucketRefMatchRegex = regEx(
 export const gitTagsRefMatchRegex = regEx(
   /(?:git::)?(?<url>(?:http|https|ssh):\/\/(?:.*@)?(?<path>.*.*\/(?<project>.*\/.*)))\?ref=(?<tag>.*)$/
 );
+export const azureDevOpsSshRefMatchRegex = regEx(
+  /(?:git::)?(?<url>git@ssh\.dev\.azure\.com:v3\/(?<organization>[^/]*)\/(?<project>[^/]*)\/(?<repository>[^/]*))(?<modulepath>.*)?\?ref=(?<tag>.*)$/
+);
 const hostnameMatchRegex = regEx(/^(?<hostname>([\w|\d]+\.)+[\w|\d]+)/);
 
 export function extractTerraformModule(
@@ -39,6 +42,7 @@ export function analyseTerraformModule(dep: PackageDependency): void {
   const githubRefMatch = githubRefMatchRegex.exec(source);
   const bitbucketRefMatch = bitbucketRefMatchRegex.exec(source);
   const gitTagsRefMatch = gitTagsRefMatchRegex.exec(source);
+  const azureDevOpsSshRefMatch = azureDevOpsSshRefMatchRegex.exec(source);
 
   if (githubRefMatch?.groups) {
     dep.packageName = githubRefMatch.groups.project.replace(
@@ -71,6 +75,12 @@ export function analyseTerraformModule(dep: PackageDependency): void {
     }
     dep.currentValue = gitTagsRefMatch.groups.tag;
     dep.datasource = GitTagsDatasource.id;
+  } else if (azureDevOpsSshRefMatch?.groups) {
+    dep.depType = 'module';
+    dep.depName = `${azureDevOpsSshRefMatch.groups.organization}/${azureDevOpsSshRefMatch.groups.project}/${azureDevOpsSshRefMatch.groups.repository}${azureDevOpsSshRefMatch.groups.modulepath}`;
+    dep.packageName = azureDevOpsSshRefMatch.groups.url;
+    dep.currentValue = azureDevOpsSshRefMatch.groups.tag;
+    dep.datasource = GitTagsDatasource.id;
   } else if (source) {
     const moduleParts = source.split('//')[0].split('/');
     if (moduleParts[0] === '..') {