apps: penpot
diff --git a/core/installer/app.go b/core/installer/app.go
index 85f1cba..6312e8b 100644
--- a/core/installer/app.go
+++ b/core/installer/app.go
@@ -131,6 +131,7 @@
 		CreateAppVaultwarden(valuesTmpls, tmpls),
 		CreateAppMatrix(valuesTmpls, tmpls),
 		CreateAppPihole(valuesTmpls, tmpls),
+		CreateAppPenpot(valuesTmpls, tmpls),
 		CreateAppMaddy(valuesTmpls, tmpls),
 		CreateAppQBittorrent(valuesTmpls, tmpls),
 		CreateAppJellyfin(valuesTmpls, tmpls),
@@ -268,6 +269,27 @@
 	}
 }
 
+func CreateAppPenpot(fs embed.FS, tmpls *template.Template) StoreApp {
+	schema, err := fs.ReadFile("values-tmpl/penpot.jsonschema")
+	if err != nil {
+		panic(err)
+	}
+	return StoreApp{
+		App{
+			"penpot",
+			[]string{"app-penpot"},
+			[]*template.Template{
+				tmpls.Lookup("penpot.yaml"),
+			},
+			string(schema),
+			tmpls.Lookup("penpot.md"),
+		},
+		// "simple-icons:pihole",
+		`<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><path fill="currentColor" d="M7.654 0L5.13 3.554v2.01L2.934 6.608l-.02-.009v13.109l8.563 4.045L12 24l.523-.247l8.563-4.045V6.6l-.017.008l-2.196-1.045V3.555l-.077-.108L16.349.001l-2.524 3.554v.004L11.989.973l-1.823 2.566l-.065-.091zm.447 2.065l.976 1.374H6.232l.964-1.358zm8.694 0l.976 1.374h-2.845l.965-1.358zm-4.36.971l.976 1.375h-2.845l.965-1.359zM5.962 4.132h1.35v4.544l-1.35-.638Zm2.042 0h1.343v5.506l-1.343-.635zm6.652 0h1.35V9l-1.35.637zm2.042 0h1.343v3.905l-1.343.634zm-6.402.972h1.35v5.62l-1.35-.638zm2.042 0h1.343v4.993l-1.343.634zm6.534 1.493l1.188.486l-1.188.561zM5.13 6.6v1.047l-1.187-.561ZM3.96 8.251l7.517 3.55v10.795l-7.516-3.55zm16.08 0v10.794l-7.517 3.55V11.802z"/></svg>`,
+		"Penpot is the first Open Source design and prototyping platform meant for cross-domain teams. Non dependent on operating systems, Penpot is web based and works with open standards (SVG). Penpot invites designers all over the world to fall in love with open source while getting developers excited about the design process in return.",
+	}
+}
+
 func CreateAppMaddy(fs embed.FS, tmpls *template.Template) StoreApp {
 	schema, err := fs.ReadFile("values-tmpl/maddy.jsonschema")
 	if err != nil {
diff --git a/core/installer/values-tmpl/penpot.jsonschema b/core/installer/values-tmpl/penpot.jsonschema
new file mode 100644
index 0000000..0824944
--- /dev/null
+++ b/core/installer/values-tmpl/penpot.jsonschema
@@ -0,0 +1,8 @@
+{
+  "type": "object",
+  "properties": {
+    "Network": { "type": "string", "default": "Public", "role": "network" },
+    "Subdomain": { "type": "string", "default": "penpot" }
+  },
+  "additionalProperties": false
+}
diff --git a/core/installer/values-tmpl/penpot.md b/core/installer/values-tmpl/penpot.md
new file mode 100644
index 0000000..d750a90
--- /dev/null
+++ b/core/installer/values-tmpl/penpot.md
@@ -0,0 +1 @@
+Penpot application will be installed on {{ .Values.Network.Name }} network and be accessible to any user on https://{{ .Values.Subdomain }}.{{ .Values.Network.Domain }}
diff --git a/core/installer/values-tmpl/penpot.yaml b/core/installer/values-tmpl/penpot.yaml
index f40972d..ae67f39 100644
--- a/core/installer/values-tmpl/penpot.yaml
+++ b/core/installer/values-tmpl/penpot.yaml
@@ -1,3 +1,24 @@
+apiVersion: hydra.ory.sh/v1alpha1
+kind: OAuth2Client
+metadata:
+  name: penpot
+  namespace: {{ .Release.Namespace }}
+spec:
+  grantTypes:
+  - authorization_code
+  responseTypes:
+  - code
+  scope: "openid profile email"
+  secretName: oauth2-credentials # TODO(gio): config
+  redirectUris:
+  - https://{{ .Values.Subdomain }}.{{ .Values.Network.Domain }}/api/auth/oauth/oidc/callback # TODO
+  hydraAdmin:
+    endpoint: /admin/clients
+    forwardedProto: https
+    port: 80
+    url: http://hydra-admin.esrt-core-auth.svc.cluster.local
+  tokenEndpointAuthMethod: client_secret_post
+---
 apiVersion: helm.toolkit.fluxcd.io/v2beta1
 kind: HelmRelease
 metadata:
@@ -20,22 +41,24 @@
     frontend:
       ingress:
         enabled: true
-        className: pcloud-ingress-public
+        className: {{ .Values.Network.IngressClass }}
+        {{ if .Values.Network.CertificateIssuer }}
         annotations:
           acme.cert-manager.io/http01-edit-in-place: "true"
-          cert-manager.io/cluster-issuer: "{{ .Global.Id }}-public"
+          cert-manager.io/cluster-issuer: "{{ .Values.Network.CertificateIssuer }}"
+        {{ end }}
         hosts:
-        - "penpot.{{ .Global.Domain }}"
+        - "{{ .Values.Subdomain }}.{{ .Values.Network.Domain }}"
         tls:
         - hosts:
-          - "penpot.{{ .Global.Domain }}"
-          secretName: cert-penpot.{{ .Global.Domain }}
+          - "{{ .Values.Subdomain }}.{{ .Values.Network.Domain }}"
+          secretName: cert-{{ .Values.Subdomain }}.{{ .Values.Network.Domain }}
     persistence:
       enabled: true
     config:
-      publicURI: https://penpot.{{ .Global.Domain }}
+      publicURI: https://{{ .Values.Subdomain }}.{{ .Values.Network.Domain }}
       # flags: "enable-registration enable-login"
-      flags: "enable-registration enable-insecure-register disable-demo-users disable-demo-warning"
+      flags: "enable-login-with-oidc enable-registration enable-insecure-register disable-demo-users disable-demo-warning" # TODO(gio): remove enable-insecure-register?
       postgresql:
         host: penpot-postgresql.{{ .Release.Namespace }}.svc.cluster.local
         database: penpot
@@ -43,6 +66,24 @@
         password: penpot
       redis:
         host: penpot-redis-headless.{{ .Release.Namespace }}.svc.cluster.local
+      providers:
+        oidc:
+          enabled: true
+          baseURI: https://hydra.{{ .Global.Domain }}
+          clientID: ""
+          clientSecret: ""
+          authURI: ""
+          tokenURI: ""
+          userURI: ""
+          roles: ""
+          rolesAttribute: ""
+          scopes: ""
+          nameAttribute: "name"
+          emailAttribute: "email"
+        existingSecret: oauth2-credentials
+        secretKeys:
+          oidcClientIDKey: client_id
+          oidcClientSecretKey: client_secret
     redis:
       image:
         tag: 7.0.8-debian-11-r16