diff --git a/gems/gitlab-backup-cli/lib/gitlab/backup/cli/source_context.rb b/gems/gitlab-backup-cli/lib/gitlab/backup/cli/source_context.rb
index a73aec577b0d6220e75f635a754d9acee77d3d5e..a3d60e21108add2538de4fb76cae1bf3b1767cc0 100644
--- a/gems/gitlab-backup-cli/lib/gitlab/backup/cli/source_context.rb
+++ b/gems/gitlab-backup-cli/lib/gitlab/backup/cli/source_context.rb
@@ -13,8 +13,9 @@ def gitlab_version
         end
 
         def backup_basedir
-          # TODO: decouple from Rails codebase, load from gitlab.yml file
-          Rails.root.join('tmp/backups')
+          path = gitlab_config[env]['backup']['path']
+
+          absolute_path(path)
         end
 
         # CI Builds basepath
@@ -78,6 +79,17 @@ def env
 
         private
 
+        # Return a fullpath for a given path
+        #
+        # When the path is already a full one return itself as a Pathname
+        # otherwise uses gitlab_basepath as its base
+        # @param [String|Pathname] path
+        # @return [Pathname]
+        def absolute_path(path)
+          # Joins with gitlab_basepath when relative, otherwise return full path
+          Pathname(File.expand_path(path, gitlab_basepath))
+        end
+
         def gitlab_basepath
           return Pathname.new(GITLAB_PATH) if GITLAB_PATH
 
diff --git a/gems/gitlab-backup-cli/spec/fixtures/gitlab-relativepaths.yml b/gems/gitlab-backup-cli/spec/fixtures/gitlab-relativepaths.yml
new file mode 100644
index 0000000000000000000000000000000000000000..e681f25f2957b369e76042b069de556a1d7174e8
--- /dev/null
+++ b/gems/gitlab-backup-cli/spec/fixtures/gitlab-relativepaths.yml
@@ -0,0 +1,222 @@
+# # # # # # # # # # # # # # # # # #
+# GitLab application config file  #
+# # # # # # # # # # # # # # # # # #
+
+test:
+  object_store:
+    enabled: false
+  gravatar:
+    enabled: true
+  external_diffs:
+    enabled: false
+    # Diffs may be `always` external (the default), or they can be made external
+    # after they have become `outdated` (i.e., the MR is closed or a new version
+    # has been pushed).
+    # when: always
+    # The location where external diffs are stored (default: shared/external-diffs).
+    storage_path: tmp/tests/external-diffs
+    object_store:
+      enabled: false
+      remote_directory: external-diffs # The bucket name
+      connection:
+        provider: AWS # Only AWS supported at the moment
+        aws_access_key_id: AWS_ACCESS_KEY_ID
+        aws_secret_access_key: AWS_SECRET_ACCESS_KEY
+        region: us-east-1
+  lfs:
+    enabled: false
+    # The location where LFS objects are stored (default: shared/lfs-objects).
+    # storage_path: shared/lfs-objects
+    object_store:
+      enabled: false
+      remote_directory: lfs-objects # The bucket name
+      connection:
+        provider: AWS # Only AWS supported at the moment
+        aws_access_key_id: AWS_ACCESS_KEY_ID
+        aws_secret_access_key: AWS_SECRET_ACCESS_KEY
+        region: us-east-1
+  artifacts:
+    path: tmp/tests/artifacts
+    enabled: true
+    # The location where build artifacts are stored (default: shared/artifacts).
+    # path: shared/artifacts
+    object_store:
+      enabled: false
+      remote_directory: artifacts # The bucket name
+      connection:
+        provider: AWS # Only AWS supported at the moment
+        aws_access_key_id: AWS_ACCESS_KEY_ID
+        aws_secret_access_key: AWS_SECRET_ACCESS_KEY
+        region: us-east-1
+  uploads:
+    storage_path: tmp/tests/public
+    object_store:
+      enabled: false
+      connection:
+        provider: AWS # Only AWS supported at the moment
+        aws_access_key_id: AWS_ACCESS_KEY_ID
+        aws_secret_access_key: AWS_SECRET_ACCESS_KEY
+        region: us-east-1
+
+  terraform_state:
+    enabled: true
+    storage_path: tmp/tests/terraform_state
+    object_store:
+      enabled: false
+      remote_directory: terraform
+      connection:
+        provider: AWS # Only AWS supported at the moment
+        aws_access_key_id: AWS_ACCESS_KEY_ID
+        aws_secret_access_key: AWS_SECRET_ACCESS_KEY
+        region: us-east-1
+
+  ci_secure_files:
+    enabled: true
+    storage_path: tmp/tests/ci_secure_files
+    object_store:
+      enabled: false
+      remote_directory: ci-secure-files
+      connection:
+        provider: AWS # Only AWS supported at the moment
+        aws_access_key_id: AWS_ACCESS_KEY_ID
+        aws_secret_access_key: AWS_SECRET_ACCESS_KEY
+        region: us-east-1
+
+  gitlab:
+    host: localhost
+    port: 80
+
+    content_security_policy:
+      enabled: true
+      report_only: false
+      directives:
+        base_uri:
+        child_src:
+        connect_src:
+        default_src: "'self'"
+        font_src:
+        form_action:
+        frame_ancestors: "'self'"
+        frame_src: "'self' https://www.google.com/recaptcha/ https://www.recaptcha.net/ https://content.googleapis.com https://content-compute.googleapis.com https://content-cloudbilling.googleapis.com https://content-cloudresourcemanager.googleapis.com"
+        img_src: "* data: blob:"
+        manifest_src:
+        media_src:
+        object_src: "'none'"
+        script_src: "'self' 'unsafe-eval' http://localhost:* https://www.google.com/recaptcha/ https://www.recaptcha.net/ https://www.gstatic.com/recaptcha/ https://apis.google.com"
+        style_src: "'self' 'unsafe-inline'"
+        worker_src: "'self' blob:"
+        report_uri:
+
+    # When you run tests we clone and set up gitlab-shell
+    # In order to set it up correctly you need to specify
+    # your system username you use to run GitLab
+    # user: YOUR_USERNAME
+  pages:
+    path: tmp/tests/pages
+    object_store:
+      enabled: false
+      remote_directory: pages # The bucket name
+      connection:
+        provider: AWS
+        aws_access_key_id: AWS_ACCESS_KEY_ID
+        aws_secret_access_key: AWS_SECRET_ACCESS_KEY
+        region: us-east-1
+    local_store:
+      enabled: true
+      path: tmp/tests/pages
+  repositories:
+    storages:
+      default:
+        path: tmp/tests/repositories/
+        gitaly_address: unix:tmp/tests/gitaly/praefect.socket
+
+  gitaly:
+    client_path: tmp/tests/gitaly/_build/bin
+    token: secret
+  workhorse:
+    secret_file: tmp/gitlab_workhorse_test_secret
+  backup:
+    path: /tmp/gitlab/full/backups
+    gitaly_backup_path: tmp/tests/gitaly/_build/bin/gitaly-backup
+  gitlab_shell:
+    path: tmp/tests/gitlab-shell/
+    authorized_keys_file: tmp/tests/authorized_keys
+  issues_tracker:
+    redmine:
+      title: "Redmine"
+      project_url: "http://redmine/projects/:issues_tracker_id"
+      issues_url: "http://redmine/:project_id/:issues_tracker_id/:id"
+      new_issue_url: "http://redmine/projects/:issues_tracker_id/issues/new"
+    jira:
+      title: "Jira"
+      url: https://sample_company.atlassian.net
+      project_key: PROJECT
+
+  omniauth:
+    # enabled: true
+    allow_single_sign_on: true
+    external_providers: []
+
+    providers:
+      - { name: 'alicloud',
+          app_id: 'YOUR_APP_ID',
+          app_secret: 'YOUR_APP_SECRET' }
+      - { name: 'github',
+          app_id: 'YOUR_APP_ID',
+          app_secret: 'YOUR_APP_SECRET',
+          url: "https://github.com/",
+          verify_ssl: false,
+          args: { scope: 'user:email' } }
+      - { name: 'bitbucket',
+          app_id: 'YOUR_APP_ID',
+          app_secret: 'YOUR_APP_SECRET' }
+      - { name: 'gitlab',
+          app_id: 'YOUR_APP_ID',
+          app_secret: 'YOUR_APP_SECRET',
+          args: { scope: 'api' } }
+      - { name: 'google_oauth2',
+          app_id: 'YOUR_APP_ID',
+          app_secret: 'YOUR_APP_SECRET',
+          args: { access_type: 'offline', approval_prompt: '' } }
+      - { name: 'jwt',
+          app_secret: 'YOUR_APP_SECRET',
+          args: {
+                  algorithm: 'HS256',
+                  uid_claim: 'email',
+                  required_claims: ["name", "email"],
+                  info_map: { name: "name", email: "email" },
+                  auth_url: 'https://example.com/',
+                  valid_within: null,
+                }
+        }
+      - { name: 'auth0',
+          args: {
+            client_id: 'YOUR_AUTH0_CLIENT_ID',
+            client_secret: 'YOUR_AUTH0_CLIENT_SECRET',
+            domain: 'YOUR_AUTH0_DOMAIN',
+            scope: 'openid profile email' } }
+      - { name: 'salesforce',
+          app_id: 'YOUR_CLIENT_ID',
+          app_secret: 'YOUR_CLIENT_SECRET'
+        }
+      - { name: 'atlassian_oauth2',
+          app_id: 'YOUR_CLIENT_ID',
+          app_secret: 'YOUR_CLIENT_SECRET',
+          args: { scope: 'offline_access read:jira-user read:jira-work', prompt: 'consent' }
+      }
+  ldap:
+    enabled: false
+    servers:
+      main:
+        label: ldap
+        host: 127.0.0.1
+        port: 3890
+        uid: 'uid'
+        encryption: 'plain' # "start_tls" or "simple_tls" or "plain"
+        base: 'dc=example,dc=com'
+        user_filter: ''
+        group_base: 'ou=groups,dc=example,dc=com'
+        admin_group: ''
+  prometheus:
+    enabled: true
+    server_address: 'localhost:9090'
diff --git a/gems/gitlab-backup-cli/spec/fixtures/gitlab.yml b/gems/gitlab-backup-cli/spec/fixtures/gitlab.yml
new file mode 100644
index 0000000000000000000000000000000000000000..77454e2a0498d5dd20e17e985202b8f80a89c160
--- /dev/null
+++ b/gems/gitlab-backup-cli/spec/fixtures/gitlab.yml
@@ -0,0 +1,222 @@
+# # # # # # # # # # # # # # # # # #
+# GitLab application config file  #
+# # # # # # # # # # # # # # # # # #
+
+test:
+  object_store:
+    enabled: false
+  gravatar:
+    enabled: true
+  external_diffs:
+    enabled: false
+    # Diffs may be `always` external (the default), or they can be made external
+    # after they have become `outdated` (i.e., the MR is closed or a new version
+    # has been pushed).
+    # when: always
+    # The location where external diffs are stored (default: shared/external-diffs).
+    storage_path: tmp/tests/external-diffs
+    object_store:
+      enabled: false
+      remote_directory: external-diffs # The bucket name
+      connection:
+        provider: AWS # Only AWS supported at the moment
+        aws_access_key_id: AWS_ACCESS_KEY_ID
+        aws_secret_access_key: AWS_SECRET_ACCESS_KEY
+        region: us-east-1
+  lfs:
+    enabled: false
+    # The location where LFS objects are stored (default: shared/lfs-objects).
+    # storage_path: shared/lfs-objects
+    object_store:
+      enabled: false
+      remote_directory: lfs-objects # The bucket name
+      connection:
+        provider: AWS # Only AWS supported at the moment
+        aws_access_key_id: AWS_ACCESS_KEY_ID
+        aws_secret_access_key: AWS_SECRET_ACCESS_KEY
+        region: us-east-1
+  artifacts:
+    path: tmp/tests/artifacts
+    enabled: true
+    # The location where build artifacts are stored (default: shared/artifacts).
+    # path: shared/artifacts
+    object_store:
+      enabled: false
+      remote_directory: artifacts # The bucket name
+      connection:
+        provider: AWS # Only AWS supported at the moment
+        aws_access_key_id: AWS_ACCESS_KEY_ID
+        aws_secret_access_key: AWS_SECRET_ACCESS_KEY
+        region: us-east-1
+  uploads:
+    storage_path: tmp/tests/public
+    object_store:
+      enabled: false
+      connection:
+        provider: AWS # Only AWS supported at the moment
+        aws_access_key_id: AWS_ACCESS_KEY_ID
+        aws_secret_access_key: AWS_SECRET_ACCESS_KEY
+        region: us-east-1
+
+  terraform_state:
+    enabled: true
+    storage_path: tmp/tests/terraform_state
+    object_store:
+      enabled: false
+      remote_directory: terraform
+      connection:
+        provider: AWS # Only AWS supported at the moment
+        aws_access_key_id: AWS_ACCESS_KEY_ID
+        aws_secret_access_key: AWS_SECRET_ACCESS_KEY
+        region: us-east-1
+
+  ci_secure_files:
+    enabled: true
+    storage_path: tmp/tests/ci_secure_files
+    object_store:
+      enabled: false
+      remote_directory: ci-secure-files
+      connection:
+        provider: AWS # Only AWS supported at the moment
+        aws_access_key_id: AWS_ACCESS_KEY_ID
+        aws_secret_access_key: AWS_SECRET_ACCESS_KEY
+        region: us-east-1
+
+  gitlab:
+    host: localhost
+    port: 80
+
+    content_security_policy:
+      enabled: true
+      report_only: false
+      directives:
+        base_uri:
+        child_src:
+        connect_src:
+        default_src: "'self'"
+        font_src:
+        form_action:
+        frame_ancestors: "'self'"
+        frame_src: "'self' https://www.google.com/recaptcha/ https://www.recaptcha.net/ https://content.googleapis.com https://content-compute.googleapis.com https://content-cloudbilling.googleapis.com https://content-cloudresourcemanager.googleapis.com"
+        img_src: "* data: blob:"
+        manifest_src:
+        media_src:
+        object_src: "'none'"
+        script_src: "'self' 'unsafe-eval' http://localhost:* https://www.google.com/recaptcha/ https://www.recaptcha.net/ https://www.gstatic.com/recaptcha/ https://apis.google.com"
+        style_src: "'self' 'unsafe-inline'"
+        worker_src: "'self' blob:"
+        report_uri:
+
+    # When you run tests we clone and set up gitlab-shell
+    # In order to set it up correctly you need to specify
+    # your system username you use to run GitLab
+    # user: YOUR_USERNAME
+  pages:
+    path: tmp/tests/pages
+    object_store:
+      enabled: false
+      remote_directory: pages # The bucket name
+      connection:
+        provider: AWS
+        aws_access_key_id: AWS_ACCESS_KEY_ID
+        aws_secret_access_key: AWS_SECRET_ACCESS_KEY
+        region: us-east-1
+    local_store:
+      enabled: true
+      path: tmp/tests/pages
+  repositories:
+    storages:
+      default:
+        path: tmp/tests/repositories/
+        gitaly_address: unix:tmp/tests/gitaly/praefect.socket
+
+  gitaly:
+    client_path: tmp/tests/gitaly/_build/bin
+    token: secret
+  workhorse:
+    secret_file: tmp/gitlab_workhorse_test_secret
+  backup:
+    path: tmp/tests/backups
+    gitaly_backup_path: tmp/tests/gitaly/_build/bin/gitaly-backup
+  gitlab_shell:
+    path: tmp/tests/gitlab-shell/
+    authorized_keys_file: tmp/tests/authorized_keys
+  issues_tracker:
+    redmine:
+      title: "Redmine"
+      project_url: "http://redmine/projects/:issues_tracker_id"
+      issues_url: "http://redmine/:project_id/:issues_tracker_id/:id"
+      new_issue_url: "http://redmine/projects/:issues_tracker_id/issues/new"
+    jira:
+      title: "Jira"
+      url: https://sample_company.atlassian.net
+      project_key: PROJECT
+
+  omniauth:
+    # enabled: true
+    allow_single_sign_on: true
+    external_providers: []
+
+    providers:
+      - { name: 'alicloud',
+          app_id: 'YOUR_APP_ID',
+          app_secret: 'YOUR_APP_SECRET' }
+      - { name: 'github',
+          app_id: 'YOUR_APP_ID',
+          app_secret: 'YOUR_APP_SECRET',
+          url: "https://github.com/",
+          verify_ssl: false,
+          args: { scope: 'user:email' } }
+      - { name: 'bitbucket',
+          app_id: 'YOUR_APP_ID',
+          app_secret: 'YOUR_APP_SECRET' }
+      - { name: 'gitlab',
+          app_id: 'YOUR_APP_ID',
+          app_secret: 'YOUR_APP_SECRET',
+          args: { scope: 'api' } }
+      - { name: 'google_oauth2',
+          app_id: 'YOUR_APP_ID',
+          app_secret: 'YOUR_APP_SECRET',
+          args: { access_type: 'offline', approval_prompt: '' } }
+      - { name: 'jwt',
+          app_secret: 'YOUR_APP_SECRET',
+          args: {
+                  algorithm: 'HS256',
+                  uid_claim: 'email',
+                  required_claims: ["name", "email"],
+                  info_map: { name: "name", email: "email" },
+                  auth_url: 'https://example.com/',
+                  valid_within: null,
+                }
+        }
+      - { name: 'auth0',
+          args: {
+            client_id: 'YOUR_AUTH0_CLIENT_ID',
+            client_secret: 'YOUR_AUTH0_CLIENT_SECRET',
+            domain: 'YOUR_AUTH0_DOMAIN',
+            scope: 'openid profile email' } }
+      - { name: 'salesforce',
+          app_id: 'YOUR_CLIENT_ID',
+          app_secret: 'YOUR_CLIENT_SECRET'
+        }
+      - { name: 'atlassian_oauth2',
+          app_id: 'YOUR_CLIENT_ID',
+          app_secret: 'YOUR_CLIENT_SECRET',
+          args: { scope: 'offline_access read:jira-user read:jira-work', prompt: 'consent' }
+      }
+  ldap:
+    enabled: false
+    servers:
+      main:
+        label: ldap
+        host: 127.0.0.1
+        port: 3890
+        uid: 'uid'
+        encryption: 'plain' # "start_tls" or "simple_tls" or "plain"
+        base: 'dc=example,dc=com'
+        user_filter: ''
+        group_base: 'ou=groups,dc=example,dc=com'
+        admin_group: ''
+  prometheus:
+    enabled: true
+    server_address: 'localhost:9090'
diff --git a/gems/gitlab-backup-cli/spec/gitlab/backup/cli/source_context_spec.rb b/gems/gitlab-backup-cli/spec/gitlab/backup/cli/source_context_spec.rb
index 9b6ad7c3b784a4a48a6b290e38ec9f2d81f1444a..49ccbd91a9676af5a9495f822fabf0cfc2f57ed6 100644
--- a/gems/gitlab-backup-cli/spec/gitlab/backup/cli/source_context_spec.rb
+++ b/gems/gitlab-backup-cli/spec/gitlab/backup/cli/source_context_spec.rb
@@ -9,6 +9,7 @@
 
   before do
     allow(context).to receive(:gitlab_basepath).and_return(fake_gitlab_basepath)
