├── .helmignore ├── Chart.yaml ├── LICENSE ├── README.md ├── templates ├── _helpers.tpl ├── cluster.service.yaml ├── cluster.statefulset.yaml ├── ingress.yaml ├── ipfs.service.yaml ├── ipfs.statefulset.yaml ├── secret.yaml └── serviceaccount.yaml └── values.yaml /.helmignore: -------------------------------------------------------------------------------- 1 | # Patterns to ignore when building packages. 2 | # This supports shell glob matching, relative path matching, and 3 | # negation (prefixed with !). Only one pattern per line. 4 | .DS_Store 5 | # Common VCS dirs 6 | .git/ 7 | .gitignore 8 | .bzr/ 9 | .bzrignore 10 | .hg/ 11 | .hgignore 12 | .svn/ 13 | # Common backup files 14 | *.swp 15 | *.bak 16 | *.tmp 17 | *.orig 18 | *~ 19 | # Various IDEs 20 | .project 21 | .idea/ 22 | *.tmproj 23 | .vscode/ 24 | -------------------------------------------------------------------------------- /Chart.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v2 2 | name: ipfs-cluster 3 | description: A Helm chart for Kubernetes 4 | 5 | # A chart can be either an 'application' or a 'library' chart. 6 | # 7 | # Application charts are a collection of templates that can be packaged into versioned archives 8 | # to be deployed. 9 | # 10 | # Library charts provide useful utilities or functions for the chart developer. They're included as 11 | # a dependency of application charts to inject those utilities and functions into the rendering 12 | # pipeline. Library charts do not define any templates and therefore cannot be deployed. 13 | type: application 14 | 15 | # This is the chart version. This version number should be incremented each time you make changes 16 | # to the chart and its templates, including the app version. 17 | # Versions are expected to follow Semantic Versioning (https://semver.org/) 18 | version: 0.1.0 19 | 20 | # This is the version number of the application being deployed. This version number should be 21 | # incremented each time you make changes to the application. Versions are not expected to 22 | # follow Semantic Versioning. They should reflect the version the application is using. 23 | # It is recommended to use it with quotes. 24 | appVersion: "v0.14.2" 25 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2021 Monaparty Project 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # helm-ipfs-cluster 2 | A Helm chart for IPFS clusters. 3 | -------------------------------------------------------------------------------- /templates/_helpers.tpl: -------------------------------------------------------------------------------- 1 | {{/* 2 | Expand the name of the chart. 3 | */}} 4 | {{- define "helm-ipfs-cluster.name" -}} 5 | {{- default .Chart.Name .Values.nameOverride | trunc 63 | trimSuffix "-" }} 6 | {{- end }} 7 | 8 | {{/* 9 | Expand the name of the chart. 10 | */}} 11 | {{- define "helm-ipfs-cluster.ipfs-name" -}} 12 | {{- if .Values.fullnameOverride }} 13 | {{- printf "ipfs-%s" .Values.fullnameOverride | trunc 63 | trimSuffix "-" }} 14 | {{- else }} 15 | {{- $name := default .Chart.Name .Values.nameOverride }} 16 | {{- if contains $name .Release.Name }} 17 | {{- printf "ipfs-%s" .Release.Name | trunc 63 | trimSuffix "-" }} 18 | {{- else }} 19 | {{- printf "ipfs-%s-%s" .Release.Name $name | trunc 63 | trimSuffix "-" }} 20 | {{- end }} 21 | {{- end }} 22 | {{- end }} 23 | 24 | {{/* 25 | Create a default fully qualified app name. 26 | We truncate at 63 chars because some Kubernetes name fields are limited to this (by the DNS naming spec). 27 | If release name contains chart name it will be used as a full name. 28 | */}} 29 | {{- define "helm-ipfs-cluster.fullname" -}} 30 | {{- if .Values.fullnameOverride }} 31 | {{- .Values.fullnameOverride | trunc 63 | trimSuffix "-" }} 32 | {{- else }} 33 | {{- $name := default .Chart.Name .Values.nameOverride }} 34 | {{- if contains $name .Release.Name }} 35 | {{- .Release.Name | trunc 63 | trimSuffix "-" }} 36 | {{- else }} 37 | {{- printf "%s-%s" .Release.Name $name | trunc 63 | trimSuffix "-" }} 38 | {{- end }} 39 | {{- end }} 40 | {{- end }} 41 | 42 | {{/* 43 | Create chart name and version as used by the chart label. 44 | */}} 45 | {{- define "helm-ipfs-cluster.chart" -}} 46 | {{- printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" | trunc 63 | trimSuffix "-" }} 47 | {{- end }} 48 | 49 | {{/* 50 | Common labels 51 | */}} 52 | {{- define "helm-ipfs-cluster.labels" -}} 53 | helm.sh/chart: {{ include "helm-ipfs-cluster.chart" . }} 54 | {{ include "helm-ipfs-cluster.selectorLabels" . }} 55 | {{- if .Chart.AppVersion }} 56 | app.kubernetes.io/version: {{ .Chart.AppVersion | quote }} 57 | {{- end }} 58 | app.kubernetes.io/managed-by: {{ .Release.Service }} 59 | {{- end }} 60 | 61 | {{/* 62 | Selector labels 63 | */}} 64 | {{- define "helm-ipfs-cluster.selectorLabels" -}} 65 | app.kubernetes.io/name: {{ include "helm-ipfs-cluster.name" . }} 66 | app.kubernetes.io/instance: {{ .Release.Name }} 67 | {{- end }} 68 | 69 | {{/* 70 | Create the name of the service account to use 71 | */}} 72 | {{- define "helm-ipfs-cluster.serviceAccountName" -}} 73 | {{- if .Values.serviceAccount.create }} 74 | {{- default (include "helm-ipfs-cluster.fullname" .) .Values.serviceAccount.name }} 75 | {{- else }} 76 | {{- default "default" .Values.serviceAccount.name }} 77 | {{- end }} 78 | {{- end }} 79 | -------------------------------------------------------------------------------- /templates/cluster.service.yaml: -------------------------------------------------------------------------------- 1 | {{- range $i, $n := (until (int .Values.replicaCount)) -}} 2 | {{- if ne $i 0 }} 3 | --- 4 | {{- end }} 5 | apiVersion: v1 6 | kind: Service 7 | metadata: 8 | name: cluster-{{ $i }}-{{ include "helm-ipfs-cluster.name" $ }} 9 | labels: 10 | {{- include "helm-ipfs-cluster.selectorLabels" $ | nindent 4 }} 11 | nodeType: cluster 12 | spec: 13 | type: {{ $.Values.cluster.service.type | default $.Values.service.type }} 14 | ports: 15 | - port: 9096 16 | name: p2p 17 | # clusterIP: None 18 | selector: 19 | {{- include "helm-ipfs-cluster.selectorLabels" $ | nindent 4 }} 20 | nodeType: cluster 21 | {{- end }} 22 | -------------------------------------------------------------------------------- /templates/cluster.statefulset.yaml: -------------------------------------------------------------------------------- 1 | {{- range $i, $n := (until (int .Values.replicaCount)) -}} 2 | {{- if ne $i 0 }} 3 | --- 4 | {{- end }} 5 | apiVersion: apps/v1 6 | kind: StatefulSet 7 | metadata: 8 | name: cluster-{{ $i }}-{{ include "helm-ipfs-cluster.name" $ }} 9 | spec: 10 | serviceName: cluster-{{ $i }}-{{ include "helm-ipfs-cluster.name" $ }} 11 | replicas: 1 # must be `1`. 12 | selector: 13 | matchLabels: 14 | {{- include "helm-ipfs-cluster.selectorLabels" $ | nindent 6 }} 15 | nodeType: cluster 16 | template: 17 | metadata: 18 | labels: 19 | {{- include "helm-ipfs-cluster.selectorLabels" $ | nindent 8 }} 20 | nodeType: cluster 21 | spec: 22 | {{- with $.Values.cluster.imagePullSecrets }} 23 | imagePullSecrets: 24 | {{- toYaml . | nindent 8 }} 25 | {{- end }} 26 | serviceAccountName: {{ include "helm-ipfs-cluster.serviceAccountName" $ }} 27 | securityContext: 28 | {{- toYaml $.Values.cluster.podSecurityContext | nindent 8 }} 29 | containers: 30 | - name: cluster 31 | env: 32 | - name: CLUSTER_PEERNAME 33 | value: {{ printf "cluster-%d" $i }} 34 | {{- with $.Values.sharedSecret }} 35 | - name: CLUSTER_SECRET 36 | valueFrom: 37 | secretKeyRef: 38 | name: {{ include "helm-ipfs-cluster.fullname" $ }} 39 | key: secret 40 | {{- end }} 41 | - name: CLUSTER_IPFSHTTP_NODEMULTIADDRESS 42 | value: /dns4/{{ include "helm-ipfs-cluster.ipfs-name" $ }}-{{ $i }}.{{ include "helm-ipfs-cluster.ipfs-name" $ }}.{{ $.Release.Namespace }}.svc.cluster.local/tcp/5001 43 | - name: CLUSTER_CRDT_TRUSTEDPEERS 44 | value: '*' # Trust all peers in Cluster 45 | - name: CLUSTER_RESTAPI_HTTPLISTENMULTIADDRESS 46 | value: /ip4/0.0.0.0/tcp/9094 # Expose API 47 | - name: CLUSTER_MONITORPINGINTERVAL 48 | value: 2s # Speed up peer discovery 49 | image: "{{ $.Values.cluster.image.repository }}:{{ $.Values.cluster.image.tag | default $.Chart.AppVersion }}" 50 | ports: 51 | - containerPort: 9096 52 | name: p2p 53 | volumeMounts: 54 | - name: data 55 | mountPath: /data/ipfs-cluster 56 | resources: 57 | {{- toYaml $.Values.cluster.resources | nindent 12 }} 58 | {{- with $.Values.cluster.nodeSelector }} 59 | nodeSelector: 60 | {{- toYaml . | nindent 8 }} 61 | {{- end }} 62 | {{- with $.Values.cluster.affinity }} 63 | affinity: 64 | {{- toYaml . | nindent 8 }} 65 | {{- end }} 66 | {{- with $.Values.cluster.tolerations }} 67 | tolerations: 68 | {{- toYaml . | nindent 8 }} 69 | {{- end }} 70 | volumeClaimTemplates: 71 | - metadata: 72 | name: data 73 | spec: 74 | accessModes: [ "ReadWriteOnce" ] 75 | {{- with $.Values.cluster.storage.storageClassName }} 76 | storageClassName: {{ . }} 77 | {{- end }} 78 | resources: 79 | requests: 80 | storage: {{ $.Values.cluster.storage.volumeSize | default "1Gi" }} 81 | {{- end }} 82 | -------------------------------------------------------------------------------- /templates/ingress.yaml: -------------------------------------------------------------------------------- 1 | {{- if .Values.ingress.enabled -}} 2 | {{- $fullName := include "helm-ipfs-cluster.fullname" . -}} 3 | {{- $svcPort := .Values.ipfs.service.port -}} 4 | {{- if and .Values.ingress.className (not (semverCompare ">=1.18-0" .Capabilities.KubeVersion.GitVersion)) }} 5 | {{- if not (hasKey .Values.ingress.annotations "kubernetes.io/ingress.class") }} 6 | {{- $_ := set .Values.ingress.annotations "kubernetes.io/ingress.class" .Values.ingress.className}} 7 | {{- end }} 8 | {{- end }} 9 | {{- if semverCompare ">=1.19-0" .Capabilities.KubeVersion.GitVersion -}} 10 | apiVersion: networking.k8s.io/v1 11 | {{- else if semverCompare ">=1.14-0" .Capabilities.KubeVersion.GitVersion -}} 12 | apiVersion: networking.k8s.io/v1beta1 13 | {{- else -}} 14 | apiVersion: extensions/v1beta1 15 | {{- end }} 16 | kind: Ingress 17 | metadata: 18 | name: {{ $fullName }} 19 | labels: 20 | {{- include "helm-ipfs-cluster.labels" . | nindent 4 }} 21 | {{- with .Values.ingress.annotations }} 22 | annotations: 23 | {{- toYaml . | nindent 4 }} 24 | {{- end }} 25 | spec: 26 | {{- if and .Values.ingress.className (semverCompare ">=1.18-0" .Capabilities.KubeVersion.GitVersion) }} 27 | ingressClassName: {{ .Values.ingress.className }} 28 | {{- end }} 29 | {{- if .Values.ingress.tls }} 30 | tls: 31 | {{- range .Values.ingress.tls }} 32 | - hosts: 33 | {{- range .hosts }} 34 | - {{ . | quote }} 35 | {{- end }} 36 | secretName: {{ .secretName }} 37 | {{- end }} 38 | {{- end }} 39 | rules: 40 | {{- range .Values.ingress.hosts }} 41 | - host: {{ .host | quote }} 42 | http: 43 | paths: 44 | {{- range .paths }} 45 | - path: {{ .path }} 46 | {{- if and .pathType (semverCompare ">=1.18-0" $.Capabilities.KubeVersion.GitVersion) }} 47 | pathType: {{ .pathType }} 48 | {{- end }} 49 | backend: 50 | {{- if semverCompare ">=1.19-0" $.Capabilities.KubeVersion.GitVersion }} 51 | service: 52 | name: {{ $fullName }} 53 | port: 54 | number: {{ $svcPort }} 55 | {{- else }} 56 | serviceName: {{ $fullName }} 57 | servicePort: {{ $svcPort }} 58 | {{- end }} 59 | {{- end }} 60 | {{- end }} 61 | {{- end }} 62 | -------------------------------------------------------------------------------- /templates/ipfs.service.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Service 3 | metadata: 4 | name: {{ include "helm-ipfs-cluster.ipfs-name" . }} 5 | labels: 6 | {{- include "helm-ipfs-cluster.selectorLabels" . | nindent 4 }} 7 | nodeType: ipfs 8 | spec: 9 | type: {{ .Values.ipfs.service.type | default .Values.service.type }} 10 | ports: 11 | - port: 4001 12 | name: swarm 13 | - port: 5001 14 | name: api 15 | - port: 8080 16 | name: gateway 17 | # clusterIP: None 18 | selector: 19 | {{- include "helm-ipfs-cluster.selectorLabels" . | nindent 4 }} 20 | nodeType: ipfs 21 | -------------------------------------------------------------------------------- /templates/ipfs.statefulset.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: apps/v1 2 | kind: StatefulSet 3 | metadata: 4 | name: {{ include "helm-ipfs-cluster.ipfs-name" . }} 5 | spec: 6 | serviceName: {{ include "helm-ipfs-cluster.ipfs-name" . }} 7 | replicas: {{ .Values.replicaCount }} 8 | selector: 9 | matchLabels: 10 | {{- include "helm-ipfs-cluster.selectorLabels" . | nindent 6 }} 11 | nodeType: ipfs 12 | template: 13 | metadata: 14 | labels: 15 | {{- include "helm-ipfs-cluster.selectorLabels" . | nindent 8 }} 16 | nodeType: ipfs 17 | spec: 18 | {{- with .Values.ipfs.imagePullSecrets }} 19 | imagePullSecrets: 20 | {{- toYaml . | nindent 8 }} 21 | {{- end }} 22 | serviceAccountName: {{ include "helm-ipfs-cluster.serviceAccountName" . }} 23 | securityContext: 24 | {{- toYaml .Values.ipfs.podSecurityContext | nindent 8 }} 25 | containers: 26 | - name: ipfs 27 | image: {{ .Values.ipfs.image.repository }}:{{ .Values.ipfs.image.tag | default "latest" }} 28 | ports: 29 | - containerPort: 4001 30 | name: swarm 31 | - containerPort: 5001 32 | name: api 33 | - containerPort: 8080 34 | name: gateway 35 | - containerPort: 5353 36 | name: zeroconf 37 | protocol: UDP 38 | # livenessProbe: 39 | # httpGet: 40 | # path: / 41 | # port: gateway 42 | # readinessProbe: 43 | # httpGet: 44 | # path: / 45 | # port: gateway 46 | volumeMounts: 47 | - name: data 48 | mountPath: /data/ipfs 49 | resources: 50 | {{- toYaml .Values.ipfs.resources | nindent 12 }} 51 | {{- with .Values.ipfs.nodeSelector }} 52 | nodeSelector: 53 | {{- toYaml . | nindent 8 }} 54 | {{- end }} 55 | {{- with .Values.ipfs.affinity }} 56 | affinity: 57 | {{- toYaml . | nindent 8 }} 58 | {{- end }} 59 | {{- with .Values.ipfs.tolerations }} 60 | tolerations: 61 | {{- toYaml . | nindent 8 }} 62 | {{- end }} 63 | volumeClaimTemplates: 64 | - metadata: 65 | name: data 66 | spec: 67 | accessModes: [ "ReadWriteOnce" ] 68 | {{- with .Values.ipfs.storage.storageClassName }} 69 | storageClassName: {{ . }} 70 | {{- end }} 71 | resources: 72 | requests: 73 | storage: {{ .Values.ipfs.storage.volumeSize | default "1Gi" }} 74 | -------------------------------------------------------------------------------- /templates/secret.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Secret 3 | metadata: 4 | name: {{ include "helm-ipfs-cluster.fullname" . }} 5 | type: Opaque 6 | data: 7 | {{- with .Values.sharedSecret }} 8 | secret: {{ . | b64enc }} 9 | {{- end }} 10 | -------------------------------------------------------------------------------- /templates/serviceaccount.yaml: -------------------------------------------------------------------------------- 1 | {{- if .Values.serviceAccount.create -}} 2 | apiVersion: v1 3 | kind: ServiceAccount 4 | metadata: 5 | name: {{ include "helm-ipfs-cluster.serviceAccountName" . }} 6 | labels: 7 | {{- include "helm-ipfs-cluster.labels" . | nindent 4 }} 8 | {{- with .Values.serviceAccount.annotations }} 9 | annotations: 10 | {{- toYaml . | nindent 4 }} 11 | {{- end }} 12 | {{- end }} 13 | -------------------------------------------------------------------------------- /values.yaml: -------------------------------------------------------------------------------- 1 | # Default values for helm-ipfs-cluster. 2 | # This is a YAML-formatted file. 3 | # Declare variables to be passed into your templates. 4 | 5 | replicaCount: 2 6 | 7 | cluster: 8 | image: 9 | repository: ipfs/ipfs-cluster 10 | pullPolicy: IfNotPresent 11 | # Overrides the image tag whose default is the chart appVersion. 12 | tag: "" 13 | imagePullSecrets: [] 14 | nameOverride: "" 15 | podSecurityContext: {} 16 | # fsGroup: 2000 17 | 18 | resources: {} 19 | # We usually recommend not to specify default resources and to leave this as a conscious 20 | # choice for the user. This also increases chances charts run on environments with little 21 | # resources, such as Minikube. If you do want to specify resources, uncomment the following 22 | # lines, adjust them as necessary, and remove the curly braces after 'resources:'. 23 | # limits: 24 | # cpu: 100m 25 | # memory: 128Mi 26 | # requests: 27 | # cpu: 100m 28 | # memory: 128Mi 29 | 30 | nodeSelector: {} 31 | 32 | tolerations: [] 33 | 34 | affinity: {} 35 | 36 | storage: 37 | storageClassName: "" 38 | volumeSize: "" # "1Gi" 39 | 40 | service: 41 | type: "" 42 | 43 | ipfs: 44 | image: 45 | repository: ipfs/go-ipfs 46 | pullPolicy: IfNotPresent 47 | # Overrides the image tag whose default is `latest`. 48 | tag: "" 49 | imagePullSecrets: [] 50 | nameOverride: "" 51 | podSecurityContext: {} 52 | # fsGroup: 2000 53 | 54 | resources: {} 55 | # We usually recommend not to specify default resources and to leave this as a conscious 56 | # choice for the user. This also increases chances charts run on environments with little 57 | # resources, such as Minikube. If you do want to specify resources, uncomment the following 58 | # lines, adjust them as necessary, and remove the curly braces after 'resources:'. 59 | # limits: 60 | # cpu: 100m 61 | # memory: 128Mi 62 | # requests: 63 | # cpu: 100m 64 | # memory: 128Mi 65 | 66 | nodeSelector: {} 67 | 68 | tolerations: [] 69 | 70 | affinity: {} 71 | 72 | storage: 73 | storageClassName: "" 74 | volumeSize: "" # "1Gi" 75 | 76 | service: 77 | type: ClusterIP 78 | 79 | fullnameOverride: "" 80 | 81 | sharedSecret: "" 82 | 83 | serviceAccount: 84 | # Specifies whether a service account should be created 85 | create: true 86 | # Annotations to add to the service account 87 | annotations: {} 88 | # The name of the service account to use. 89 | # If not set and create is true, a name is generated using the fullname template 90 | name: "" 91 | 92 | podAnnotations: {} 93 | 94 | securityContext: {} 95 | # capabilities: 96 | # drop: 97 | # - ALL 98 | # readOnlyRootFilesystem: true 99 | # runAsNonRoot: true 100 | # runAsUser: 1000 101 | 102 | # `service.type` may be overridden by `cluster.service.type` and/or `ipfs.sercive.type`. 103 | service: 104 | type: ClusterIP 105 | 106 | ingress: 107 | enabled: false 108 | className: "" 109 | annotations: {} 110 | # kubernetes.io/ingress.class: nginx 111 | # kubernetes.io/tls-acme: "true" 112 | hosts: 113 | - host: chart-example.local 114 | paths: 115 | - path: / 116 | pathType: ImplementationSpecific 117 | tls: [] 118 | # - secretName: chart-example-tls 119 | # hosts: 120 | # - chart-example.local 121 | 122 | 123 | 124 | --------------------------------------------------------------------------------