Archify Sync server, Dockerfile and Helm chart

Rust server (axum, yrs, sqlx/PostgreSQL): live shared models over the y-websocket protocol, versions, browser sign-in with PKCE, invites, single sign-on through OIDC, metrics. Docker image on distroless, compose file, and a Helm chart with one pod, optional bundled PostgreSQL and secrets from existing Secrets.
This commit is contained in:
root-at-skic committed 2026-11-06 12:06:59 +02:00
commit 5c43b90ef8
67 files changed
+8362

No files matched your search

+8
View File
@@ -0,0 +1,8 @@
Archify Sync is starting at {{ .Values.publicUrl }}
On the first start the server prints a one-time setup code:
kubectl -n {{ .Release.Namespace }} logs deploy/{{ include "archify-sync.fullname" . }} | grep "with code"
Open {{ .Values.publicUrl }}/setup, enter the code and create the first admin.
Then in VS Code: "Archify | Sign in to Sync Server" with {{ .Values.publicUrl }}.
@@ -0,0 +1,45 @@
{{- define "archify-sync.fullname" -}}
{{- if contains .Chart.Name .Release.Name -}}
{{- .Release.Name | trunc 63 | trimSuffix "-" -}}
{{- else -}}
{{- printf "%s-%s" .Release.Name .Chart.Name | trunc 63 | trimSuffix "-" -}}
{{- end -}}
{{- end -}}
{{- define "archify-sync.labels" -}}
helm.sh/chart: {{ printf "%s-%s" .Chart.Name .Chart.Version }}
app.kubernetes.io/managed-by: {{ .Release.Service }}
app.kubernetes.io/part-of: archify-sync
app.kubernetes.io/version: {{ .Chart.AppVersion | quote }}
{{- end -}}
{{- define "archify-sync.selector" -}}
app.kubernetes.io/name: archify-sync
app.kubernetes.io/instance: {{ .Release.Name }}
{{- end -}}
{{- define "archify-sync.dbSelector" -}}
app.kubernetes.io/name: archify-sync-postgresql
app.kubernetes.io/instance: {{ .Release.Name }}
{{- end -}}
{{/* The Secret and key that hold the database URL. */}}
{{- define "archify-sync.dbSecret" -}}
{{- if and .Values.postgresql.enabled .Values.postgresql.existingSecret -}}
{{ .Values.postgresql.existingSecret }}
{{- else if .Values.postgresql.enabled -}}
{{ include "archify-sync.fullname" . }}-postgresql
{{- else if .Values.database.existingSecret -}}
{{ .Values.database.existingSecret }}
{{- else -}}
{{ include "archify-sync.fullname" . }}-database
{{- end -}}
{{- end -}}
{{- define "archify-sync.dbSecretKey" -}}
{{- if or .Values.postgresql.enabled (not .Values.database.existingSecret) -}}
url
{{- else -}}
{{ .Values.database.existingSecretKey }}
{{- end -}}
{{- end -}}
@@ -0,0 +1,151 @@
{{- if not (or .Values.postgresql.enabled .Values.database.existingSecret .Values.database.url) }}
{{- fail "Set database.url, database.existingSecret or postgresql.enabled" }}
{{- end }}
apiVersion: apps/v1
kind: Deployment
metadata:
name: {{ include "archify-sync.fullname" . }}
labels:
{{- include "archify-sync.labels" . | nindent 4 }}
{{- include "archify-sync.selector" . | nindent 4 }}
spec:
# One server holds the live copy of each space; see values.yaml.
replicas: 1
strategy:
type: Recreate
selector:
matchLabels:
{{- include "archify-sync.selector" . | nindent 6 }}
template:
metadata:
labels:
{{- include "archify-sync.labels" . | nindent 8 }}
{{- include "archify-sync.selector" . | nindent 8 }}
{{- with .Values.podAnnotations }}
annotations:
{{- toYaml . | nindent 8 }}
{{- end }}
spec:
{{- with .Values.imagePullSecrets }}
imagePullSecrets:
{{- toYaml . | nindent 8 }}
{{- end }}
automountServiceAccountToken: false
# Leaving stores a snapshot of every open space.
terminationGracePeriodSeconds: 30
securityContext:
runAsNonRoot: true
runAsUser: 65532
runAsGroup: 65532
seccompProfile:
type: RuntimeDefault
containers:
- name: server
image: "{{ .Values.image.repository }}:{{ .Values.image.tag | default .Chart.AppVersion }}"
imagePullPolicy: {{ .Values.image.pullPolicy }}
securityContext:
allowPrivilegeEscalation: false
readOnlyRootFilesystem: true
capabilities:
drop: [ALL]
ports:
- name: http
containerPort: 8080
{{- if .Values.metrics.enabled }}
- name: metrics
containerPort: {{ .Values.metrics.port }}
{{- end }}
env:
- name: ARCHIFY_SYNC_DATABASE_URL
valueFrom:
secretKeyRef:
name: {{ include "archify-sync.dbSecret" . }}
key: {{ include "archify-sync.dbSecretKey" . }}
- name: ARCHIFY_SYNC_DATABASE_MAX_CONNECTIONS
value: {{ .Values.database.maxConnections | quote }}
- name: ARCHIFY_SYNC_LISTEN
value: "0.0.0.0:8080"
- name: ARCHIFY_SYNC_PUBLIC_URL
value: {{ .Values.publicUrl | quote }}
- name: ARCHIFY_SYNC_NAME
value: {{ .Values.config.name | quote }}
- name: ARCHIFY_SYNC_SNAPSHOT_IDLE_SECS
value: {{ .Values.config.snapshotIdleSecs | quote }}
- name: ARCHIFY_SYNC_SNAPSHOT_MAX_SECS
value: {{ .Values.config.snapshotMaxSecs | quote }}
- name: ARCHIFY_SYNC_SNAPSHOT_MAX_EDITS
value: {{ .Values.config.snapshotMaxEdits | quote }}
- name: ARCHIFY_SYNC_INVITE_HOURS
value: {{ .Values.config.inviteHours | quote }}
- name: ARCHIFY_SYNC_MEMBERS_CAN_INVITE
value: {{ .Values.config.membersCanInvite | quote }}
- name: ARCHIFY_SYNC_ACCESS_TTL_SECS
value: {{ .Values.config.accessTtlSecs | quote }}
- name: ARCHIFY_SYNC_REFRESH_TTL_DAYS
value: {{ .Values.config.refreshTtlDays | quote }}
- name: ARCHIFY_SYNC_REFRESH_GRACE_SECS
value: {{ .Values.config.refreshGraceSecs | quote }}
- name: ARCHIFY_SYNC_REDIRECT_SCHEMES
value: {{ .Values.config.redirectSchemes | quote }}
- name: ARCHIFY_SYNC_MAX_MESSAGE_BYTES
value: {{ .Values.config.maxMessageBytes | int64 | quote }}
- name: ARCHIFY_SYNC_LOG_JSON
value: {{ .Values.config.logJson | quote }}
{{- if .Values.metrics.enabled }}
- name: ARCHIFY_SYNC_METRICS_LISTEN
value: "0.0.0.0:{{ .Values.metrics.port }}"
{{- end }}
{{- with .Values.oidc }}
{{- if .enabled }}
- name: ARCHIFY_SYNC_OIDC_ISSUER
value: {{ required "oidc.issuer is required when oidc.enabled" .issuer | quote }}
- name: ARCHIFY_SYNC_OIDC_CLIENT_ID
value: {{ .clientId | quote }}
{{- if .existingSecret }}
- name: ARCHIFY_SYNC_OIDC_CLIENT_SECRET
valueFrom:
secretKeyRef:
name: {{ .existingSecret }}
key: {{ .existingSecretKey }}
{{- end }}
- name: ARCHIFY_SYNC_OIDC_LABEL
value: {{ .label | quote }}
- name: ARCHIFY_SYNC_OIDC_SCOPES
value: {{ .scopes | quote }}
- name: ARCHIFY_SYNC_OIDC_GROUPS_CLAIM
value: {{ .groupsClaim | quote }}
- name: ARCHIFY_SYNC_OIDC_ALLOWED_GROUPS
value: {{ join "," .allowedGroups | quote }}
- name: ARCHIFY_SYNC_OIDC_ADMIN_GROUPS
value: {{ join "," .adminGroups | quote }}
{{- end }}
{{- end }}
- name: RUST_LOG
value: {{ .Values.config.logLevel | quote }}
{{- with .Values.extraEnv }}
{{- toYaml . | nindent 12 }}
{{- end }}
startupProbe:
httpGet: { path: /healthz, port: http }
periodSeconds: 2
failureThreshold: 60
livenessProbe:
httpGet: { path: /healthz, port: http }
periodSeconds: 10
readinessProbe:
httpGet: { path: /readyz, port: http }
periodSeconds: 5
resources:
{{- toYaml .Values.resources | nindent 12 }}
{{- with .Values.nodeSelector }}
nodeSelector:
{{- toYaml . | nindent 8 }}
{{- end }}
{{- with .Values.tolerations }}
tolerations:
{{- toYaml . | nindent 8 }}
{{- end }}
{{- with .Values.affinity }}
affinity:
{{- toYaml . | nindent 8 }}
{{- end }}
@@ -0,0 +1,31 @@
{{- if .Values.ingress.enabled }}
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: {{ include "archify-sync.fullname" . }}
labels:
{{- include "archify-sync.labels" . | nindent 4 }}
{{- with .Values.ingress.annotations }}
annotations:
{{- toYaml . | nindent 4 }}
{{- end }}
spec:
{{- with .Values.ingress.className }}
ingressClassName: {{ . }}
{{- end }}
{{- with .Values.ingress.tls }}
tls:
{{- toYaml . | nindent 4 }}
{{- end }}
rules:
- host: {{ .Values.ingress.host | quote }}
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: {{ include "archify-sync.fullname" . }}
port:
name: http
{{- end }}
@@ -0,0 +1,34 @@
{{- if .Values.metrics.enabled }}
apiVersion: v1
kind: Service
metadata:
name: {{ include "archify-sync.fullname" . }}-metrics
labels:
{{- include "archify-sync.labels" . | nindent 4 }}
app.kubernetes.io/component: metrics
spec:
type: ClusterIP
selector:
{{- include "archify-sync.selector" . | nindent 4 }}
ports:
- name: metrics
port: {{ .Values.metrics.port }}
targetPort: metrics
{{- if .Values.metrics.serviceMonitor.enabled }}
---
apiVersion: monitoring.coreos.com/v1
kind: ServiceMonitor
metadata:
name: {{ include "archify-sync.fullname" . }}
labels:
{{- include "archify-sync.labels" . | nindent 4 }}
spec:
selector:
matchLabels:
app.kubernetes.io/component: metrics
app.kubernetes.io/instance: {{ .Release.Name }}
endpoints:
- port: metrics
interval: {{ .Values.metrics.serviceMonitor.interval }}
{{- end }}
{{- end }}
@@ -0,0 +1,111 @@
{{- if .Values.postgresql.enabled }}
{{- $name := printf "%s-postgresql" (include "archify-sync.fullname" .) }}
{{- $secret := .Values.postgresql.existingSecret | default $name }}
{{- if not .Values.postgresql.existingSecret }}
{{- $password := .Values.postgresql.password }}
{{- if not $password }}
{{- $existing := lookup "v1" "Secret" .Release.Namespace $name }}
{{- $password = $existing | dig "data" "password" "" | b64dec | default (randAlphaNum 32) }}
{{- end }}
apiVersion: v1
kind: Secret
metadata:
name: {{ $name }}
labels:
{{- include "archify-sync.labels" . | nindent 4 }}
annotations:
helm.sh/resource-policy: keep
type: Opaque
stringData:
password: {{ $password | quote }}
url: {{ printf "postgres://archify:%s@%s:5432/archify" $password $name | quote }}
---
{{- end }}
apiVersion: v1
kind: Service
metadata:
name: {{ $name }}
labels:
{{- include "archify-sync.labels" . | nindent 4 }}
spec:
selector:
{{- include "archify-sync.dbSelector" . | nindent 4 }}
ports:
- name: postgres
port: 5432
targetPort: postgres
---
apiVersion: apps/v1
kind: StatefulSet
metadata:
name: {{ $name }}
labels:
{{- include "archify-sync.labels" . | nindent 4 }}
{{- include "archify-sync.dbSelector" . | nindent 4 }}
spec:
serviceName: {{ $name }}
replicas: 1
selector:
matchLabels:
{{- include "archify-sync.dbSelector" . | nindent 6 }}
template:
metadata:
labels:
{{- include "archify-sync.labels" . | nindent 8 }}
{{- include "archify-sync.dbSelector" . | nindent 8 }}
spec:
automountServiceAccountToken: false
securityContext:
runAsNonRoot: true
runAsUser: 70
fsGroup: 70
seccompProfile:
type: RuntimeDefault
containers:
- name: postgres
image: {{ .Values.postgresql.image }}
securityContext:
allowPrivilegeEscalation: false
capabilities:
drop: [ALL]
env:
- name: POSTGRES_DB
value: archify
- name: POSTGRES_USER
value: archify
- name: POSTGRES_PASSWORD
valueFrom:
secretKeyRef:
name: {{ $secret }}
key: password
- name: PGDATA
value: /var/lib/postgresql/data/pgdata
ports:
- name: postgres
containerPort: 5432
readinessProbe:
exec:
command: [pg_isready, -U, archify, -d, archify]
periodSeconds: 5
volumeMounts:
- name: data
mountPath: /var/lib/postgresql/data
- name: run
mountPath: /var/run/postgresql
resources:
{{- toYaml .Values.postgresql.resources | nindent 12 }}
volumes:
- name: run
emptyDir: {}
volumeClaimTemplates:
- metadata:
name: data
spec:
accessModes: [ReadWriteOnce]
{{- with .Values.postgresql.storageClass }}
storageClassName: {{ . }}
{{- end }}
resources:
requests:
storage: {{ .Values.postgresql.storage }}
{{- end }}
+11
View File
@@ -0,0 +1,11 @@
{{- if and (not .Values.postgresql.enabled) (not .Values.database.existingSecret) }}
apiVersion: v1
kind: Secret
metadata:
name: {{ include "archify-sync.fullname" . }}-database
labels:
{{- include "archify-sync.labels" . | nindent 4 }}
type: Opaque
stringData:
url: {{ .Values.database.url | quote }}
{{- end }}
@@ -0,0 +1,14 @@
apiVersion: v1
kind: Service
metadata:
name: {{ include "archify-sync.fullname" . }}
labels:
{{- include "archify-sync.labels" . | nindent 4 }}
spec:
type: {{ .Values.service.type }}
selector:
{{- include "archify-sync.selector" . | nindent 4 }}
ports:
- name: http
port: {{ .Values.service.port }}
targetPort: http