diff --git a/cmd/flux/bootstrap.go b/cmd/flux/bootstrap.go
index 47b01127eebba156bab78be17524adcd617fe89c..1cef362e22a0d2380b2e283f138742a170448a8d 100644
--- a/cmd/flux/bootstrap.go
+++ b/cmd/flux/bootstrap.go
@@ -57,6 +57,7 @@ var (
 	bootstrapArch               = flags.Arch(defaults.Arch)
 	bootstrapLogLevel           = flags.LogLevel(defaults.LogLevel)
 	bootstrapRequiredComponents = []string{"source-controller", "kustomize-controller"}
+	bootstrapTokenAuth          bool
 )
 
 const (
@@ -75,14 +76,16 @@ func init() {
 	bootstrapCmd.PersistentFlags().Var(&bootstrapArch, "arch", bootstrapArch.Description())
 	bootstrapCmd.PersistentFlags().StringVar(&bootstrapBranch, "branch", bootstrapDefaultBranch,
 		"default branch (for GitHub this must match the default branch setting for the organization)")
-	rootCmd.AddCommand(bootstrapCmd)
 	bootstrapCmd.PersistentFlags().BoolVar(&bootstrapWatchAllNamespaces, "watch-all-namespaces", true,
 		"watch for custom resources in all namespaces, if set to false it will only watch the namespace where the toolkit is installed")
 	bootstrapCmd.PersistentFlags().BoolVar(&bootstrapNetworkPolicy, "network-policy", true,
 		"deny ingress access to the toolkit controllers from other namespaces using network policies")
+	bootstrapCmd.PersistentFlags().BoolVar(&bootstrapTokenAuth, "token-auth", false,
+		"when enabled, the personal access token will be used instead of SSH deploy key")
 	bootstrapCmd.PersistentFlags().Var(&bootstrapLogLevel, "log-level", bootstrapLogLevel.Description())
 	bootstrapCmd.PersistentFlags().StringVar(&bootstrapManifestsPath, "manifests", "", "path to the manifest directory")
 	bootstrapCmd.PersistentFlags().MarkHidden("manifests")
+	rootCmd.AddCommand(bootstrapCmd)
 }
 
 func bootstrapValidate() error {
diff --git a/cmd/flux/bootstrap_github.go b/cmd/flux/bootstrap_github.go
index 5565a98ac895d171f2dd12309b8f3fd7b411242f..0fd0a1aa6d41058c29ab66af49f2cffcbc52750d 100644
--- a/cmd/flux/bootstrap_github.go
+++ b/cmd/flux/bootstrap_github.go
@@ -26,6 +26,8 @@ import (
 	"time"
 
 	"github.com/spf13/cobra"
+	corev1 "k8s.io/api/core/v1"
+	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
 
 	"github.com/fluxcd/flux2/internal/utils"
 	"github.com/fluxcd/pkg/git"
@@ -35,7 +37,7 @@ var bootstrapGitHubCmd = &cobra.Command{
 	Use:   "github",
 	Short: "Bootstrap toolkit components in a GitHub repository",
 	Long: `The bootstrap github command creates the GitHub repository if it doesn't exists and
-commits the toolkit components manifests to the master branch.
+commits the toolkit components manifests to the main branch.
 Then it configures the target cluster to synchronize with the repository.
 If the toolkit components are present on the cluster,
 the bootstrap command will perform an upgrade if needed.`,
@@ -54,8 +56,11 @@ the bootstrap command will perform an upgrade if needed.`,
   # Run bootstrap for a public repository on a personal account
   flux bootstrap github --owner=<user> --repository=<repo name> --private=false --personal=true 
 
-  # Run bootstrap for a private repo hosted on GitHub Enterprise
-  flux bootstrap github --owner=<organization> --repository=<repo name> --hostname=<domain>
+  # Run bootstrap for a private repo hosted on GitHub Enterprise using SSH auth
+  flux bootstrap github --owner=<organization> --repository=<repo name> --hostname=<domain> --ssh-hostname=<domain>
+
+  # Run bootstrap for a private repo hosted on GitHub Enterprise using HTTPS auth
+  flux bootstrap github --owner=<organization> --repository=<repo name> --hostname=<domain> --token-auth
 
   # Run bootstrap for a an existing repository with a branch named main
   flux bootstrap github --owner=<organization> --repository=<repo name> --branch=main
@@ -64,15 +69,16 @@ the bootstrap command will perform an upgrade if needed.`,
 }
 
 var (
-	ghOwner      string
-	ghRepository string
-	ghInterval   time.Duration
-	ghPersonal   bool
-	ghPrivate    bool
-	ghHostname   string
-	ghPath       string
-	ghTeams      []string
-	ghDelete     bool
+	ghOwner       string
+	ghRepository  string
+	ghInterval    time.Duration
+	ghPersonal    bool
+	ghPrivate     bool
+	ghHostname    string
+	ghPath        string
+	ghTeams       []string
+	ghDelete      bool
+	ghSSHHostname string
 )
 
 const (
@@ -87,6 +93,7 @@ func init() {
 	bootstrapGitHubCmd.Flags().BoolVar(&ghPrivate, "private", true, "is private repository")
 	bootstrapGitHubCmd.Flags().DurationVar(&ghInterval, "interval", time.Minute, "sync interval")
 	bootstrapGitHubCmd.Flags().StringVar(&ghHostname, "hostname", git.GitHubDefaultHostname, "GitHub hostname")
+	bootstrapGitHubCmd.Flags().StringVar(&ghSSHHostname, "ssh-hostname", "", "GitHub SSH hostname, to be used when the SSH host differs from the HTTPS one")
 	bootstrapGitHubCmd.Flags().StringVar(&ghPath, "path", "", "repository path, when specified the cluster sync will be scoped to this path")
 
 	bootstrapGitHubCmd.Flags().BoolVar(&ghDelete, "delete", false, "delete repository (used for testing only)")
@@ -110,6 +117,10 @@ func bootstrapGitHubCmdRun(cmd *cobra.Command, args []string) error {
 		return err
 	}
 
+	if ghSSHHostname != "" {
+		repository.SSHHost = ghSSHHostname
+	}
+
 	provider := &git.GithubProvider{
 		IsPrivate:  ghPrivate,
 		IsPersonal: ghPersonal,
@@ -155,7 +166,7 @@ func bootstrapGitHubCmdRun(cmd *cobra.Command, args []string) error {
 		}
 	}
 
-	// clone repository and checkout the master branch
+	// clone repository and checkout the main branch
 	if err := repository.Checkout(ctx, bootstrapBranch, tmpDir); err != nil {
 		return err
 	}
@@ -201,28 +212,45 @@ func bootstrapGitHubCmdRun(cmd *cobra.Command, args []string) error {
 		logger.Successf("install completed")
 	}
 
-	// setup SSH deploy key
-	if shouldCreateDeployKey(ctx, kubeClient, namespace) {
-		logger.Actionf("configuring deploy key")
-		u, err := url.Parse(repository.GetSSH())
-		if err != nil {
-			return fmt.Errorf("git URL parse failed: %w", err)
+	if bootstrapTokenAuth {
+		// setup HTTPS token auth
+		secret := corev1.Secret{
+			ObjectMeta: metav1.ObjectMeta{
+				Name:      namespace,
+				Namespace: namespace,
+			},
+			StringData: map[string]string{
+				"username": "git",
+				"password": ghToken,
+			},
 		}
-
-		key, err := generateDeployKey(ctx, kubeClient, u, namespace)
-		if err != nil {
-			return fmt.Errorf("generating deploy key failed: %w", err)
+		if err := upsertSecret(ctx, kubeClient, secret); err != nil {
+			return err
 		}
+	} else {
+		// setup SSH deploy key
+		if shouldCreateDeployKey(ctx, kubeClient, namespace) {
+			logger.Actionf("configuring deploy key")
+			u, err := url.Parse(repository.GetSSH())
+			if err != nil {
+				return fmt.Errorf("git URL parse failed: %w", err)
+			}
 
-		keyName := "flux"
-		if ghPath != "" {
-			keyName = fmt.Sprintf("flux-%s", ghPath)
-		}
+			key, err := generateDeployKey(ctx, kubeClient, u, namespace)
+			if err != nil {
+				return fmt.Errorf("generating deploy key failed: %w", err)
+			}
 
-		if changed, err := provider.AddDeployKey(ctx, repository, key, keyName); err != nil {
-			return err
-		} else if changed {
-			logger.Successf("deploy key configured")
+			keyName := "flux"
+			if ghPath != "" {
+				keyName = fmt.Sprintf("flux-%s", ghPath)
+			}
+
+			if changed, err := provider.AddDeployKey(ctx, repository, key, keyName); err != nil {
+				return err
+			} else if changed {
+				logger.Successf("deploy key configured")
+			}
 		}
 	}
 
diff --git a/cmd/flux/bootstrap_gitlab.go b/cmd/flux/bootstrap_gitlab.go
index 5d504def91d84a73b40fcf62c872991a56605d42..546d93fb0be68e8833022501a83e510179bde0ad 100644
--- a/cmd/flux/bootstrap_gitlab.go
+++ b/cmd/flux/bootstrap_gitlab.go
@@ -45,22 +45,22 @@ the bootstrap command will perform an upgrade if needed.`,
   export GITLAB_TOKEN=<my-token>
 
   # Run bootstrap for a private repo using HTTPS token authentication 
-  flux bootstrap gitlab --owner=<group> --repository=<repo name>
+  flux bootstrap gitlab --owner=<group> --repository=<repo name> --token-auth
 
   # Run bootstrap for a private repo using SSH authentication
-  flux bootstrap gitlab --owner=<group> --repository=<repo name> --ssh-hostname=gitlab.com
+  flux bootstrap gitlab --owner=<group> --repository=<repo name>
 
   # Run bootstrap for a repository path
   flux bootstrap gitlab --owner=<group> --repository=<repo name> --path=dev-cluster
 
   # Run bootstrap for a public repository on a personal account
-  flux bootstrap gitlab --owner=<user> --repository=<repo name> --private=false --personal=true
+  flux bootstrap gitlab --owner=<user> --repository=<repo name> --private=false --personal --token-auth
 
   # Run bootstrap for a private repo hosted on a GitLab server 
-  flux bootstrap gitlab --owner=<group> --repository=<repo name> --hostname=<domain>
+  flux bootstrap gitlab --owner=<group> --repository=<repo name> --hostname=<domain> --token-auth
 
   # Run bootstrap for a an existing repository with a branch named main
-  flux bootstrap gitlab --owner=<organization> --repository=<repo name> --branch=main
+  flux bootstrap gitlab --owner=<organization> --repository=<repo name> --branch=main --token-auth
 `,
 	RunE: bootstrapGitLabCmdRun,
 }
@@ -83,7 +83,7 @@ func init() {
 	bootstrapGitLabCmd.Flags().BoolVar(&glPrivate, "private", true, "is private repository")
 	bootstrapGitLabCmd.Flags().DurationVar(&glInterval, "interval", time.Minute, "sync interval")
 	bootstrapGitLabCmd.Flags().StringVar(&glHostname, "hostname", git.GitLabDefaultHostname, "GitLab hostname")
-	bootstrapGitLabCmd.Flags().StringVar(&glSSHHostname, "ssh-hostname", "", "GitLab SSH hostname, when specified a deploy key will be added to the repository")
+	bootstrapGitLabCmd.Flags().StringVar(&glSSHHostname, "ssh-hostname", "", "GitLab SSH hostname, to be used when the SSH host differs from the HTTPS one")
 	bootstrapGitLabCmd.Flags().StringVar(&glPath, "path", "", "repository path, when specified the cluster sync will be scoped to this path")
 
 	bootstrapCmd.AddCommand(bootstrapGitLabCmd)
@@ -180,7 +180,22 @@ func bootstrapGitLabCmdRun(cmd *cobra.Command, args []string) error {
 
 	repoURL := repository.GetURL()
 
-	if glSSHHostname != "" {
+	if bootstrapTokenAuth {
+		// setup HTTPS token auth
+		secret := corev1.Secret{
+			ObjectMeta: metav1.ObjectMeta{
+				Name:      namespace,
+				Namespace: namespace,
+			},
+			StringData: map[string]string{
+				"username": "git",
+				"password": glToken,
+			},
+		}
+		if err := upsertSecret(ctx, kubeClient, secret); err != nil {
+			return err
+		}
+	} else {
 		// setup SSH deploy key
 		repoURL = repository.GetSSH()
 		if shouldCreateDeployKey(ctx, kubeClient, namespace) {
@@ -206,21 +221,6 @@ func bootstrapGitLabCmdRun(cmd *cobra.Command, args []string) error {
 				logger.Successf("deploy key configured")
 			}
 		}
-	} else {
-		// setup HTTPS token auth
-		secret := corev1.Secret{
-			ObjectMeta: metav1.ObjectMeta{
-				Name:      namespace,
-				Namespace: namespace,
-			},
-			StringData: map[string]string{
-				"username": "git",
-				"password": glToken,
-			},
-		}
-		if err := upsertSecret(ctx, kubeClient, secret); err != nil {
-			return err
-		}
 	}
 
 	// configure repo synchronization
diff --git a/docs/cmd/flux_bootstrap.md b/docs/cmd/flux_bootstrap.md
index 5a74161ae959c4e7f1a4b398acb4223bfca5f7a4..4d1f20b0f3efdbf5f34588655c8610f1fe5b5a46 100644
--- a/docs/cmd/flux_bootstrap.md
+++ b/docs/cmd/flux_bootstrap.md
@@ -17,6 +17,7 @@ The bootstrap sub-commands bootstrap the toolkit components on the targeted Git
       --log-level logLevel         log level, available options are: (debug, info, error) (default info)
       --network-policy             deny ingress access to the toolkit controllers from other namespaces using network policies (default true)
       --registry string            container registry where the toolkit images are published (default "ghcr.io/fluxcd")
+      --token-auth                 when enabled, the personal access token will be used instead of SSH deploy key
   -v, --version string             toolkit version (default "latest")
       --watch-all-namespaces       watch for custom resources in all namespaces, if set to false it will only watch the namespace where the toolkit is installed (default true)
 ```
diff --git a/docs/cmd/flux_bootstrap_github.md b/docs/cmd/flux_bootstrap_github.md
index a105a216fc15385b06837f7778fb8331b59f4460..4186515a7f2bf1062e35498c7c16c95881050548 100644
--- a/docs/cmd/flux_bootstrap_github.md
+++ b/docs/cmd/flux_bootstrap_github.md
@@ -5,7 +5,7 @@ Bootstrap toolkit components in a GitHub repository
 ### Synopsis
 
 The bootstrap github command creates the GitHub repository if it doesn't exists and
-commits the toolkit components manifests to the master branch.
+commits the toolkit components manifests to the main branch.
 Then it configures the target cluster to synchronize with the repository.
 If the toolkit components are present on the cluster,
 the bootstrap command will perform an upgrade if needed.
@@ -32,8 +32,11 @@ flux bootstrap github [flags]
   # Run bootstrap for a public repository on a personal account
   flux bootstrap github --owner=<user> --repository=<repo name> --private=false --personal=true 
 
-  # Run bootstrap for a private repo hosted on GitHub Enterprise
-  flux bootstrap github --owner=<organization> --repository=<repo name> --hostname=<domain>
+  # Run bootstrap for a private repo hosted on GitHub Enterprise using SSH auth
+  flux bootstrap github --owner=<organization> --repository=<repo name> --hostname=<domain> --ssh-hostname=<domain>
+
+  # Run bootstrap for a private repo hosted on GitHub Enterprise using HTTPS auth
+  flux bootstrap github --owner=<organization> --repository=<repo name> --hostname=<domain> --token-auth
 
   # Run bootstrap for a an existing repository with a branch named main
   flux bootstrap github --owner=<organization> --repository=<repo name> --branch=main
@@ -43,15 +46,16 @@ flux bootstrap github [flags]
 ### Options
 
 ```
-  -h, --help                help for github
-      --hostname string     GitHub hostname (default "github.com")
-      --interval duration   sync interval (default 1m0s)
-      --owner string        GitHub user or organization name
-      --path string         repository path, when specified the cluster sync will be scoped to this path
-      --personal            is personal repository
-      --private             is private repository (default true)
-      --repository string   GitHub repository name
-      --team stringArray    GitHub team to be given maintainer access
+  -h, --help                  help for github
+      --hostname string       GitHub hostname (default "github.com")
+      --interval duration     sync interval (default 1m0s)
+      --owner string          GitHub user or organization name
+      --path string           repository path, when specified the cluster sync will be scoped to this path
+      --personal              is personal repository
+      --private               is private repository (default true)
+      --repository string     GitHub repository name
+      --ssh-hostname string   GitHub SSH hostname, to be used when the SSH host differs from the HTTPS one
+      --team stringArray      GitHub team to be given maintainer access
 ```
 
 ### Options inherited from parent commands
@@ -68,6 +72,7 @@ flux bootstrap github [flags]
       --network-policy             deny ingress access to the toolkit controllers from other namespaces using network policies (default true)
       --registry string            container registry where the toolkit images are published (default "ghcr.io/fluxcd")
       --timeout duration           timeout for this operation (default 5m0s)
+      --token-auth                 when enabled, the personal access token will be used instead of SSH deploy key
       --verbose                    print generated objects
   -v, --version string             toolkit version (default "latest")
       --watch-all-namespaces       watch for custom resources in all namespaces, if set to false it will only watch the namespace where the toolkit is installed (default true)
diff --git a/docs/cmd/flux_bootstrap_gitlab.md b/docs/cmd/flux_bootstrap_gitlab.md
index 131d7441b9fd6842983edce60f2e42eb97cdff8b..a4682511c8455945c7da04b4f19fa84e60c60a88 100644
--- a/docs/cmd/flux_bootstrap_gitlab.md
+++ b/docs/cmd/flux_bootstrap_gitlab.md
@@ -21,22 +21,22 @@ flux bootstrap gitlab [flags]
   export GITLAB_TOKEN=<my-token>
 
   # Run bootstrap for a private repo using HTTPS token authentication 
-  flux bootstrap gitlab --owner=<group> --repository=<repo name>
+  flux bootstrap gitlab --owner=<group> --repository=<repo name> --token-auth
 
   # Run bootstrap for a private repo using SSH authentication
-  flux bootstrap gitlab --owner=<group> --repository=<repo name> --ssh-hostname=gitlab.com
+  flux bootstrap gitlab --owner=<group> --repository=<repo name>
 
   # Run bootstrap for a repository path
   flux bootstrap gitlab --owner=<group> --repository=<repo name> --path=dev-cluster
 
   # Run bootstrap for a public repository on a personal account
-  flux bootstrap gitlab --owner=<user> --repository=<repo name> --private=false --personal=true
+  flux bootstrap gitlab --owner=<user> --repository=<repo name> --private=false --personal --token-auth
 
   # Run bootstrap for a private repo hosted on a GitLab server 
-  flux bootstrap gitlab --owner=<group> --repository=<repo name> --hostname=<domain>
+  flux bootstrap gitlab --owner=<group> --repository=<repo name> --hostname=<domain> --token-auth
 
   # Run bootstrap for a an existing repository with a branch named main
-  flux bootstrap gitlab --owner=<organization> --repository=<repo name> --branch=main
+  flux bootstrap gitlab --owner=<organization> --repository=<repo name> --branch=main --token-auth
 
 ```
 
@@ -51,7 +51,7 @@ flux bootstrap gitlab [flags]
       --personal              is personal repository
       --private               is private repository (default true)
       --repository string     GitLab repository name
-      --ssh-hostname string   GitLab SSH hostname, when specified a deploy key will be added to the repository
+      --ssh-hostname string   GitLab SSH hostname, to be used when the SSH host differs from the HTTPS one
 ```
 
 ### Options inherited from parent commands
@@ -68,6 +68,7 @@ flux bootstrap gitlab [flags]
       --network-policy             deny ingress access to the toolkit controllers from other namespaces using network policies (default true)
       --registry string            container registry where the toolkit images are published (default "ghcr.io/fluxcd")
       --timeout duration           timeout for this operation (default 5m0s)
+      --token-auth                 when enabled, the personal access token will be used instead of SSH deploy key
       --verbose                    print generated objects
   -v, --version string             toolkit version (default "latest")
       --watch-all-namespaces       watch for custom resources in all namespaces, if set to false it will only watch the namespace where the toolkit is installed (default true)
diff --git a/docs/guides/installation.md b/docs/guides/installation.md
index bfd34816495e675962eab0b4b7341786f977630c..f8270a3a42addcf07c59dad52b646f834c89f080 100644
--- a/docs/guides/installation.md
+++ b/docs/guides/installation.md
@@ -129,6 +129,19 @@ To run the bootstrap for a repository hosted on GitHub Enterprise, you have to s
 
 ```sh
 flux bootstrap github \
+  --hostname=my-github-enterprise.com \
+  --ssh-hostname=my-github-enterprise.com \
+  --owner=my-github-organization \
+  --repository=my-repository \
+  --branch=main \
+  --path=clusters/my-cluster
+```
+
+If your GitHub Enterprise has SSH access disabled, you can use HTTPS and token authentication with:
+
+```sh
+flux bootstrap github \
+  --token-auth \
   --hostname=my-github-enterprise.com \
   --owner=my-github-organization \
   --repository=my-repository \
@@ -155,6 +168,7 @@ flux bootstrap gitlab \
   --repository=my-repository \
   --branch=master \
   --path=clusters/my-cluster \
+  --token-auth \
   --personal
 ```
 
@@ -189,6 +203,7 @@ To run the bootstrap for a repository hosted on GitLab on-prem or enterprise, yo
 ```sh
 flux bootstrap gitlab \
   --hostname=my-gitlab.com \
+  --token-auth \
   --owner=my-gitlab-group \
   --repository=my-repository \
   --branch=master \