diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml
index e95c537f128b64dc1597c088bba9eb24d6d193cf..b0504ab91128ae43bb240dc5d936c6cd9f79fccc 100644
--- a/.gitlab-ci.yml
+++ b/.gitlab-ci.yml
@@ -9,6 +9,10 @@ include:
   - project: 'paas-tools/infrastructure-ci'
     file: 'docker-images-ci-templates/DockerImages.gitlab-ci.yml'
 
+Build Topic Branch:
+  variables:
+    TAG: "${CI_COMMIT_REF_SLUG}-${CI_COMMIT_SHORT_SHA}"
+
 stages:
   - build
   - test
diff --git a/chart/drupalsite-operator/templates/manager-deploy.yaml b/chart/drupalsite-operator/templates/manager-deploy.yaml
index 887b93968ef43a8ae52bcb9efe72e3f3bc60aff1..2311e037733ae7f2386a83bb15fb62c22073b561 100644
--- a/chart/drupalsite-operator/templates/manager-deploy.yaml
+++ b/chart/drupalsite-operator/templates/manager-deploy.yaml
@@ -35,6 +35,7 @@ spec:
         - --easystart-backup-name={{.Values.drupalsiteOperator.easystartBackupName}}
         - --supported-drupal-version-name={{.Values.drupalsiteOperator.supportedDrupalVersionName}}
         - --velero-backup-storage-location={{.Values.drupalsiteOperator.veleroBackupStorageLocation}}
+        - --ckeditor-license-key={{.Values.drupalsiteOperator.ckeditorLicenseKey}}
         command:
         - /manager
         image: {{ .Values.image | quote }}
diff --git a/chart/drupalsite-operator/values.yaml b/chart/drupalsite-operator/values.yaml
index b7450610015179eac5eefeb2918f842c3c08dced..80005cfaeee072ee887641d5b68f46c48fcfd46c 100644
--- a/chart/drupalsite-operator/values.yaml
+++ b/chart/drupalsite-operator/values.yaml
@@ -33,3 +33,4 @@ drupalsiteOperator:
   clusterName: {}
   easystartBackupName: ""
   veleroBackupStorageLocation: "default"
+  ckeditorLicenseKey: ""
diff --git a/controllers/drupalsite_controller.go b/controllers/drupalsite_controller.go
index 83e817451bf4cfdd8bb1e4a1572be37f32ac04d9..0e44c24668eb69c3efcd9884fd6d71c4cb807e38 100644
--- a/controllers/drupalsite_controller.go
+++ b/controllers/drupalsite_controller.go
@@ -84,6 +84,8 @@ var (
 	SupportedDrupalVersionName string
 	// VeleroBackupStorageLocation refers to the name of the Velero backupStorageLocation to be used
 	VeleroBackupStorageLocation string
+	// CkeditorLicenseKey refers to the name of the License key for the ckeditor4lts module
+	CkeditorLicenseKey string
 )
 
 // DrupalSiteReconciler reconciles a DrupalSite object
diff --git a/controllers/drupalsite_resources.go b/controllers/drupalsite_resources.go
index 77ad859791c63be77f4b87feaff82a44a1f9fc28..f99d284affb2f7d4e0237c13ee60b0ea45a43bb9 100644
--- a/controllers/drupalsite_resources.go
+++ b/controllers/drupalsite_resources.go
@@ -100,6 +100,9 @@ func (r *DrupalSiteReconciler) ensureResources(drp *webservicesv1a1.DrupalSite,
 	if transientErr := r.ensureResourceX(ctx, drp, "webdav_secret", log); transientErr != nil {
 		transientErrs = append(transientErrs, transientErr.Wrap("%v: for WebDAV Secret"))
 	}
+	if transientErr := r.ensureResourceX(ctx, drp, "ckeditor_license_key_secret", log); transientErr != nil {
+		transientErrs = append(transientErrs, transientErr.Wrap("%v: for Ckeditor4LTS Secret"))
+	}
 
 	// 3. Serving layer
 
@@ -212,6 +215,7 @@ ensureResourceX ensure the requested resource is created, with the following val
   - oidc_return_uri: Redirection URI for OIDC
   - dbod_cr: DBOD custom resource to establish database & respective connection for the drupalsite
   - webdav_secret: Secret with credential for WebDAV
+  - ckeditor_license_key_secret: Secret with license key for ckeditor4lts
   - backup_schedule: Velero Schedule for scheduled backups of the drupalSite
   - tekton_extra_perm_rbac: ClusterRoleBinding for tekton tasks
   - gitlab_trigger_secret: Secret for Gitlab trigger config in buildconfig
@@ -253,6 +257,18 @@ func (r *DrupalSiteReconciler) ensureResourceX(ctx context.Context, d *webservic
 			return newApplicationError(err, ErrClientK8s)
 		}
 		return nil
+	case "ckeditor_license_key_secret":
+		secretName := fmt.Sprintf("ckeditor-license-key-%s", d.Name)
+		ckeditorLicenseKeySecret := &corev1.Secret{ObjectMeta: metav1.ObjectMeta{Name: secretName, Namespace: d.Namespace}}
+		_, err := controllerruntime.CreateOrUpdate(ctx, r.Client, ckeditorLicenseKeySecret, func() error {
+			log.V(4).Info("Ensuring Resource", "Kind", ckeditorLicenseKeySecret.TypeMeta.Kind, "Resource.Namespace", ckeditorLicenseKeySecret.Namespace, "Resource.Name", ckeditorLicenseKeySecret.Name)
+			return secretForCKEditorLicenseKey(ckeditorLicenseKeySecret, d, CkeditorLicenseKey)
+		})
+		if err != nil {
+			log.Error(err, "Failed to ensure Resource", "Kind", ckeditorLicenseKeySecret.TypeMeta.Kind, "Resource.Namespace", ckeditorLicenseKeySecret.Namespace, "Resource.Name", ckeditorLicenseKeySecret.Name)
+			return newApplicationError(err, ErrClientK8s)
+		}
+		return nil
 	case "svc_nginx":
 		svc := &corev1.Service{ObjectMeta: metav1.ObjectMeta{Name: d.Name, Namespace: d.Namespace}}
 		_, err := controllerruntime.CreateOrUpdate(ctx, r.Client, svc, func() error {
@@ -903,16 +919,6 @@ func deploymentForDrupalSite(currentobject *appsv1.Deployment, databaseSecret st
 					Name:          "php-fpm",
 					Protocol:      "TCP",
 				}}
-				currentobject.Spec.Template.Spec.Containers[i].Env = []corev1.EnvVar{
-					{
-						Name:  "DRUPAL_SHARED_VOLUME",
-						Value: "/drupal-data",
-					},
-					{
-						Name:  "SMTPHOST",
-						Value: SMTPHost,
-					},
-				}
 				currentobject.Spec.Template.Spec.Containers[i].EnvFrom = []corev1.EnvFromSource{
 					{
 						SecretRef: &corev1.SecretEnvSource{
@@ -1165,6 +1171,28 @@ func deploymentForDrupalSite(currentobject *appsv1.Deployment, databaseSecret st
 				FailureThreshold:    3,
 				SuccessThreshold:    1,
 			}
+
+			currentobject.Spec.Template.Spec.Containers[i].Env = []corev1.EnvVar{
+				{
+					Name:  "DRUPAL_SHARED_VOLUME",
+					Value: "/drupal-data",
+				},
+				{
+					Name:  "SMTPHOST",
+					Value: SMTPHost,
+				},
+				{
+					Name: "CKEDITOR_LICENSE_KEY",
+					ValueFrom: &v1.EnvVarSource{
+						SecretKeyRef: &v1.SecretKeySelector{
+							LocalObjectReference: v1.LocalObjectReference{
+								Name: fmt.Sprintf("ckeditor-license-key-%s", d.Name),
+							},
+							Key: "CKEDITOR_LICENSE_KEY",
+						},
+					},
+				},
+			}
 		case "php-fpm-exporter":
 			currentobject.Spec.Template.Spec.Containers[i].Image = PhpFpmExporterImage
 			currentobject.Spec.Template.Spec.Containers[i].Resources = config.phpExporterResources
@@ -1419,6 +1447,27 @@ func secretForWebDAV(currentobject *corev1.Secret, d *webservicesv1a1.DrupalSite
 	return nil
 }
 
+// secretForCKEditorLicenseKey returns the CKEditor license key from a parameter
+func secretForCKEditorLicenseKey(currentobject *corev1.Secret, d *webservicesv1a1.DrupalSite, ckeditorLicenseKey string) error {
+	addOwnerRefToObject(currentobject, asOwner(d))
+	currentobject.Type = "Opaque"
+	if ckeditorLicenseKey == "" {
+		return fmt.Errorf("CKEDITOR_LICENSE_KEY parameter is not set")
+	}
+	currentobject.StringData = map[string]string{
+		"CKEDITOR_LICENSE_KEY": ckeditorLicenseKey,
+	}
+	if currentobject.Labels == nil {
+		currentobject.Labels = map[string]string{}
+	}
+	ls := labelsForDrupalSite(d.Name)
+	ls["app"] = "drupal"
+	for k, v := range ls {
+		currentobject.Labels[k] = v
+	}
+	return nil
+}
+
 // persistentVolumeClaimForDrupalSite returns a PVC object
 func persistentVolumeClaimForDrupalSite(currentobject *corev1.PersistentVolumeClaim, d *webservicesv1a1.DrupalSite) error {
 	addOwnerRefToObject(currentobject, asOwner(d))
@@ -1604,6 +1653,17 @@ func jobForDrupalSiteInstallation(currentobject *batchv1.Job, databaseSecret str
 						Name:  "SMTPHOST",
 						Value: SMTPHost,
 					},
+					{
+						Name: "CKEDITOR_LICENSE_KEY",
+						ValueFrom: &v1.EnvVarSource{
+							SecretKeyRef: &v1.SecretKeySelector{
+								LocalObjectReference: v1.LocalObjectReference{
+									Name: fmt.Sprintf("ckeditor-license-key-%s", d.Name),
+								},
+								Key: "CKEDITOR_LICENSE_KEY",
+							},
+						},
+					},
 				},
 				EnvFrom: []corev1.EnvFromSource{
 					{
@@ -1756,6 +1816,17 @@ func jobForDrupalSiteClone(currentobject *batchv1.Job, databaseSecret string, d
 						Name:  "DRUPAL_SHARED_VOLUME",
 						Value: "/drupal-data-source",
 					},
+					{
+						Name: "CKEDITOR_LICENSE_KEY",
+						ValueFrom: &v1.EnvVarSource{
+							SecretKeyRef: &v1.SecretKeySelector{
+								LocalObjectReference: v1.LocalObjectReference{
+									Name: fmt.Sprintf("ckeditor-license-key-%s", d.Name),
+								},
+								Key: "CKEDITOR_LICENSE_KEY",
+							},
+						},
+					},
 				},
 				EnvFrom: []corev1.EnvFromSource{
 					{
diff --git a/controllers/suite_test.go b/controllers/suite_test.go
index 090f679facab43ffda0bdba45071c4218e776aea..86ca34b44a778631559aa5ccc26371797c6ce406 100644
--- a/controllers/suite_test.go
+++ b/controllers/suite_test.go
@@ -85,6 +85,7 @@ var _ = BeforeSuite(func(done Done) {
 	EasystartBackupName = "easystart-backup"
 	SupportedDrupalVersionName = "supported-drupal-versions"
 	VeleroBackupStorageLocation = "default"
+	CkeditorLicenseKey = ""
 
 	By("bootstrapping test environment")
 	testEnv = &envtest.Environment{
diff --git a/main.go b/main.go
index 651a25f9e41b03163807b42dc773c511ded9adab..3522c8ad8c81bedd65c8c45b86bcbf44ae758b2f 100644
--- a/main.go
+++ b/main.go
@@ -96,6 +96,7 @@ func main() {
 	flag.StringVar(&controllers.SupportedDrupalVersionName, "supported-drupal-version-name", "supported-drupal-versions", "The name of the resource used cluster-wide for supported drupal versions")
 	flag.StringVar(&controllers.VeleroBackupStorageLocation, "velero-backup-storage-location", "default", "The name of the backupStorageLocation to be used for Velero Schedules created by the controller")
 	flag.StringVar(&websiteImagePullPolicyString, "websiteImagePullPolicy", "IfNotPresent", "The default image pull policy for deployed pods. We avoid 'Always' as it makes us more vulnerable to container registry downtime.")
+	flag.StringVar(&controllers.CkeditorLicenseKey, "ckeditor-license-key", "", "License key for the ckeditor4lts module")
 	opts := zap.Options{
 		Development: false,
 	}