diff --git a/.gitignore b/.gitignore
index 3b72af06f63e14ea65f6aac0929f38aa57590d94..9447f01bf62ca54d5388a3996cf8b6b63d5ba02e 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,2 +1,3 @@
 .env
 __pycache__
+.lock
diff --git a/helmchart/.helmignore b/helmchart/.helmignore
new file mode 100644
index 0000000000000000000000000000000000000000..50af0317254197a5a019f4ac2f8ecc223f93f5a7
--- /dev/null
+++ b/helmchart/.helmignore
@@ -0,0 +1,22 @@
+# Patterns to ignore when building packages.
+# This supports shell glob matching, relative path matching, and
+# negation (prefixed with !). Only one pattern per line.
+.DS_Store
+# Common VCS dirs
+.git/
+.gitignore
+.bzr/
+.bzrignore
+.hg/
+.hgignore
+.svn/
+# Common backup files
+*.swp
+*.bak
+*.tmp
+*~
+# Various IDEs
+.project
+.idea/
+*.tmproj
+.vscode/
diff --git a/helmchart/Chart.yaml b/helmchart/Chart.yaml
new file mode 100644
index 0000000000000000000000000000000000000000..a200c6841926d6ebc2b33bc3064e0ecd9ba8daf7
--- /dev/null
+++ b/helmchart/Chart.yaml
@@ -0,0 +1,5 @@
+apiVersion: v1
+appVersion: "1.0"
+description: A Helm chart for OpenAppStacks Signle Sign on components
+name: single-sign-on
+version: 0.1.0
diff --git a/helmchart/requirements.yaml b/helmchart/requirements.yaml
new file mode 100644
index 0000000000000000000000000000000000000000..26eab31ca057cdec713cbfd6a06d100b172ae228
--- /dev/null
+++ b/helmchart/requirements.yaml
@@ -0,0 +1,6 @@
+dependencies:
+  - name: hydra
+    version: 0.0.17
+    repository: "@ory"
+    tags:
+      - single-sign-on
diff --git a/helmchart/templates/NOTES.txt b/helmchart/templates/NOTES.txt
new file mode 100644
index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391
diff --git a/helmchart/templates/_helpers.tpl b/helmchart/templates/_helpers.tpl
new file mode 100644
index 0000000000000000000000000000000000000000..74008849c376be3c80aee0466acf249d494a34ec
--- /dev/null
+++ b/helmchart/templates/_helpers.tpl
@@ -0,0 +1,45 @@
+{{/* vim: set filetype=mustache: */}}
+{{/*
+Expand the name of the chart.
+*/}}
+{{- define "single-sign-on.name" -}}
+{{- default .Chart.Name .Values.nameOverride | trunc 63 | trimSuffix "-" -}}
+{{- end -}}
+
+{{/*
+Create a default fully qualified app name.
+We truncate at 63 chars because some Kubernetes name fields are limited to this (by the DNS naming spec).
+If release name contains chart name it will be used as a full name.
+*/}}
+{{- define "single-sign-on.fullname" -}}
+{{- if .Values.fullnameOverride -}}
+{{- .Values.fullnameOverride | trunc 63 | trimSuffix "-" -}}
+{{- else -}}
+{{- $name := default .Chart.Name .Values.nameOverride -}}
+{{- if contains $name .Release.Name -}}
+{{- .Release.Name | trunc 63 | trimSuffix "-" -}}
+{{- else -}}
+{{- printf "%s-%s" .Release.Name $name | trunc 63 | trimSuffix "-" -}}
+{{- end -}}
+{{- end -}}
+{{- end -}}
+
+{{/*
+Create chart name and version as used by the chart label.
+*/}}
+{{- define "single-sign-on.chart" -}}
+{{- printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" | trunc 63 | trimSuffix "-" -}}
+{{- end -}}
+
+{{/*
+Common labels
+*/}}
+{{- define "single-sign-on.labels" -}}
+app.kubernetes.io/name: {{ include "single-sign-on.name" . }}
+helm.sh/chart: {{ include "single-sign-on.chart" . }}
+app.kubernetes.io/instance: {{ .Release.Name }}
+{{- if .Chart.AppVersion }}
+app.kubernetes.io/version: {{ .Chart.AppVersion | quote }}
+{{- end }}
+app.kubernetes.io/managed-by: {{ .Release.Service }}
+{{- end -}}
diff --git a/helmchart/templates/deployment-consent.yaml b/helmchart/templates/deployment-consent.yaml
new file mode 100644
index 0000000000000000000000000000000000000000..f055e6a14e30a9b345e0df4a8bfa4450bd8d9fe1
--- /dev/null
+++ b/helmchart/templates/deployment-consent.yaml
@@ -0,0 +1,35 @@
+apiVersion: apps/v1
+kind: Deployment
+metadata:
+  name: {{ include "single-sign-on.fullname" . }}-consent
+  labels:
+{{ include "single-sign-on.labels" . | indent 4 }}
+spec:
+  replicas: 1
+  selector:
+    matchLabels:
+      app.kubernetes.io/name: {{ include "single-sign-on.name" . }}-consent
+  template:
+    metadata:
+      labels:
+        app.kubernetes.io/name: {{ include "single-sign-on.name" . }}-consent
+    spec:
+      containers:
+        - name: {{ .Chart.Name }}-consent
+          image: "consent-provider"
+          imagePullPolicy: Never
+          env:
+            - name: HYDRA_ADMIN_URL
+              value: {{ .Values.global.hydraAdminUrl }}
+          ports:
+            - name: consent-http
+              containerPort: 5001
+              protocol: TCP
+              #livenessProbe:
+              #httpGet:
+              #path: /consent
+              #port: consent-http
+              #readinessProbe:
+              #httpGet:
+              #path: /consent
+              #port: consent-http
diff --git a/helmchart/templates/deployment-login.yaml b/helmchart/templates/deployment-login.yaml
new file mode 100644
index 0000000000000000000000000000000000000000..911f62bc2d925bb2879d1d43e16fd87d2bcb9b48
--- /dev/null
+++ b/helmchart/templates/deployment-login.yaml
@@ -0,0 +1,35 @@
+apiVersion: apps/v1
+kind: Deployment
+metadata:
+  name: {{ include "single-sign-on.fullname" . }}-login
+  labels:
+{{ include "single-sign-on.labels" . | indent 4 }}
+spec:
+  replicas: 1
+  selector:
+    matchLabels:
+      app.kubernetes.io/name: {{ include "single-sign-on.name" . }}-login
+  template:
+    metadata:
+      labels:
+        app.kubernetes.io/name: {{ include "single-sign-on.name" . }}-login
+    spec:
+      containers:
+        - name: {{ .Chart.Name }}-login
+          image: "login-provider"
+          imagePullPolicy: Never
+          env:
+            - name: HYDRA_ADMIN_URL
+              value: {{ .Values.global.hydraAdminUrl }}
+          ports:
+            - name: login-http
+              containerPort: 5000
+              protocol: TCP
+              livenessProbe:
+              #httpGet:
+              #path: /
+              #port: login-http
+              #readinessProbe:
+              #httpGet:
+              #path: /
+              #port: login-http
diff --git a/helmchart/templates/ingress.yaml b/helmchart/templates/ingress.yaml
new file mode 100644
index 0000000000000000000000000000000000000000..8de6d95a161f693343a9d324e73bc872d81bb3c3
--- /dev/null
+++ b/helmchart/templates/ingress.yaml
@@ -0,0 +1,35 @@
+apiVersion: extensions/v1beta1
+kind: Ingress
+metadata:
+  name: {{ include "single-sign-on.fullname" . }}
+  labels:
+{{ include "single-sign-on.labels" . | indent 4 }}
+  annotations:
+    kubernetes.io/tls-acme: "true"
+spec:
+  rules:
+  - host: {{ .Values.consentProvider.ingress.host }}
+    http:
+      paths:
+      - path: /
+        backend:
+          serviceName: {{ include "single-sign-on.fullname" . }}-consent
+          servicePort: 5001
+  - host: {{ .Values.loginProvider.ingress.host }}
+    http:
+      paths:
+      - path: /
+        backend:
+          serviceName: {{ include "single-sign-on.fullname" . }}-login
+          servicePort: 5000
+  tls:
+  - hosts:
+    - {{ .Values.loginProvider.ingress.host }}
+    secretName: {{ include "single-sign-on.fullname" . }}-login
+  - hosts:
+    - {{ .Values.consentProvider.ingress.host }}
+    secretName: {{ include "single-sign-on.fullname" . }}-consent
+status:
+  loadBalancer:
+    ingress:
+    - {}
diff --git a/helmchart/templates/service-consent.yaml b/helmchart/templates/service-consent.yaml
new file mode 100644
index 0000000000000000000000000000000000000000..74bb0ca254a4d0f1fd02aa7f2216d7f0ffac3db6
--- /dev/null
+++ b/helmchart/templates/service-consent.yaml
@@ -0,0 +1,14 @@
+apiVersion: v1
+kind: Service
+metadata:
+  name: {{ include "single-sign-on.fullname" . }}-consent
+  labels:
+{{ include "single-sign-on.labels" . | indent 4 }}
+spec:
+  ports:
+    - port: 5001
+      targetPort: consent-http
+      protocol: TCP
+      name: consent-http
+  selector:
+    app.kubernetes.io/name: {{ include "single-sign-on.name" . }}-consent
diff --git a/helmchart/templates/service-login.yaml b/helmchart/templates/service-login.yaml
new file mode 100644
index 0000000000000000000000000000000000000000..dc615d97f8b17339922834d6768dd833b81ccbdc
--- /dev/null
+++ b/helmchart/templates/service-login.yaml
@@ -0,0 +1,14 @@
+apiVersion: v1
+kind: Service
+metadata:
+  name: {{ include "single-sign-on.fullname" . }}-login
+  labels:
+{{ include "single-sign-on.labels" . | indent 4 }}
+spec:
+  ports:
+    - port: 5000
+      targetPort: login-http
+      protocol: TCP
+      name: login-http
+  selector:
+    app.kubernetes.io/name: {{ include "single-sign-on.name" . }}-login
diff --git a/helmchart/templates/tests/test-connection.yaml b/helmchart/templates/tests/test-connection.yaml
new file mode 100644
index 0000000000000000000000000000000000000000..af0221f34aabe95690c0dda60ca46f228cfbb89e
--- /dev/null
+++ b/helmchart/templates/tests/test-connection.yaml
@@ -0,0 +1,15 @@
+apiVersion: v1
+kind: Pod
+metadata:
+  name: "{{ include "single-sign-on.fullname" . }}-test-connection"
+  labels:
+{{ include "single-sign-on.labels" . | indent 4 }}
+  annotations:
+    "helm.sh/hook": test-success
+spec:
+  containers:
+    - name: wget
+      image: busybox
+      command: ['wget']
+      args:  ['{{ include "single-sign-on.fullname" . }}:5000']
+  restartPolicy: Never
diff --git a/helmchart/values.yaml b/helmchart/values.yaml
new file mode 100644
index 0000000000000000000000000000000000000000..ab75ae126fb6b25cb7f0eb0cb836703708b76349
--- /dev/null
+++ b/helmchart/values.yaml
@@ -0,0 +1,65 @@
+global:
+  hydraAdminUrl: https://hydra-admin.oas.example.net
+
+loginProvider:
+  ingress:
+    host: login.oas.example.net
+
+consentProvider:
+  ingress:
+    host: consent.oas.example.net
+
+hydra:
+  hydra:
+    config:
+      serve:
+        public:
+          port: 4444
+        admin:
+          port: 4445
+        tls:
+          allow_termination_from:
+            - 10.0.0.0/8
+            - 172.16.0.0/12
+            - 192.168.0.0/16
+      dsn: memory
+      urls:
+        self:
+          issuer: https://hydra-admin.oas.example.net
+          public: https://hydra.oas.example.net
+        login: https://login.oas.example.net
+        consent: https://consent.oas.example.net
+      secrets:
+        system: "YouReallyNeedToChangeThis"
+  ingress:
+    public:
+      enabled: true
+      annotations:
+        kubernetes.io/tls-acme: "true"
+      hosts:
+        - host: hydra.oas.example.net
+          paths: ["/"]
+      tls:
+        - hosts:
+          - hydra.oas.example.net
+          secretName: hydra-proxy-example.tls
+    admin:
+      enabled: true
+      annotations:
+        kubernetes.io/tls-acme: "true"
+      hosts:
+        - host: hydra-admin.oas.example.net
+          paths: ["/"]
+      tls:
+        - hosts:
+          - hydra-admin.oas.example.net
+          secretName: hydra-admin-proxy-example.tls
+  service:
+    public:
+      enabled: true
+      type: ClusterIP
+      port: 4444
+    admin:
+      enabled: true
+      type: ClusterIP
+      port: 4445