update
diff --git a/charts/headscale/templates/headscale.yaml b/charts/headscale/templates/headscale.yaml
new file mode 100644
index 0000000..d483854
--- /dev/null
+++ b/charts/headscale/templates/headscale.yaml
@@ -0,0 +1,202 @@
+apiVersion: networking.k8s.io/v1
+kind: Ingress
+metadata:
+  name: ingress
+  namespace: {{ .Release.Namespace }}
+  annotations:
+    acme.cert-manager.io/http01-edit-in-place: "true"
+    cert-manager.io/cluster-issuer: {{ .Values.certificateIssuer}}
+    {{ if .Values.ui.enabled }}
+    nginx.org/rewrites: "serviceName=headscale rewrite=/;serviceName=headscale-ui rewrite=/"
+    {{ end }}
+spec:
+  ingressClassName: {{ .Values.ingressClassName }}
+  tls:
+  - hosts:
+    - {{ .Values.domain }}
+    secretName: cert-{{ .Values.domain }}
+  rules:
+  - host: {{ .Values.domain }}
+    http:
+      paths:
+      - path: /
+        pathType: Prefix
+        backend:
+          service:
+            name: headscale
+            port:
+              name: http
+      {{ if .Values.ui.enabled }}
+      - path: /web
+        pathType: Prefix
+        backend:
+          service:
+            name: headscale-ui
+            port:
+              name: http
+      {{ end }}
+---
+apiVersion: v1
+kind: Service
+metadata:
+  name: headscale
+  namespace: {{ .Release.Namespace }}
+  annotations:
+    metallb.universe.tf/address-pool: {{ .Values.ipAddressPool }}
+spec:
+  type: LoadBalancer
+  selector:
+    app: headscale
+  ports:
+  - name: http
+    port: 80
+    targetPort: http
+    protocol: TCP
+{{ if .Values.ui.enabled }}
+---
+apiVersion: v1
+kind: Service
+metadata:
+  name: headscale-ui
+  namespace: {{ .Release.Namespace }}
+  # annotations:
+  #   metallb.universe.tf/address-pool: {{ .Values.ipAddressPool }}
+spec:
+  type: ClusterIP
+  selector:
+    app: headscale
+  ports:
+  - name: http
+    port: 80
+    targetPort: http-ui
+    protocol: TCP
+{{ end }}
+---
+apiVersion: v1
+kind: Service
+metadata:
+  name: headscale-api
+  namespace: {{ .Release.Namespace }}
+spec:
+  type: ClusterIP
+  selector:
+    app: headscale
+  ports:
+  - name: http
+    port: 80
+    targetPort: http-api
+    protocol: TCP
+---
+apiVersion: v1
+kind: PersistentVolumeClaim
+metadata:
+  name: data
+  namespace: {{ .Release.Namespace }}
+spec:
+  accessModes:
+    - ReadWriteOnce
+  resources:
+    requests:
+      storage: {{ .Values.storage.size }}
+---
+apiVersion: v1
+kind: PersistentVolumeClaim
+metadata:
+  name: acls
+  namespace: {{ .Release.Namespace }}
+spec:
+  accessModes:
+    - ReadWriteOnce
+  resources:
+    requests:
+      storage: 1Gi # TODO(gio): configurable
+---
+apiVersion: apps/v1
+kind: StatefulSet
+metadata:
+  name: headscale
+  namespace: {{ .Release.Namespace }}
+spec:
+  selector:
+    matchLabels:
+      app: headscale
+  serviceName: headscale
+  replicas: 1
+  template:
+    metadata:
+      labels:
+        app: headscale
+    spec:
+      volumes:
+      - name: data
+        persistentVolumeClaim:
+          claimName: data
+      - name: acls
+        persistentVolumeClaim:
+          claimName: acls
+      - name: config
+        configMap:
+          name: config
+      - name: api-socket
+        emptyDir: {}
+      containers:
+      - name: headscale
+        image: {{ .Values.image.repository }}:{{ .Values.image.tag }}
+        imagePullPolicy: {{ .Values.image.pullPolicy }}
+        ports:
+        - name: http
+          containerPort: 8080
+          protocol: TCP
+        - name: grpc
+          containerPort: 50443
+          protocol: TCP
+        command:
+        - headscale
+        - --config=/headscale/config/config.yaml
+        - serve
+        volumeMounts:
+        - name: data
+          mountPath: /headscale/data
+          readOnly: false
+        - name: config
+          mountPath: /headscale/config
+          readOnly: true
+        - name: acls
+          mountPath: /headscale/acls
+          readOnly: true
+        - mountPath: /headscale-api
+          name: api-socket
+      - name: headscale-api
+        image: {{ .Values.api.image.repository }}:{{ .Values.api.image.tag }}
+        imagePullPolicy: {{ .Values.api.image.pullPolicy }}
+        ports:
+        - name: http-api
+          containerPort: {{ .Values.api.port }}
+          protocol: TCP
+        command:
+        - headscale-api
+        - --port={{ .Values.api.port }}
+        - --config=/headscale/config/config.yaml
+        - --ip-subnet={{ .Values.api.ipSubnet }}
+        - --acls=/headscale/acls/config.hujson
+        volumeMounts:
+        - name: data
+          mountPath: /headscale/data
+          readOnly: false
+        - name: config
+          mountPath: /headscale/config
+          readOnly: true
+        - name: acls
+          mountPath: /headscale/acls
+          readOnly: false
+        - mountPath: /headscale-api
+          name: api-socket
+      {{ if .Values.ui.enabled }}
+      - name: headscale-ui # TODO(gio): separate deployment
+        image: {{ .Values.ui.image.repository }}:{{ .Values.ui.image.tag }}
+        imagePullPolicy: {{ .Values.ui.image.pullPolicy }}
+        ports:
+        - name: http-ui
+          containerPort: 80
+          protocol: TCP
+      {{ end }}