commit 0cf7c9b90865ea470a9f80b7defb73a03e2fa436 Author: Paul Mathieu Date: Mon Mar 2 06:48:46 2026 +0000 Initial commit: mushroom, zetikettes With basic config to have TLS certs with ACME. It works! TODO: - gitea - bar-jupyter diff --git a/jenova/ingress.yaml b/jenova/ingress.yaml new file mode 100644 index 0000000..4935af1 --- /dev/null +++ b/jenova/ingress.yaml @@ -0,0 +1,22 @@ +apiVersion: networking.k8s.io/v1 +kind: Ingress +metadata: + name: jenova.ponteilla.net + annotations: + traefik.ingress.kubernetes.io/router.tls.certresolver: "default" +spec: + rules: + - host: jenova.ponteilla.net + http: + paths: + - path: / + pathType: Prefix + backend: + service: + name: jenova + port: + number: 80 + tls: + - hosts: + - jenova.ponteilla.net + secretName: jenova-tls diff --git a/jenova/nginx-config.yaml b/jenova/nginx-config.yaml new file mode 100644 index 0000000..922851d --- /dev/null +++ b/jenova/nginx-config.yaml @@ -0,0 +1,13 @@ +apiVersion: v1 +kind: ConfigMap +metadata: + name: nginx-config +data: + default.conf: | + server { + listen 80; + root /usr/share/nginx/html; + location /zetikettes { + return 301 https://zetikettes.jenova.ponteilla.net; + } + } diff --git a/jenova/web.yaml b/jenova/web.yaml new file mode 100644 index 0000000..35421cc --- /dev/null +++ b/jenova/web.yaml @@ -0,0 +1,81 @@ +apiVersion: apps/v1 +kind: Deployment +metadata: + labels: + app: web + name: web +spec: + replicas: 1 + selector: + matchLabels: + app: web + strategy: {} + template: + metadata: + labels: + app: web + spec: + containers: + - image: nginx + name: nginx + ports: + - containerPort: 80 + volumeMounts: + - name: index + mountPath: /usr/share/nginx/html/index.html + subPath: index.html + - name: nginx-config + mountPath: /etc/nginx/conf.d/default.conf + subPath: default.conf + volumes: + - name: index + configMap: + name: jenova-index-html + - name: nginx-config + configMap: + name: nginx-config + +--- +apiVersion: v1 +kind: ConfigMap +metadata: + name: jenova-index-html +data: + index.html: | + + + + + P + + +
+
+
+     .----------------.
+    | .--------------. |
+    | |   ______     | |
+    | |  |_   __ \   | |
+    | |    | |__) |  | |
+    | |    |  ___/   | |
+    | |   _| |_      | |
+    | |  |_____|     | |
+    | |              | |
+    | '--------------' |
+     '----------------'
+            
+
+
+ + + +--- +apiVersion: v1 +kind: Service +metadata: + name: jenova +spec: + selector: + app: web + ports: + - port: 80 diff --git a/mushroom/Makefile b/mushroom/Makefile new file mode 100644 index 0000000..5e577d0 --- /dev/null +++ b/mushroom/Makefile @@ -0,0 +1,13 @@ +.PHONY: lint +lint: ## Lint the helm chart + helm lint helm + +.PHONY: deploy +deploy: ## Deploy the helm chart on a running cluster + helm upgrade --install mushroom ./helm + +.PHONY: help +help: ## Show this help + @echo Noteworthy targets: + @egrep '^[a-zA-Z_-]+:.*?## .*$$' $(MAKEFILE_LIST) | sort | awk 'BEGIN {FS = ":.*?## "}; {printf "\033[36m%-20s\033[0m %s\n", $$1, $$2}' +.DEFAULT_GOAL := help diff --git a/mushroom/helm/.helmignore b/mushroom/helm/.helmignore new file mode 100644 index 0000000..0e8a0eb --- /dev/null +++ b/mushroom/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/mushroom/helm/Chart.yaml b/mushroom/helm/Chart.yaml new file mode 100644 index 0000000..fd7a2b3 --- /dev/null +++ b/mushroom/helm/Chart.yaml @@ -0,0 +1,6 @@ +apiVersion: v2 +name: mushroom +description: mushroom server and web front-end +type: application +version: 0.1.0 +appVersion: "0.3" diff --git a/mushroom/helm/index.html b/mushroom/helm/index.html new file mode 100644 index 0000000..511110c --- /dev/null +++ b/mushroom/helm/index.html @@ -0,0 +1,211 @@ + + + + A simple netcat client + + + + + + + + +
+ + online +
+

+        
+ +
+ + + diff --git a/mushroom/helm/nginx-default.conf b/mushroom/helm/nginx-default.conf new file mode 100644 index 0000000..8162312 --- /dev/null +++ b/mushroom/helm/nginx-default.conf @@ -0,0 +1,24 @@ +server { + listen 80; + server_name localhost; + + location / { + root /usr/share/nginx/html; + index index.html index.htm; + } + + location /ws { + proxy_pass http://127.0.0.1:1338; + proxy_http_version 1.1; + proxy_set_header Upgrade $http_upgrade; + proxy_set_header Connection "Upgrade"; + proxy_set_header Host $host; + + proxy_read_timeout 10h; + } + + error_page 500 502 503 504 /50x.html; + location = /50x.html { + root /usr/share/nginx/html; + } +} diff --git a/mushroom/helm/templates/_helpers.tpl b/mushroom/helm/templates/_helpers.tpl new file mode 100644 index 0000000..83c9cb2 --- /dev/null +++ b/mushroom/helm/templates/_helpers.tpl @@ -0,0 +1,51 @@ +{{/* +Expand the name of the chart. +*/}} +{{- define "mushroom.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 "mushroom.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 }} + +{{/* +Create chart name and version as used by the chart label. +*/}} +{{- define "mushroom.chart" -}} +{{- printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" | trunc 63 | trimSuffix "-" }} +{{- end }} + +{{/* +Common labels +*/}} +{{- define "mushroom.labels" -}} +helm.sh/chart: {{ include "mushroom.chart" . }} +{{ include "mushroom.selectorLabels" . }} +{{- if .Chart.AppVersion }} +app.kubernetes.io/version: {{ .Chart.AppVersion | quote }} +{{- end }} +app.kubernetes.io/managed-by: {{ .Release.Service }} +{{- end }} + +{{/* +Selector labels +*/}} +{{- define "mushroom.selectorLabels" -}} +app.kubernetes.io/name: {{ include "mushroom.name" . }} +app.kubernetes.io/instance: {{ .Release.Name }} +{{- end }} diff --git a/mushroom/helm/templates/ingress.yaml b/mushroom/helm/templates/ingress.yaml new file mode 100644 index 0000000..79338ad --- /dev/null +++ b/mushroom/helm/templates/ingress.yaml @@ -0,0 +1,36 @@ +{{- if .Values.ingress.enabled -}} +apiVersion: networking.k8s.io/v1 +kind: Ingress +metadata: + name: {{ include "mushroom.fullname" . }} + labels: + {{- include "mushroom.labels" . | nindent 4 }} + {{- with .Values.ingress.annotations }} + annotations: + {{- toYaml . | nindent 4 }} + {{- end }} +spec: + {{- with .Values.ingress.className }} + ingressClassName: {{ . }} + {{- end }} + {{- if .Values.ingress.tls }} + tls: + - hosts: + {{- range .Values.ingress.hosts }} + - {{ . | quote }} + {{- end }} + {{- end }} + rules: + {{- range .Values.ingress.hosts }} + - host: {{ . | quote }} + http: + paths: + - path: / + pathType: Prefix + backend: + service: + name: {{ include "mushroom.fullname" $ }} + port: + number: {{ $.Values.service.port }} + {{- end }} +{{- end }} diff --git a/mushroom/helm/templates/service.yaml b/mushroom/helm/templates/service.yaml new file mode 100644 index 0000000..88db0f2 --- /dev/null +++ b/mushroom/helm/templates/service.yaml @@ -0,0 +1,15 @@ +apiVersion: v1 +kind: Service +metadata: + name: {{ include "mushroom.fullname" . }} + labels: + {{- include "mushroom.labels" . | nindent 4 }} +spec: + type: {{ .Values.service.type }} + ports: + - port: {{ .Values.service.port }} + targetPort: http + protocol: TCP + name: http + selector: + {{- include "mushroom.selectorLabels" . | nindent 4 }} diff --git a/mushroom/helm/templates/statefulset.yaml b/mushroom/helm/templates/statefulset.yaml new file mode 100644 index 0000000..ecc7ff6 --- /dev/null +++ b/mushroom/helm/templates/statefulset.yaml @@ -0,0 +1,70 @@ +apiVersion: apps/v1 +kind: StatefulSet +metadata: + name: {{ include "mushroom.fullname" . }} + labels: + {{- include "mushroom.labels" . | nindent 4 }} +spec: + selector: + matchLabels: + {{- include "mushroom.selectorLabels" . | nindent 6 }} + serviceName: {{ include "mushroom.fullname" . }} + template: + metadata: + {{- with .Values.podAnnotations }} + annotations: + {{- toYaml . | nindent 8 }} + {{- end }} + labels: + {{- include "mushroom.labels" . | nindent 8 }} + {{- with .Values.podLabels }} + {{- toYaml . | nindent 8 }} + {{- end }} + spec: + containers: + - name: mushroomd + image: "{{ .Values.images.server.repository }}:{{ .Values.images.server.tag | default .Chart.AppVersion }}" + ports: + - containerPort: 1337 + volumeMounts: + - name: data + mountPath: /data + - name: webproxy + image: "{{ .Values.images.proxy.repository }}:{{ .Values.images.proxy.tag | default .Chart.AppVersion }}" + ports: + - containerPort: 1338 + - name: nginx + image: "{{ .Values.images.nginx.repository }}:{{ .Values.images.nginx.tag | default "1.29.5" }}" + ports: + - name: http + containerPort: {{ .Values.service.port }} + protocol: TCP + volumeMounts: + - name: config + mountPath: /usr/share/nginx/html/index.html + subPath: index.html + - name: config + mountPath: /etc/nginx/conf.d/default.conf + subPath: default.conf + volumes: + - name: config + configMap: + name: {{ .Chart.Name }}-nginx + volumeClaimTemplates: + - metadata: + name: data + spec: + accessModes: [ "ReadWriteOnce" ] + resources: + requests: + storage: 32Mi +--- +apiVersion: v1 +kind: ConfigMap +metadata: + name: {{ .Chart.Name }}-nginx +data: + index.html: | +{{ .Files.Get "index.html" | indent 4 }} + default.conf: | +{{ .Files.Get "nginx-default.conf" | indent 4 }} diff --git a/mushroom/helm/templates/tests/test-connection.yaml b/mushroom/helm/templates/tests/test-connection.yaml new file mode 100644 index 0000000..062fc7b --- /dev/null +++ b/mushroom/helm/templates/tests/test-connection.yaml @@ -0,0 +1,15 @@ +apiVersion: v1 +kind: Pod +metadata: + name: "{{ include "mushroom.fullname" . }}-test-connection" + labels: + {{- include "mushroom.labels" . | nindent 4 }} + annotations: + "helm.sh/hook": test +spec: + containers: + - name: wget + image: busybox + command: ['wget'] + args: ['{{ include "mushroom.fullname" . }}:{{ .Values.service.port }}'] + restartPolicy: Never diff --git a/mushroom/helm/values.yaml b/mushroom/helm/values.yaml new file mode 100644 index 0000000..37d4edd --- /dev/null +++ b/mushroom/helm/values.yaml @@ -0,0 +1,31 @@ +# Default values for mushroom. +# This is a YAML-formatted file. +# Declare variables to be passed into your templates. + +images: + server: + repository: mushroom +# tag: latest + proxy: + repository: mushroom-proxy +# tag: latest + nginx: + repository: nginx + tag: 1.29.5 + +# This is for setting up a service more information can be found here: https://kubernetes.io/docs/concepts/services-networking/service/ +service: + # This sets the service type more information can be found here: https://kubernetes.io/docs/concepts/services-networking/service/#publishing-services-service-types + type: ClusterIP + # This sets the ports more information can be found here: https://kubernetes.io/docs/concepts/services-networking/service/#field-spec-ports + port: 80 + +# This block is for setting up the ingress for more information can be found here: https://kubernetes.io/docs/concepts/services-networking/ingress/ +ingress: + enabled: true + className: "traefik" + annotations: + traefik.ingress.kubernetes.io/router.tls.certresolver: "default" + hosts: + - mushroom.jenova.ponteilla.net + tls: true diff --git a/traefik-helmchartconfig.yaml b/traefik-helmchartconfig.yaml new file mode 100644 index 0000000..b46146a --- /dev/null +++ b/traefik-helmchartconfig.yaml @@ -0,0 +1,19 @@ +apiVersion: helm.cattle.io/v1 +kind: HelmChartConfig +metadata: + name: traefik + namespace: kube-system +spec: + failurePolicy: reinstall + valuesContent: |- + additionalArguments: + - "--certificatesresolvers.default.acme.email=paul@ponteilla.net" + - "--certificatesresolvers.default.acme.storage=/data/acme.json" + - "--certificatesresolvers.default.acme.httpchallenge.entrypoint=web" + ports: + web: + redirections: + entryPoint: + to: websecure + scheme: https + permanent: true diff --git a/zetikettes/Makefile b/zetikettes/Makefile new file mode 100644 index 0000000..f00fa7b --- /dev/null +++ b/zetikettes/Makefile @@ -0,0 +1,15 @@ +namespace := zetikettes + +.PHONY: deploy +deploy: ## Deploy the service on a running cluster + kubectl -n $(namespace) apply \ + -f app.yaml \ + -f ingress.yaml \ + -f nginx-config.yaml \ + -f service.yaml + +.PHONY: help +help: ## Show this help + @echo Noteworthy targets: + @egrep '^[a-zA-Z_-]+:.*?## .*$$' $(MAKEFILE_LIST) | sort | awk 'BEGIN {FS = ":.*?## "}; {printf "\033[36m%-20s\033[0m %s\n", $$1, $$2}' +.DEFAULT_GOAL := help diff --git a/zetikettes/app.yaml b/zetikettes/app.yaml new file mode 100644 index 0000000..55fc477 --- /dev/null +++ b/zetikettes/app.yaml @@ -0,0 +1,52 @@ +apiVersion: apps/v1 +kind: StatefulSet +metadata: + name: zetikettes-app +spec: + serviceName: "zetikettes" + replicas: 1 + selector: + matchLabels: + app: zetikettes + template: + metadata: + labels: + app: zetikettes + spec: + containers: + # --- The Backend (Stateful) --- + - name: backend + image: pol/zetikettes:latest + imagePullPolicy: Never + ports: + - containerPort: 8000 + volumeMounts: + - name: var-lib-zetikettes + mountPath: /data + subPath: data + env: + - name: CSRF_TRUSTED_ORIGINS + value: https://zetikettes.jenova.ponteilla.net + - name: STATIC_URL + value: /zetikettes/srv/static/ + + # --- The Frontend (Nginx Sidecar) --- + - name: nginx-sidecar + image: nginx:alpine + ports: + - containerPort: 80 + volumeMounts: + - name: var-lib-zetikettes + mountPath: /var/lib/zetikettes + - name: config-volume + mountPath: /etc/nginx/conf.d/default.conf + subPath: default.conf + + volumes: + - name: config-volume + configMap: + name: nginx-config + - name: var-lib-zetikettes + hostPath: + path: /var/lib/zetikettes + type: DirectoryOrCreate diff --git a/zetikettes/ingress.yaml b/zetikettes/ingress.yaml new file mode 100644 index 0000000..efe06b6 --- /dev/null +++ b/zetikettes/ingress.yaml @@ -0,0 +1,21 @@ +apiVersion: networking.k8s.io/v1 +kind: Ingress +metadata: + name: zetikettes + annotations: + traefik.ingress.kubernetes.io/router.tls.certresolver: default +spec: + tls: + - hosts: + - zetikettes.jenova.ponteilla.net + rules: + - host: zetikettes.jenova.ponteilla.net + http: + paths: + - path: / + pathType: Prefix + backend: + service: + name: zetikettes + port: + number: 80 diff --git a/zetikettes/nginx-config.yaml b/zetikettes/nginx-config.yaml new file mode 100644 index 0000000..e831206 --- /dev/null +++ b/zetikettes/nginx-config.yaml @@ -0,0 +1,26 @@ +apiVersion: v1 +kind: ConfigMap +metadata: + name: nginx-config +data: + default.conf: | + server { + listen 80; + root /var/lib/zetikettes/frontend; + location /zetikettes/srv/static { + alias /var/lib/zetikettes/www_static; + } + location /zetikettes/srv/data { + alias /var/lib/zetikettes/data; + } + location ^~ /zetikettes/srv { + proxy_pass http://127.0.0.1:8000; + proxy_set_header SCRIPT_NAME /zetikettes/srv; + proxy_set_header Host $http_host; + + # generating stuff takes time + proxy_read_timeout 10m; + + client_max_body_size 10M; + } + } diff --git a/zetikettes/service.yaml b/zetikettes/service.yaml new file mode 100644 index 0000000..66466d8 --- /dev/null +++ b/zetikettes/service.yaml @@ -0,0 +1,12 @@ +apiVersion: v1 +kind: Service +metadata: + name: zetikettes +spec: + selector: + app: zetikettes + ports: + - protocol: TCP + port: 80 + targetPort: 80 + type: ClusterIP