Skip to content

Commit f1af9b8

Browse files
authored
Merge pull request #21 from vshn/feat/rclone-chart
Add Helm chart for rclone as an S3 encryption proxy
2 parents 3a46f56 + 624e184 commit f1af9b8

File tree

7 files changed

+366
-0
lines changed

7 files changed

+366
-0
lines changed

README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ helm repo add appcat https://charts.appcat.ch
1515

1616
| Downloads & Changelog | Chart |
1717
| --- | --- |
18+
| [![chart downloads](https://img.shields.io/github/downloads/vshn/appcat-charts/rcloneproxy-0.0.1/total)](https://github.com/vshn/appcat-charts/releases/tag/rcloneproxy-0.0.1) | [rcloneproxy](charts/rcloneproxy/README.md) |
1819
| [![chart downloads](https://img.shields.io/github/downloads/vshn/appcat-charts/vshnmariadb-0.0.12/total)](https://github.com/vshn/appcat-charts/releases/tag/vshnmariadb-0.0.12) | [vshnmariadb](charts/vshnmariadb/README.md) |
1920
| [![chart downloads](https://img.shields.io/github/downloads/vshn/appcat-charts/vshnpostgresql-0.6.0/total)](https://github.com/vshn/appcat-charts/releases/tag/vshnpostgresql-0.6.0) | [vshnpostgresql](charts/vshnpostgresql/README.md) |
2021

charts/rcloneproxy/Chart.yaml

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
apiVersion: v2
2+
name: rcloneproxy
3+
description: A Helm chart for deploying rclone as an intermediate s3 proxy
4+
type: application
5+
version: 0.0.1
6+
maintainers:
7+
- name: Schedar Team
8+
email: info@vshn.ch

charts/rcloneproxy/README.md

Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
# rcloneproxy
2+
3+
![Version: 0.0.1](https://img.shields.io/badge/Version-0.0.1-informational?style=flat-square) ![Type: application](https://img.shields.io/badge/Type-application-informational?style=flat-square)
4+
5+
A Helm chart for deploying rclone as an intermediate s3 proxy
6+
7+
## Installation
8+
9+
```bash
10+
helm repo add appcat https://charts.appcat.ch
11+
helm install rcloneproxy vshn/rcloneproxy
12+
```
13+
14+
<!---
15+
Common/Useful Link references from values.yaml
16+
-->
17+
[resource-units]: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/#resource-units-in-kubernetes
18+
[prometheus-operator]: https://github.com/coreos/prometheus-operator
19+
# rcloneproxy
20+
21+
![Version: 0.0.1](https://img.shields.io/badge/Version-0.0.1-informational?style=flat-square) ![Type: application](https://img.shields.io/badge/Type-application-informational?style=flat-square)
22+
23+
A Helm chart for deploying rclone as an intermediate s3 proxy
24+
25+
## Maintainers
26+
27+
| Name | Email | Url |
28+
| ---- | ------ | --- |
29+
| Schedar Team | <info@vshn.ch> | |
30+
31+
## Values
32+
33+
| Key | Type | Default | Description |
34+
|-----|------|---------|-------------|
35+
| backend | object | `{"secretRef":{"keys":{"accessKeyID":"access-key-id","accessKeySecret":"access-key-secret","bucket":"bucket","endpoint":"endpoint","region":"region"},"name":""}}` | Backend S3 storage configuration |
36+
| backend.secretRef | object | `{"keys":{"accessKeyID":"access-key-id","accessKeySecret":"access-key-secret","bucket":"bucket","endpoint":"endpoint","region":"region"},"name":""}` | Reference to an existing secret containing backend S3 credentials |
37+
| backend.secretRef.keys | object | `{"accessKeyID":"access-key-id","accessKeySecret":"access-key-secret","bucket":"bucket","endpoint":"endpoint","region":"region"}` | Keys in the secret for each configuration value |
38+
| backend.secretRef.keys.accessKeyID | string | `"access-key-id"` | Key for S3 access key ID |
39+
| backend.secretRef.keys.accessKeySecret | string | `"access-key-secret"` | Key for S3 access key secret |
40+
| backend.secretRef.keys.bucket | string | `"bucket"` | Key for S3 bucket name |
41+
| backend.secretRef.keys.endpoint | string | `"endpoint"` | Key for S3 endpoint URL |
42+
| backend.secretRef.keys.region | string | `"region"` | Key for S3 region |
43+
| backend.secretRef.name | string | `""` | Name of the secret containing backend credentials |
44+
| containerSecurityContext | object | `{"allowPrivilegeEscalation":false,"capabilities":{"drop":["ALL"]},"enabled":true,"readOnlyRootFilesystem":false,"runAsNonRoot":true,"runAsUser":65532}` | Container security context configuration |
45+
| containerSecurityContext.allowPrivilegeEscalation | bool | `false` | Disallow privilege escalation |
46+
| containerSecurityContext.capabilities | object | `{"drop":["ALL"]}` | Linux capabilities to drop |
47+
| containerSecurityContext.enabled | bool | `true` | Enable container security context |
48+
| containerSecurityContext.readOnlyRootFilesystem | bool | `false` | Read-only root filesystem |
49+
| containerSecurityContext.runAsNonRoot | bool | `true` | Run as non-root user |
50+
| containerSecurityContext.runAsUser | int | `65532` | User ID to run the container |
51+
| image.pullPolicy | string | `"IfNotPresent"` | Image pull policy |
52+
| image.repository | string | `"ghcr.io/rclone/rclone"` | Image repository for rclone |
53+
| image.tag | string | `"1.73.0"` | Configure the image tag |
54+
| podSecurityContext | object | `{"enabled":true,"fsGroup":65532,"fsGroupChangePolicy":"OnRootMismatch","seLinuxOptions":{}}` | Pod security context configuration |
55+
| podSecurityContext.enabled | bool | `true` | Enable pod security context |
56+
| podSecurityContext.fsGroup | int | `65532` | FSGroup for volume ownership |
57+
| podSecurityContext.fsGroupChangePolicy | string | `"OnRootMismatch"` | FSGroupChangePolicy for volume ownership changes |
58+
| podSecurityContext.seLinuxOptions | object | `{}` | SELinux options for OpenShift compatibility |
59+
| replicaCount | int | `1` | Number of replicas |
60+
| resources | object | `{"limits":{"cpu":"25m","memory":"512Mi"},"requests":{"cpu":"10m","memory":"256Mi"}}` | Resource requests and limits |
61+
| service | object | `{"port":9095,"type":"ClusterIP"}` | Service configuration |
62+
| service.port | int | `9095` | Service port (rclone S3 server port) |
63+
| service.type | string | `"ClusterIP"` | Service type |
64+
Lines changed: 181 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,181 @@
1+
apiVersion: apps/v1
2+
kind: Deployment
3+
metadata:
4+
name: rcloneproxy
5+
labels:
6+
app: rcloneproxy
7+
spec:
8+
replicas: {{ .Values.replicaCount }}
9+
selector:
10+
matchLabels:
11+
app: rcloneproxy
12+
template:
13+
metadata:
14+
labels:
15+
app: rcloneproxy
16+
spec:
17+
{{- if .Values.podSecurityContext.enabled }}
18+
securityContext:
19+
{{- if .Values.podSecurityContext.fsGroup }}
20+
fsGroup: {{ .Values.podSecurityContext.fsGroup }}
21+
{{- end }}
22+
{{- if .Values.podSecurityContext.fsGroupChangePolicy }}
23+
fsGroupChangePolicy: {{ .Values.podSecurityContext.fsGroupChangePolicy }}
24+
{{- end }}
25+
{{- if .Values.podSecurityContext.seLinuxOptions }}
26+
seLinuxOptions:
27+
{{- toYaml .Values.podSecurityContext.seLinuxOptions | nindent 10 }}
28+
{{- end }}
29+
{{- end }}
30+
initContainers:
31+
- name: generate-config
32+
image: "{{ .Values.image.repository }}:{{ .Values.image.tag }}"
33+
imagePullPolicy: {{ .Values.image.pullPolicy }}
34+
{{- if .Values.containerSecurityContext.enabled }}
35+
securityContext:
36+
{{- if .Values.containerSecurityContext.runAsUser }}
37+
runAsUser: {{ .Values.containerSecurityContext.runAsUser }}
38+
{{- end }}
39+
{{- if .Values.containerSecurityContext.runAsNonRoot }}
40+
runAsNonRoot: {{ .Values.containerSecurityContext.runAsNonRoot }}
41+
{{- end }}
42+
{{- if ne .Values.containerSecurityContext.allowPrivilegeEscalation nil }}
43+
allowPrivilegeEscalation: {{ .Values.containerSecurityContext.allowPrivilegeEscalation }}
44+
{{- end }}
45+
{{- if ne .Values.containerSecurityContext.readOnlyRootFilesystem nil }}
46+
readOnlyRootFilesystem: {{ .Values.containerSecurityContext.readOnlyRootFilesystem }}
47+
{{- end }}
48+
{{- if .Values.containerSecurityContext.capabilities }}
49+
capabilities:
50+
{{- toYaml .Values.containerSecurityContext.capabilities | nindent 14 }}
51+
{{- end }}
52+
{{- end }}
53+
command:
54+
- /bin/sh
55+
- -c
56+
args:
57+
- |
58+
set -e
59+
# Obscure the encryption passwords
60+
OBSCURED_PASSWORD=$(echo -n "$ENCRYPTION_PASSWORD" | rclone obscure -)
61+
OBSCURED_PASSWORD2=$(echo -n "$ENCRYPTION_PASSWORD2" | rclone obscure -)
62+
63+
# Generate rclone.conf with obscured passwords
64+
cat > /config/rclone/rclone.conf <<EOF
65+
[target]
66+
type = s3
67+
provider = Other
68+
env_auth = false
69+
access_key_id = $BACKEND_ACCESS_KEY_ID
70+
secret_access_key = $BACKEND_SECRET_ACCESS_KEY
71+
endpoint = $BACKEND_ENDPOINT
72+
region = $BACKEND_REGION
73+
location_constraint = $BACKEND_REGION
74+
force_path_style = true
75+
76+
[s3-crypt]
77+
type = crypt
78+
remote = target:$BACKEND_BUCKET
79+
filename_encryption = standard
80+
directory_name_encryption = true
81+
password = $OBSCURED_PASSWORD
82+
password2 = $OBSCURED_PASSWORD2
83+
EOF
84+
85+
echo "Generated rclone.conf with obscured passwords"
86+
env:
87+
- name: BACKEND_ACCESS_KEY_ID
88+
valueFrom:
89+
secretKeyRef:
90+
name: {{ .Values.backend.secretRef.name }}
91+
key: {{ .Values.backend.secretRef.keys.accessKeyID }}
92+
- name: BACKEND_SECRET_ACCESS_KEY
93+
valueFrom:
94+
secretKeyRef:
95+
name: {{ .Values.backend.secretRef.name }}
96+
key: {{ .Values.backend.secretRef.keys.accessKeySecret }}
97+
- name: BACKEND_ENDPOINT
98+
valueFrom:
99+
secretKeyRef:
100+
name: {{ .Values.backend.secretRef.name }}
101+
key: {{ .Values.backend.secretRef.keys.endpoint }}
102+
- name: BACKEND_REGION
103+
valueFrom:
104+
secretKeyRef:
105+
name: {{ .Values.backend.secretRef.name }}
106+
key: {{ .Values.backend.secretRef.keys.region }}
107+
- name: BACKEND_BUCKET
108+
valueFrom:
109+
secretKeyRef:
110+
name: {{ .Values.backend.secretRef.name }}
111+
key: {{ .Values.backend.secretRef.keys.bucket }}
112+
- name: ENCRYPTION_PASSWORD
113+
valueFrom:
114+
secretKeyRef:
115+
name: rcloneproxy-encryption-key
116+
key: password
117+
- name: ENCRYPTION_PASSWORD2
118+
valueFrom:
119+
secretKeyRef:
120+
name: rcloneproxy-encryption-key
121+
key: password2
122+
volumeMounts:
123+
- name: rclone-config
124+
mountPath: /config/rclone
125+
containers:
126+
- name: rcloneproxy
127+
image: "{{ .Values.image.repository }}:{{ .Values.image.tag }}"
128+
imagePullPolicy: {{ .Values.image.pullPolicy }}
129+
{{- if .Values.containerSecurityContext.enabled }}
130+
securityContext:
131+
{{- if .Values.containerSecurityContext.runAsUser }}
132+
runAsUser: {{ .Values.containerSecurityContext.runAsUser }}
133+
{{- end }}
134+
{{- if .Values.containerSecurityContext.runAsNonRoot }}
135+
runAsNonRoot: {{ .Values.containerSecurityContext.runAsNonRoot }}
136+
{{- end }}
137+
{{- if ne .Values.containerSecurityContext.allowPrivilegeEscalation nil }}
138+
allowPrivilegeEscalation: {{ .Values.containerSecurityContext.allowPrivilegeEscalation }}
139+
{{- end }}
140+
{{- if ne .Values.containerSecurityContext.readOnlyRootFilesystem nil }}
141+
readOnlyRootFilesystem: {{ .Values.containerSecurityContext.readOnlyRootFilesystem }}
142+
{{- end }}
143+
{{- if .Values.containerSecurityContext.capabilities }}
144+
capabilities:
145+
{{- toYaml .Values.containerSecurityContext.capabilities | nindent 14 }}
146+
{{- end }}
147+
{{- end }}
148+
command:
149+
- /bin/sh
150+
- -c
151+
args:
152+
- |
153+
rclone serve s3 s3-crypt: --addr :{{ .Values.service.port }} --auth-key "${BACKEND_ACCESS_KEY_ID},${BACKEND_SECRET_ACCESS_KEY}"
154+
env:
155+
- name: RCLONE_CONFIG
156+
value: /config/rclone/rclone.conf
157+
- name: BACKEND_ACCESS_KEY_ID
158+
valueFrom:
159+
secretKeyRef:
160+
name: {{ .Values.backend.secretRef.name }}
161+
key: {{ .Values.backend.secretRef.keys.accessKeyID }}
162+
- name: BACKEND_SECRET_ACCESS_KEY
163+
valueFrom:
164+
secretKeyRef:
165+
name: {{ .Values.backend.secretRef.name }}
166+
key: {{ .Values.backend.secretRef.keys.accessKeySecret }}
167+
ports:
168+
- name: s3
169+
containerPort: {{ .Values.service.port }}
170+
protocol: TCP
171+
resources:
172+
{{- toYaml .Values.resources | nindent 12 }}
173+
volumeMounts:
174+
- name: rclone-config
175+
mountPath: /config/rclone
176+
readOnly: true
177+
stdin: true
178+
tty: true
179+
volumes:
180+
- name: rclone-config
181+
emptyDir: {}
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
{{- $existingSecret := lookup "v1" "Secret" .Release.Namespace "rcloneproxy-encryption-key" -}}
2+
{{- $encryptionPassword := "" -}}
3+
{{- $encryptionPassword2 := "" -}}
4+
{{- if $existingSecret -}}
5+
{{- $encryptionPassword = index $existingSecret.data "password" | b64dec -}}
6+
{{- $encryptionPassword2 = index $existingSecret.data "password2" | b64dec -}}
7+
{{- else -}}
8+
{{- $encryptionPassword = randAlphaNum 32 -}}
9+
{{- $encryptionPassword2 = randAlphaNum 32 -}}
10+
{{- end -}}
11+
---
12+
apiVersion: v1
13+
kind: Secret
14+
metadata:
15+
name: rcloneproxy-encryption-key
16+
labels:
17+
app: rcloneproxy
18+
annotations:
19+
helm.sh/resource-policy: keep
20+
type: Opaque
21+
stringData:
22+
password: "{{ $encryptionPassword }}"
23+
password2: "{{ $encryptionPassword2 }}"
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
apiVersion: v1
2+
kind: Service
3+
metadata:
4+
name: rcloneproxy
5+
labels:
6+
app: rcloneproxy
7+
spec:
8+
type: {{ .Values.service.type }}
9+
ports:
10+
- port: {{ .Values.service.port }}
11+
targetPort: s3
12+
protocol: TCP
13+
name: s3
14+
selector:
15+
app: rcloneproxy

charts/rcloneproxy/values.yaml

Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,74 @@
1+
image:
2+
# -- Image repository for rclone
3+
repository: ghcr.io/rclone/rclone
4+
# -- Configure the image tag
5+
tag: "1.73.0"
6+
# -- Image pull policy
7+
pullPolicy: IfNotPresent
8+
9+
# -- Number of replicas
10+
replicaCount: 1
11+
12+
# -- Service configuration
13+
service:
14+
# -- Service type
15+
type: ClusterIP
16+
# -- Service port (rclone S3 server port)
17+
port: 9095
18+
19+
# -- Backend S3 storage configuration
20+
backend:
21+
# -- Reference to an existing secret containing backend S3 credentials
22+
secretRef:
23+
# -- Name of the secret containing backend credentials
24+
name: ""
25+
# -- Keys in the secret for each configuration value
26+
keys:
27+
# -- Key for S3 access key ID
28+
accessKeyID: "access-key-id"
29+
# -- Key for S3 access key secret
30+
accessKeySecret: "access-key-secret"
31+
# -- Key for S3 endpoint URL
32+
endpoint: "endpoint"
33+
# -- Key for S3 region
34+
region: "region"
35+
# -- Key for S3 bucket name
36+
bucket: "bucket"
37+
38+
# -- Resource requests and limits
39+
resources:
40+
requests:
41+
memory: "256Mi"
42+
cpu: "10m"
43+
limits:
44+
memory: "512Mi"
45+
cpu: "25m"
46+
47+
# -- Pod security context configuration
48+
podSecurityContext:
49+
# -- Enable pod security context
50+
enabled: true
51+
# -- FSGroup for volume ownership
52+
fsGroup: 65532
53+
# -- FSGroupChangePolicy for volume ownership changes
54+
fsGroupChangePolicy: "OnRootMismatch"
55+
# -- SELinux options for OpenShift compatibility
56+
seLinuxOptions: {}
57+
# type: "spc_t"
58+
59+
# -- Container security context configuration
60+
containerSecurityContext:
61+
# -- Enable container security context
62+
enabled: true
63+
# -- Run as non-root user
64+
runAsNonRoot: true
65+
# -- User ID to run the container
66+
runAsUser: 65532
67+
# -- Disallow privilege escalation
68+
allowPrivilegeEscalation: false
69+
# -- Read-only root filesystem
70+
readOnlyRootFilesystem: false
71+
# -- Linux capabilities to drop
72+
capabilities:
73+
drop:
74+
- ALL

0 commit comments

Comments
 (0)