feat: add charts template and normalize oxicloud's chart with it
This commit is contained in:
parent
abd0e9bb4d
commit
8597cf5730
25 changed files with 749 additions and 249 deletions
4
.gitignore
vendored
4
.gitignore
vendored
|
|
@ -17,3 +17,7 @@ secrets.yaml
|
||||||
*~
|
*~
|
||||||
*.tgz
|
*.tgz
|
||||||
STABILITY.md
|
STABILITY.md
|
||||||
|
AGENTS.md
|
||||||
|
k8s/charts/README.md
|
||||||
|
.opencode/
|
||||||
|
opencode.json
|
||||||
|
|
|
||||||
|
|
@ -7,3 +7,9 @@
|
||||||
```bash
|
```bash
|
||||||
ethtool -K eno1 tx off rx off
|
ethtool -K eno1 tx off rx off
|
||||||
```
|
```
|
||||||
|
|
||||||
|
- upgrade argo
|
||||||
|
|
||||||
|
```bash
|
||||||
|
helm upgrade argo-cd argo/argo-cd -n argo-cd -f k8s/helm/argo-cd/values.yaml
|
||||||
|
```
|
||||||
|
|
|
||||||
36
k8s/charts/README.md
Normal file
36
k8s/charts/README.md
Normal file
|
|
@ -0,0 +1,36 @@
|
||||||
|
# Helm Charts
|
||||||
|
|
||||||
|
This directory contains Helm charts for self-hosted services.
|
||||||
|
|
||||||
|
## Chart Template
|
||||||
|
|
||||||
|
Use the `_template/` directory as a starting point for new charts:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
cp -r k8s/charts/_template k8s/charts/my-new-service
|
||||||
|
# Edit Chart.yaml, values.yaml, and update image/repository
|
||||||
|
```
|
||||||
|
|
||||||
|
The template includes standard Kubernetes resources (Deployment, Service, Ingress, PVC, ConfigMap, Secret) with sensible defaults.
|
||||||
|
|
||||||
|
## Charts
|
||||||
|
|
||||||
|
| Chart | Version | Status |
|
||||||
|
|-------|---------|--------|
|
||||||
|
| dokuwiki | 0.1.0 | Needs normalization |
|
||||||
|
| helm-rustical | 0.3.0 | Needs normalization |
|
||||||
|
| immich | 0.2.3 | Partially normalized |
|
||||||
|
| miniflux | 0.1.0 | Needs normalization |
|
||||||
|
| oxicloud | 1.0.0 | Normalized |
|
||||||
|
| vaultwarden | 0.1.0 | Needs normalization |
|
||||||
|
|
||||||
|
## Normalization
|
||||||
|
|
||||||
|
Charts should follow a consistent structure:
|
||||||
|
- Values nested under chart name key
|
||||||
|
- LoadBalancer service type
|
||||||
|
- PVC named `<chart>-data`
|
||||||
|
- Secrets via existingSecretName
|
||||||
|
- Proper probes and resource limits
|
||||||
|
|
||||||
|
See individual chart READMEs for configuration details.
|
||||||
13
k8s/charts/_template/.helmignore
Normal file
13
k8s/charts/_template/.helmignore
Normal file
|
|
@ -0,0 +1,13 @@
|
||||||
|
# Patterns to ignore when building packages.
|
||||||
|
# This supports shell glob matching.
|
||||||
|
*.tgz
|
||||||
|
.env
|
||||||
|
.git
|
||||||
|
.git_cache
|
||||||
|
.idea
|
||||||
|
*.md
|
||||||
|
docs/*
|
||||||
|
tmp/*
|
||||||
|
vendor/*
|
||||||
|
.travis.yml
|
||||||
|
.testignore
|
||||||
16
k8s/charts/_template/Chart.yaml
Normal file
16
k8s/charts/_template/Chart.yaml
Normal file
|
|
@ -0,0 +1,16 @@
|
||||||
|
apiVersion: v2
|
||||||
|
name: chart
|
||||||
|
description: A Helm chart template with standardized structure
|
||||||
|
type: application
|
||||||
|
version: 0.1.0
|
||||||
|
appVersion: "latest"
|
||||||
|
annotations:
|
||||||
|
artifacthub.io/images: |
|
||||||
|
- name: chart
|
||||||
|
image: nginx:latest
|
||||||
|
artifacthub.io/changes: |
|
||||||
|
- kind: added
|
||||||
|
description: Initial chart template
|
||||||
|
artifacthub.io/maintainers: |
|
||||||
|
- name: catalin
|
||||||
|
email: catalin@example.com
|
||||||
105
k8s/charts/_template/README.md
Normal file
105
k8s/charts/_template/README.md
Normal file
|
|
@ -0,0 +1,105 @@
|
||||||
|
# chart
|
||||||
|
|
||||||
|
A Helm chart template with standardized structure for self-hosted services.
|
||||||
|
|
||||||
|
## TL;DR
|
||||||
|
|
||||||
|
```bash
|
||||||
|
helm install chart oci://git.roboces.dev/catalin/fukuops/chart --version 1.0.0 -n apps-roboces
|
||||||
|
```
|
||||||
|
|
||||||
|
## Prerequisites
|
||||||
|
|
||||||
|
- Kubernetes 1.19+
|
||||||
|
- Helm 3+
|
||||||
|
- A NFS storage class (default: `truenas-nfs-csi`) - only if persistence is enabled
|
||||||
|
- An existing `Secret` with credentials if required (see `secret.existingSecretName`)
|
||||||
|
|
||||||
|
## Configuration
|
||||||
|
|
||||||
|
### Basic Configuration
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
service:
|
||||||
|
type: LoadBalancer
|
||||||
|
port: 80
|
||||||
|
ingress:
|
||||||
|
enabled: true
|
||||||
|
className: "traefik"
|
||||||
|
hosts:
|
||||||
|
- host: chart.example.com
|
||||||
|
paths:
|
||||||
|
- path: /
|
||||||
|
pathType: Prefix
|
||||||
|
```
|
||||||
|
|
||||||
|
### With Persistence
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
persistence:
|
||||||
|
enabled: true
|
||||||
|
storageClass: "truenas-nfs-csi"
|
||||||
|
accessMode: ReadWriteMany
|
||||||
|
size: 10Gi
|
||||||
|
```
|
||||||
|
|
||||||
|
### With Secrets
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
secret:
|
||||||
|
existingSecretName: chart-secrets
|
||||||
|
```
|
||||||
|
|
||||||
|
## Values Reference
|
||||||
|
|
||||||
|
| Key | Type | Default | Description |
|
||||||
|
|-----|------|---------|-------------|
|
||||||
|
| `replicaCount` | int | `1` | Number of replicas |
|
||||||
|
| `image.repository` | string | `nginx` | Image repository |
|
||||||
|
| `image.pullPolicy` | string | `IfNotPresent` | Image pull policy |
|
||||||
|
| `image.tag` | string | `.Chart.AppVersion` | Image tag |
|
||||||
|
| `service.type` | string | `LoadBalancer` | Service type |
|
||||||
|
| `service.port` | int | `80` | Service port |
|
||||||
|
| `service.targetPort` | int | `80` | Container port |
|
||||||
|
| `ingress.enabled` | bool | `false` | Enable ingress |
|
||||||
|
| `ingress.className` | string | `traefik` | Ingress class |
|
||||||
|
| `persistence.enabled` | bool | `false` | Enable persistence |
|
||||||
|
| `persistence.storageClass` | string | `truenas-nfs-csi` | Storage class |
|
||||||
|
| `persistence.accessMode` | string | `ReadWriteMany` | Access mode |
|
||||||
|
| `persistence.size` | string | `1Gi` | PVC size |
|
||||||
|
| `persistence.name` | string | `chart-data` | PVC name |
|
||||||
|
| `secret.existingSecretName` | string | `""` | Existing secret name |
|
||||||
|
| `resources` | object | `{}` | Container resources |
|
||||||
|
| `livenessProbe` | object | (see values.yaml) | Liveness probe |
|
||||||
|
| `readinessProbe` | object | (see values.yaml) | Readiness probe |
|
||||||
|
| `nodeSelector` | object | `{}` | Node selector |
|
||||||
|
| `tolerations` | array | `[]` | Tolerations |
|
||||||
|
| `affinity` | object | `{}` | Affinity rules |
|
||||||
|
|
||||||
|
## Persistence
|
||||||
|
|
||||||
|
When persistence is enabled, a PVC named `chart-data` is created. The PVC uses the `truenas-nfs-csi` storage class by default with `ReadWriteMany` access mode.
|
||||||
|
|
||||||
|
## Secret Management
|
||||||
|
|
||||||
|
The chart looks for an existing `Secret` with the name specified in `secret.existingSecretName`. If not provided, no secret is mounted.
|
||||||
|
|
||||||
|
## Troubleshooting
|
||||||
|
|
||||||
|
### Pod not starting
|
||||||
|
|
||||||
|
```bash
|
||||||
|
kubectl get pvc -n apps-roboces -l app.kubernetes.io/name=chart
|
||||||
|
```
|
||||||
|
|
||||||
|
### Check logs
|
||||||
|
|
||||||
|
```bash
|
||||||
|
kubectl logs chart-0 -n apps-roboces
|
||||||
|
```
|
||||||
|
|
||||||
|
### Verify configmap
|
||||||
|
|
||||||
|
```bash
|
||||||
|
kubectl get configmap chart-config -n apps-roboces -o yaml
|
||||||
|
```
|
||||||
37
k8s/charts/_template/templates/_helpers.tpl
Normal file
37
k8s/charts/_template/templates/_helpers.tpl
Normal file
|
|
@ -0,0 +1,37 @@
|
||||||
|
{{/* Expand the name of the chart. */}}
|
||||||
|
{{- define "name" -}}
|
||||||
|
{{- default .Chart.Name .Values.nameOverride | trunc 63 | trimSuffix "-" }}
|
||||||
|
{{- end }}
|
||||||
|
|
||||||
|
{{/* Create a default fully qualified app name. */}}
|
||||||
|
{{- define "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 }}
|
||||||
|
|
||||||
|
{{/* Common labels */}}
|
||||||
|
{{- define "labels" -}}
|
||||||
|
helm.sh/chart: {{ printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" | trunc 63 | trimSuffix "-" }}
|
||||||
|
{{ include "selectorLabels" . }}
|
||||||
|
app.kubernetes.io/version: {{ .Chart.AppVersion | quote }}
|
||||||
|
app.kubernetes.io/managed-by: {{ .Release.Service }}
|
||||||
|
{{- end }}
|
||||||
|
|
||||||
|
{{/* Selector labels */}}
|
||||||
|
{{- define "selectorLabels" -}}
|
||||||
|
app.kubernetes.io/name: {{ include "name" . }}
|
||||||
|
app.kubernetes.io/instance: {{ .Release.Name }}
|
||||||
|
{{- end }}
|
||||||
|
|
||||||
|
{{/* Chart name as the PVC name */}}
|
||||||
|
{{- define "pvcName" -}}
|
||||||
|
{{- .Values.persistence.name | default (printf "%s-data" (include "name" .)) }}
|
||||||
|
{{- end }}
|
||||||
12
k8s/charts/_template/templates/configmap.yaml
Normal file
12
k8s/charts/_template/templates/configmap.yaml
Normal file
|
|
@ -0,0 +1,12 @@
|
||||||
|
{{- if .Values.config }}
|
||||||
|
apiVersion: v1
|
||||||
|
kind: ConfigMap
|
||||||
|
metadata:
|
||||||
|
name: {{ include "fullname" . }}-config
|
||||||
|
labels:
|
||||||
|
{{- include "labels" . | nindent 4 }}
|
||||||
|
data:
|
||||||
|
{{- range $key, $value := .Values.config }}
|
||||||
|
{{ $key }}: {{ $value | quote }}
|
||||||
|
{{- end }}
|
||||||
|
{{- end }}
|
||||||
68
k8s/charts/_template/templates/deployment.yaml
Normal file
68
k8s/charts/_template/templates/deployment.yaml
Normal file
|
|
@ -0,0 +1,68 @@
|
||||||
|
apiVersion: apps/v1
|
||||||
|
kind: Deployment
|
||||||
|
metadata:
|
||||||
|
name: {{ include "fullname" . }}
|
||||||
|
labels:
|
||||||
|
{{- include "labels" . | nindent 4 }}
|
||||||
|
spec:
|
||||||
|
replicas: {{ .Values.replicaCount }}
|
||||||
|
selector:
|
||||||
|
matchLabels:
|
||||||
|
{{- include "selectorLabels" . | nindent 6 }}
|
||||||
|
template:
|
||||||
|
metadata:
|
||||||
|
labels:
|
||||||
|
{{- include "selectorLabels" . | nindent 8 }}
|
||||||
|
spec:
|
||||||
|
containers:
|
||||||
|
- name: {{ .Chart.Name }}
|
||||||
|
image: "{{ .Values.image.repository }}:{{ .Values.image.tag | default .Chart.AppVersion }}"
|
||||||
|
imagePullPolicy: {{ .Values.image.pullPolicy }}
|
||||||
|
ports:
|
||||||
|
- name: http
|
||||||
|
containerPort: {{ .Values.service.targetPort }}
|
||||||
|
protocol: TCP
|
||||||
|
{{- if .Values.config }}
|
||||||
|
envFrom:
|
||||||
|
- configMapRef:
|
||||||
|
name: {{ include "fullname" . }}-config
|
||||||
|
{{- end }}
|
||||||
|
{{- if .Values.secret.existingSecretName }}
|
||||||
|
envFrom:
|
||||||
|
- secretRef:
|
||||||
|
name: {{ .Values.secret.existingSecretName }}
|
||||||
|
{{- end }}
|
||||||
|
{{- if .Values.persistence.enabled }}
|
||||||
|
volumeMounts:
|
||||||
|
- name: {{ include "pvcName" . }}
|
||||||
|
mountPath: /data
|
||||||
|
{{- end }}
|
||||||
|
{{- with .Values.resources }}
|
||||||
|
resources:
|
||||||
|
{{- toYaml . | nindent 12 }}
|
||||||
|
{{- end }}
|
||||||
|
{{- with .Values.livenessProbe }}
|
||||||
|
livenessProbe:
|
||||||
|
{{- toYaml . | nindent 12 }}
|
||||||
|
{{- end }}
|
||||||
|
{{- with .Values.readinessProbe }}
|
||||||
|
readinessProbe:
|
||||||
|
{{- toYaml . | nindent 12 }}
|
||||||
|
{{- end }}
|
||||||
|
{{- if not .Values.persistence.enabled }}
|
||||||
|
volumes:
|
||||||
|
- name: {{ include "pvcName" . }}
|
||||||
|
emptyDir: {}
|
||||||
|
{{- end }}
|
||||||
|
{{- with .Values.nodeSelector }}
|
||||||
|
nodeSelector:
|
||||||
|
{{- toYaml . | nindent 8 }}
|
||||||
|
{{- end }}
|
||||||
|
{{- with .Values.tolerations }}
|
||||||
|
tolerations:
|
||||||
|
{{- toYaml . | nindent 8 }}
|
||||||
|
{{- end }}
|
||||||
|
{{- with .Values.affinity }}
|
||||||
|
affinity:
|
||||||
|
{{- toYaml . | nindent 8 }}
|
||||||
|
{{- end }}
|
||||||
41
k8s/charts/_template/templates/ingress.yaml
Normal file
41
k8s/charts/_template/templates/ingress.yaml
Normal file
|
|
@ -0,0 +1,41 @@
|
||||||
|
{{- if .Values.ingress.enabled }}
|
||||||
|
apiVersion: networking.k8s.io/v1
|
||||||
|
kind: Ingress
|
||||||
|
metadata:
|
||||||
|
name: {{ include "fullname" . }}
|
||||||
|
labels:
|
||||||
|
{{- include "labels" . | nindent 4 }}
|
||||||
|
{{- with .Values.ingress.annotations }}
|
||||||
|
annotations:
|
||||||
|
{{- toYaml . | nindent 4 }}
|
||||||
|
{{- end }}
|
||||||
|
spec:
|
||||||
|
{{- if .Values.ingress.className }}
|
||||||
|
ingressClassName: {{ .Values.ingress.className }}
|
||||||
|
{{- end }}
|
||||||
|
{{- if .Values.ingress.tls }}
|
||||||
|
tls:
|
||||||
|
{{- range .Values.ingress.tls }}
|
||||||
|
- hosts:
|
||||||
|
{{- range .hosts }}
|
||||||
|
- {{ . | quote }}
|
||||||
|
{{- end }}
|
||||||
|
secretName: {{ .secretName }}
|
||||||
|
{{- end }}
|
||||||
|
{{- end }}
|
||||||
|
rules:
|
||||||
|
{{- range .Values.ingress.hosts }}
|
||||||
|
- host: {{ .host | quote }}
|
||||||
|
http:
|
||||||
|
paths:
|
||||||
|
{{- range .paths }}
|
||||||
|
- path: {{ .path }}
|
||||||
|
pathType: {{ .pathType | default "Prefix" }}
|
||||||
|
backend:
|
||||||
|
service:
|
||||||
|
name: {{ include "fullname" $ }}
|
||||||
|
port:
|
||||||
|
number: {{ $.Values.service.port }}
|
||||||
|
{{- end }}
|
||||||
|
{{- end }}
|
||||||
|
{{- end }}
|
||||||
17
k8s/charts/_template/templates/pvc.yaml
Normal file
17
k8s/charts/_template/templates/pvc.yaml
Normal file
|
|
@ -0,0 +1,17 @@
|
||||||
|
{{- if .Values.persistence.enabled }}
|
||||||
|
apiVersion: v1
|
||||||
|
kind: PersistentVolumeClaim
|
||||||
|
metadata:
|
||||||
|
name: {{ include "pvcName" . }}
|
||||||
|
labels:
|
||||||
|
{{- include "labels" . | nindent 4 }}
|
||||||
|
spec:
|
||||||
|
accessModes:
|
||||||
|
- {{ .Values.persistence.accessMode | default "ReadWriteMany" }}
|
||||||
|
{{- if .Values.persistence.storageClass }}
|
||||||
|
storageClassName: {{ .Values.persistence.storageClass }}
|
||||||
|
{{- end }}
|
||||||
|
resources:
|
||||||
|
requests:
|
||||||
|
storage: {{ .Values.persistence.size | default "1Gi" }}
|
||||||
|
{{- end }}
|
||||||
13
k8s/charts/_template/templates/secret.yaml
Normal file
13
k8s/charts/_template/templates/secret.yaml
Normal file
|
|
@ -0,0 +1,13 @@
|
||||||
|
{{- if and .Values.secret.enabled (not .Values.secret.existingSecretName) .Values.secret.data }}
|
||||||
|
apiVersion: v1
|
||||||
|
kind: Secret
|
||||||
|
metadata:
|
||||||
|
name: {{ include "fullname" . }}-secret
|
||||||
|
labels:
|
||||||
|
{{- include "labels" . | nindent 4 }}
|
||||||
|
type: Opaque
|
||||||
|
data:
|
||||||
|
{{- range $key, $value := .Values.secret.data }}
|
||||||
|
{{ $key }}: {{ $value | b64enc | quote }}
|
||||||
|
{{- end }}
|
||||||
|
{{- end }}
|
||||||
15
k8s/charts/_template/templates/service.yaml
Normal file
15
k8s/charts/_template/templates/service.yaml
Normal file
|
|
@ -0,0 +1,15 @@
|
||||||
|
apiVersion: v1
|
||||||
|
kind: Service
|
||||||
|
metadata:
|
||||||
|
name: {{ include "fullname" . }}
|
||||||
|
labels:
|
||||||
|
{{- include "labels" . | nindent 4 }}
|
||||||
|
spec:
|
||||||
|
type: {{ .Values.service.type }}
|
||||||
|
ports:
|
||||||
|
- port: {{ .Values.service.port }}
|
||||||
|
targetPort: http
|
||||||
|
protocol: TCP
|
||||||
|
name: http
|
||||||
|
selector:
|
||||||
|
{{- include "selectorLabels" . | nindent 4 }}
|
||||||
60
k8s/charts/_template/values.yaml
Normal file
60
k8s/charts/_template/values.yaml
Normal file
|
|
@ -0,0 +1,60 @@
|
||||||
|
replicaCount: 1
|
||||||
|
|
||||||
|
image:
|
||||||
|
repository: nginx
|
||||||
|
pullPolicy: IfNotPresent
|
||||||
|
tag: ""
|
||||||
|
|
||||||
|
service:
|
||||||
|
type: LoadBalancer
|
||||||
|
port: 80
|
||||||
|
targetPort: 80
|
||||||
|
|
||||||
|
ingress:
|
||||||
|
enabled: false
|
||||||
|
className: "traefik"
|
||||||
|
annotations: {}
|
||||||
|
hosts:
|
||||||
|
- host: chart.example.com
|
||||||
|
paths:
|
||||||
|
- path: /
|
||||||
|
pathType: Prefix
|
||||||
|
tls: []
|
||||||
|
|
||||||
|
config: {}
|
||||||
|
|
||||||
|
persistence:
|
||||||
|
enabled: false
|
||||||
|
storageClass: "truenas-nfs-csi"
|
||||||
|
accessMode: ReadWriteMany
|
||||||
|
size: 1Gi
|
||||||
|
name: "chart-data"
|
||||||
|
|
||||||
|
resources: {}
|
||||||
|
|
||||||
|
livenessProbe:
|
||||||
|
tcpSocket:
|
||||||
|
port: 80
|
||||||
|
initialDelaySeconds: 30
|
||||||
|
timeoutSeconds: 15
|
||||||
|
successThreshold: 1
|
||||||
|
failureThreshold: 3
|
||||||
|
periodSeconds: 10
|
||||||
|
|
||||||
|
readinessProbe:
|
||||||
|
tcpSocket:
|
||||||
|
port: 80
|
||||||
|
initialDelaySeconds: 15
|
||||||
|
timeoutSeconds: 2
|
||||||
|
successThreshold: 1
|
||||||
|
failureThreshold: 3
|
||||||
|
periodSeconds: 10
|
||||||
|
|
||||||
|
nodeSelector: {}
|
||||||
|
tolerations: []
|
||||||
|
affinity: {}
|
||||||
|
|
||||||
|
secret:
|
||||||
|
enabled: true
|
||||||
|
existingSecretName: ""
|
||||||
|
data: {}
|
||||||
|
|
@ -5,9 +5,13 @@ description: 'Ultra-fast, secure & lightweight self-hosted cloud storage — you
|
||||||
|
|
||||||
'
|
'
|
||||||
type: application
|
type: application
|
||||||
version: 0.1.0
|
version: 1.0.0
|
||||||
appVersion: 0.8.6
|
appVersion: 0.8.6
|
||||||
annotations:
|
annotations:
|
||||||
artifacthub.io/images: |
|
artifacthub.io/images: "- name: oxicloud\n image: diocrafts/oxicloud:0.8.6\n"
|
||||||
- name: oxicloud
|
artifacthub.io/changes: "- kind: changed\n description: \"Normalized structure\
|
||||||
image: diocrafts/oxicloud:0.8.6
|
\ to use hierarchical values under `oxicloud:` key\"\n- kind: changed\n description:\
|
||||||
|
\ \"Changed service type default to LoadBalancer\"\n- kind: changed\n description:\
|
||||||
|
\ \"Renamed PVC to `oxicloud-data`\"\n- kind: changed\n description: \"Disabled\
|
||||||
|
\ WOPI/Collabora by default\"\n- kind: security\n description: \"Removed hardcoded\
|
||||||
|
\ credentials from values.yaml; use existingSecretName instead\"\n"
|
||||||
|
|
|
||||||
133
k8s/charts/oxicloud/README.md
Normal file
133
k8s/charts/oxicloud/README.md
Normal file
|
|
@ -0,0 +1,133 @@
|
||||||
|
# oxicloud
|
||||||
|
|
||||||
|
Ultra-fast, secure & lightweight self-hosted cloud storage — your files, photos, calendars & contacts, all in one place. Built in Rust.
|
||||||
|
|
||||||
|
## TL;DR
|
||||||
|
|
||||||
|
```bash
|
||||||
|
helm install oxicloud oci://git.roboces.dev/catalin/fukuops/oxicloud --version 1.0.0 -n apps-roboces
|
||||||
|
```
|
||||||
|
|
||||||
|
## Prerequisites
|
||||||
|
|
||||||
|
- Kubernetes 1.19+
|
||||||
|
- Helm 3+
|
||||||
|
- A NFS storage class (default: `truenas-nfs-csi`)
|
||||||
|
- An existing `Secret` containing:
|
||||||
|
- `OXICLOUD_JWT_SECRET` (optional - generated if not provided)
|
||||||
|
|
||||||
|
## Configuration
|
||||||
|
|
||||||
|
All values are nested under the `oxicloud:` key. Example:
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
oxicloud:
|
||||||
|
persistence:
|
||||||
|
enabled: true
|
||||||
|
storageClass: "truenas-nfs-csi"
|
||||||
|
accessMode: ReadWriteMany
|
||||||
|
size: 50Gi
|
||||||
|
service:
|
||||||
|
type: LoadBalancer
|
||||||
|
port: 8086
|
||||||
|
config:
|
||||||
|
server:
|
||||||
|
port: 8086
|
||||||
|
host: "0.0.0.0"
|
||||||
|
baseUrl: "https://cloud.example.com"
|
||||||
|
features:
|
||||||
|
enableAuth: true
|
||||||
|
enableSharing: true
|
||||||
|
secret:
|
||||||
|
existingSecretName: oxicloud
|
||||||
|
wopi:
|
||||||
|
enabled: false
|
||||||
|
ingress:
|
||||||
|
enabled: true
|
||||||
|
className: "traefik"
|
||||||
|
hosts:
|
||||||
|
- host: cloud.example.com
|
||||||
|
paths:
|
||||||
|
- path: /
|
||||||
|
pathType: ImplementationSpecific
|
||||||
|
```
|
||||||
|
|
||||||
|
## Values Reference
|
||||||
|
|
||||||
|
| Key | Type | Default | Description |
|
||||||
|
|-----|------|---------|-------------|
|
||||||
|
| `oxicloud.replicaCount` | int | `1` | Number of replicas |
|
||||||
|
| `oxicloud.image.repository` | string | `diocrafts/oxicloud` | Image repository |
|
||||||
|
| `oxicloud.image.pullPolicy` | string | `Always` | Image pull policy |
|
||||||
|
| `oxicloud.image.tag` | string | `.Chart.AppVersion` | Image tag |
|
||||||
|
| `oxicloud.service.type` | string | `LoadBalancer` | Service type |
|
||||||
|
| `oxicloud.service.port` | int | `8086` | Service port |
|
||||||
|
| `oxicloud.config.server.port` | int | `8086` | Server port |
|
||||||
|
| `oxicloud.config.server.host` | string | `0.0.0.0` | Server host |
|
||||||
|
| `oxicloud.config.server.baseUrl` | string | `https://cloud.example.com` | Public base URL |
|
||||||
|
| `oxicloud.config.features.enableAuth` | bool | `true` | Enable authentication |
|
||||||
|
| `oxicloud.config.features.enableSharing` | bool | `true` | Enable file sharing |
|
||||||
|
| `oxicloud.persistence.enabled` | bool | `true` | Enable persistence |
|
||||||
|
| `oxicloud.persistence.storageClass` | string | `""` | Storage class |
|
||||||
|
| `oxicloud.persistence.accessMode` | string | `ReadWriteOnce` | Access mode |
|
||||||
|
| `oxicloud.persistence.size` | string | `50Gi` | PVC size |
|
||||||
|
| `oxicloud.secret.existingSecretName` | string | `""` | Existing secret name |
|
||||||
|
| `oxicloud.wopi.enabled` | bool | `false` | Enable WOPI/Collabora integration |
|
||||||
|
| `oxicloud.ingress.enabled` | bool | `false` | Enable ingress |
|
||||||
|
| `oxicloud.ingress.className` | string | `""` | Ingress class |
|
||||||
|
| `oxicloud.resources` | object | `{}` | Container resources |
|
||||||
|
| `oxicloud.livenessProbe` | object | (see values.yaml) | Liveness probe |
|
||||||
|
| `oxicloud.readinessProbe` | object | (see values.yaml) | Readiness probe |
|
||||||
|
|
||||||
|
## WOPI/Collabora
|
||||||
|
|
||||||
|
WOPI integration is disabled by default. To enable it:
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
oxicloud:
|
||||||
|
wopi:
|
||||||
|
enabled: true
|
||||||
|
collabora:
|
||||||
|
url: "cloud.example.com"
|
||||||
|
domain: "cloud.example.com"
|
||||||
|
image:
|
||||||
|
repository: collabora/code
|
||||||
|
tag: latest
|
||||||
|
service:
|
||||||
|
port: 9980
|
||||||
|
admin:
|
||||||
|
existingSecretName: "collabora-admin"
|
||||||
|
```
|
||||||
|
|
||||||
|
When enabling WOPI, you must provide an existing `Secret` containing `WOPI_ADMIN_USERNAME` and `WOPI_ADMIN_PASSWORD` keys.
|
||||||
|
|
||||||
|
## Persistence
|
||||||
|
|
||||||
|
The chart creates a `StatefulSet` with a PVC named `oxicloud-data`. The PVC uses the `truenas-nfs-csi` storage class by default (when not specified).
|
||||||
|
|
||||||
|
## Secret Management
|
||||||
|
|
||||||
|
The chart looks for an existing `Secret` with the name specified in `oxicloud.secret.existingSecretName`. If not provided, a chart-managed secret will be created (only if additional secrets are needed).
|
||||||
|
|
||||||
|
Required secret keys depend on configuration:
|
||||||
|
- `OXICLOUD_JWT_SECRET` - JWT signing secret (recommended)
|
||||||
|
- `WOPI_ADMIN_USERNAME` / `WOPI_ADMIN_PASSWORD` - Collabora admin credentials (when WOPI enabled)
|
||||||
|
|
||||||
|
## Troubleshooting
|
||||||
|
|
||||||
|
### Pod not starting
|
||||||
|
|
||||||
|
Check if the PVC is bound:
|
||||||
|
```bash
|
||||||
|
kubectl get pvc -n apps-roboces -l app.kubernetes.io/name=oxicloud
|
||||||
|
```
|
||||||
|
|
||||||
|
### Check logs
|
||||||
|
```bash
|
||||||
|
kubectl logs oxicloud-0 -n apps-roboces
|
||||||
|
```
|
||||||
|
|
||||||
|
### Verify configmap
|
||||||
|
```bash
|
||||||
|
kubectl get configmap oxicloud-config -n apps-roboces -o yaml
|
||||||
|
```
|
||||||
|
|
@ -4,19 +4,19 @@ kind: ConfigMap
|
||||||
metadata:
|
metadata:
|
||||||
name: {{ include "oxicloud.fullname" . }}-config
|
name: {{ include "oxicloud.fullname" . }}-config
|
||||||
data:
|
data:
|
||||||
OXICLOUD_SERVER_PORT: {{ .Values.config.server.port | quote }}
|
OXICLOUD_SERVER_PORT: {{ .Values.oxicloud.config.server.port | quote }}
|
||||||
OXICLOUD_SERVER_HOST: {{ .Values.config.server.host | quote }}
|
OXICLOUD_SERVER_HOST: {{ .Values.oxicloud.config.server.host | quote }}
|
||||||
{{- if .Values.config.server.baseUrl }}
|
{{- if .Values.oxicloud.config.server.baseUrl }}
|
||||||
OXICLOUD_BASE_URL: {{ .Values.config.server.baseUrl | quote }}
|
OXICLOUD_BASE_URL: {{ .Values.oxicloud.config.server.baseUrl | quote }}
|
||||||
{{- end }}
|
{{- end }}
|
||||||
OXICLOUD_ENABLE_AUTH: {{ .Values.config.features.enableAuth | quote }}
|
OXICLOUD_ENABLE_AUTH: {{ .Values.oxicloud.config.features.enableAuth | quote }}
|
||||||
OXICLOUD_ENABLE_FILE_SHARING: {{ .Values.config.features.enableSharing | quote }}
|
OXICLOUD_ENABLE_FILE_SHARING: {{ .Values.oxicloud.config.features.enableSharing | quote }}
|
||||||
MIMALLOC_PURGE_DELAY: {{ .Values.config.mimalloc.purgeDelay | quote }}
|
MIMALLOC_PURGE_DELAY: {{ .Values.oxicloud.config.mimalloc.purgeDelay | quote }}
|
||||||
MIMALLOC_ALLOW_LARGE_OS_PAGES: {{ .Values.config.mimalloc.allowLargeOsPages | quote }}
|
MIMALLOC_ALLOW_LARGE_OS_PAGES: {{ .Values.oxicloud.config.mimalloc.allowLargeOsPages | quote }}
|
||||||
|
|
||||||
{{- if .Values.wopi.enabled }}
|
{{- if .Values.oxicloud.wopi.enabled }}
|
||||||
OXICLOUD_WOPI_ENABLED: "true"
|
OXICLOUD_WOPI_ENABLED: "true"
|
||||||
OXICLOUD_WOPI_DISCOVERY_URL: "{{ .Values.config.server.baseUrl }}/hosting/discovery"
|
OXICLOUD_WOPI_DISCOVERY_URL: "{{ .Values.oxicloud.config.server.baseUrl }}/hosting/discovery"
|
||||||
{{- else }}
|
{{- else }}
|
||||||
OXICLOUD_WOPI_ENABLED: "false"
|
OXICLOUD_WOPI_ENABLED: "false"
|
||||||
{{- end }}
|
{{- end }}
|
||||||
|
|
|
||||||
|
|
@ -1,22 +1,22 @@
|
||||||
---
|
---
|
||||||
{{- if .Values.ingress.enabled -}}
|
{{- if .Values.oxicloud.ingress.enabled -}}
|
||||||
apiVersion: networking.k8s.io/v1
|
apiVersion: networking.k8s.io/v1
|
||||||
kind: Ingress
|
kind: Ingress
|
||||||
metadata:
|
metadata:
|
||||||
name: {{ include "oxicloud.fullname" . }}
|
name: {{ include "oxicloud.fullname" . }}
|
||||||
labels:
|
labels:
|
||||||
{{- include "oxicloud.labels" . | nindent 4 }}
|
{{- include "oxicloud.labels" . | nindent 4 }}
|
||||||
{{- with .Values.ingress.annotations }}
|
{{- with .Values.oxicloud.ingress.annotations }}
|
||||||
annotations:
|
annotations:
|
||||||
{{- toYaml . | nindent 4 }}
|
{{- toYaml . | nindent 4 }}
|
||||||
{{- end }}
|
{{- end }}
|
||||||
spec:
|
spec:
|
||||||
{{- if .Values.ingress.className }}
|
{{- if .Values.oxicloud.ingress.className }}
|
||||||
ingressClassName: {{ .Values.ingress.className }}
|
ingressClassName: {{ .Values.oxicloud.ingress.className }}
|
||||||
{{- end }}
|
{{- end }}
|
||||||
{{- if .Values.ingress.tls }}
|
{{- if .Values.oxicloud.ingress.tls }}
|
||||||
tls:
|
tls:
|
||||||
{{- range .Values.ingress.tls }}
|
{{- range .Values.oxicloud.ingress.tls }}
|
||||||
- hosts:
|
- hosts:
|
||||||
{{- range .hosts }}
|
{{- range .hosts }}
|
||||||
- {{ . | quote }}
|
- {{ . | quote }}
|
||||||
|
|
@ -25,40 +25,38 @@ spec:
|
||||||
{{- end }}
|
{{- end }}
|
||||||
{{- end }}
|
{{- end }}
|
||||||
rules:
|
rules:
|
||||||
- host: {{ (index .Values.ingress.hosts 0).host | quote }}
|
- host: {{ (index .Values.oxicloud.ingress.hosts 0).host | quote }}
|
||||||
http:
|
http:
|
||||||
paths:
|
paths:
|
||||||
{{- if .Values.wopi.enabled }}
|
{{- if .Values.oxicloud.wopi.enabled }}
|
||||||
# Route Collabora traffic to the WOPI pod
|
|
||||||
- path: /browser
|
- path: /browser
|
||||||
pathType: Prefix
|
pathType: Prefix
|
||||||
backend:
|
backend:
|
||||||
service:
|
service:
|
||||||
name: {{ include "oxicloud.fullname" $ }}-wopi
|
name: {{ include "oxicloud.fullname" $ }}-wopi
|
||||||
port:
|
port:
|
||||||
number: {{ .Values.wopi.collabora.service.port }}
|
number: {{ .Values.oxicloud.wopi.collabora.service.port }}
|
||||||
- path: /hosting
|
- path: /hosting
|
||||||
pathType: Prefix
|
pathType: Prefix
|
||||||
backend:
|
backend:
|
||||||
service:
|
service:
|
||||||
name: {{ include "oxicloud.fullname" $ }}-wopi
|
name: {{ include "oxicloud.fullname" $ }}-wopi
|
||||||
port:
|
port:
|
||||||
number: {{ .Values.wopi.collabora.service.port }}
|
number: {{ .Values.oxicloud.wopi.collabora.service.port }}
|
||||||
- path: /cool
|
- path: /cool
|
||||||
pathType: Prefix
|
pathType: Prefix
|
||||||
backend:
|
backend:
|
||||||
service:
|
service:
|
||||||
name: {{ include "oxicloud.fullname" $ }}-wopi
|
name: {{ include "oxicloud.fullname" $ }}-wopi
|
||||||
port:
|
port:
|
||||||
number: {{ .Values.wopi.collabora.service.port }}
|
number: {{ .Values.oxicloud.wopi.collabora.service.port }}
|
||||||
{{- end }}
|
{{- end }}
|
||||||
|
|
||||||
# Default Catch-All: Route everything else to OxiCloud
|
|
||||||
- path: /
|
- path: /
|
||||||
pathType: Prefix
|
pathType: Prefix
|
||||||
backend:
|
backend:
|
||||||
service:
|
service:
|
||||||
name: {{ include "oxicloud.fullname" $ }}
|
name: {{ include "oxicloud.fullname" $ }}
|
||||||
port:
|
port:
|
||||||
number: {{ $.Values.service.port }}
|
number: {{ $.Values.oxicloud.service.port }}
|
||||||
{{- end }}
|
{{- end }}
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
---
|
---
|
||||||
{{- if not .Values.secrets.existingSecret }}
|
{{- if not .Values.oxicloud.secret.existingSecretName }}
|
||||||
apiVersion: v1
|
apiVersion: v1
|
||||||
kind: Secret
|
kind: Secret
|
||||||
metadata:
|
metadata:
|
||||||
|
|
@ -8,12 +8,15 @@ metadata:
|
||||||
{{- include "oxicloud.labels" . | nindent 4 }}
|
{{- include "oxicloud.labels" . | nindent 4 }}
|
||||||
type: Opaque
|
type: Opaque
|
||||||
data:
|
data:
|
||||||
{{- if .Values.secrets.jwtSecret }}
|
{{- if .Values.oxicloud.secret.data.jwtSecret }}
|
||||||
OXICLOUD_JWT_SECRET: {{ .Values.secrets.jwtSecret | b64enc | quote }}
|
OXICLOUD_JWT_SECRET: {{ .Values.oxicloud.secret.data.jwtSecret | b64enc | quote }}
|
||||||
|
{{- end }}
|
||||||
|
{{- if .Values.oxicloud.wopi.enabled }}
|
||||||
|
{{- if .Values.oxicloud.wopi.collabora.admin.username }}
|
||||||
|
WOPI_ADMIN_USERNAME: {{ .Values.oxicloud.wopi.collabora.admin.username | b64enc | quote }}
|
||||||
|
{{- end }}
|
||||||
|
{{- if .Values.oxicloud.wopi.collabora.admin.password }}
|
||||||
|
WOPI_ADMIN_PASSWORD: {{ .Values.oxicloud.wopi.collabora.admin.password | b64enc | quote }}
|
||||||
{{- end }}
|
{{- end }}
|
||||||
DB_PASSWORD: {{ .Values.database.password | b64enc | quote }}
|
|
||||||
{{- if .Values.wopi.enabled }}
|
|
||||||
WOPI_ADMIN_USERNAME: {{ .Values.wopi.collabora.admin.username | b64enc | quote }}
|
|
||||||
WOPI_ADMIN_PASSWORD: {{ .Values.wopi.collabora.admin.password | b64enc | quote }}
|
|
||||||
{{- end }}
|
{{- end }}
|
||||||
{{- end }}
|
{{- end }}
|
||||||
|
|
|
||||||
|
|
@ -6,9 +6,9 @@ metadata:
|
||||||
labels:
|
labels:
|
||||||
{{- include "oxicloud.labels" . | nindent 4 }}
|
{{- include "oxicloud.labels" . | nindent 4 }}
|
||||||
spec:
|
spec:
|
||||||
type: {{ .Values.service.type }}
|
type: {{ .Values.oxicloud.service.type }}
|
||||||
ports:
|
ports:
|
||||||
- port: {{ .Values.service.port }}
|
- port: {{ .Values.oxicloud.service.port }}
|
||||||
targetPort: http
|
targetPort: http
|
||||||
protocol: TCP
|
protocol: TCP
|
||||||
name: http
|
name: http
|
||||||
|
|
@ -24,7 +24,7 @@ metadata:
|
||||||
spec:
|
spec:
|
||||||
clusterIP: None
|
clusterIP: None
|
||||||
ports:
|
ports:
|
||||||
- port: {{ .Values.service.port }}
|
- port: {{ .Values.oxicloud.service.port }}
|
||||||
targetPort: http
|
targetPort: http
|
||||||
protocol: TCP
|
protocol: TCP
|
||||||
name: http
|
name: http
|
||||||
|
|
|
||||||
|
|
@ -6,7 +6,7 @@ metadata:
|
||||||
{{- include "oxicloud.labels" . | nindent 4 }}
|
{{- include "oxicloud.labels" . | nindent 4 }}
|
||||||
spec:
|
spec:
|
||||||
serviceName: {{ include "oxicloud.fullname" . }}-headless
|
serviceName: {{ include "oxicloud.fullname" . }}-headless
|
||||||
replicas: {{ .Values.replicaCount }}
|
replicas: {{ .Values.oxicloud.replicaCount }}
|
||||||
selector:
|
selector:
|
||||||
matchLabels:
|
matchLabels:
|
||||||
{{- include "oxicloud.selectorLabels" . | nindent 6 }}
|
{{- include "oxicloud.selectorLabels" . | nindent 6 }}
|
||||||
|
|
@ -17,37 +17,61 @@ spec:
|
||||||
spec:
|
spec:
|
||||||
containers:
|
containers:
|
||||||
- name: oxicloud
|
- name: oxicloud
|
||||||
image: "{{ .Values.image.repository }}:{{ .Values.image.tag | default .Chart.AppVersion }}"
|
image: "{{ .Values.oxicloud.image.repository }}:{{ .Values.oxicloud.image.tag | default .Chart.AppVersion }}"
|
||||||
imagePullPolicy: {{ .Values.image.pullPolicy }}
|
imagePullPolicy: {{ .Values.oxicloud.image.pullPolicy }}
|
||||||
ports:
|
ports:
|
||||||
- name: http
|
- name: http
|
||||||
containerPort: 8086
|
containerPort: {{ .Values.oxicloud.config.server.port }}
|
||||||
protocol: TCP
|
protocol: TCP
|
||||||
envFrom:
|
envFrom:
|
||||||
- configMapRef:
|
- configMapRef:
|
||||||
name: {{ include "oxicloud.fullname" . }}-config
|
name: {{ include "oxicloud.fullname" . }}-config
|
||||||
- secretRef:
|
- secretRef:
|
||||||
name: {{ if .Values.secrets.existingSecret }}{{ .Values.secrets.existingSecret }}{{ else }}{{ include "oxicloud.fullname" . }}-secret{{ end }}
|
name: {{ if .Values.oxicloud.secret.existingSecretName }}{{ .Values.oxicloud.secret.existingSecretName }}{{ else }}{{ include "oxicloud.fullname" . }}-secret{{ end }}
|
||||||
volumeMounts:
|
volumeMounts:
|
||||||
- name: storage-data
|
- name: oxicloud-data
|
||||||
mountPath: /app/storage
|
mountPath: /app/storage
|
||||||
{{- if not .Values.persistence.enabled }}
|
{{- with .Values.oxicloud.resources }}
|
||||||
|
resources:
|
||||||
|
{{- toYaml . | nindent 12 }}
|
||||||
|
{{- end }}
|
||||||
|
{{- with .Values.oxicloud.livenessProbe }}
|
||||||
|
livenessProbe:
|
||||||
|
{{- toYaml . | nindent 12 }}
|
||||||
|
{{- end }}
|
||||||
|
{{- with .Values.oxicloud.readinessProbe }}
|
||||||
|
readinessProbe:
|
||||||
|
{{- toYaml . | nindent 12 }}
|
||||||
|
{{- end }}
|
||||||
|
{{- if not .Values.oxicloud.persistence.enabled }}
|
||||||
volumes:
|
volumes:
|
||||||
- name: storage-data
|
- name: oxicloud-data
|
||||||
emptyDir: {}
|
emptyDir: {}
|
||||||
{{- end }}
|
{{- end }}
|
||||||
|
{{- with .Values.oxicloud.nodeSelector }}
|
||||||
|
nodeSelector:
|
||||||
|
{{- toYaml . | nindent 8 }}
|
||||||
|
{{- end }}
|
||||||
|
{{- with .Values.oxicloud.tolerations }}
|
||||||
|
tolerations:
|
||||||
|
{{- toYaml . | nindent 8 }}
|
||||||
|
{{- end }}
|
||||||
|
{{- with .Values.oxicloud.affinity }}
|
||||||
|
affinity:
|
||||||
|
{{- toYaml . | nindent 8 }}
|
||||||
|
{{- end }}
|
||||||
|
|
||||||
{{- if .Values.persistence.enabled }}
|
{{- if .Values.oxicloud.persistence.enabled }}
|
||||||
volumeClaimTemplates:
|
volumeClaimTemplates:
|
||||||
- metadata:
|
- metadata:
|
||||||
name: storage-data
|
name: oxicloud-data
|
||||||
spec:
|
spec:
|
||||||
accessModes:
|
accessModes:
|
||||||
- {{ .Values.persistence.accessMode }}
|
- {{ .Values.oxicloud.persistence.accessMode }}
|
||||||
{{- if .Values.persistence.storageClass }}
|
{{- if .Values.oxicloud.persistence.storageClass }}
|
||||||
storageClassName: {{ .Values.persistence.storageClass }}
|
storageClassName: {{ .Values.oxicloud.persistence.storageClass }}
|
||||||
{{- end }}
|
{{- end }}
|
||||||
resources:
|
resources:
|
||||||
requests:
|
requests:
|
||||||
storage: {{ .Values.persistence.size }}
|
storage: {{ .Values.oxicloud.persistence.size }}
|
||||||
{{- end }}
|
{{- end }}
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
---
|
---
|
||||||
{{- if .Values.wopi.enabled -}}
|
{{- if .Values.oxicloud.wopi.enabled -}}
|
||||||
apiVersion: apps/v1
|
apiVersion: apps/v1
|
||||||
kind: Deployment
|
kind: Deployment
|
||||||
metadata:
|
metadata:
|
||||||
|
|
@ -21,9 +21,8 @@ spec:
|
||||||
spec:
|
spec:
|
||||||
containers:
|
containers:
|
||||||
- name: collabora
|
- name: collabora
|
||||||
image: "{{ .Values.wopi.collabora.image.repository }}:{{ .Values.wopi.collabora.image.tag }}"
|
image: "{{ .Values.oxicloud.wopi.collabora.image.repository }}:{{ .Values.oxicloud.wopi.collabora.image.tag }}"
|
||||||
imagePullPolicy: {{ .Values.wopi.collabora.image.pullPolicy }}
|
imagePullPolicy: {{ .Values.oxicloud.wopi.collabora.image.pullPolicy }}
|
||||||
# Required for Collabora to build chroot jails
|
|
||||||
securityContext:
|
securityContext:
|
||||||
capabilities:
|
capabilities:
|
||||||
add:
|
add:
|
||||||
|
|
@ -34,20 +33,20 @@ spec:
|
||||||
protocol: TCP
|
protocol: TCP
|
||||||
env:
|
env:
|
||||||
- name: aliasgroup1
|
- name: aliasgroup1
|
||||||
value: "http://{{ .Values.wopi.collabora.domain }}"
|
value: "http://{{ .Values.oxicloud.wopi.collabora.domain }}"
|
||||||
- name: server_name
|
- name: server_name
|
||||||
value: {{ .Values.wopi.collabora.domain | quote }}
|
value: {{ .Values.oxicloud.wopi.collabora.domain | quote }}
|
||||||
- name: extra_params
|
- name: extra_params
|
||||||
value: {{ .Values.wopi.collabora.extraParams | quote }}
|
value: {{ .Values.oxicloud.wopi.collabora.extraParams | quote }}
|
||||||
- name: username
|
- name: username
|
||||||
valueFrom:
|
valueFrom:
|
||||||
secretKeyRef:
|
secretKeyRef:
|
||||||
name: {{ if .Values.secrets.existingSecret }}{{ .Values.secrets.existingSecret }}{{ else }}{{ include "oxicloud.fullname" . }}-secret{{ end }}
|
name: {{ if .Values.oxicloud.secret.existingSecretName }}{{ .Values.oxicloud.secret.existingSecretName }}{{ else if .Values.oxicloud.wopi.collabora.admin.existingSecretName }}{{ .Values.oxicloud.wopi.collabora.admin.existingSecretName }}{{ else }}{{ include "oxicloud.fullname" . }}-secret{{ end }}
|
||||||
key: WOPI_ADMIN_USERNAME
|
key: WOPI_ADMIN_USERNAME
|
||||||
- name: password
|
- name: password
|
||||||
valueFrom:
|
valueFrom:
|
||||||
secretKeyRef:
|
secretKeyRef:
|
||||||
name: {{ if .Values.secrets.existingSecret }}{{ .Values.secrets.existingSecret }}{{ else }}{{ include "oxicloud.fullname" . }}-secret{{ end }}
|
name: {{ if .Values.oxicloud.secret.existingSecretName }}{{ .Values.oxicloud.secret.existingSecretName }}{{ else if .Values.oxicloud.wopi.collabora.admin.existingSecretName }}{{ .Values.oxicloud.wopi.collabora.admin.existingSecretName }}{{ else }}{{ include "oxicloud.fullname" . }}-secret{{ end }}
|
||||||
key: WOPI_ADMIN_PASSWORD
|
key: WOPI_ADMIN_PASSWORD
|
||||||
readinessProbe:
|
readinessProbe:
|
||||||
httpGet:
|
httpGet:
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
---
|
---
|
||||||
{{- if .Values.wopi.enabled -}}
|
{{- if .Values.oxicloud.wopi.enabled -}}
|
||||||
apiVersion: v1
|
apiVersion: v1
|
||||||
kind: Service
|
kind: Service
|
||||||
metadata:
|
metadata:
|
||||||
|
|
@ -10,7 +10,7 @@ metadata:
|
||||||
spec:
|
spec:
|
||||||
type: ClusterIP
|
type: ClusterIP
|
||||||
ports:
|
ports:
|
||||||
- port: {{ .Values.wopi.collabora.service.port }}
|
- port: {{ .Values.oxicloud.wopi.collabora.service.port }}
|
||||||
targetPort: wopi
|
targetPort: wopi
|
||||||
protocol: TCP
|
protocol: TCP
|
||||||
name: wopi
|
name: wopi
|
||||||
|
|
|
||||||
|
|
@ -1,56 +1,17 @@
|
||||||
---
|
---
|
||||||
replicaCount: 1
|
oxicloud:
|
||||||
|
replicaCount: 1
|
||||||
|
|
||||||
|
image:
|
||||||
|
|
||||||
image:
|
|
||||||
repository: diocrafts/oxicloud
|
repository: diocrafts/oxicloud
|
||||||
pullpolicy: Always
|
pullPolicy: Always
|
||||||
tag: ""
|
tag: ""
|
||||||
|
|
||||||
config:
|
|
||||||
server:
|
|
||||||
port: 8086
|
|
||||||
host: "0.0.0.0"
|
|
||||||
baseUrl: "https://cloud.example.com"
|
|
||||||
features:
|
|
||||||
enableAuth: "true"
|
|
||||||
enableSharing: "true"
|
|
||||||
mimalloc:
|
|
||||||
purgeDelay: "0"
|
|
||||||
allowLargeOsPages: "0"
|
|
||||||
|
|
||||||
persistence:
|
|
||||||
enabled: true
|
|
||||||
storageClass: ""
|
|
||||||
accessMode: ReadWriteOnce
|
|
||||||
size: 50Gi
|
|
||||||
|
|
||||||
wopi:
|
|
||||||
enabled: true
|
|
||||||
collabora:
|
|
||||||
url: "cloud.example.com"
|
|
||||||
image:
|
|
||||||
repository: collabora/code
|
|
||||||
tag: latest
|
|
||||||
pullPolicy: IfNotPresent
|
|
||||||
service:
|
service:
|
||||||
port: 9980
|
type: LoadBalancer
|
||||||
admin:
|
|
||||||
username: admin
|
|
||||||
password: "wopi_admin_password"
|
|
||||||
extraParams: "--o:ssl.enable=false --o:ssl.termination=false --o:net.frame_ancestors=http://* https://*"
|
|
||||||
|
|
||||||
secrets:
|
|
||||||
existingSecret: ""
|
|
||||||
jwtSecret: ""
|
|
||||||
oidcClientSecret: ""
|
|
||||||
|
|
||||||
service:
|
|
||||||
type: ClusterIP
|
|
||||||
port: 8086
|
port: 8086
|
||||||
|
|
||||||
ingress:
|
ingress:
|
||||||
enabled: true
|
enabled: true
|
||||||
className: "traefik"
|
className: "traefik"
|
||||||
annotations: {}
|
annotations: {}
|
||||||
|
|
@ -60,3 +21,67 @@ ingress:
|
||||||
- path: /
|
- path: /
|
||||||
pathType: ImplementationSpecific
|
pathType: ImplementationSpecific
|
||||||
tls: []
|
tls: []
|
||||||
|
|
||||||
|
config:
|
||||||
|
server:
|
||||||
|
port: 8086
|
||||||
|
host: "0.0.0.0"
|
||||||
|
baseUrl: "https://cloud.example.com"
|
||||||
|
features:
|
||||||
|
enableAuth: true
|
||||||
|
enableSharing: true
|
||||||
|
mimalloc:
|
||||||
|
purgeDelay: "0"
|
||||||
|
allowLargeOsPages: "0"
|
||||||
|
|
||||||
|
persistence:
|
||||||
|
enabled: true
|
||||||
|
storageClass: ""
|
||||||
|
accessMode: ReadWriteOnce
|
||||||
|
size: 50Gi
|
||||||
|
|
||||||
|
wopi:
|
||||||
|
enabled: false
|
||||||
|
collabora:
|
||||||
|
url: "cloud.example.com"
|
||||||
|
domain: "cloud.example.com"
|
||||||
|
image:
|
||||||
|
repository: collabora/code
|
||||||
|
tag: latest
|
||||||
|
pullPolicy: IfNotPresent
|
||||||
|
service:
|
||||||
|
port: 9980
|
||||||
|
admin:
|
||||||
|
existingSecretName: ""
|
||||||
|
username: ""
|
||||||
|
password: ""
|
||||||
|
extraParams: "--o:ssl.enable=false --o:ssl.termination=false --o:net.frame_ancestors=http://* https://*"
|
||||||
|
|
||||||
|
resources: {}
|
||||||
|
|
||||||
|
livenessProbe:
|
||||||
|
tcpSocket:
|
||||||
|
port: 8086
|
||||||
|
initialDelaySeconds: 30
|
||||||
|
timeoutSeconds: 15
|
||||||
|
successThreshold: 1
|
||||||
|
failureThreshold: 3
|
||||||
|
periodSeconds: 10
|
||||||
|
|
||||||
|
readinessProbe:
|
||||||
|
tcpSocket:
|
||||||
|
port: 8086
|
||||||
|
initialDelaySeconds: 15
|
||||||
|
timeoutSeconds: 2
|
||||||
|
successThreshold: 1
|
||||||
|
failureThreshold: 3
|
||||||
|
periodSeconds: 10
|
||||||
|
|
||||||
|
nodeSelector: {}
|
||||||
|
tolerations: []
|
||||||
|
affinity: {}
|
||||||
|
|
||||||
|
secret:
|
||||||
|
enabled: true
|
||||||
|
existingSecretName: "oxicloud-secret"
|
||||||
|
data: {}
|
||||||
|
|
|
||||||
|
|
@ -1,129 +0,0 @@
|
||||||
#!/usr/bin/env bash
|
|
||||||
|
|
||||||
check_kubectl() {
|
|
||||||
if ! command -v kubectl &>/dev/null; then
|
|
||||||
echo "Error: kubectl is not installed or not in PATH" >&2
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
log_info "kubectl found at $(command -v kubectl)"
|
|
||||||
}
|
|
||||||
|
|
||||||
VERBOSE=0
|
|
||||||
|
|
||||||
log_debug() { [[ $VERBOSE -ge 3 ]] && echo "[DEBUG] $*" || true; }
|
|
||||||
log_verbose() { [[ $VERBOSE -ge 2 ]] && echo "[VERBOSE] $*" || true; }
|
|
||||||
log_info() { [[ $VERBOSE -ge 1 ]] && echo "[INFO] $*" || true; }
|
|
||||||
log_error() { echo "[ERROR] $*" >&2; }
|
|
||||||
|
|
||||||
usage() {
|
|
||||||
cat <<EOF
|
|
||||||
Usage: $(basename "$0") [OPTIONS] [VERSION]
|
|
||||||
|
|
||||||
Upgrade ArgoCD to a new version. Requires an existing ArgoCD installation.
|
|
||||||
|
|
||||||
Examples:
|
|
||||||
$(basename "$0") # queries the current argo version and tries to update to the immediate newest version
|
|
||||||
$(basename "$0") v4.3.0 # incrementally update to target version
|
|
||||||
|
|
||||||
Options:
|
|
||||||
-h, --help Show this help message
|
|
||||||
--dry-run Show what would be done without making changes
|
|
||||||
-v Verbose output (info level)
|
|
||||||
-vv More verbose output (info + verbose level)
|
|
||||||
-vvv Debug output (all log levels)
|
|
||||||
EOF
|
|
||||||
}
|
|
||||||
|
|
||||||
DRY_RUN=false
|
|
||||||
|
|
||||||
while [[ $# -gt 0 ]]; do
|
|
||||||
case "$1" in
|
|
||||||
-h|--help)
|
|
||||||
usage
|
|
||||||
exit 0
|
|
||||||
;;
|
|
||||||
--dry-run)
|
|
||||||
DRY_RUN=true
|
|
||||||
shift
|
|
||||||
;;
|
|
||||||
-v|-vv|-vvv)
|
|
||||||
case "$1" in
|
|
||||||
-v) VERBOSE=1 ;;
|
|
||||||
-vv) VERBOSE=2 ;;
|
|
||||||
-vvv) VERBOSE=3 ;;
|
|
||||||
esac
|
|
||||||
shift
|
|
||||||
;;
|
|
||||||
-*)
|
|
||||||
echo "Error: Unknown option: $1" >&2
|
|
||||||
usage >&2
|
|
||||||
exit 1
|
|
||||||
;;
|
|
||||||
*)
|
|
||||||
TARGET_VERSION="$1"
|
|
||||||
shift
|
|
||||||
;;
|
|
||||||
esac
|
|
||||||
done
|
|
||||||
|
|
||||||
log_debug "Script started with target version: ${TARGET_VERSION:-auto}"
|
|
||||||
|
|
||||||
check_kubectl
|
|
||||||
|
|
||||||
log_info "Checking current kubectl context"
|
|
||||||
CURRENT_CONTEXT=$(kubectl config current-context 2>/dev/null)
|
|
||||||
log_verbose "Current context: $CURRENT_CONTEXT"
|
|
||||||
|
|
||||||
log_info "Checking for ArgoCD installation"
|
|
||||||
if ! kubectl get ns argocd &>/dev/null; then
|
|
||||||
log_error "ArgoCD namespace not found. This script only upgrades existing installations."
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
log_verbose "ArgoCD namespace found"
|
|
||||||
|
|
||||||
log_info "Checking current ArgoCD version"
|
|
||||||
CURRENT_VERSION=$(kubectl get deployment argocd-server -n argocd -o jsonpath='{.spec.template.spec.containers[0].image}' 2>/dev/null)
|
|
||||||
if [[ -n "$CURRENT_VERSION" ]]; then
|
|
||||||
CURRENT_VERSION=$(echo "$CURRENT_VERSION" | sed 's/.*argocd:v\?//' | tr -d ' \n')
|
|
||||||
if [[ -n "$CURRENT_VERSION" ]]; then
|
|
||||||
CURRENT_VERSION="${CURRENT_VERSION#v}"
|
|
||||||
log_verbose "Current ArgoCD version: $CURRENT_VERSION"
|
|
||||||
else
|
|
||||||
log_error "Could not extract ArgoCD version from image: $CURRENT_VERSION"
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
fi
|
|
||||||
|
|
||||||
if [[ -z "$TARGET_VERSION" ]]; then
|
|
||||||
log_info "No target version specified, querying for latest version"
|
|
||||||
log_verbose "Fetching latest release from GitHub"
|
|
||||||
LATEST_VERSION=$(curl -s https://api.github.com/repos/argoproj/argo-cd/releases/latest | grep -oP '"tag_name":\s*"\K[^"]+' | sed 's/^v//')
|
|
||||||
if [[ -n "$LATEST_VERSION" ]]; then
|
|
||||||
log_verbose "Latest version available: $LATEST_VERSION"
|
|
||||||
TARGET_VERSION="$LATEST_VERSION"
|
|
||||||
else
|
|
||||||
echo "Error: Could not fetch latest version" >&2
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
fi
|
|
||||||
|
|
||||||
log_info "Target version: $TARGET_VERSION"
|
|
||||||
|
|
||||||
log_debug "Determining update path from $CURRENT_VERSION to $TARGET_VERSION"
|
|
||||||
|
|
||||||
log_info "Applying ArgoCD manifests"
|
|
||||||
log_verbose "Downloading manifest from https://raw.githubusercontent.com/argoproj/argo-cd/v${TARGET_VERSION}/manifests/install.yaml"
|
|
||||||
curl -sLO "https://raw.githubusercontent.com/argoproj/argo-cd/v${TARGET_VERSION}/manifests/install.yaml"
|
|
||||||
|
|
||||||
log_debug "Applying manifest with kubectl"
|
|
||||||
if [[ "$DRY_RUN" == true ]]; then
|
|
||||||
log_verbose "Dry-run mode: would apply manifest"
|
|
||||||
kubectl apply -n argocd -f install.yaml --dry-run=client
|
|
||||||
else
|
|
||||||
kubectl apply -n argocd -f install.yaml
|
|
||||||
fi
|
|
||||||
|
|
||||||
log_verbose "Cleaning up downloaded manifest"
|
|
||||||
rm -f install.yaml
|
|
||||||
|
|
||||||
log_info "Update to ArgoCD $TARGET_VERSION initiated"
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue