diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml
index 50d6fc895c1acc74441e671eaabd993c307052e1..6d8e1adb30b154d366d64166c4e717f78733cbb1 100644
--- a/.gitlab-ci.yml
+++ b/.gitlab-ci.yml
@@ -1,5 +1,6 @@
 variables:
   HELPERS_FILE: docker-build.yml
+  HELM_HELPERS_FILE: helm.yml
   APP_HELM_NAME: signer
   DOCKER_FILE: deployment/ci/Dockerfile
 
@@ -7,13 +8,15 @@ stages:
   - compile
   - test
   - build
-  - manifest
+  - helm
   - deploy
 
 include:
   - project: '${HELPERS_PATH}'
     file: '${HELPERS_FILE}'
   - template: 'Workflows/Branch-Pipelines.gitlab-ci.yml'
+  - project: "$HELM_HELPERS_PATH}"
+    file: "${HELM_HELPERS_FILE}"
 
 lint:
   image: golangci/golangci-lint:latest
@@ -60,14 +63,8 @@ amd64:
   tags:
     - amd64-docker
 
-manifest:
-  extends: .manifest-amd64
-  stage: manifest
-
-cloud:
-  extends: .manifest-cloud
-  stage: manifest
-
-release:
-  extends: .manifest-release
-  stage: manifest
+helm-lint:
+  extends: .helm-lint
+  stage: helm
+  tags:
+    - amd64-docker
diff --git a/deployment/helm/Chart.yaml b/deployment/helm/Chart.yaml
new file mode 100644
index 0000000000000000000000000000000000000000..6d1aff33495742bb99d819acc6555105c89c56bd
--- /dev/null
+++ b/deployment/helm/Chart.yaml
@@ -0,0 +1,6 @@
+apiVersion: v1
+appVersion:  v1.0.7
+description: signer deployment
+name: signer
+version: 1.0.7
+icon: "https://www.vereign.com/wp-content/themes/vereign2020/images/vereign-logo.svg"
diff --git a/deployment/helm/LICENSE b/deployment/helm/LICENSE
new file mode 100644
index 0000000000000000000000000000000000000000..ee3fe4d59d330da12ba6be93527e76eea5ec00c4
--- /dev/null
+++ b/deployment/helm/LICENSE
@@ -0,0 +1,16 @@
+Deployment recipe for TSA signer service
+
+
+Copyright 2022 Vereign AG
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+    http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
diff --git a/deployment/helm/README.md b/deployment/helm/README.md
new file mode 100644
index 0000000000000000000000000000000000000000..30b115af3ec9616a479b5c88bcf890c17cc32479
--- /dev/null
+++ b/deployment/helm/README.md
@@ -0,0 +1,58 @@
+# signer
+
+![Version: 1.0.1](https://img.shields.io/badge/Version-1.0.1-informational?style=flat-square) ![AppVersion: v1.0.1-rc](https://img.shields.io/badge/AppVersion-v1.0.1--rc-informational?style=flat-square)
+
+signer deployment
+
+## Values
+
+| Key | Type | Default | Description |
+|-----|------|---------|-------------|
+| autoscaling.enabled | bool | `false` | Enable autoscaling |
+| autoscaling.maxReplicas | int | `3` | Maximum replicas |
+| autoscaling.minReplicas | int | `1` | Minimum replicas |
+| autoscaling.targetCPUUtilizationPercentage | int | `70` | CPU target for autoscaling trigger |
+| autoscaling.targetMemoryUtilizationPercentage | int | `70` | Memory target for autoscaling trigger |
+| image.name | string | `"gaiax/signer"` | Image name |
+| image.pullPolicy | string | `"IfNotPresent"` | Image pull policy |
+| image.pullSecrets | string | `"deployment-key-light"` | Image pull secret when internal image is used |
+| image.repository | string | `"eu.gcr.io/vrgn-infra-prj"` |  |
+| image.sha | string | `""` | Image sha, usually generated by the CI Uses image.tag if empty |
+| image.tag | string | `""` | Image tag Uses .Chart.AppVersion if empty |
+| ingress.annotations."cert-manager.io/cluster-issuer" | string | `"letsencrypt-production-http"` |  |
+| ingress.annotations."kubernetes.io/ingress.class" | string | `"nginx"` |  |
+| ingress.annotations."kubernetes.io/ingress.global-static-ip-name" | string | `"dev-light-public"` |  |
+| ingress.annotations."nginx.ingress.kubernetes.io/rewrite-target" | string | `"/$2"` |  |
+| ingress.enabled | bool | `true` |  |
+| ingress.frontendDomain | string | `"gaiax.vereign.com"` |  |
+| ingress.frontendTlsSecretName | string | `"cert-manager-tls"` |  |
+| ingress.tlsEnabled | bool | `true` |  |
+| log.encoding | string | `"json"` |  |
+| log.level | string | `"debug"` |  |
+| metrics.enabled | bool | `true` | Enable prometheus metrics |
+| metrics.port | int | `2112` | Port for prometheus metrics |
+| name | string | `"signer"` | Application name |
+| nameOverride | string | `""` | Ovverwrites application name |
+| podAnnotations | object | `{}` |  |
+| replicaCount | int | `1` | Default number of instances to start  |
+| resources.limits.cpu | string | `"150m"` |  |
+| resources.limits.memory | string | `"128Mi"` |  |
+| resources.requests.cpu | string | `"25m"` |  |
+| resources.requests.memory | string | `"64Mi"` |  |
+| security.runAsGid | int | `0` | Group used by the apps |
+| security.runAsNonRoot | bool | `false` | by default, apps run as non-root |
+| security.runAsUid | int | `0` | User used by the apps |
+| service.port | int | `8080` |  |
+| signer.credential.issuer | string | `"did:web:gaiax.vereign.com:tsa:policy:policy:example:returnDID:1.0:evaluation"` |  |
+| signer.http.host | string | `""` |  |
+| signer.http.port | int | `8080` |  |
+| signer.http.timeout.idle | string | `"120s"` |  |
+| signer.http.timeout.read | string | `"10s"` |  |
+| signer.http.timeout.write | string | `"10s"` |  |
+| signer.vault.addr | string | `"http://vault:8200"` |  |
+| signer.vault.key.signing | string | `"key1"` |  |
+| signer.vault.key.supported | string | `"ed25519,ecdsa-p256,ecdsa-p384,ecdsa-p521,rsa-2048"` |  |
+| signer.vault.token | string | `"token"` |  |
+
+----------------------------------------------
+Autogenerated from chart metadata using [helm-docs v1.10.0](https://github.com/norwoodj/helm-docs/releases/v1.10.0)
diff --git a/deployment/helm/templates/_helpers.tpl b/deployment/helm/templates/_helpers.tpl
new file mode 100644
index 0000000000000000000000000000000000000000..6955ccba19a0e68b2918305e46546f4741fea0aa
--- /dev/null
+++ b/deployment/helm/templates/_helpers.tpl
@@ -0,0 +1,88 @@
+{{/* vim: set filetype=mustache: */}}
+{{/*
+Expand the name of the chart.
+*/}}
+{{- define "app.name" -}}
+{{- default .Chart.Name .Values.nameOverride | trunc 63 | trimSuffix "-" -}}
+{{- end -}}
+
+{{/*
+Create a fully qualified app name.
+We truncate at 63 chars because some Kubernetes name fields are limited to this (by the DNS naming spec).
+*/}}
+{{- define "app.fullname" -}}
+{{- $name := default .Chart.Name .Values.nameOverride -}}
+{{- printf "%s-%s" $name .Release.Namespace | trunc 63 | trimSuffix "-" -}}
+{{- end -}}
+
+{{/*
+Create instance name based on app version and short image sha.
+*/}}
+{{- define "app.revision" -}}
+{{- default .Release.Name .Values.appRel | trunc 63 | trimSuffix "-" -}}
+{{- end -}}
+
+{{/*
+Create chart name and version as used by the chart label.
+*/}}
+{{- define "app.chart" -}}
+{{- printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" | trunc 63 | trimSuffix "-" -}}
+{{- end -}}
+
+{{/*
+Common labels
+*/}}
+{{- define "app.labels" -}}
+helm.sh/chart: {{ include "app.chart" . }}
+{{ include "app.selectorLabels" . }}
+app.kubernetes.io/version: {{ .Chart.AppVersion }}
+app.kubernetes.io/managed-by: {{ .Release.Service }}
+{{- end -}}
+
+{{/*
+Selector labels
+*/}}
+{{- define "app.selectorLabels" -}}
+app.kubernetes.io/name: {{ include "app.name" . }}
+app.kubernetes.io/component: {{ include "app.fullname" . }}
+{{- end -}}
+
+{{/*
+Metrics Annotations
+*/}}
+{{- define "app.metricsAnnotations" -}}
+{{- if .Values.metrics.enabled -}}
+prometheus.io/scrape: "true"
+prometheus.io/port: "{{ .Values.metrics.port }}"
+prometheus.io/path: {{ .Values.metrics.path | default "/metrics" | quote }}
+{{- end -}}
+{{- end -}}
+
+{{/*
+Image string
+*/}}
+{{- define "app.image" -}}
+{{- if .Values.image.sha -}}
+{{ .Values.image.repository }}/{{ .Values.image.name }}@{{ .Values.image.sha }}
+{{- else -}}
+{{ .Values.image.repository }}/{{ .Values.image.name }}:{{ default .Chart.AppVersion .Values.image.tag }}
+{{- end -}}
+{{- end -}}
+
+{{/*
+Security context
+*/}}
+{{- define "app.securitycontext" -}}
+runAsNonRoot: {{ .Values.security.runAsNonRoot | default false }}
+runAsGroup: {{ .Values.security.runAsGid | default 0 }}
+runAsUser: {{ .Values.security.runAsUid | default 0 }}
+fsGroup: {{ .Values.security.runAsGid | default 0 }}
+{{- end -}}
+
+{{/*
+PostgreSQL Connection  string URI
+*/}}
+{{- define "app.postgresql.connectionstring" -}}
+postgresql://{{ .Values.connectionManager.database.user }}:{{ .Values.connectionManager.database.password }}@{{ .Values.connectionManager.database.host }}:{{ .Values.connectionManager.database.port }}/{{ .Release.Namespace }}_{{ include "app.name" . | replace "-" "_" }}?schema={{ .Values.connectionManager.database.schema }}
+{{- end -}}
+
diff --git a/deployment/helm/templates/deployment.yaml b/deployment/helm/templates/deployment.yaml
new file mode 100644
index 0000000000000000000000000000000000000000..e02c22be14f5d12363c25b05fd186891acc8d40b
--- /dev/null
+++ b/deployment/helm/templates/deployment.yaml
@@ -0,0 +1,83 @@
+apiVersion: apps/v1
+kind: Deployment
+metadata:
+  name: "{{ template "app.name" . }}"
+  namespace: {{ .Release.Namespace }}
+  labels:
+    {{- include "app.labels" . | nindent 4 }}
+    app.kubernetes.io/instance: {{ include "app.revision" . }}
+    app.kubernetes.io/part-of: rse
+spec:
+  replicas: {{ .Values.replicaCount }}
+  strategy:
+    type: RollingUpdate
+    rollingUpdate:
+      maxSurge: 1
+      maxUnavailable: 0
+  selector:
+    matchLabels:
+      {{- include "app.selectorLabels" . | nindent 6 }}
+  template:
+    metadata:
+      labels:
+        {{- include "app.labels" . | nindent 8 }}
+      annotations:
+        {{- include "app.metricsAnnotations" . | nindent 8 }}
+{{- if .Values.podAnnotations }}
+{{ toYaml .Values.podAnnotations | indent 8 }}
+{{- end }}
+    spec:
+      securityContext:
+{{- include "app.securitycontext" . | nindent 8 }}
+      imagePullSecrets:
+        - name: {{ .Values.image.pullSecrets }}
+      containers:
+      - name: {{ template "app.name" . }}
+        image: "{{ .Values.image.repository }}/{{ .Values.image.name }}:{{ default .Chart.AppVersion .Values.image.tag }}"
+        imagePullPolicy: {{ .Values.image.pullPolicy | quote }}
+        env:
+          - name: LOG_LEVEL
+            value: {{ .Values.log.level | default "INFO" }}
+          - name: LOG_ENCODING
+            value: {{ .Values.log.encoding | default "json" }}
+          - name: HTTP_HOST
+            value: {{ .Values.signer.http.host | quote }}
+          - name: HTTP_PORT
+            value: {{ .Values.signer.http.port | quote }}
+          - name: HTTP_IDLE_TIMEOUT
+            value: {{ .Values.signer.http.timeout.idle | quote }}
+          - name: HTTP_READ_TIMEOUT
+            value: {{ .Values.signer.http.timeout.read | quote }}
+          - name: HTTP_WRITE_TIMEOUT
+            value: {{ .Values.signer.http.timeout.write | quote }}
+          - name: VAULT_ADDR
+            value: {{ .Values.signer.vault.addr | quote }}
+          - name: VAULT_TOKEN
+            value: {{ .Values.signer.vault.token | quote }}
+          - name: VAULT_SIGNING_KEY
+            value: {{ .Values.signer.vault.key.signing | quote }}
+          - name: VAULT_SUPPORTED_KEYS
+            value: {{ .Values.signer.vault.key.supported | quote }}
+          - name: CREDENTIAL_ISSUER
+            value: {{ .Values.signer.credential.issuer | quote }}
+{{- if .Values.extraVars }}
+{{ toYaml .Values.extraVars | indent 8 }}
+{{- end }}
+        ports:
+        {{- if .Values.metrics.enabled }}
+          - name: monitoring
+            containerPort: {{ .Values.metrics.port }}
+        {{- end }}
+          - name: http
+            containerPort: {{ .Values.signer.http.port }}
+        readinessProbe:
+          httpGet:
+            path: /readiness
+            port: {{ .Values.signer.http.port }}
+          initialDelaySeconds: 5
+          periodSeconds: 5
+          successThreshold: 2
+          failureThreshold: 2
+          timeoutSeconds: 5
+        resources:
+{{ toYaml .Values.resources | indent 10 }}
diff --git a/deployment/helm/templates/hpa.yaml b/deployment/helm/templates/hpa.yaml
new file mode 100644
index 0000000000000000000000000000000000000000..fc5c29e7463c24756cfa83754e8ab9336be7b8c2
--- /dev/null
+++ b/deployment/helm/templates/hpa.yaml
@@ -0,0 +1,27 @@
+{{- if .Values.autoscaling.enabled }}
+apiVersion: autoscaling/v2
+kind: HorizontalPodAutoscaler
+metadata:
+  labels:
+    {{- include "app.labels" . | nindent 4 }}
+  name: {{ template "app.name" . }}
+  namespace: {{ .Release.Namespace }}
+spec:
+  scaleTargetRef:
+    apiVersion: apps/v1
+    kind: Deployment
+    name: {{ template "app.name" . }}
+  minReplicas: {{ .Values.autoscaling.minReplicas }}
+  maxReplicas: {{ .Values.autoscaling.maxReplicas }}
+  metrics:
+{{- with .Values.autoscaling.targetCPUUtilizationPercentage }}
+    - type: Resource
+      resource:
+        name: cpu
+{{- end }}
+{{- with .Values.autoscaling.targetMemoryUtilizationPercentage }}
+    - type: Resource
+      resource:
+        name: memory
+{{- end }}
+{{- end }}
\ No newline at end of file
diff --git a/deployment/helm/templates/ingress.yaml b/deployment/helm/templates/ingress.yaml
new file mode 100644
index 0000000000000000000000000000000000000000..23487ccf94950a184832d2e2eeb819bea29f529a
--- /dev/null
+++ b/deployment/helm/templates/ingress.yaml
@@ -0,0 +1,29 @@
+{{- if .Values.ingress.enabled }}
+apiVersion: networking.k8s.io/v1
+kind: Ingress
+metadata:
+  name: {{ template "app.name" . }}
+  namespace: {{ .Release.Namespace }}
+  annotations:
+{{ toYaml .Values.ingress.annotations | indent 4 }}
+  labels:
+    {{- include "app.labels" . | nindent 4 }}
+spec:
+{{- if .Values.ingress.tlsEnabled }}
+  tls:
+    - hosts:
+        - {{ .Values.ingress.frontendDomain }}
+      secretName: {{ .Values.ingress.frontendTlsSecretName }}
+{{- end }}
+  rules:
+    - host: {{ .Values.ingress.frontendDomain }}
+      http:
+        paths:
+          - path: /{{ template "app.name" . }}(/|$)(.*)
+            pathType: Prefix
+            backend:
+              service:
+                name: {{ template "app.name" . }}
+                port:
+                  number: {{ .Values.service.port }}
+{{- end }}
\ No newline at end of file
diff --git a/deployment/helm/templates/service.yaml b/deployment/helm/templates/service.yaml
new file mode 100644
index 0000000000000000000000000000000000000000..980440e72d9aaa41e7ad764be14a639e0f41d102
--- /dev/null
+++ b/deployment/helm/templates/service.yaml
@@ -0,0 +1,15 @@
+apiVersion: v1
+kind: Service
+metadata:
+  name: {{ template "app.name" . }}
+  namespace: {{ .Release.Namespace }}
+  labels:
+    {{- include "app.labels" . | nindent 4 }}
+spec:
+  clusterIP: None
+  ports:
+  - name: http
+    targetPort: {{ .Values.service.port }}
+    port: {{ .Values.signer.http.port }}
+  selector:
+    {{- include "app.selectorLabels" . | nindent 4 }}
diff --git a/deployment/helm/values-override.yaml b/deployment/helm/values-override.yaml
new file mode 100644
index 0000000000000000000000000000000000000000..f881319892bb578d643523e543b85b12483fad7b
--- /dev/null
+++ b/deployment/helm/values-override.yaml
@@ -0,0 +1,9 @@
+image:
+  repository: registry.gitlab.com/gaia-x/data-infrastructure-federation-services/tsa
+  # -- Image name
+  name: signer
+
+ingress:
+  frontendDomain: tsa.gxfs.dev 
+  frontendTlsSecretName: wildcard-gxfs-dev
+
diff --git a/deployment/helm/values.yaml b/deployment/helm/values.yaml
new file mode 100644
index 0000000000000000000000000000000000000000..0113664b1829b0410775eb186acd2c0dc1245c02
--- /dev/null
+++ b/deployment/helm/values.yaml
@@ -0,0 +1,93 @@
+# -- Default number of instances to start 
+replicaCount: 1
+# -- Application name
+name: signer
+# -- Ovverwrites application name
+nameOverride: ""
+
+image:
+  repository: eu.gcr.io/vrgn-infra-prj
+  # -- Image name
+  name: gaiax/signer
+  # -- Image tag
+  # Uses .Chart.AppVersion if empty
+  tag: ""
+  # -- Image sha, usually generated by the CI
+  # Uses image.tag if empty
+  sha: ""
+  # -- Image pull policy
+  pullPolicy: IfNotPresent
+  # -- Image pull secret when internal image is used
+  pullSecrets: deployment-key-light
+
+
+podAnnotations: {}
+
+resources:
+  requests:
+    cpu: 25m
+    memory: 64Mi
+  limits:
+    cpu: 150m
+    memory: 128Mi
+
+autoscaling:
+  # -- Enable autoscaling
+  enabled: false
+  # -- Minimum replicas
+  minReplicas: 1
+  # -- Maximum replicas
+  maxReplicas: 3
+  # -- CPU target for autoscaling trigger
+  targetCPUUtilizationPercentage: 70
+  # -- Memory target for autoscaling trigger
+  targetMemoryUtilizationPercentage: 70
+
+metrics:
+  # -- Enable prometheus metrics
+  enabled: true
+  # -- Port for prometheus metrics
+  port: 2112
+
+log:
+  level: "debug"
+  encoding: json
+
+
+security:
+  # -- by default, apps run as non-root
+  runAsNonRoot: false
+  # -- User used by the apps
+  runAsUid: 0
+  # -- Group used by the apps
+  runAsGid: 0
+
+service:
+  port: 8080
+
+signer:
+  http:
+    host: ""
+    port: 8080
+    timeout:
+      idle: 120s
+      read: 10s
+      write: 10s
+  vault:
+    addr: http://vault:8200
+    token: token
+    key:
+      signing: key1
+      supported: "ed25519,ecdsa-p256,ecdsa-p384,ecdsa-p521,rsa-2048"
+  credential:
+    issuer: "did:web:gaiax.vereign.com:tsa:policy:policy:example:returnDID:1.0:evaluation"
+
+ingress:
+  enabled: true
+  annotations:
+    kubernetes.io/ingress.class: nginx
+    nginx.ingress.kubernetes.io/rewrite-target: /$2
+  tlsEnabled: true
+  frontendDomain: gaiax.vereign.com
+  frontendTlsSecretName: cert-manager-tls
+