diff --git a/cmd/gotk/bootstrap.go b/cmd/gotk/bootstrap.go
index 3eccb84305247722640a1cbe62f68b932576fe68..ca26b04dd7f6ecfc28ed5089eceecd81092e86a2 100644
--- a/cmd/gotk/bootstrap.go
+++ b/cmd/gotk/bootstrap.go
@@ -52,6 +52,7 @@ var (
 	bootstrapArch               string
 	bootstrapBranch             string
 	bootstrapWatchAllNamespaces bool
+	bootstrapLogLevel           string
 )
 
 const (
@@ -77,6 +78,19 @@ func init() {
 	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().StringVar(&bootstrapLogLevel, "log-level", "info", "set the controllers log level")
+}
+
+func bootstrapValidate() error {
+	if !utils.containsItemString(supportedArch, bootstrapArch) {
+		return fmt.Errorf("arch %s is not supported, can be %v", bootstrapArch, supportedArch)
+	}
+
+	if !utils.containsItemString(supportedLogLevels, bootstrapLogLevel) {
+		return fmt.Errorf("log level %s is not supported, can be %v", bootstrapLogLevel, supportedLogLevels)
+	}
+
+	return nil
 }
 
 func generateInstallManifests(targetPath, namespace, tmpDir string) (string, error) {
@@ -88,7 +102,8 @@ func generateInstallManifests(targetPath, namespace, tmpDir string) (string, err
 	}
 
 	if err := genInstallManifests(bootstrapVersion, namespace, bootstrapComponents,
-		bootstrapWatchAllNamespaces, bootstrapRegistry, bootstrapImagePullSecret, bootstrapArch, gotkDir); err != nil {
+		bootstrapWatchAllNamespaces, bootstrapRegistry, bootstrapImagePullSecret,
+		bootstrapArch, bootstrapLogLevel, gotkDir); err != nil {
 		return "", fmt.Errorf("generating manifests failed: %w", err)
 	}
 
diff --git a/cmd/gotk/bootstrap_github.go b/cmd/gotk/bootstrap_github.go
index dfd967870063000f480e2161ced4abf020e16591..a8de23659dd4cf9894173f37d0ca2eb4ba7de90e 100644
--- a/cmd/gotk/bootstrap_github.go
+++ b/cmd/gotk/bootstrap_github.go
@@ -100,8 +100,8 @@ func bootstrapGitHubCmdRun(cmd *cobra.Command, args []string) error {
 		return fmt.Errorf("%s environment variable not found", git.GitHubTokenName)
 	}
 
-	if !utils.containsItemString(supportedArch, bootstrapArch) {
-		return fmt.Errorf("arch %s is not supported, can be %v", bootstrapArch, supportedArch)
+	if err := bootstrapValidate(); err != nil {
+		return err
 	}
 
 	repository, err := git.NewRepository(ghRepository, ghOwner, ghHostname, ghToken, "gotk", ghOwner+"@users.noreply.github.com")
diff --git a/cmd/gotk/bootstrap_gitlab.go b/cmd/gotk/bootstrap_gitlab.go
index 98d0b6310fab13f59ada95c97a318a7ac645dbc0..00611f56b8a897b3c88d1923ca3f0b3bd8badb24 100644
--- a/cmd/gotk/bootstrap_gitlab.go
+++ b/cmd/gotk/bootstrap_gitlab.go
@@ -89,8 +89,8 @@ func bootstrapGitLabCmdRun(cmd *cobra.Command, args []string) error {
 		return fmt.Errorf("%s environment variable not found", git.GitLabTokenName)
 	}
 
-	if !utils.containsItemString(supportedArch, bootstrapArch) {
-		return fmt.Errorf("arch %s is not supported, can be %v", bootstrapArch, supportedArch)
+	if err := bootstrapValidate(); err != nil {
+		return err
 	}
 
 	repository, err := git.NewRepository(glRepository, glOwner, glHostname, glToken, "gotk", glOwner+"@users.noreply.gitlab.com")
diff --git a/cmd/gotk/install.go b/cmd/gotk/install.go
index 91e9e01fd45ffec287b2de67bbaae6c70c9dd70d..94ab6abf9e03f107768bd77c82d5d53896f6bd73 100644
--- a/cmd/gotk/install.go
+++ b/cmd/gotk/install.go
@@ -64,6 +64,7 @@ var (
 	installImagePullSecret    string
 	installArch               string
 	installWatchAllNamespaces bool
+	installLogLevel           string
 )
 
 func init() {
@@ -85,6 +86,7 @@ func init() {
 		"arch can be amd64 or arm64")
 	installCmd.Flags().BoolVar(&installWatchAllNamespaces, "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")
+	installCmd.Flags().StringVar(&installLogLevel, "log-level", "info", "set the controllers log level")
 	rootCmd.AddCommand(installCmd)
 }
 
@@ -93,6 +95,10 @@ func installCmdRun(cmd *cobra.Command, args []string) error {
 		return fmt.Errorf("arch %s is not supported, can be %v", installArch, supportedArch)
 	}
 
+	if !utils.containsItemString(supportedLogLevels, installLogLevel) {
+		return fmt.Errorf("log level %s is not supported, can be %v", bootstrapLogLevel, installLogLevel)
+	}
+
 	ctx, cancel := context.WithTimeout(context.Background(), timeout)
 	defer cancel()
 
@@ -115,7 +121,8 @@ func installCmdRun(cmd *cobra.Command, args []string) error {
 	}
 	if kustomizePath == "" {
 		err = genInstallManifests(installVersion, namespace, installComponents,
-			installWatchAllNamespaces, installRegistry, installImagePullSecret, installArch, tmpDir)
+			installWatchAllNamespaces, installRegistry, installImagePullSecret,
+			installArch, installLogLevel, tmpDir)
 		if err != nil {
 			return fmt.Errorf("install failed: %w", err)
 		}
@@ -206,6 +213,7 @@ var kustomizationTmpl = `---
 {{- $watchAllNamespaces := .WatchAllNamespaces }}
 {{- $registry := .Registry }}
 {{- $arch := .Arch }}
+{{- $logLevel := .LogLevel }}
 apiVersion: kustomize.config.k8s.io/v1beta1
 kind: Kustomization
 namespace: {{.Namespace}}
@@ -238,6 +246,9 @@ patchesJson6902:
     - op: replace
       path: /spec/template/spec/containers/0/args/0
       value: --watch-all-namespaces={{$watchAllNamespaces}}
+    - op: replace
+      path: /spec/template/spec/containers/0/args/1
+      value: --log-level={{$logLevel}}
 {{- else }}
 - target:
     group: apps
@@ -251,6 +262,9 @@ patchesJson6902:
     - op: replace
       path: /spec/template/spec/containers/0/args/1
       value: --watch-all-namespaces={{$watchAllNamespaces}}
+    - op: replace
+      path: /spec/template/spec/containers/0/args/2
+      value: --log-level={{$logLevel}}
 {{- end }}
 {{- end }}
 
@@ -327,7 +341,7 @@ func downloadManifests(version string, tmpDir string) error {
 }
 
 func genInstallManifests(version string, namespace string, components []string,
-	watchAllNamespaces bool, registry, imagePullSecret, arch, tmpDir string) error {
+	watchAllNamespaces bool, registry, imagePullSecret, arch, logLevel, tmpDir string) error {
 	eventsAddr := ""
 	if utils.containsItemString(components, defaultNotification) {
 		eventsAddr = fmt.Sprintf("http://%s/", defaultNotification)
@@ -342,6 +356,7 @@ func genInstallManifests(version string, namespace string, components []string,
 		ImagePullSecret    string
 		Arch               string
 		WatchAllNamespaces bool
+		LogLevel           string
 	}{
 		Version:            version,
 		Namespace:          namespace,
@@ -351,6 +366,7 @@ func genInstallManifests(version string, namespace string, components []string,
 		ImagePullSecret:    imagePullSecret,
 		Arch:               arch,
 		WatchAllNamespaces: watchAllNamespaces,
+		LogLevel:           logLevel,
 	}
 
 	if err := downloadManifests(version, tmpDir); err != nil {
diff --git a/cmd/gotk/main.go b/cmd/gotk/main.go
index 4bf6e3dcaecd8871749abdccd1f6a74e396cc51c..039e26f194f23949a781ee021569079c4dd659dc 100644
--- a/cmd/gotk/main.go
+++ b/cmd/gotk/main.go
@@ -113,6 +113,7 @@ var (
 	supportedArch                 = []string{"arm64", "amd64"}
 	supportedDecryptionProviders  = []string{"sops"}
 	supportedHelmChartSourceKinds = []string{sourcev1.HelmRepositoryKind, sourcev1.GitRepositoryKind}
+	supportedLogLevels            = []string{"debug", "info", "error"}
 )
 
 func init() {
diff --git a/docs/cmd/gotk_bootstrap.md b/docs/cmd/gotk_bootstrap.md
index 1b87380f762c88cb97567746a46256807f14c8bf..6ac1ec1fbb0247c87b65fdfb07a7aacd94df74de 100644
--- a/docs/cmd/gotk_bootstrap.md
+++ b/docs/cmd/gotk_bootstrap.md
@@ -14,6 +14,7 @@ The bootstrap sub-commands bootstrap the toolkit components on the targeted Git
       --components strings         list of components, accepts comma-separated values (default [source-controller,kustomize-controller,helm-controller,notification-controller])
   -h, --help                       help for bootstrap
       --image-pull-secret string   Kubernetes secret name used for pulling the toolkit images from a private registry
+      --log-level string           set the controllers log level (default "info")
       --registry string            container registry where the toolkit images are published (default "ghcr.io/fluxcd")
   -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/gotk_bootstrap_github.md b/docs/cmd/gotk_bootstrap_github.md
index 650a8d4300d9b04f9875a0f6818e89805bc0fb04..7c8620c6881947b7ba337c446d4e8a9e2998f929 100644
--- a/docs/cmd/gotk_bootstrap_github.md
+++ b/docs/cmd/gotk_bootstrap_github.md
@@ -62,6 +62,7 @@ gotk bootstrap github [flags]
       --components strings         list of components, accepts comma-separated values (default [source-controller,kustomize-controller,helm-controller,notification-controller])
       --image-pull-secret string   Kubernetes secret name used for pulling the toolkit images from a private registry
       --kubeconfig string          path to the kubeconfig file (default "~/.kube/config")
+      --log-level string           set the controllers log level (default "info")
       --namespace string           the namespace scope for this operation (default "gitops-system")
       --registry string            container registry where the toolkit images are published (default "ghcr.io/fluxcd")
       --timeout duration           timeout for this operation (default 5m0s)
diff --git a/docs/cmd/gotk_bootstrap_gitlab.md b/docs/cmd/gotk_bootstrap_gitlab.md
index be8c63991303e25221affec4835fcfa63007701e..899a437f4d781672d019ecb891814e5c6f70fc42 100644
--- a/docs/cmd/gotk_bootstrap_gitlab.md
+++ b/docs/cmd/gotk_bootstrap_gitlab.md
@@ -59,6 +59,7 @@ gotk bootstrap gitlab [flags]
       --components strings         list of components, accepts comma-separated values (default [source-controller,kustomize-controller,helm-controller,notification-controller])
       --image-pull-secret string   Kubernetes secret name used for pulling the toolkit images from a private registry
       --kubeconfig string          path to the kubeconfig file (default "~/.kube/config")
+      --log-level string           set the controllers log level (default "info")
       --namespace string           the namespace scope for this operation (default "gitops-system")
       --registry string            container registry where the toolkit images are published (default "ghcr.io/fluxcd")
       --timeout duration           timeout for this operation (default 5m0s)
diff --git a/docs/cmd/gotk_install.md b/docs/cmd/gotk_install.md
index 1cdc400a161cb6429288ccb109b54f1d54a028b2..d92d1503aa509c28ea9ea93e5fa90d8dc15c9ee6 100644
--- a/docs/cmd/gotk_install.md
+++ b/docs/cmd/gotk_install.md
@@ -37,6 +37,7 @@ gotk install [flags]
       --export                     write the install manifests to stdout and exit
   -h, --help                       help for install
       --image-pull-secret string   Kubernetes secret name used for pulling the toolkit images from a private registry
+      --log-level string           set the controllers log level (default "info")
       --manifests string           path to the manifest directory, dev only
       --registry string            container registry where the toolkit images are published (default "ghcr.io/fluxcd")
   -v, --version string             toolkit version (default "latest")