charts: penpot
diff --git a/charts/penpot/templates/frontend/configmap.yaml b/charts/penpot/templates/frontend/configmap.yaml
new file mode 100644
index 0000000..b31698d
--- /dev/null
+++ b/charts/penpot/templates/frontend/configmap.yaml
@@ -0,0 +1,129 @@
+apiVersion: v1
+kind: ConfigMap
+metadata:
+  name: "{{ include "penpot.fullname" . }}-frontend-nginx"
+  namespace: {{ .Release.Namespace }}
+  labels:
+    {{- include "penpot.labels" . | nindent 4 }}
+data:
+  nginx.conf: |
+    user www-data;
+    worker_processes auto;
+    pid /run/nginx.pid;
+    include /etc/nginx/modules-enabled/*.conf;
+
+    events {
+        worker_connections 2048;
+        # multi_accept on;
+    }
+
+    http {
+        sendfile on;
+        tcp_nopush on;
+        tcp_nodelay on;
+        keepalive_requests 30;
+        keepalive_timeout 65;
+        types_hash_max_size 2048;
+
+        server_tokens off;
+
+        reset_timedout_connection on;
+        client_body_timeout 30s;
+        client_header_timeout 30s;
+
+        include /etc/nginx/mime.types;
+        default_type application/octet-stream;
+
+        error_log /dev/stdout;
+        access_log /dev/stdout;
+
+        gzip on;
+        gzip_vary on;
+        gzip_proxied any;
+        gzip_static on;
+        gzip_comp_level 4;
+        gzip_buffers 16 8k;
+        gzip_http_version 1.1;
+
+        gzip_types text/plain text/css text/javascript application/javascript application/json application/transit+json;
+
+        resolver 127.0.0.11;
+
+        map $http_upgrade $connection_upgrade {
+            default upgrade;
+            ''      close;
+        }
+
+        server {
+            listen 80 default_server;
+            server_name _;
+
+            client_max_body_size 100M;
+            charset utf-8;
+
+            proxy_http_version 1.1;
+            proxy_set_header Host $http_host;
+            proxy_set_header X-Real-IP $remote_addr;
+            proxy_set_header X-Scheme $scheme;
+            proxy_set_header X-Forwarded-Proto $scheme;
+            proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
+
+            etag off;
+            root /var/www/app/;
+
+            location ~* \.(js|css).*$ {
+                add_header Cache-Control "max-age=86400" always; # 24 hours
+            }
+
+            location ~* \.(html).*$ {
+                add_header Cache-Control "no-cache, max-age=0" always;
+            }
+
+            location /api/export {
+                proxy_pass http://{{ include "penpot.fullname" . }}-exporter:6061;
+            }
+
+            location /api {
+                proxy_pass http://{{ include "penpot.fullname" . }}-backend:6060/api;
+            }
+
+            location /ws/notifications {
+                proxy_set_header Upgrade $http_upgrade;
+                proxy_set_header Connection 'upgrade';
+                proxy_pass http://{{ include "penpot.fullname" . }}-backend:6060/ws/notifications;
+            }
+
+            location @handle_redirect {
+                set $redirect_uri "$upstream_http_location";
+                set $redirect_host "$upstream_http_x_host";
+                set $redirect_cache_control "$upstream_http_cache_control";
+
+                proxy_buffering off;
+
+                proxy_set_header Host "$redirect_host";
+                proxy_hide_header etag;
+                proxy_hide_header x-amz-id-2;
+                proxy_hide_header x-amz-request-id;
+                proxy_hide_header x-amz-meta-server-side-encryption;
+                proxy_hide_header x-amz-server-side-encryption;
+                proxy_pass $redirect_uri;
+
+                add_header x-internal-redirect "$redirect_uri";
+                add_header x-cache-control "$redirect_cache_control";
+                add_header cache-control "$redirect_cache_control";
+            }
+
+            location /assets {
+                proxy_pass http://{{ include "penpot.fullname" . }}-backend:6060/assets;
+                recursive_error_pages on;
+                proxy_intercept_errors on;
+                error_page 301 302 307 = @handle_redirect;
+            }
+
+            location /internal/assets {
+                internal;
+                alias /opt/data/assets;
+                add_header x-internal-redirect "$upstream_http_x_accel_redirect";
+            }
+        }
+    }
diff --git a/charts/penpot/templates/frontend/deployment.yaml b/charts/penpot/templates/frontend/deployment.yaml
new file mode 100644
index 0000000..f464a6f
--- /dev/null
+++ b/charts/penpot/templates/frontend/deployment.yaml
@@ -0,0 +1,375 @@
+apiVersion: apps/v1
+kind: Deployment
+metadata:
+  name: {{ include "penpot.fullname" . }}-frontend
+  namespace: {{ .Release.Namespace }}
+  labels:
+    {{- include "penpot.labels" . | nindent 4 }}
+spec:
+  replicas: {{ .Values.frontend.replicaCount }}
+  selector:
+    matchLabels:
+      {{- include "penpot.frontendSelectorLabels" . | nindent 6 }}
+  template:
+    metadata:
+      labels:
+        {{- include "penpot.frontendSelectorLabels" . | nindent 8 }}
+    spec:
+    {{- with .Values.global.imagePullSecrets }}
+      imagePullSecrets:
+        {{- toYaml . | nindent 8 }}
+    {{- end }}
+      serviceAccountName: {{ include "penpot.serviceAccountName" . }}
+      affinity:
+        podAffinity:
+          requiredDuringSchedulingIgnoredDuringExecution:
+          - labelSelector:
+              matchExpressions:
+              - key: app.kubernetes.io/instance
+                operator: In
+                values:
+                - {{ .Release.Name }}
+            topologyKey: "kubernetes.io/hostname"
+      containers:
+        - name: {{ .Chart.Name }}-frontend
+          image: "{{ .Values.frontend.image.repository }}:{{ .Values.frontend.image.tag }}"
+          imagePullPolicy: {{ .Values.frontend.image.imagePullPolicy }}
+          env:
+            - name: PENPOT_PUBLIC_URI
+              value: {{ .Values.config.publicURI | quote }}
+            - name: PENPOT_FLAGS
+              value: "$PENPOT_FLAGS {{ .Values.config.flags }}"
+            - name: PENPOT_SECRET_KEY
+              value: {{ .Values.config.apiSecretKey | quote }}
+            - name: PENPOT_DATABASE_URI
+              value: "postgresql://{{ .Values.config.postgresql.host }}:{{ .Values.config.postgresql.port }}/{{ .Values.config.postgresql.database }}"
+            - name: PENPOT_DATABASE_USERNAME
+            {{- if not .Values.config.postgresql.secretKeys.usernameKey }}
+              value: {{ .Values.config.postgresql.username | quote }}
+            {{- else }}
+              valueFrom:
+                secretKeyRef:
+                  name: {{ .Values.config.postgresql.existingSecret }}
+                  key: {{ .Values.config.postgresql.secretKeys.usernameKey }}
+            {{- end }}
+            - name: PENPOT_DATABASE_PASSWORD
+            {{- if not .Values.config.postgresql.secretKeys.passwordKey }}
+              value: {{ .Values.config.postgresql.password | quote }}
+            {{- else }}
+              valueFrom:
+                secretKeyRef:
+                  name: {{ .Values.config.postgresql.existingSecret }}
+                  key: {{ .Values.config.postgresql.secretKeys.passwordKey }}
+            {{- end }}
+            - name: PENPOT_REDIS_URI
+              value: "redis://{{ .Values.config.redis.host }}:{{ .Values.config.redis.port }}/{{ .Values.config.redis.database }}"
+            - name: PENPOT_ASSETS_STORAGE_BACKEND
+              value: {{ .Values.config.assets.storageBackend | quote }}
+          {{- if eq .Values.config.assets.storageBackend "assets-fs" }}
+            - name: PENPOT_STORAGE_ASSETS_FS_DIRECTORY
+              value: {{ .Values.config.assets.filesystem.directory | quote }}
+          {{- else if eq .Values.config.assets.storageBackend "assets-s3" }}
+            - name: PENPOT_STORAGE_ASSETS_S3_REGION
+              value: {{ .Values.config.assets.s3.region | quote }}
+            - name: PENPOT_STORAGE_ASSETS_S3_BUCKET
+              value: {{ .Values.config.assets.s3.bucket | quote }}
+            - name: AWS_ACCESS_KEY_ID
+          {{- if not .Values.config.assets.s3.secretKeys.accessKeyIDKey }}
+              value: {{ .Values.config.assets.s3.accessKeyID | quote }}
+          {{- else }}
+              valueFrom:
+                secretKeyRef:
+                  name: {{ .Values.config.assets.s3.existingSecret }}
+                  key: {{ .Values.config.assets.s3.secretKeys.accessKeyIDKey }}
+          {{- end }}
+            - name: AWS_SECRET_ACCESS_KEY
+          {{- if not .Values.config.assets.s3.secretKeys.secretAccessKey }}
+              value: {{ .Values.config.assets.s3.secretAccessKey | quote }}
+          {{- else }}
+              valueFrom:
+                secretKeyRef:
+                  name: {{ .Values.config.assets.s3.existingSecret }}
+                  key: {{ .Values.config.assets.s3.secretKeys.secretAccessKey }}
+          {{- end }}
+            - name: PENPOT_STORAGE_ASSETS_S3_ENDPOINT
+          {{- if not .Values.config.assets.s3.secretKeys.endpointURIKey }}
+              value: {{ .Values.config.assets.s3.endpointURI | quote }}
+          {{- else }}
+              valueFrom:
+                secretKeyRef:
+                  name: {{ .Values.config.assets.s3.existingSecret }}
+                  key: {{ .Values.config.assets.s3.secretKeys.endpointURIKey }}
+          {{- end }}
+          {{- end }}
+            - name: PENPOT_TELEMETRY_ENABLED
+              value: {{ .Values.config.telemetryEnabled | quote }}
+
+          {{- if .Values.config.smtp.enabled }}
+          {{- if .Values.config.smtp.defaultFrom }}
+            - name: PENPOT_SMTP_DEFAULT_FROM
+              value: {{ .Values.config.smtp.defaultFrom | quote }}
+          {{- end }}
+          {{- if .Values.config.smtp.defaultReplyTo }}
+            - name: PENPOT_SMTP_DEFAULT_REPLY_TO
+              value: {{ .Values.config.smtp.defaultReplyTo | quote }}
+          {{- end }}
+          {{- if .Values.config.smtp.host }}
+            - name: PENPOT_SMTP_HOST
+              value: {{ .Values.config.smtp.host | quote }}
+          {{- end }}
+          {{- if .Values.config.smtp.port }}
+            - name: PENPOT_SMTP_PORT
+              value: {{ .Values.config.smtp.port | quote }}
+          {{- end }}
+          {{- if not .Values.config.smtp.secretKeys.usernameKey }}
+            - name: PENPOT_SMTP_USERNAME
+              value: {{ .Values.config.smtp.username | quote }}
+          {{- else }}
+            - name: PENPOT_SMTP_USERNAME
+              valueFrom:
+                secretKeyRef:
+                  name: {{ .Values.config.smtp.existingSecret }}
+                  key: {{ .Values.config.smtp.secretKeys.usernameKey }}
+          {{- end }}
+          {{- if not .Values.config.smtp.secretKeys.passwordKey }}
+            - name: PENPOT_SMTP_PASSWORD
+              value: {{ .Values.config.smtp.password | quote }}
+          {{- else }}
+            - name: PENPOT_SMTP_PASSWORD
+              valueFrom:
+                secretKeyRef:
+                  name: {{ .Values.config.smtp.existingSecret }}
+                  key: {{ .Values.config.smtp.secretKeys.passwordKey }}
+          {{- end }}
+          {{- if .Values.config.smtp.tls }}
+            - name: PENPOT_SMTP_TLS
+              value: {{ .Values.config.smtp.tls | quote }}
+          {{- end }}
+          {{- if .Values.config.smtp.ssl }}
+            - name: PENPOT_SMTP_SSL
+              value: {{ .Values.config.smtp.ssl | quote }}
+          {{- end }}
+          {{- end }}
+
+
+          {{- if .Values.config.registrationDomainWhitelist }}
+            - name: PENPOT_REGISTRATION_DOMAIN_WHITELIST
+              value: {{ .Values.config.registrationDomainWhitelist | quote }}
+          {{- end }}
+
+          {{- if .Values.config.providers.google.enabled }}
+          {{- if not .Values.config.providers.secretKeys.googleClientIDKey }}
+            - name: PENPOT_GOOGLE_CLIENT_ID
+              value: {{ .Values.config.providers.google.clientID | quote }}
+          {{- else }}
+            - name: PENPOT_GOOGLE_CLIENT_ID
+              valueFrom:
+                secretKeyRef:
+                  name: {{ .Values.config.providers.existingSecret }}
+                  key: {{ .Values.config.providers.secretKeys.googleClientIDKey }}
+          {{- end }}
+          {{- if not .Values.config.providers.secretKeys.googleClientSecretKey}}
+            - name: PENPOT_GOOGLE_CLIENT_SECRET
+              value: {{ .Values.config.providers.google.clientSecret | quote }}
+          {{- else }}
+            - name: PENPOT_GOOGLE_CLIENT_SECRET
+              valueFrom:
+                secretKeyRef:
+                  name: {{ .Values.config.providers.existingSecret }}
+                  key: {{ .Values.config.providers.secretKeys.googleClientSecretKey }}
+          {{- end }}
+          {{- end }}
+
+          {{- if .Values.config.providers.github.enabled }}
+          {{- if not .Values.config.providers.secretKeys.githubClientIDKey }}
+            - name: PENPOT_GITHUB_CLIENT_ID
+              value: {{ .Values.config.providers.github.clientID | quote }}
+          {{- else }}
+            - name: PENPOT_GITHUB_CLIENT_ID
+              valueFrom:
+                secretKeyRef:
+                  name: {{ .Values.config.providers.existingSecret }}
+                  key: {{ .Values.config.providers.secretKeys.githubClientIDKey }}
+          {{- end }}
+          {{- if not .Values.config.providers.secretKeys.githubClientSecretKey  }}
+            - name: PENPOT_GITHUB_CLIENT_SECRET
+              value: {{ .Values.config.providers.github.clientSecret | quote }}
+          {{- else }}
+            - name: PENPOT_GITHUB_CLIENT_SECRET
+              valueFrom:
+                secretKeyRef:
+                  name: {{ .Values.config.providers.existingSecret }}
+                  key: {{ .Values.config.providers.secretKeys.githubClientSecretKey }}
+          {{- end }}
+          {{- end }}
+
+          {{- if .Values.config.providers.gitlab.enabled }}
+          {{- if .Values.config.providers.gitlab.baseURI }}
+            - name: PENPOT_GITLAB_BASE_URI
+              value: {{ .Values.config.providers.gitlab.baseURI | quote }}
+          {{- end }}
+          {{- if not .Values.config.providers.secretKeys.gitlabClientIDKey }}
+            - name: PENPOT_GITLAB_CLIENT_ID
+              value: {{ .Values.config.providers.gitlab.clientID | quote }}
+          {{- else }}
+            - name: PENPOT_GITLAB_CLIENT_ID
+              valueFrom:
+                secretKeyRef:
+                  name: {{ .Values.config.providers.existingSecret }}
+                  key: {{ .Values.config.providers.secretKeys.gitlabClientIDKey }}
+          {{- end }}
+          {{- if not .Values.config.providers.secretKeys.gitlabClientSecretKey }}
+            - name: PENPOT_GITLAB_CLIENT_SECRET
+              value: {{ .Values.config.providers.gitlab.clientSecret | quote }}
+          {{- else }}
+            - name: PENPOT_GITLAB_CLIENT_SECRET
+              valueFrom:
+                secretKeyRef:
+                  name: {{ .Values.config.providers.existingSecret }}
+                  key: {{ .Values.config.providers.secretKeys.gitlabClientSecretKey }}
+          {{- end }}
+          {{- end }}
+
+          {{- if .Values.config.providers.oidc.enabled }}
+          {{- if .Values.config.providers.oidc.baseURI }}
+            - name: PENPOT_OIDC_BASE_URI
+              value: {{ .Values.config.providers.oidc.baseURI | quote }}
+          {{- end }}
+          {{- if not .Values.config.providers.secretKeys.oidcClientIDKey }}
+            - name: PENPOT_OIDC_CLIENT_ID
+              value: {{ .Values.config.providers.oidc.clientID | quote}}
+          {{- else }}
+            - name: PENPOT_OIDC_CLIENT_ID
+              valueFrom:
+                secretKeyRef:
+                  name: {{ .Values.config.providers.existingSecret }}
+                  key: {{ .Values.config.providers.secretKeys.oidcClientIDKey }}
+          {{- end }}
+          {{- if not .Values.config.providers.secretKeys.oidcClientSecretKey}}
+            - name: PENPOT_OIDC_CLIENT_SECRET
+              value: {{ .Values.config.providers.oidc.clientSecret | quote }}
+          {{- else }}
+            - name: PENPOT_OIDC_CLIENT_SECRET
+              valueFrom:
+                secretKeyRef:
+                  name: {{ .Values.config.providers.existingSecret }}
+                  key: {{ .Values.config.providers.secretKeys.oidcClientSecretKey }}
+          {{- end }}
+          {{- if .Values.config.providers.oidc.authURI }}
+            - name: PENPOT_OIDC_AUTH_URI
+              value: {{ .Values.config.providers.oidc.authURI | quote }}
+          {{- end }}
+          {{- if .Values.config.providers.oidc.tokenURI }}
+            - name: PENPOT_OIDC_TOKEN_URI
+              value: {{ .Values.config.providers.oidc.tokenURI | quote }}
+          {{- end }}
+          {{- if .Values.config.providers.oidc.userURI }}
+            - name: PENPOT_OIDC_USER_URI
+              value: {{ .Values.config.providers.oidc.userURI | quote }}
+          {{- end }}
+          {{- if .Values.config.providers.oidc.roles }}
+            - name: PENPOT_OIDC_ROLES
+              value: {{ .Values.config.providers.oidc.roles | quote }}
+          {{- end }}
+          {{- if .Values.config.providers.oidc.rolesAttribute }}
+            - name: PENPOT_OIDC_ROLES_ATTR
+              value: {{ .Values.config.providers.oidc.rolesAttribute | quote }}
+          {{- end }}
+          {{- if .Values.config.providers.oidc.scopes }}
+            - name: PENPOT_OIDC_SCOPES
+              value: {{ .Values.config.providers.oidc.scopes | quote }}
+          {{- end }}
+          {{- if .Values.config.providers.oidc.nameAttribute }}
+            - name: PENPOT_OIDC_NAME_ATTR
+              value: {{ .Values.config.providers.oidc.nameAttribute | quote }}
+          {{- end }}
+          {{- if .Values.config.providers.oidc.emailAttribute }}
+            - name: PENPOT_OIDC_EMAIL_ATTR
+              value: {{ .Values.config.providers.oidc.emailAttribute | quote }}
+          {{- end }}
+          {{- end }}
+
+          {{- if .Values.config.providers.ldap.enabled }}
+          {{- if .Values.config.providers.ldap.host }}
+            - name: PENPOT_LDAP_HOST
+              value: {{ .Values.config.providers.ldap.host | quote }}
+          {{- end }}
+          {{- if .Values.config.providers.ldap.port }}
+            - name: PENPOT_LDAP_PORT
+              value: {{ .Values.config.providers.ldap.port | quote }}
+          {{- end }}
+          {{- if .Values.config.providers.ldap.ssl }}
+            - name: PENPOT_LDAP_SSL
+              value: {{ .Values.config.providers.ldap.ssl | quote }}
+          {{- end }}
+          {{- if .Values.config.providers.ldap.startTLS }}
+            - name: PENPOT_LDAP_STARTTLS
+              value: {{ .Values.config.providers.ldap.startTLS | quote }}
+          {{- end }}
+          {{- if .Values.config.providers.ldap.baseDN }}
+            - name: PENPOT_LDAP_BASE_DN
+              value: {{ .Values.config.providers.ldap.baseDN | quote }}
+          {{- end }}
+          {{- if .Values.config.providers.ldap.bindDN }}
+            - name: PENPOT_LDAP_BIND_DN
+              value: {{ .Values.config.providers.ldap.bindDN | quote }}
+          {{- end }}
+          {{- if .Values.config.providers.ldap.bindPassword }}
+            - name: PENPOT_LDAP_BIND_PASSWORD
+              value: {{ .Values.config.providers.ldap.bindPassword | quote }}
+          {{- end }}
+          {{- if .Values.config.providers.ldap.attributesUsername }}
+            - name: PENPOT_LDAP_ATTRS_USERNAME
+              value: {{ .Values.config.providers.ldap.attributesUsername | quote }}
+          {{- end }}
+          {{- if .Values.config.providers.ldap.attributesEmail }}
+            - name: PENPOT_LDAP_ATTRS_EMAIL
+              value: {{ .Values.config.providers.ldap.attributesEmail | quote }}
+          {{- end }}
+          {{- if .Values.config.providers.ldap.attributesFullname }}
+            - name: PENPOT_LDAP_ATTRS_FULLNAME
+              value: {{ .Values.config.providers.ldap.attributesFullname | quote }}
+          {{- end }}
+          {{- if .Values.config.providers.ldap.attributesPhoto }}
+            - name: PENPOT_LDAP_ATTRS_PHOTO
+              value: {{ .Values.config.providers.ldap.attributesPhoto | quote }}
+          {{- end }}
+          {{- end }}
+          volumeMounts:
+            - mountPath: /opt/data
+              name: app-data
+              readOnly: false
+            - mountPath: /etc/nginx/nginx.conf
+              name: "{{ include "penpot.fullname" . }}-frontend-nginx"
+              readOnly: true
+              subPath: nginx.conf
+          ports:
+            - name: http
+              containerPort: {{ .Values.frontend.service.port }}
+              protocol: TCP
+          resources:
+            {{- toYaml .Values.frontend.resources | nindent 12 }}
+      {{- with .Values.frontend.nodeSelector }}
+      nodeSelector:
+        {{- toYaml . | nindent 8 }}
+      {{- end }}
+    {{- with .Values.frontend.affinity }}
+      affinity:
+        {{- toYaml . | nindent 8 }}
+    {{- end }}
+    {{- with .Values.frontend.tolerations }}
+      tolerations:
+        {{- toYaml . | nindent 8 }}
+    {{- end }}
+      volumes:
+      - name: app-data
+      {{- if .Values.persistence.enabled }}
+        persistentVolumeClaim:
+          claimName: {{ .Values.persistence.existingClaim | default ( include "penpot.fullname" . ) }}
+      {{- else }}
+        emptyDir: {}
+      {{- end }}
+      - configMap:
+          defaultMode: 420
+          name: "{{ include "penpot.fullname" . }}-frontend-nginx"
+        name: "{{ include "penpot.fullname" . }}-frontend-nginx"
diff --git a/charts/penpot/templates/frontend/ingress.yaml b/charts/penpot/templates/frontend/ingress.yaml
new file mode 100644
index 0000000..4dbfa05
--- /dev/null
+++ b/charts/penpot/templates/frontend/ingress.yaml
@@ -0,0 +1,56 @@
+{{- if .Values.frontend.ingress.enabled -}}
+{{- $gitVersion := .Capabilities.KubeVersion.GitVersion -}}
+{{- $fullName := include "penpot.fullname" . -}}
+{{- $svcPort := .Values.frontend.service.port -}}
+{{- if semverCompare ">=1.19-0" .Capabilities.KubeVersion.GitVersion -}}
+apiVersion: networking.k8s.io/v1
+{{- else if semverCompare ">=1.14-0" .Capabilities.KubeVersion.GitVersion -}}
+apiVersion: networking.k8s.io/v1beta1
+{{- else -}}
+apiVersion: extensions/v1beta1
+{{- end }}
+kind: Ingress
+metadata:
+  name: {{ $fullName }}
+  namespace: {{ .Release.Namespace }}
+  labels:
+    {{- include "penpot.labels" . | nindent 4 }}
+  {{- with .Values.frontend.ingress.annotations }}
+  annotations:
+    {{- toYaml . | nindent 4 }}
+  {{- end }}
+spec:
+{{- if .Values.frontend.ingress.className }}
+  ingressClassName: {{ .Values.frontend.ingress.className }} # TODO(giolekva): contribute back
+{{- end }}
+{{- if .Values.frontend.ingress.tls }}
+  tls:
+  {{- range .Values.frontend.ingress.tls }} # TODO(giolekva): contribute back
+    - hosts:
+      {{- range .hosts }}
+        - {{ . | quote }}
+      {{- end }}
+      secretName: {{ .secretName }}
+  {{- end }}
+{{- end }}
+  rules:
+  {{- range .Values.frontend.ingress.hosts }}
+    - host: {{ . | quote }} # TODO(giolekva): contribute back
+      http:
+        paths:
+{{ if semverCompare ">=1.19-0" $gitVersion }}
+          - path: /
+            pathType: Prefix
+            backend:
+              service:
+                name: {{ $fullName }}
+                port:
+                  number: {{ $svcPort }}
+{{ else }}
+          - path: /
+            backend:
+              serviceName: {{ $fullName }}
+              servicePort: {{ $svcPort }}
+{{- end }}
+  {{- end }}
+{{- end }}
diff --git a/charts/penpot/templates/frontend/service.yaml b/charts/penpot/templates/frontend/service.yaml
new file mode 100644
index 0000000..2ceb04f
--- /dev/null
+++ b/charts/penpot/templates/frontend/service.yaml
@@ -0,0 +1,16 @@
+apiVersion: v1
+kind: Service
+metadata:
+  name: {{ include "penpot.fullname" . }}
+  namespace: {{ .Release.Namespace }}
+  labels:
+    {{- include "penpot.labels" . | nindent 4 }}
+spec:
+  type: {{ .Values.frontend.service.type }}
+  ports:
+    - port: {{ .Values.frontend.service.port }}
+      targetPort: http
+      protocol: TCP
+      name: http
+  selector:
+    {{- include "penpot.frontendSelectorLabels" . | nindent 4 }}