diff --git a/cmd/flux/bootstrap_git.go b/cmd/flux/bootstrap_git.go
index 1a583a2a4e432264a92ed657b430caea8dc40f6b..e71302438ad559a958c243576ffc4f4a97185612 100644
--- a/cmd/flux/bootstrap_git.go
+++ b/cmd/flux/bootstrap_git.go
@@ -199,6 +199,15 @@ func bootstrapGitCmdRun(cmd *cobra.Command, args []string) error {
 		RecurseSubmodules: bootstrapArgs.recurseSubmodules,
 	}
 
+	var caBundle []byte
+	if bootstrapArgs.caFile != "" {
+		var err error
+		caBundle, err = os.ReadFile(bootstrapArgs.caFile)
+		if err != nil {
+			return fmt.Errorf("unable to read TLS CA file: %w", err)
+		}
+	}
+
 	// Bootstrap config
 	bootstrapOpts := []bootstrap.GitOption{
 		bootstrap.WithRepositoryURL(gitArgs.url),
@@ -208,6 +217,7 @@ func bootstrapGitCmdRun(cmd *cobra.Command, args []string) error {
 		bootstrap.WithKubeconfig(rootArgs.kubeconfig, rootArgs.kubecontext),
 		bootstrap.WithPostGenerateSecretFunc(promptPublicKey),
 		bootstrap.WithLogger(logger),
+		bootstrap.WithCABundle(caBundle),
 	}
 
 	// Setup bootstrapper with constructed configs
diff --git a/internal/bootstrap/bootstrap.go b/internal/bootstrap/bootstrap.go
index 34d54840e3685d0b0c559083135e7519945673df..91a9fa3c2f5a3cea1dfa9a3746a1fcf8cdc09d50 100644
--- a/internal/bootstrap/bootstrap.go
+++ b/internal/bootstrap/bootstrap.go
@@ -47,7 +47,7 @@ type Reconciler interface {
 	// manifests with the provided values, committing them to Git and
 	// pushing to remote if there are any changes, and applying them
 	// to the cluster.
-	ReconcileComponents(ctx context.Context, manifestsBase string, options install.Options) error
+	ReconcileComponents(ctx context.Context, manifestsBase string, options install.Options, secretOpts sourcesecret.Options) error
 
 	// ReconcileSourceSecret reconciles the source secret by generating
 	// a new secret with the provided values if the secret does not
@@ -87,7 +87,7 @@ func Run(ctx context.Context, reconciler Reconciler, manifestsBase string,
 		}
 	}
 
-	if err := reconciler.ReconcileComponents(ctx, manifestsBase, installOpts); err != nil {
+	if err := reconciler.ReconcileComponents(ctx, manifestsBase, installOpts, secretOpts); err != nil {
 		return err
 	}
 	if err := reconciler.ReconcileSourceSecret(ctx, secretOpts); err != nil {
diff --git a/internal/bootstrap/bootstrap_plain_git.go b/internal/bootstrap/bootstrap_plain_git.go
index e0018b8907b71db343743e199bce024bc3f766c6..6475c40f4821cab657a3e57e7cd58f33e97e1167 100644
--- a/internal/bootstrap/bootstrap_plain_git.go
+++ b/internal/bootstrap/bootstrap_plain_git.go
@@ -46,8 +46,9 @@ import (
 )
 
 type PlainGitBootstrapper struct {
-	url    string
-	branch string
+	url      string
+	branch   string
+	caBundle []byte
 
 	author                git.Author
 	commitMessageAppendix string
@@ -70,6 +71,16 @@ func WithRepositoryURL(url string) GitOption {
 	return repositoryURLOption(url)
 }
 
+func WithCABundle(b []byte) GitOption {
+	return caBundleOption(b)
+}
+
+type caBundleOption []byte
+
+func (o caBundleOption) applyGit(b *PlainGitBootstrapper) {
+	b.caBundle = o
+}
+
 type repositoryURLOption string
 
 func (o repositoryURLOption) applyGit(b *PlainGitBootstrapper) {
@@ -97,7 +108,7 @@ func NewPlainGitProvider(git git.Git, kube client.Client, opts ...GitOption) (*P
 	return b, nil
 }
 
-func (b *PlainGitBootstrapper) ReconcileComponents(ctx context.Context, manifestsBase string, options install.Options) error {
+func (b *PlainGitBootstrapper) ReconcileComponents(ctx context.Context, manifestsBase string, options install.Options, secretOpts sourcesecret.Options) error {
 	// Clone if not already
 	if _, err := b.git.Status(); err != nil {
 		if err != git.ErrNoGitRepository {
@@ -107,7 +118,7 @@ func (b *PlainGitBootstrapper) ReconcileComponents(ctx context.Context, manifest
 		b.logger.Actionf("cloning branch %q from Git repository %q", b.branch, b.url)
 		var cloned bool
 		if err = retry(1, 2*time.Second, func() (err error) {
-			cloned, err = b.git.Clone(ctx, b.url, b.branch)
+			cloned, err = b.git.Clone(ctx, b.url, b.branch, b.caBundle)
 			return
 		}); err != nil {
 			return fmt.Errorf("failed to clone repository: %w", err)
@@ -145,7 +156,7 @@ func (b *PlainGitBootstrapper) ReconcileComponents(ctx context.Context, manifest
 	if err == nil {
 		b.logger.Successf("committed sync manifests to %q (%q)", b.branch, commit)
 		b.logger.Actionf("pushing component manifests to %q", b.url)
-		if err = b.git.Push(ctx); err != nil {
+		if err = b.git.Push(ctx, b.caBundle); err != nil {
 			return fmt.Errorf("failed to push manifests: %w", err)
 		}
 	} else {
@@ -260,7 +271,7 @@ func (b *PlainGitBootstrapper) ReconcileSyncConfig(ctx context.Context, options
 			b.logger.Actionf("cloning branch %q from Git repository %q", b.branch, b.url)
 			var cloned bool
 			if err = retry(1, 2*time.Second, func() (err error) {
-				cloned, err = b.git.Clone(ctx, b.url, b.branch)
+				cloned, err = b.git.Clone(ctx, b.url, b.branch, b.caBundle)
 				return
 			}); err != nil {
 				return fmt.Errorf("failed to clone repository: %w", err)
@@ -309,7 +320,7 @@ func (b *PlainGitBootstrapper) ReconcileSyncConfig(ctx context.Context, options
 	if err == nil {
 		b.logger.Successf("committed sync manifests to %q (%q)", b.branch, commit)
 		b.logger.Actionf("pushing sync manifests to %q", b.url)
-		if err = b.git.Push(ctx); err != nil {
+		if err = b.git.Push(ctx, b.caBundle); err != nil {
 			return fmt.Errorf("failed to push sync manifests: %w", err)
 		}
 	} else {
diff --git a/internal/bootstrap/git/git.go b/internal/bootstrap/git/git.go
index 86466e795e4638a9960d77126a9e0fa2d1a8353d..103ea49b50c3fd6cea287baa9f8418f7ebfffdc0 100644
--- a/internal/bootstrap/git/git.go
+++ b/internal/bootstrap/git/git.go
@@ -42,10 +42,10 @@ type Commit struct {
 // remote repository.
 type Git interface {
 	Init(url, branch string) (bool, error)
-	Clone(ctx context.Context, url, branch string) (bool, error)
+	Clone(ctx context.Context, url, branch string, caBundle []byte) (bool, error)
 	Write(path string, reader io.Reader) error
 	Commit(message Commit) (string, error)
-	Push(ctx context.Context) error
+	Push(ctx context.Context, caBundle []byte) error
 	Status() (bool, error)
 	Head() (string, error)
 	Path() string
diff --git a/internal/bootstrap/git/gogit/gogit.go b/internal/bootstrap/git/gogit/gogit.go
index b11acd0c63a903c73ddf6bc8b2097060e916e843..0724879196bb084cb476c743d8e19e4c99b70595 100644
--- a/internal/bootstrap/git/gogit/gogit.go
+++ b/internal/bootstrap/git/gogit/gogit.go
@@ -82,7 +82,7 @@ func (g *GoGit) Init(url, branch string) (bool, error) {
 	return true, nil
 }
 
-func (g *GoGit) Clone(ctx context.Context, url, branch string) (bool, error) {
+func (g *GoGit) Clone(ctx context.Context, url, branch string, caBundle []byte) (bool, error) {
 	branchRef := plumbing.NewBranchReferenceName(branch)
 	r, err := gogit.PlainCloneContext(ctx, g.path, false, &gogit.CloneOptions{
 		URL:           url,
@@ -94,6 +94,7 @@ func (g *GoGit) Clone(ctx context.Context, url, branch string) (bool, error) {
 		NoCheckout: false,
 		Progress:   nil,
 		Tags:       gogit.NoTags,
+		CABundle:   caBundle,
 	})
 	if err != nil {
 		if err == transport.ErrEmptyRemoteRepository || isRemoteBranchNotFoundErr(err, branchRef.String()) {
@@ -185,7 +186,7 @@ func (g *GoGit) Commit(message git.Commit) (string, error) {
 	return commit.String(), nil
 }
 
-func (g *GoGit) Push(ctx context.Context) error {
+func (g *GoGit) Push(ctx context.Context, caBundle []byte) error {
 	if g.repository == nil {
 		return git.ErrNoGitRepository
 	}
@@ -194,6 +195,7 @@ func (g *GoGit) Push(ctx context.Context) error {
 		RemoteName: gogit.DefaultRemoteName,
 		Auth:       g.auth,
 		Progress:   nil,
+		CABundle:   caBundle,
 	})
 }