+    FileUtils.mkdir fake_gitlab_basepath.join('config')
   end
 
   after do
@@ -23,4 +24,27 @@
       expect(context.gitlab_version).to eq('17.0.3-ee')
     end
   end
+
+  describe '#backup_basedir' do
+    context 'with a relative path configured in gitlab.yml' do
+      it 'returns a full path based on gitlab basepath' do
+        use_gitlab_config_fixture('gitlab.yml')
+
+        expect(context.backup_basedir).to eq(fake_gitlab_basepath.join('tmp/tests/backups'))
+      end
+    end
+
+    context 'with full path configure in gitlab.yml' do
+      it 'returns a full path as configured in gitlab.yml' do
+        use_gitlab_config_fixture('gitlab-relativepaths.yml')
+
+        expect(context.backup_basedir).to eq(Pathname('/tmp/gitlab/full/backups'))
+      end
+    end
+  end
+
+  def use_gitlab_config_fixture(fixture)
+    gitlab_yml_fixture = fixtures_path.join(fixture)
+    FileUtils.copy(gitlab_yml_fixture, fake_gitlab_basepath.join('config/gitlab.yml'))
+  end
 end
diff --git a/gems/gitlab-backup-cli/spec/spec_helper.rb b/gems/gitlab-backup-cli/spec/spec_helper.rb
index 02246b5a4dd6dec711dab9431ce3eb9491bae498..82c2604b9c3dcc38ead19a7f826f51b0050da37c 100644
--- a/gems/gitlab-backup-cli/spec/spec_helper.rb
+++ b/gems/gitlab-backup-cli/spec/spec_helper.rb
@@ -7,6 +7,8 @@
 require 'factory_bot'
 require 'gitlab/rspec/next_instance_of'
 
+ENV["RAILS_ENV"] ||= "test"
+
 # Load spec support code
 Dir['spec/support/**/*.rb'].each { |f| load f }