diff --git a/charts/gitea/.helmignore b/charts/gitea/.helmignore
new file mode 100644
index 0000000000000000000000000000000000000000..f82e96d46779ce5283d066ead0140dd0f7ce8d06
--- /dev/null
+++ b/charts/gitea/.helmignore
@@ -0,0 +1,23 @@
+# 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
+*.orig
+*~
+# Various IDEs
+.project
+.idea/
+*.tmproj
+.vscode/
diff --git a/charts/gitea/Chart.lock b/charts/gitea/Chart.lock
new file mode 100644
index 0000000000000000000000000000000000000000..4fe5bfaaf3283d8ac491f7ae078bef91e8d1df33
--- /dev/null
+++ b/charts/gitea/Chart.lock
@@ -0,0 +1,12 @@
+dependencies:
+- name: mariadb
+  repository: https://groundhog2k.github.io/helm-charts
+  version: 0.1.4
+- name: postgres
+  repository: https://groundhog2k.github.io/helm-charts
+  version: 0.1.2
+- name: redis
+  repository: https://groundhog2k.github.io/helm-charts
+  version: 0.1.2
+digest: sha256:ad9b3c1c3b617da6a8e299ddfef6af01767ac13f9b98010f580bece672df3117
+generated: "2020-11-18T07:45:24.7041208+01:00"
diff --git a/charts/gitea/Chart.yaml b/charts/gitea/Chart.yaml
new file mode 100644
index 0000000000000000000000000000000000000000..89592f906e8271455b7d76cf6e5d3e3ed5675e2a
--- /dev/null
+++ b/charts/gitea/Chart.yaml
@@ -0,0 +1,28 @@
+apiVersion: v2
+name: gitea
+description: A Helm chart for Gitea on Kubernetes
+
+type: application
+
+maintainers:
+  - name: groundhog2k
+
+# This is the chart version
+version: 0.1.0
+
+# This is the version number of the application being deployed.
+appVersion: "1.12.6"
+
+dependencies:
+  - name: mariadb
+    version: 0.1.4
+    repository: "https://groundhog2k.github.io/helm-charts"
+    condition: mariadb.enabled
+  - name: postgres
+    version: 0.1.2
+    repository: "https://groundhog2k.github.io/helm-charts"
+    condition: postgres.enabled
+  - name: redis
+    version: 0.1.2
+    repository: "https://groundhog2k.github.io/helm-charts"
+    condition: redis.enabled
diff --git a/charts/gitea/README.md b/charts/gitea/README.md
new file mode 100644
index 0000000000000000000000000000000000000000..4a58d67a1ecdf5319d151459bd99ae9a1390d3c2
--- /dev/null
+++ b/charts/gitea/README.md
@@ -0,0 +1,147 @@
+#  Gitea
+
+![Version: 0.0.1](https://img.shields.io/badge/Version-0.0.1-informational?style=flat-square) ![Type: application](https://img.shields.io/badge/Type-application-informational?style=flat-square) ![AppVersion: 1.12.6](https://img.shields.io/badge/AppVersion-1.12.5-informational?style=flat-square)
+
+A Helm chart for Gitea on Kubernetes
+
+## TL;DR
+
+```bash
+$ helm repo add groundhog2k https://groundhog2k.github.io/helm-charts/
+$ helm install my-release groundhog2k/gitea
+```
+
+## Introduction
+
+This chart uses the original [Gitea from Docker](https://hub.docker.com/r/gitea/gitea) to deploy Gitea in Kubernetes.
+
+It allows fully supports deployment of the [ARM64v8 image of Gitea](https://hub.docker.com/layers/gitea/gitea/linux-arm64/images/sha256-21cf22dace8dcd3ccd3188a65380ae028b9dc891a9385caeb0db27b62c3d7a42?context=explore) on a ARM64 based Kubernetes cluster just by exchanging the existing `node.selector` value.
+
+## Prerequisites
+
+- Kubernetes 1.12+
+- Helm 3.x
+- PV provisioner support in the underlying infrastructure
+
+## Installing the Chart
+
+To install the chart with the release name `my-release`:
+
+```bash
+$ helm install my-release groundhog2k/gitea
+```
+
+## Uninstalling the Chart
+
+To uninstall/delete the `my-release` deployment:
+
+```bash
+$ helm uninstall my-release
+```
+
+## Requirements
+
+| Repository | Name | Version |
+|------------|------|---------|
+| @groundhog2k | mariadb | 0.1.4 |
+| @groundhog2k | postgres | 0.1.2 |
+| @groundhog2k | redis | 0.1.2 |
+
+## Common parameters
+
+| Key | Type | Default | Description |
+|-----|------|---------|-------------|
+| fullnameOverride | string | `""` | Fully override the deployment name |
+| nameOverride | string | `""` | Partially override the deployment name |
+
+## Deployment parameters
+
+| Key | Type | Default | Description |
+|-----|------|---------|-------------|
+| image.pullPolicy | string | `"IfNotPresent"` | Image pull policy |
+| image.repository | string | `"gitea/gitea"` | Image name |
+| image.tag | string | `""` | Image tag |
+| imagePullSecrets | list | `[]` | Image pull secrets |
+| livenessProbe | object | `see values.yaml` | Liveness probe configuration |
+| readinessProbe | object | `see values.yaml` | Readiness probe configuration |
+| resources | object | `{}` | Resource limits and requests |
+| nodeSelector."kubernetes.io/arch" | string | `"amd64"` | Deployment node selector |
+| podAnnotations | object | `{}` | Additional pod annotations |
+| podSecurityContext | object | `see values.yaml` | Pod security context |
+| securityContext | object | `see values.yaml` | Container security context |
+| env | list | `[]` | Additional container environmment variables |
+| serviceAccount.create | bool | `false` | Enable service account creation |
+| serviceAccount.name | string | `""` | Optional name of the service account |
+| serviceAccount.annotations | object | `{}` | Additional service account annotations |
+| affinity | object | `{}` | Affinity for pod assignment |
+| tolerations | list | `[]` | Tolerations for pod assignment |
+| containerHttpPort | int | `8000` | Internal http container port |
+| containerSshPort | int | `8022` | Internal ssh container port |
+| replicaCount | int | `1` | Number of replicas |
+
+## Service paramters
+
+| Key | Type | Default | Description |
+|-----|------|---------|-------------|
+| services.http.type | string | `"ClusterIP"` | Service type |
+| services.http.port | int | `80` | Gitea HTTP service port |
+| services.ssh.type | string | `"ClusterIP"` | Service type |
+| services.ssh.port | int | `22` | Gitea SSH service port |
+| services.ssh.nodePort | int | `nil` | Gitea SSH NodePort (if type NodePort is used) |
+| services.ssh.clusterIP | int | `nil` | Gitea SSH ClusterIP (if type LoadBalancer is used) |
+
+## Ingress parameters
+
+| Key | Type | Default | Description |
+|-----|------|---------|-------------|
+| ingress.enabled | bool | `false` | Enable ingress for Gitea service |
+| ingress.annotations | string | `nil` | Additional annotations for ingress |
+| ingress.hosts[0].host | string | `""` | Hostname for the ingress endpoint |
+| ingress.tls | list | `[]` | Ingress TLS parameters |
+| ingress.maxBodySize | string | `"64m"` | Maximum body size for post requests |
+
+## Redis session cache
+
+| Key | Type | Default | Description |
+|-----|------|---------|-------------|
+| redis.enabled | bool | `false` | Enable Redis cache deployment (will disable external cache settings) |
+| redis.storage | string | `nil` | Redis storage settings |
+
+## Database settings
+
+| Key | Type | Default | Description |
+|-----|------|---------|-------------|
+| mariadb.enabled | bool | `false` | Enable MariaDB deployment (will disable external database settings) |
+| mariadb.settings.arguments[0] | string | `"--character-set-server=utf8mb4"` | Enable MariaDB UTF8MB4 character set|
+| mariadb.settings.arguments[1] | string | `"--collation-server=utf8mb4_unicode_ci"` | Enable UTF8MB4 unicode |
+| mariadb.settings.rootPassword | string | `nil` | MariaDB root user password |
+| mariadb.storage | string | `nil` | MariaDB storage settings |
+| mariadb.userDatabase.name | string | `nil` | MariaDB Gitea database name |
+| mariadb.userDatabase.password | string | `nil` | MariaDB Gitea database user |
+| mariadb.userDatabase.user | string | `nil` | MariaDB Gitea database user password |
+| postgres.enabled | bool | `false` | Enable PostgreSQL deployment (will disable external database settings) |
+| postgres.settings.superuserPassword | string | `nil` | PostgreSQL superuser password |
+| postgres.storage | string | `nil` | PostgreSQL storage settings |
+| postgres.userDatabase.name | string | `nil` | PostgreSQL Gitea database name |
+| postgres.userDatabase.user | string | `nil` | PostgreSQL Gitea database user |
+| postgres.userDatabase.password | string | `nil` | PostgreSQL Gitea database user password |
+
+## Gitea parameters
+
+| Key | Type | Default | Description |
+|-----|------|---------|-------------|
+| settings.postInstallDelay | int | `60` | Delay after installation before adminstrative user gets created (Database must be ready and connected) |
+| settings.defaultAdmin.name | string | `root` | Gitea administrator user |
+| settings.defaultAdmin.password | string | `admin` | Gitea admin user password (Must be changed during first login) |
+| settings.defaultAdmin.email | string | `root@admin.local` | Gitea administrator users email |
+| gitea.config | object | `see values.yaml` | Gitea specific configuration as described in https://docs.gitea.io/en-us/config-cheat-sheet/ - More values and sections can be added - All values will only be created once during install!
+
+## Storage parameters
+
+| Key | Type | Default | Description |
+|-----|------|---------|-------------|
+| storage | object | `{}` | Gitea data storage |
+| storage.accessModes[0] | string | `"ReadWriteOnce"` | Storage access mode |
+| storage.persistentVolumeClaimName | string | `""` | PVC name when existing storage volume should be used |
+| storage.requestedSize | string | `""` | Size for new PVC, when no existing PVC is used |
+| storage.className | string | `""` | Storage class name |
diff --git a/charts/gitea/charts/mariadb-0.1.4.tgz b/charts/gitea/charts/mariadb-0.1.4.tgz
new file mode 100644
index 0000000000000000000000000000000000000000..13530022952aaa7f779ff2a8294064f6586ec8f5
Binary files /dev/null and b/charts/gitea/charts/mariadb-0.1.4.tgz differ
diff --git a/charts/gitea/charts/postgres-0.1.2.tgz b/charts/gitea/charts/postgres-0.1.2.tgz
new file mode 100644
index 0000000000000000000000000000000000000000..a76bf914680f5f362f39a73999b1211b99fb3bad
Binary files /dev/null and b/charts/gitea/charts/postgres-0.1.2.tgz differ
diff --git a/charts/gitea/charts/redis-0.1.2.tgz b/charts/gitea/charts/redis-0.1.2.tgz
new file mode 100644
index 0000000000000000000000000000000000000000..2984482e8b6abaaddfce97b4660fa623c4a23157
Binary files /dev/null and b/charts/gitea/charts/redis-0.1.2.tgz differ
diff --git a/charts/gitea/templates/_helpers.tpl b/charts/gitea/templates/_helpers.tpl
new file mode 100644
index 0000000000000000000000000000000000000000..67ac00ac397c362a05abd952030417b365643469
--- /dev/null
+++ b/charts/gitea/templates/_helpers.tpl
@@ -0,0 +1,102 @@
+{{/* vim: set filetype=mustache: */}}
+{{/*
+Expand the name of the chart.
+*/}}
+{{- define "gitea.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 "gitea.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 }}
+
+{{- define "mariadb.servicename" -}}
+{{- if .Values.mariadb.fullnameOverride }}
+{{- .Values.mariadb.fullnameOverride | trunc 63 | trimSuffix "-" }}
+{{- else }}
+{{- $name := default "mariadb" .Values.mariadb.nameOverride }}
+{{- if contains $name .Release.Name }}
+{{- .Release.Name | trunc 63 | trimSuffix "-" }}
+{{- else }}
+{{- printf "%s-%s" .Release.Name $name | trunc 63 | trimSuffix "-" }}
+{{- end }}
+{{- end }}
+{{- end }}
+
+{{- define "postgres.servicename" -}}
+{{- if .Values.postgres.fullnameOverride }}
+{{- .Values.postgres.fullnameOverride | trunc 63 | trimSuffix "-" }}
+{{- else }}
+{{- $name := default "postgres" .Values.postgres.nameOverride }}
+{{- if contains $name .Release.Name }}
+{{- .Release.Name | trunc 63 | trimSuffix "-" }}
+{{- else }}
+{{- printf "%s-%s" .Release.Name $name | trunc 63 | trimSuffix "-" }}
+{{- end }}
+{{- end }}
+{{- end }}
+
+{{- define "redis.servicename" -}}
+{{- if .Values.redis.fullnameOverride }}
+{{- .Values.redis.fullnameOverride | trunc 63 | trimSuffix "-" }}
+{{- else }}
+{{- $name := default "redis" .Values.redis.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 "gitea.chart" -}}
+{{- printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" | trunc 63 | trimSuffix "-" }}
+{{- end }}
+
+{{/*
+Common labels
+*/}}
+{{- define "gitea.labels" -}}
+helm.sh/chart: {{ include "gitea.chart" . }}
+{{ include "gitea.selectorLabels" . }}
+{{- if .Chart.AppVersion }}
+app.kubernetes.io/version: {{ .Chart.AppVersion | quote }}
+{{- end }}
+app.kubernetes.io/managed-by: {{ .Release.Service }}
+{{- end }}
+
+{{/*
+Selector labels
+*/}}
+{{- define "gitea.selectorLabels" -}}
+app.kubernetes.io/name: {{ include "gitea.name" . }}
+app.kubernetes.io/instance: {{ .Release.Name }}
+{{- end }}
+
+{{/*
+Create the name of the service account to use
+*/}}
+{{- define "gitea.serviceAccountName" -}}
+{{- if .Values.serviceAccount.create }}
+{{- default (include "gitea.fullname" .) .Values.serviceAccount.name }}
+{{- else }}
+{{- default "default" .Values.serviceAccount.name }}
+{{- end }}
+{{- end }}
diff --git a/charts/gitea/templates/deployment.yaml b/charts/gitea/templates/deployment.yaml
new file mode 100644
index 0000000000000000000000000000000000000000..ca5dae68362e9f28ed52dba5e9ed70c557978fe1
--- /dev/null
+++ b/charts/gitea/templates/deployment.yaml
@@ -0,0 +1,125 @@
+apiVersion: apps/v1
+kind: Deployment
+metadata:
+  name: {{ include "gitea.fullname" . }}
+  labels:
+    {{- include "gitea.labels" . | nindent 4 }}
+spec:
+  replicas: {{ .Values.replicaCount }}
+  selector:
+    matchLabels:
+      {{- include "gitea.selectorLabels" . | nindent 6 }}
+  template:
+    metadata:
+    {{- with .Values.podAnnotations }}
+      annotations:
+        {{- toYaml . | nindent 8 }}
+    {{- end }}
+      labels:
+        {{- include "gitea.selectorLabels" . | nindent 8 }}
+    spec:
+      {{- with .Values.imagePullSecrets }}
+      imagePullSecrets:
+        {{- toYaml . | nindent 8 }}
+      {{- end }}
+      serviceAccountName: {{ include "gitea.serviceAccountName" . }}
+      securityContext:
+        {{- toYaml .Values.podSecurityContext | nindent 8 }}
+      initContainers:
+        - name: init
+          securityContext:
+            {{- toYaml .Values.securityContext | nindent 12 }}         
+          image: "{{ .Values.image.repository }}:{{ .Values.image.tag | default .Chart.AppVersion }}"
+          command: [ "/scripts/init.sh" ]
+          volumeMounts:
+            - name: scripts
+              mountPath: /scripts
+            - name: config
+              mountPath: /config
+            - name: gitea-vol
+              mountPath: /data
+      containers:
+        - name: {{ .Chart.Name }}
+          securityContext:
+            {{- toYaml .Values.securityContext | nindent 12 }}
+          image: "{{ .Values.image.repository }}:{{ .Values.image.tag | default .Chart.AppVersion }}"
+          imagePullPolicy: {{ .Values.image.pullPolicy }}
+          command: [ "/app/gitea/gitea" ]
+          ports:
+            - name: http
+              containerPort: {{ .Values.containerHttpPort }}
+              protocol: TCP
+            - name: ssh
+              containerPort: {{ .Values.containerSshPort }}
+              protocol: TCP
+          {{- if .Values.env }}
+          env:
+          {{- with .Values.env }}
+            {{- toYaml . | nindent 12 }}
+          {{- end }}
+          {{- end }}
+          {{- if .Values.livenessProbe.enabled }}
+          livenessProbe:
+            tcpSocket:
+              port: http
+          {{- with .Values.livenessProbe }}
+            initialDelaySeconds: {{ .initialDelaySeconds }}
+            timeoutSeconds: {{ .timeoutSeconds }}
+            failureThreshold: {{ .failureThreshold }}
+            successThreshold: {{ .successThreshold }}
+            periodSeconds: {{ .periodSeconds }}
+          {{- end }}
+          {{- end }}
+          {{- if .Values.readinessProbe.enabled }}
+          readinessProbe:
+            tcpSocket:
+              port: http
+          {{- with .Values.readinessProbe }}
+            initialDelaySeconds: {{ .initialDelaySeconds }}
+            timeoutSeconds: {{ .timeoutSeconds }}
+            failureThreshold: {{ .failureThreshold }}
+            successThreshold: {{ .successThreshold }}
+            periodSeconds: {{ .periodSeconds }}
+          {{- end }}
+          {{- end }}
+          resources:
+            {{- toYaml .Values.resources | nindent 12 }}
+          volumeMounts:
+            - name: run
+              mountPath: /var/run
+            - name: gitea-vol
+              mountPath: /data
+      {{- with .Values.nodeSelector }}
+      nodeSelector:
+        {{- toYaml . | nindent 8 }}
+      {{- end }}
+      {{- with .Values.affinity }}
+      affinity:
+        {{- toYaml . | nindent 8 }}
+      {{- end }}
+      {{- with .Values.tolerations }}
+      tolerations:
+        {{- toYaml . | nindent 8 }}
+      {{- end }}
+      volumes:
+        - name: run
+          emptyDir: {}
+        - name: scripts
+          configMap:
+            name: {{ include "gitea.fullname" . }}-scripts
+            defaultMode: 0555
+        - name: config
+          secret:
+            secretName: {{ include "gitea.fullname" . }}
+        - name: gitea-vol
+        {{- if .Values.storage.persistentVolumeClaimName }}
+          persistentVolumeClaim:
+            claimName: {{ .Values.storage.persistentVolumeClaimName }}
+        {{- else }}
+        {{- if .Values.storage.requestedSize }}
+          persistentVolumeClaim:
+            claimName: {{ include "gitea.fullname" . }}
+        {{- else }}
+          emptyDir: {}
+        {{- end }}
+        {{- end }}
diff --git a/charts/gitea/templates/ingress.yaml b/charts/gitea/templates/ingress.yaml
new file mode 100644
index 0000000000000000000000000000000000000000..d995aebf7209d28fd78e57d152b29798e7606eac
--- /dev/null
+++ b/charts/gitea/templates/ingress.yaml
@@ -0,0 +1,43 @@
+{{- if .Values.ingress.enabled -}}
+{{- $fullName := include "gitea.fullname" . -}}
+{{- $svcPort := .Values.services.http.port -}}
+{{- $maxSize := .Values.ingress.maxBodySize -}}
+{{- if semverCompare ">=1.14-0" .Capabilities.KubeVersion.GitVersion -}}
+apiVersion: networking.k8s.io/v1beta1
+{{- else -}}
+apiVersion: extensions/v1beta1
+{{- end }}
+kind: Ingress
+metadata:
+  name: {{ $fullName }}
+  labels:
+    {{- include "gitea.labels" . | nindent 4 }}
+  annotations:
+    nginx.ingress.kubernetes.io/proxy-body-size: {{ $maxSize }}
+  {{- with .Values.ingress.annotations }}
+    {{- toYaml . | nindent 4 }}
+  {{- end }}
+spec:
+  {{- if .Values.ingress.tls }}
+  tls:
+    {{- range .Values.ingress.tls }}
+    - hosts:
+        {{- range .hosts }}
+        - {{ . | quote }}
+        {{- end }}
+      secretName: {{ .secretName }}
+    {{- end }}
+  {{- end }}
+  rules:
+    {{- range .Values.ingress.hosts }}
+    - host: {{ .host | quote }}
+      http:
+        paths:
+          {{- range .paths }}
+          - path: {{ . }}
+            backend:
+              serviceName: {{ $fullName }}-http
+              servicePort: {{ $svcPort }}
+          {{- end }}
+    {{- end }}
+  {{- end }}
diff --git a/charts/gitea/templates/post-install.yaml b/charts/gitea/templates/post-install.yaml
new file mode 100644
index 0000000000000000000000000000000000000000..54d0de53c3c1b0028e01e7cc9b50ae62e0406b4c
--- /dev/null
+++ b/charts/gitea/templates/post-install.yaml
@@ -0,0 +1,74 @@
+apiVersion: batch/v1
+kind: Job
+metadata:
+  name: {{ include "gitea.fullname" . }}-postinstall
+  labels:
+    {{- include "gitea.labels" . | nindent 4 }}
+  annotations:
+    "helm.sh/hook": post-install
+    "helm.sh/hook-delete-policy": hook-succeeded
+spec:
+  template:
+    spec:
+      securityContext:
+        {{- toYaml .Values.podSecurityContext | nindent 8 }}
+      restartPolicy: OnFailure
+      containers:
+        - name: {{ .Chart.Name }}-postinstall
+          securityContext:
+            {{- toYaml .Values.securityContext | nindent 12 }}
+          image: "{{ .Values.image.repository }}:{{ .Values.image.tag | default .Chart.AppVersion }}"
+          imagePullPolicy: {{ .Values.image.pullPolicy }}
+          envFrom:
+            - secretRef:
+                name: {{ include "gitea.fullname" . }}
+          {{- if .Values.env }}
+          env:
+          {{- with .Values.env }}
+            {{- toYaml . | nindent 12 }}
+          {{- end }}
+          {{- end }}
+          args:
+            - /bin/sh
+            - -c
+            - /scripts/createdefaultadmin.sh
+          volumeMounts:
+            - name: gitea-vol
+              mountPath: /data
+            - name: scripts
+              mountPath: /scripts
+      restartPolicy: OnFailure
+      {{- with .Values.nodeSelector }}
+      nodeSelector:
+        {{- toYaml . | nindent 8 }}
+      {{- end }}
+      {{- with .Values.affinity }}
+      affinity:
+        {{- toYaml . | nindent 8 }}
+      {{- end }}
+      {{- with .Values.tolerations }}
+      tolerations:
+        {{- toYaml . | nindent 8 }}
+      {{- end }}
+      volumes:
+        - name: run
+          emptyDir: {}
+        - name: scripts
+          configMap:
+            name: {{ include "gitea.fullname" . }}-scripts
+            defaultMode: 0555
+        - name: config
+          secret:
+            secretName: {{ include "gitea.fullname" . }}
+        - name: gitea-vol
+        {{- if .Values.storage.persistentVolumeClaimName }}
+          persistentVolumeClaim:
+            claimName: {{ .Values.storage.persistentVolumeClaimName }}
+        {{- else }}
+        {{- if .Values.storage.requestedSize }}
+          persistentVolumeClaim:
+            claimName: {{ include "gitea.fullname" . }}
+        {{- else }}
+          emptyDir: {}
+        {{- end }}
+        {{- end }}
diff --git a/charts/gitea/templates/pvcs.yaml b/charts/gitea/templates/pvcs.yaml
new file mode 100644
index 0000000000000000000000000000000000000000..01392eda39ca0845c3c56d41a4c89b58475a5415
--- /dev/null
+++ b/charts/gitea/templates/pvcs.yaml
@@ -0,0 +1,21 @@
+{{- $createNcPvc := and (empty .Values.storage.persistentVolumeClaimName) (.Values.storage.requestedSize) }}
+{{- if $createNcPvc }}
+apiVersion: v1
+kind: PersistentVolumeClaim
+metadata:
+  name: {{ include "gitea.fullname" . }}
+  labels:
+    {{- include "gitea.labels" . | nindent 4 }}
+spec:
+  {{- with .Values.storage }}
+  accessModes:
+    {{- toYaml .accessModes | nindent 4 }}
+  volumeMode: Filesystem
+  resources:
+    requests:
+      storage: {{ .requestedSize }}
+  {{- if .storageClassName }}
+  storageClassName: {{ .storageClassName }}
+  {{- end }}
+  {{- end }}  
+{{- end }}
diff --git a/charts/gitea/templates/scripts.yaml b/charts/gitea/templates/scripts.yaml
new file mode 100644
index 0000000000000000000000000000000000000000..f49309584dd027a5b0b176636f7037248b6e6d7a
--- /dev/null
+++ b/charts/gitea/templates/scripts.yaml
@@ -0,0 +1,27 @@
+apiVersion: v1
+kind: ConfigMap
+metadata:
+  name: {{ include "gitea.fullname" . }}-scripts
+  labels:
+    {{- include "gitea.labels" . | nindent 4 }}
+data:
+  init.sh: |
+    #!/bin/bash
+    if [ ! -f /data/gitea/conf/app.ini ]; then
+      mkdir -p /data/gitea/conf
+      mkdir -p /data/gitea/lfs
+      mkdir -p /data/git
+      mkdir -p /data/git/gitea-repositories
+      mkdir -p /data/log
+      cp /config/app.ini /data/gitea/conf/app.ini
+      chmod u+rw /data/gitea/conf/app.ini
+    fi
+  createdefaultadmin.sh: |
+    #!/bin/bash
+    if [ ! -f /data/gitea/conf/.post-install-done ]; then
+      sleep {{ .Values.settings.postInstallDelay }}
+      {{- with .Values.settings.defaultAdmin }}
+      /app/gitea/gitea admin create-user --username {{ .user }} --password {{ .password }} --email {{ .email }} --admin --must-change-password
+      {{- end }}
+      touch /data/gitea/conf/.post-install-done
+    fi
diff --git a/charts/gitea/templates/secureconfig.yaml b/charts/gitea/templates/secureconfig.yaml
new file mode 100644
index 0000000000000000000000000000000000000000..8a1f0bd2780add6d665dd5fffb8508b6a48f4eac
--- /dev/null
+++ b/charts/gitea/templates/secureconfig.yaml
@@ -0,0 +1,109 @@
+apiVersion: v1
+kind: Secret
+metadata:
+  name: {{ include "gitea.fullname" . }}
+  labels:
+    {{- include "gitea.labels" . | nindent 4 }}
+stringData:
+  app.ini: |-
+    {{- if not (hasKey .Values.gitea.config "database") -}}
+    {{- $_ := set .Values.gitea.config "database" dict -}}
+    {{- end -}}
+    {{- if not (hasKey .Values.gitea.config "cache") -}}
+    {{- $_ := set .Values.gitea.config "cache" dict -}}
+    {{- end -}}
+    {{- if not (hasKey .Values.gitea.config "session") -}}
+    {{- $_ := set .Values.gitea.config "session" dict -}}
+    {{- end -}}
+    {{- if not (hasKey .Values.gitea.config "server") -}}
+    {{- $_ := set .Values.gitea.config "server" dict -}}
+    {{- end -}}
+    {{- if not (hasKey .Values.gitea.config "security") -}}
+    {{- $_ := set .Values.gitea.config "security" dict -}}
+    {{- end -}}
+    {{- if not (hasKey .Values.gitea.config "oauth2") -}}
+    {{- $_ := set .Values.gitea.config "oauth2" dict -}}
+    {{- end -}}
+  {{- if .Values.mariadb.enabled }}
+    {{- $_ := set .Values.gitea.config.database "SSL_MODE" "disable" -}}
+    {{- $_ := set .Values.gitea.config.database "DB_TYPE" "mysql" -}}
+    {{- $_ := set .Values.gitea.config.database "CHARSET" "utf8mb4" -}}
+    {{- $_ := set .Values.gitea.config.database "HOST" (include "mariadb.servicename" .) -}}
+    {{- $_ := set .Values.gitea.config.database "NAME" .Values.mariadb.userDatabase.name -}}
+    {{- $_ := set .Values.gitea.config.database "USER" .Values.mariadb.userDatabase.user -}}
+    {{- $_ := set .Values.gitea.config.database "PASSWD" .Values.mariadb.userDatabase.password -}}
+  {{- else }}
+  {{- if .Values.postgres.enabled }}
+    {{- $_ := set .Values.gitea.config.database "SSL_MODE" "disable" -}}
+    {{- $_ := set .Values.gitea.config.database "DB_TYPE" "postgres" -}}
+    {{- $_ := set .Values.gitea.config.database "HOST" (include "postgres.servicename" .) -}}
+    {{- $_ := set .Values.gitea.config.database "NAME" .Values.postgres.userDatabase.name -}}
+    {{- $_ := set .Values.gitea.config.database "USER" .Values.postgres.userDatabase.user -}}
+    {{- $_ := set .Values.gitea.config.database "PASSWD" .Values.postgres.userDatabase.password -}}
+  {{- else }}
+    {{- $_ := set .Values.gitea.config.database "DB_TYPE" "sqlite3" -}}
+  {{- end }}
+  {{- end }}
+  {{- if .Values.redis.enabled }}
+    {{- $_ := set .Values.gitea.config.cache "ENABLED" "true" -}}
+    {{- $_ := set .Values.gitea.config.cache "ADAPTER" "redis" -}}
+    {{- $_ := set .Values.gitea.config.cache "HOST" (printf "network=tcp,addr=%s:%s,db=0,pool_size=100,idle_timeout=180" (include "redis.servicename" .) (toString .Values.redis.service.port)) -}}
+    {{- $_ := set .Values.gitea.config.session "PROVIDER" "redis" -}}
+    {{- $_ := set .Values.gitea.config.session "PROVIDER_CONFIG" (printf "network=tcp,addr=%s:%s,db=0,pool_size=100,idle_timeout=180" (include "redis.servicename" .) (toString .Values.redis.service.port)) -}}
+  {{- end }}
+    {{- if not (hasKey .Values.gitea.config.server "ROOT_URL") -}}
+    {{- if .Values.ingress.enabled -}}
+    {{- if gt (len .Values.ingress.tls) 0 -}}
+    {{- $_ := set .Values.gitea.config.server "ROOT_URL" (printf "%s://%s" "https" (index (index .Values.ingress.tls 0).hosts 0)) -}}
+    {{- if not (hasKey .Values.gitea.config.server "DOMAIN") -}}
+    {{- $_ := set .Values.gitea.config.server "DOMAIN" (index (index .Values.ingress.tls 0).hosts 0) -}}
+    {{- end -}}
+    {{- else -}}
+    {{- $_ := set .Values.gitea.config.server "ROOT_URL" (printf "%s://%s" .Values.gitea.config.server.PROTOCOL (index .Values.ingress.hosts 0)) -}}
+    {{- if not (hasKey .Values.gitea.config.server "DOMAIN") -}}
+    {{- $_ := set .Values.gitea.config.server "DOMAIN" (index .Values.ingress.hosts 0) -}}
+    {{- end -}}
+    {{- end -}}
+    {{- else -}}
+    {{- $_ := set .Values.gitea.config.server "ROOT_URL" (printf "%s://%s" .Values.gitea.config.server.PROTOCOL .Values.gitea.config.server.DOMAIN) -}}
+    {{- end -}}
+    {{- end -}}
+    {{- if not (hasKey .Values.gitea.config.server "SSH_DOMAIN") -}}
+    {{- $_ := set .Values.gitea.config.server "SSH_DOMAIN" .Values.gitea.config.server.DOMAIN -}}
+    {{- end -}}
+    {{- if not (hasKey .Values.gitea.config.server "SSH_LISTEN_PORT") -}}
+    {{- $_ := set .Values.gitea.config.server "SSH_LISTEN_PORT" .Values.containerSshPort -}}
+    {{- $_ := set .Values.gitea.config.server "SSH_PORT" .Values.services.ssh.port -}}
+    {{- end -}}
+    {{- if not (hasKey .Values.gitea.config.server "HTTP_PORT") -}}
+    {{- $_ := set .Values.gitea.config.server "HTTP_PORT" .Values.containerHttpPort -}}
+    {{- end -}}
+
+    {{- if not (hasKey .Values.gitea.config.server "LFS_JWT_SECRET") -}}
+    {{- $_ := set .Values.gitea.config.server "LFS_JWT_SECRET" (randAlphaNum 43) -}}
+    {{- end -}}
+
+    {{- if not (hasKey .Values.gitea.config.security "SECRET_KEY") -}}
+    {{- $_ := set .Values.gitea.config.security "SECRET_KEY" (randAlphaNum 65) -}}
+    {{- end -}}
+    {{- if not (hasKey .Values.gitea.config.security "INTERNAL_TOKEN") -}}
+    {{- $_ := set .Values.gitea.config.security "INTERNAL_TOKEN" (randAlphaNum 105) -}}
+    {{- end -}}
+
+    {{- if not (hasKey .Values.gitea.config.oauth2 "JWT_SECRET") -}}
+    {{- $_ := set .Values.gitea.config.oauth2 "JWT_SECRET" (randAlphaNum 43) -}}
+    {{- end -}}
+
+    {{- /* autogenerate app.ini */ -}}
+    {{- range $key, $value := .Values.gitea.config  }}
+    {{- if kindIs "map" $value }}
+    {{- if gt (len $value) 0 }}
+    [{{ $key }}]
+    {{- range $n_key, $n_value := $value }}
+    {{ $n_key | upper }} = {{ $n_value }}
+    {{- end }}
+    {{- end }}
+    {{- else }}
+    {{ $key | upper }} = {{ $value }}
+    {{- end }}
+    {{- end }}
\ No newline at end of file
diff --git a/charts/gitea/templates/serviceaccount.yaml b/charts/gitea/templates/serviceaccount.yaml
new file mode 100644
index 0000000000000000000000000000000000000000..331f084aa79f00de57ee8d7031a145cbc3a03db7
--- /dev/null
+++ b/charts/gitea/templates/serviceaccount.yaml
@@ -0,0 +1,12 @@
+{{- if .Values.serviceAccount.create -}}
+apiVersion: v1
+kind: ServiceAccount
+metadata:
+  name: {{ include "gitea.serviceAccountName" . }}
+  labels:
+    {{- include "gitea.labels" . | nindent 4 }}
+  {{- with .Values.serviceAccount.annotations }}
+  annotations:
+    {{- toYaml . | nindent 4 }}
+  {{- end }}
+{{- end }}
diff --git a/charts/gitea/templates/services.yaml b/charts/gitea/templates/services.yaml
new file mode 100644
index 0000000000000000000000000000000000000000..227d0fe945a79a755d730bd5292131497a439458
--- /dev/null
+++ b/charts/gitea/templates/services.yaml
@@ -0,0 +1,37 @@
+apiVersion: v1
+kind: Service
+metadata:
+  name: {{ include "gitea.fullname" . }}-http
+  labels:
+    {{- include "gitea.labels" . | nindent 4 }}
+spec:
+  type: {{ .Values.services.http.type }}
+  ports:
+    - port: {{ .Values.services.http.port }}
+      targetPort: http
+      protocol: TCP
+      name: http
+  selector:
+    {{- include "gitea.selectorLabels" . | nindent 4 }}
+---
+apiVersion: v1
+kind: Service
+metadata:
+  name: {{ include "gitea.fullname" . }}-ssh
+  labels:
+    {{- include "gitea.labels" . | nindent 4 }}
+spec:
+  type: {{ .Values.services.ssh.type }}
+  ports:
+    - port: {{ .Values.services.ssh.port }}
+      targetPort: ssh
+      protocol: TCP
+      name: ssh
+      {{- if and (eq .Values.services.ssh.type "NodePort") (.Values.services.ssh.nodePort) }}
+      nodePort: {{ .Values.services.ssh.nodePort }}
+      {{- end }}
+  {{- if and (eq .Values.services.ssh.type "LoadBalancer") (.Values.services.ssh.clusterIP) }}
+  clusterIP: {{ .Values.services.ssh.clusterIP }}
+  {{- end }}
+  selector:
+    {{- include "gitea.selectorLabels" . | nindent 4 }}
diff --git a/charts/gitea/templates/tests/test-connection.yaml b/charts/gitea/templates/tests/test-connection.yaml
new file mode 100644
index 0000000000000000000000000000000000000000..093352715df1597d216344d2e21368aac4799cb4
--- /dev/null
+++ b/charts/gitea/templates/tests/test-connection.yaml
@@ -0,0 +1,15 @@
+apiVersion: v1
+kind: Pod
+metadata:
+  name: "{{ include "gitea.fullname" . }}-test-connection"
+  labels:
+    {{- include "gitea.labels" . | nindent 4 }}
+  annotations:
+    "helm.sh/hook": test-success
+spec:
+  containers:
+    - name: wget
+      image: busybox
+      command: ['wget']
+      args: ['{{ include "gitea.fullname" . }}:{{ .Values.services.http.port }}']
+  restartPolicy: Never
diff --git a/charts/gitea/values.yaml b/charts/gitea/values.yaml
new file mode 100644
index 0000000000000000000000000000000000000000..79095243c95f8bf7c7f17602b2a9528765c06757
--- /dev/null
+++ b/charts/gitea/values.yaml
@@ -0,0 +1,302 @@
+## Default values for Gitea deployment
+
+## Gitea docker image
+## use tag *-linux-arm64 for the same image on ARM64v8
+image:
+  repository: gitea/gitea
+  pullPolicy: IfNotPresent
+  # Overrides the image tag whose default is the chart appVersion.
+  tag: ""
+
+## Number of replicas
+replicaCount: 1
+
+## Pull secrets and name override options
+imagePullSecrets: []
+nameOverride: ""
+fullnameOverride: ""
+
+## Optional service account
+serviceAccount:
+  # Specifies whether a service account should be created
+  create: false
+  # Annotations to add to the service account
+  annotations: {}
+  # The name of the service account to use.
+  # If not set and create is true, a name is generated using the fullname template
+  name: ""
+
+## Additional pod annotations
+podAnnotations: {}
+
+## Pod security options (default: fsGroup)
+podSecurityContext:
+  fsGroup: 1000
+
+## Default security options to run Gitea as read only container without privilege escalation
+securityContext:
+  allowPrivilegeEscalation: false
+  privileged: false
+  readOnlyRootFilesystem: true
+  runAsNonRoot: true
+  runAsGroup: 1000
+  runAsUser: 1000
+
+## Default Gitea service ports (default web and ssh port)
+services:
+  http:
+    type: ClusterIP
+    port: 80
+  ssh:
+    type: ClusterIP
+    port: 22
+    # nodePort:
+    # clusterIP:
+
+## Ingress configuration
+ingress:
+  enabled: false
+
+  ## Maximal body size (default: 64m - increase if uploads to gitea failing)
+  maxBodySize: 64m
+
+  ## Additional ingress annotations
+  annotations: {}
+#   kubernetes.io/ingress.class: nginx
+#   kubernetes.io/tls-acme: "true"
+
+  ## Hosts
+  hosts:
+    - host: chart-example.local
+      paths: []
+
+  ## TLS settings for hosts
+  tls: []
+  #  - secretName: chart-example-tls
+  #    hosts:
+  #      - chart-example.local
+
+## Resource limits and requests
+resources: {}
+# limits:
+#   cpu: 100m
+#   memory: 128Mi
+# requests:
+#   cpu: 100m
+#   memory: 128Mi
+
+## Default liveness probe
+livenessProbe:
+  enabled: true
+  initialDelaySeconds: 10
+  timeoutSeconds: 10
+  failureThreshold: 5
+  successThreshold: 1
+  periodSeconds: 30
+
+## Default readiness probe
+readinessProbe:
+  enabled: true
+  initialDelaySeconds: 10
+  timeoutSeconds: 10
+  failureThreshold: 5
+  successThreshold: 1
+  periodSeconds: 10
+
+## Default node type for the image
+## use arm64v8 for the *-linux-arm64 image
+nodeSelector:
+  kubernetes.io/arch: amd64
+
+tolerations: []
+
+affinity: {}
+
+## Internal container HTTP port (default: 8000)
+containerHttpPort: 8000
+## Internal container SSH port (default: 8022)
+containerSshPort: 8022
+
+## Additional environment variables
+env: []
+
+## Additional Gitea settings defined in this chart
+settings:
+  ## Delay after installation before adminstrative user gets created (Database must be ready and connected)
+  postInstallDelay: 60
+  ## Defines the default administrator (first user) - Password must be changed after first login!
+  defaultAdmin:
+    user: root
+    password: admin
+    email: root@admin.local
+
+## Gitea specific configuration as described in https://docs.gitea.io/en-us/config-cheat-sheet/
+## More values and sections can be added - All values will only be created once during install!
+gitea:
+  config:
+    RUN_MODE: "prod"
+    APP_NAME: "Gitea: Git with a cup of tea"
+
+    database:
+      PATH: "/data/gitea/gitea.db"
+
+    log:
+      ROOT_PATH: "/data/log"
+      MODE: "file"
+      LEVEL: "info"
+
+    server:
+      PROTOCOL: http
+      DISABLE_SSH: "false"
+      START_SSH_SERVER: "true"
+      LFS_START_SERVER: "true"
+      LFS_CONTENT_PATH: "/data/gitea/lfs"
+      OFFLINE_MODE: "false"
+      # LFS_JWT_SECRET:
+
+      SSH_ROOT_PATH: "/data/ssh"
+      APP_DATA_PATH: "/data/gitea"
+
+    security:
+      INSTALL_LOCK: "true"
+      # Internal secret and token or random value
+      # SECRET_KEY:
+      # INTERNAL_TOKEN:
+
+    repositories:
+      ROOT: "/data/git/gitea-repositories"
+
+    service:
+      REGISTER_EMAIL_CONFIRM: "false"
+      ENABLE_NOTIFY_MAIL: "false"
+      DISABLE_REGISTRATION: "true"
+      ALLOW_ONLY_EXTERNAL_REGISTRATION: "false"
+      ENABLE_CAPTCHA: "false"
+      REQUIRE_SIGNIN_VIEW: "false"
+      DEFAULT_KEEP_EMAIL_PRIVATE: "true"
+      DEFAULT_ALLOW_CREATE_ORGANIZATION: "true"
+      DEFAULT_ENABLE_TIMETRACKING: "true"
+      NO_REPLY_ADDRESS: "noreply.dev.k8.local"
+
+    openid:
+      ENABLE_OPENID_SIGNIN: "false"
+      ENABLE_OPENID_SIGNUP: "false"
+
+    picture:
+      DISABLE_GRAVATAR: "false"
+      ENABLE_FEDERATED_AVATAR: "true"
+
+    # OAuth2 JWT secrent or random value
+    # oauth2:
+      # JWT_SECRET:
+
+    mailer:
+      ENABLED: "false"
+      # HOST:
+      # FROM:
+      # USER:
+      # PASSWD:
+
+    # Indexer prevents scaling Gitea with replicas option and instances (>1) will crash - as a workaround the indexer STARTUP_TIMEOUT can be set to infinite
+    # This workaround is working but not fully tested
+    # Session cache must enabled and database must be MySQL/MariaDB or PostgreSQL!
+    # Try at your own risk!
+    # indexer:
+      # STARTUP_TIMEOUT: 0
+
+## Gitea storage parameters
+storage:
+  ## Set persistentVolumenClaimName to reference an existing PVC
+  # persistentVolumeClaimName: <own-pvc-name>
+
+  ## Alternative set requestedSize to define a size for a dynmaically created PVC
+  # requestedSize: <volume-size>
+
+  ## the storage class name
+  # className:
+
+  ## Default access mode (ReadWriteOnce)
+  accessModes:
+    - ReadWriteOnce
+
+## MariaDB configuration
+mariadb:
+  ## Enable MariaDB helm chart for deployment (default: false)
+  enabled: false
+
+  ## Database configuration
+  settings:
+    ## Database startup arguments (enable UTF8MB4 and Unicode support)
+    arguments:
+      - --character-set-server=utf8mb4
+      - --collation-server=utf8mb4_unicode_ci
+
+    ## The root user password (default: a 10 char. alpahnumerical random password will be generated)
+    rootPassword:
+
+  ## Optional user database which is created during first startup with user and password
+  userDatabase:
+    ## Name of the user database
+    name:
+    ## Database user with full access rights
+    user:
+    ## Password of the database user (default: a 10 char. alpahnumerical random password will be generated)
+    password:
+
+  # Storage parameters
+  storage:
+    ## Set persistentVolumenClaimName to reference an existing PVC
+    # persistentVolumeClaimName: <own-pvc-name>
+
+    ## Alternative set requestedSize to define a size for a dynmaically created PVC
+    # requestedSize: <volume-size>
+
+    ## the storage class name
+    # className:
+
+## PostgreSQL configuration
+postgres:
+  ## Enable PostgreSQL helm chart for deployment (default: false)
+  enabled: false
+
+  ## Database configuration
+  settings:
+
+    ## The superuser password (default: a 10 char. alpahnumerical random password will be generated)
+    superuserPassword:
+
+  ## User database which is created during first startup with user and password
+  userDatabase:
+    ## Database name
+    name:
+    ## Database user
+    user:
+    ## Database password (default: 10 alphanum. random characters)
+    password:
+
+  # Storage parameters
+  storage:
+    ## Set persistentVolumenClaimName to reference an existing PVC
+    # persistentVolumeClaimName: <own-pvc-name>
+
+    ## Alternative set requestedSize to define a size for a dynmaically created PVC
+    # requestedSize: <volume-size>
+
+    ## the storage class name
+    # className:
+
+## Redis configuration
+redis:
+  ## Enable Redis helm chart for deployment (default: false)
+  enabled: false
+
+  # Storage parameters
+  storage:
+    ## Set persistentVolumenClaimName to reference an existing PVC
+    # persistentVolumeClaimName: <own-pvc-name>
+
+    ## Alternative set requestedSize to define a size for a dynmaically created PVC
+    # requestedSize: <volume-size>
+
+    ## the storage class name
+    # className: