commit 2f149e0e7dd8234665af5d9c91801ec98005cba6 Author: Swordsteel Date: Tue Sep 30 13:22:00 2025 +0200 init commit diff --git a/.editorconfig b/.editorconfig new file mode 100644 index 0000000..c84a12f --- /dev/null +++ b/.editorconfig @@ -0,0 +1,10 @@ +root = true + +[*] +charset = utf-8 +end_of_line = lf +indent_size = 2 +indent_style = space +insert_final_newline = true +max_line_length = 1024 +tab_width = 2 diff --git a/.gitea/workflows/release.yaml b/.gitea/workflows/release.yaml new file mode 100644 index 0000000..0dced27 --- /dev/null +++ b/.gitea/workflows/release.yaml @@ -0,0 +1,11 @@ +name: Publish Helm Chart + +on: + workflow_dispatch: + +jobs: + call-helm-ci: + uses: helm/common-workflows/.gitea/workflows/release.yaml@master + secrets: + CI_BOT_USERNAME: ${{ secrets.CI_BOT_USERNAME }} + CI_BOT_TOKEN: ${{ secrets.CI_BOT_TOKEN }} diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..1a2ac86 --- /dev/null +++ b/.gitignore @@ -0,0 +1,2 @@ +.idea/ +/helm/Chart.lock diff --git a/README.md b/README.md new file mode 100644 index 0000000..f2219ef --- /dev/null +++ b/README.md @@ -0,0 +1,27 @@ +# UniFi Network Application + +## Basic stuff + +### Install + +```shell +helm install unifi ./helm --namespace unifi --create-namespace +``` + +### Update + +```shell +helm -n unifi upgrade unifi .\helm +``` + +### Check + +```shell +kubectl -n unifi get secret,cm,pvc,pod,svc +``` + +### Delete + +```shell +kubectl delete ns unifi +``` diff --git a/helm/ .helmignore b/helm/ .helmignore new file mode 100644 index 0000000..0e8a0eb --- /dev/null +++ b/helm/ .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/helm/Chart.yaml b/helm/Chart.yaml new file mode 100644 index 0000000..aa1b047 --- /dev/null +++ b/helm/Chart.yaml @@ -0,0 +1,12 @@ +apiVersion: v2 +name: unifi-network-application +description: A Helm chart for UniFi Network Application (linuxserver/unifi-network-application) +type: application +version: 0.1.0 +appVersion: "9.4.19" + +dependencies: + - name: mongodb + version: 0.1.0 + repository: "oci://gitea.lulz.ltd/helm" + condition: mongodb.enabled diff --git a/helm/templates/_helpers.tpl b/helm/templates/_helpers.tpl new file mode 100644 index 0000000..8db1011 --- /dev/null +++ b/helm/templates/_helpers.tpl @@ -0,0 +1,26 @@ +{{- define "unifi.name" -}} +{{- printf "%s" .Chart.Name | trunc 63 | trimSuffix "-" -}} +{{- end -}} + +{{- define "unifi.name.config" -}} +{{- printf "%s-config" .Chart.Name | trunc 56 | trimSuffix "-" -}} +{{- end -}} + +{{- define "unifi.name.secret" -}} +{{- printf "%s-secret" .Chart.Name | trunc 56 | trimSuffix "-" -}} +{{- end -}} + +{{- define "unifi.credentials.name" -}} +{{- printf "%s-credentials" .Chart.Name | trunc 51 | trimSuffix "-" -}} +{{- end -}} + +{{- define "unifi.credentials.name.secret" -}} +{{- printf "%s-credentials-secret" .Chart.Name | trunc 44 | trimSuffix "-" -}} +{{- end -}} + +{{- define "unifi.labels" -}} +app.kubernetes.io/name: {{ include "unifi.name" . }} +app.kubernetes.io/instance: {{ .Release.Name }} +app.kubernetes.io/version: {{ .Chart.AppVersion | quote }} +helm.sh/chart: {{ .Chart.Name }}-{{ .Chart.Version }} +{{- end -}} diff --git a/helm/templates/config.yaml b/helm/templates/config.yaml new file mode 100644 index 0000000..9ec8299 --- /dev/null +++ b/helm/templates/config.yaml @@ -0,0 +1,15 @@ +apiVersion: v1 +kind: ConfigMap +metadata: + name: {{ include "unifi.name.config" . }} + labels: + {{- include "unifi.labels" . | nindent 4 }} +data: + PUID: {{ .Values.config.puid | quote }} + PGID: {{ .Values.config.pgid | quote }} + TZ: {{ .Values.config.timezone | quote }} + MONGO_HOST: {{ .Values.mongo.hostname | quote }} + MONGO_PORT: {{ .Values.mongo.port | quote }} + MONGO_DBNAME: {{ .Values.mongo.database | quote }} + MONGO_USER: {{ .Values.mongo.username | quote }} + MONGO_AUTHSOURCE: "admin" diff --git a/helm/templates/credentials/job.yaml b/helm/templates/credentials/job.yaml new file mode 100644 index 0000000..a2fce28 --- /dev/null +++ b/helm/templates/credentials/job.yaml @@ -0,0 +1,51 @@ +{{- if .Values.initJob.enabled }} +apiVersion: batch/v1 +kind: Job +metadata: + name: {{ include "unifi.credentials.name" . }} + labels: + {{- include "unifi.labels" . | nindent 4 }} +spec: + template: + metadata: + name: {{ include "unifi.credentials.name" . }} + labels: + app.kubernetes.io/name: {{ include "unifi.name" . }} + app.kubernetes.io/instance: {{ .Release.Name }} + spec: + restartPolicy: OnFailure + containers: + - name: mongo-init + image: "{{ .Values.initJob.image.repository }}:{{ .Values.initJob.image.tag }}" + imagePullPolicy: {{ .Values.initJob.image.pullPolicy }} + envFrom: + - secretRef: + name: {{ include "unifi.credentials.name.secret" . }} + command: + - bash + - -c + - | + # Wait until MongoDB is ready + until mongosh "mongodb://$MONGO_ROOT_USERNAME:$MONGO_ROOT_PASSWORD@{{ .Values.mongo.hostname }}:{{ .Values.mongo.port }}/admin" --eval "db.adminCommand('ping')" > /dev/null 2>&1; do + echo "Waiting for MongoDB..." + sleep 5 + done + + mongosh "mongodb://$MONGO_ROOT_USERNAME:$MONGO_ROOT_PASSWORD@{{ .Values.mongo.hostname }}:{{ .Values.mongo.port }}/admin" --eval " + db = db.getSiblingDB('admin'); + if (!db.getUser('{{ .Values.mongo.username }}')) { + print('Creating user: {{ .Values.mongo.username }}'); + db.createUser({ + user: '{{ .Values.mongo.username }}', + pwd: '{{ .Values.mongo.password }}', + roles: [ + { db: '{{ .Values.mongo.database }}', role: 'dbOwner' }, + { db: '{{ .Values.mongo.database }}_stat', role: 'dbOwner' }, + { db: '{{ .Values.mongo.database }}_audit', role: 'dbOwner' } + ] + }); + } else { + print('User already exists, skipping'); + } + " +{{- end }} diff --git a/helm/templates/credentials/secret.yaml b/helm/templates/credentials/secret.yaml new file mode 100644 index 0000000..d32cdf3 --- /dev/null +++ b/helm/templates/credentials/secret.yaml @@ -0,0 +1,12 @@ +{{- if .Values.initJob.enabled }} +apiVersion: v1 +kind: Secret +metadata: + name: {{ include "unifi.credentials.name.secret" . }} + labels: + {{- include "unifi.labels" . | nindent 4 }} +type: Opaque +stringData: + MONGO_ROOT_PASSWORD: "{{ .Values.mongodb.auth.rootPassword }}" + MONGO_ROOT_USERNAME: "{{ .Values.mongodb.auth.rootUsername }}" +{{- end }} \ No newline at end of file diff --git a/helm/templates/secret.yaml b/helm/templates/secret.yaml new file mode 100644 index 0000000..09c7a22 --- /dev/null +++ b/helm/templates/secret.yaml @@ -0,0 +1,9 @@ +apiVersion: v1 +kind: Secret +metadata: + name: {{ include "unifi.name.secret" . }} + labels: + {{- include "unifi.labels" . | nindent 4 }} +type: Opaque +stringData: + MONGO_PASS: {{ .Values.mongo.password | quote }} \ No newline at end of file diff --git a/helm/templates/service.yaml b/helm/templates/service.yaml new file mode 100644 index 0000000..a88fb23 --- /dev/null +++ b/helm/templates/service.yaml @@ -0,0 +1,20 @@ +apiVersion: v1 +kind: Service +metadata: + name: {{ include "unifi.name" . }} + labels: + {{- include "unifi.labels" . | nindent 4 }} +spec: + type: {{ .Values.service.type }} + {{- if and .Values.service.loadBalancerIP (ne .Values.service.loadBalancerIP "") }} + loadBalancerIP: {{ .Values.service.loadBalancerIP }} + {{- end }} + selector: + app.kubernetes.io/name: {{ include "unifi.name" . }} + ports: + {{- range .Values.service.ports }} + - name: {{ .name }} + port: {{ .port }} + targetPort: {{ .targetPort }} + protocol: {{ default "TCP" .protocol }} + {{- end }} \ No newline at end of file diff --git a/helm/templates/statefulset.yaml b/helm/templates/statefulset.yaml new file mode 100644 index 0000000..5364c93 --- /dev/null +++ b/helm/templates/statefulset.yaml @@ -0,0 +1,54 @@ +apiVersion: apps/v1 +kind: StatefulSet +metadata: + name: {{ include "unifi.name" . }} + labels: + {{- include "unifi.labels" . | nindent 4 }} +spec: + serviceName: {{ include "unifi.name" . }} + replicas: {{ .Values.replicaCount }} + selector: + matchLabels: + app.kubernetes.io/name: {{ include "unifi.name" . }} + template: + metadata: + labels: + app.kubernetes.io/name: {{ include "unifi.name" . }} + app.kubernetes.io/instance: {{ .Release.Name }} + spec: + {{- if .Values.config.hostNetwork }} + hostNetwork: true + dnsPolicy: ClusterFirstWithHostNet + {{- end }} + containers: + - name: unifi + image: "{{ .Values.image.repository }}:{{ .Values.image.tag }}" + imagePullPolicy: {{ .Values.image.pullPolicy }} + envFrom: + - configMapRef: + name: {{ include "unifi.name.config" . }} + - secretRef: + name: {{ include "unifi.name.secret" . }} + ports: + {{- range .Values.service.ports }} + - name: {{ .name }} + containerPort: {{ .targetPort }} + protocol: {{ default "TCP" .protocol }} + {{- end }} + volumeMounts: + - name: data + mountPath: /config + resources: + {{- toYaml .Values.resources | nindent 12 }} + volumeClaimTemplates: + - metadata: + name: data + spec: + accessModes: + {{ toYaml .Values.persistence.accessModes | nindent 10 }} + resources: + requests: + storage: {{ .Values.persistence.size }} + {{- if .Values.persistence.storageClass }} + storageClassName: {{ .Values.persistence.storageClass }} + {{- end }} diff --git a/helm/values.yaml b/helm/values.yaml new file mode 100644 index 0000000..a32255f --- /dev/null +++ b/helm/values.yaml @@ -0,0 +1,83 @@ +replicaCount: 1 + +image: + repository: lscr.io/linuxserver/unifi-network-application + tag: 9.4.19 + pullPolicy: IfNotPresent + +service: + type: ClusterIP + ports: + - name: gui + port: 8443 + targetPort: 8443 + - name: inform + port: 8080 + targetPort: 8080 + - name: stun + port: 3478 + targetPort: 3478 + protocol: UDP + - name: discovery + port: 10001 + targetPort: 10001 + protocol: UDP + - name: discoverable + port: 1900 + targetPort: 1900 + protocol: UDP + - name: portalhttps + port: 8843 + targetPort: 8843 + - name: portalhttp + port: 8880 + targetPort: 8880 + - name: throughput + port: 6789 + targetPort: 6789 + - name: syslog + port: 5514 + targetPort: 5514 + protocol: UDP + +persistence: + accessModes: + - ReadWriteOnce + size: 2Gi + storageClass: "" + +config: + timezone: Etc/UTC + puid: 65534 + pgid: 65534 + # set true for easier device adoption (Layer2 discovery) + hostNetwork: true + +mongo: + hostname: mongodb + port: 27017 + database: unifi-db + username: unifi + password: securePassword + +initJob: + enabled: true + image: + repository: mongo + tag: "8.0" + pullPolicy: IfNotPresent + +mongodb: + enabled: true + auth: + rootPassword: verySecurePassword + persistence: + size: 8Gi + +resources: + requests: + cpu: "250m" + memory: "512Mi" + limits: + cpu: "1000m" + memory: "2Gi"