refactor: remove La Suite services (except Meet + Collabora), delete local overlay
La Suite Messages, Calendars, Drive, Projects, Hive, Integration, and Postfix are replaced by Stalwart (mail) and Tuwunel (messaging). Meet and Collabora remain for video conferencing and document editing. Local overlay was POC only — all deployment targets production now. Deleted: 37 La Suite manifests, Drive Helm chart, 7 local overlay files, stale MTA-in hostPort patch. Cleaned up production image overrides and resource patches for removed services.
This commit is contained in:
@@ -1,163 +0,0 @@
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
metadata:
|
||||
name: calendars-backend
|
||||
namespace: lasuite
|
||||
spec:
|
||||
replicas: 1
|
||||
selector:
|
||||
matchLabels:
|
||||
app: calendars-backend
|
||||
template:
|
||||
metadata:
|
||||
labels:
|
||||
app: calendars-backend
|
||||
spec:
|
||||
initContainers:
|
||||
- name: migrate
|
||||
image: calendars-backend
|
||||
command: ["python", "manage.py", "migrate", "--no-input"]
|
||||
envFrom:
|
||||
- configMapRef:
|
||||
name: calendars-config
|
||||
- configMapRef:
|
||||
name: lasuite-postgres
|
||||
- configMapRef:
|
||||
name: lasuite-oidc-provider
|
||||
env:
|
||||
- name: DB_PASSWORD
|
||||
valueFrom:
|
||||
secretKeyRef:
|
||||
name: calendars-db-credentials
|
||||
key: password
|
||||
- name: DJANGO_SECRET_KEY
|
||||
valueFrom:
|
||||
secretKeyRef:
|
||||
name: calendars-django-secret
|
||||
key: DJANGO_SECRET_KEY
|
||||
- name: SALT_KEY
|
||||
valueFrom:
|
||||
secretKeyRef:
|
||||
name: calendars-django-secret
|
||||
key: SALT_KEY
|
||||
- name: CALDAV_INBOUND_API_KEY
|
||||
valueFrom:
|
||||
secretKeyRef:
|
||||
name: calendars-django-secret
|
||||
key: CALDAV_INBOUND_API_KEY
|
||||
- name: CALDAV_OUTBOUND_API_KEY
|
||||
valueFrom:
|
||||
secretKeyRef:
|
||||
name: calendars-django-secret
|
||||
key: CALDAV_OUTBOUND_API_KEY
|
||||
- name: CALDAV_INTERNAL_API_KEY
|
||||
valueFrom:
|
||||
secretKeyRef:
|
||||
name: calendars-django-secret
|
||||
key: CALDAV_INTERNAL_API_KEY
|
||||
- name: OIDC_RP_CLIENT_ID
|
||||
valueFrom:
|
||||
secretKeyRef:
|
||||
name: oidc-calendars
|
||||
key: CLIENT_ID
|
||||
- name: OIDC_RP_CLIENT_SECRET
|
||||
valueFrom:
|
||||
secretKeyRef:
|
||||
name: oidc-calendars
|
||||
key: CLIENT_SECRET
|
||||
resources:
|
||||
limits:
|
||||
memory: 512Mi
|
||||
cpu: 500m
|
||||
requests:
|
||||
memory: 128Mi
|
||||
cpu: 100m
|
||||
containers:
|
||||
- name: calendars-backend
|
||||
image: calendars-backend
|
||||
command:
|
||||
- gunicorn
|
||||
- -c
|
||||
- /app/gunicorn.conf.py
|
||||
- calendars.wsgi:application
|
||||
ports:
|
||||
- containerPort: 8000
|
||||
envFrom:
|
||||
- configMapRef:
|
||||
name: calendars-config
|
||||
- configMapRef:
|
||||
name: lasuite-postgres
|
||||
- configMapRef:
|
||||
name: lasuite-oidc-provider
|
||||
env:
|
||||
- name: DB_PASSWORD
|
||||
valueFrom:
|
||||
secretKeyRef:
|
||||
name: calendars-db-credentials
|
||||
key: password
|
||||
- name: DJANGO_SECRET_KEY
|
||||
valueFrom:
|
||||
secretKeyRef:
|
||||
name: calendars-django-secret
|
||||
key: DJANGO_SECRET_KEY
|
||||
- name: SALT_KEY
|
||||
valueFrom:
|
||||
secretKeyRef:
|
||||
name: calendars-django-secret
|
||||
key: SALT_KEY
|
||||
- name: CALDAV_INBOUND_API_KEY
|
||||
valueFrom:
|
||||
secretKeyRef:
|
||||
name: calendars-django-secret
|
||||
key: CALDAV_INBOUND_API_KEY
|
||||
- name: CALDAV_OUTBOUND_API_KEY
|
||||
valueFrom:
|
||||
secretKeyRef:
|
||||
name: calendars-django-secret
|
||||
key: CALDAV_OUTBOUND_API_KEY
|
||||
- name: CALDAV_INTERNAL_API_KEY
|
||||
valueFrom:
|
||||
secretKeyRef:
|
||||
name: calendars-django-secret
|
||||
key: CALDAV_INTERNAL_API_KEY
|
||||
- name: OIDC_RP_CLIENT_ID
|
||||
valueFrom:
|
||||
secretKeyRef:
|
||||
name: oidc-calendars
|
||||
key: CLIENT_ID
|
||||
- name: OIDC_RP_CLIENT_SECRET
|
||||
valueFrom:
|
||||
secretKeyRef:
|
||||
name: oidc-calendars
|
||||
key: CLIENT_SECRET
|
||||
volumeMounts:
|
||||
- name: theme
|
||||
mountPath: /app/theme.json
|
||||
subPath: theme.json
|
||||
- name: translations
|
||||
mountPath: /data/translations.json
|
||||
subPath: translations.json
|
||||
livenessProbe:
|
||||
tcpSocket:
|
||||
port: 8000
|
||||
initialDelaySeconds: 15
|
||||
periodSeconds: 20
|
||||
readinessProbe:
|
||||
tcpSocket:
|
||||
port: 8000
|
||||
initialDelaySeconds: 10
|
||||
periodSeconds: 10
|
||||
resources:
|
||||
limits:
|
||||
memory: 512Mi
|
||||
cpu: 500m
|
||||
requests:
|
||||
memory: 256Mi
|
||||
cpu: 100m
|
||||
volumes:
|
||||
- name: theme
|
||||
configMap:
|
||||
name: calendars-theme
|
||||
- name: translations
|
||||
configMap:
|
||||
name: calendars-translations
|
||||
@@ -1,11 +0,0 @@
|
||||
apiVersion: v1
|
||||
kind: Service
|
||||
metadata:
|
||||
name: calendars-backend
|
||||
namespace: lasuite
|
||||
spec:
|
||||
selector:
|
||||
app: calendars-backend
|
||||
ports:
|
||||
- port: 80
|
||||
targetPort: 8000
|
||||
@@ -1,97 +0,0 @@
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
metadata:
|
||||
name: calendars-caldav
|
||||
namespace: lasuite
|
||||
spec:
|
||||
replicas: 1
|
||||
selector:
|
||||
matchLabels:
|
||||
app: calendars-caldav
|
||||
template:
|
||||
metadata:
|
||||
labels:
|
||||
app: calendars-caldav
|
||||
spec:
|
||||
initContainers:
|
||||
- name: init-database
|
||||
image: calendars-caldav
|
||||
command: ["/usr/local/bin/init-database.sh"]
|
||||
env:
|
||||
- name: PGHOST
|
||||
valueFrom:
|
||||
configMapKeyRef:
|
||||
name: lasuite-postgres
|
||||
key: DB_HOST
|
||||
- name: PGPORT
|
||||
valueFrom:
|
||||
configMapKeyRef:
|
||||
name: lasuite-postgres
|
||||
key: DB_PORT
|
||||
- name: PGDATABASE
|
||||
value: calendars_db
|
||||
- name: PGUSER
|
||||
value: calendars
|
||||
- name: PGPASSWORD
|
||||
valueFrom:
|
||||
secretKeyRef:
|
||||
name: calendars-db-credentials
|
||||
key: password
|
||||
resources:
|
||||
limits:
|
||||
memory: 128Mi
|
||||
cpu: 100m
|
||||
requests:
|
||||
memory: 64Mi
|
||||
cpu: 10m
|
||||
containers:
|
||||
- name: calendars-caldav
|
||||
image: calendars-caldav
|
||||
ports:
|
||||
- containerPort: 80
|
||||
env:
|
||||
- name: PGHOST
|
||||
valueFrom:
|
||||
configMapKeyRef:
|
||||
name: lasuite-postgres
|
||||
key: DB_HOST
|
||||
- name: PGPORT
|
||||
valueFrom:
|
||||
configMapKeyRef:
|
||||
name: lasuite-postgres
|
||||
key: DB_PORT
|
||||
- name: PGDATABASE
|
||||
value: calendars_db
|
||||
- name: PGUSER
|
||||
value: calendars
|
||||
- name: PGPASSWORD
|
||||
valueFrom:
|
||||
secretKeyRef:
|
||||
name: calendars-db-credentials
|
||||
key: password
|
||||
- name: CALDAV_INBOUND_API_KEY
|
||||
valueFrom:
|
||||
secretKeyRef:
|
||||
name: calendars-django-secret
|
||||
key: CALDAV_INBOUND_API_KEY
|
||||
- name: CALDAV_OUTBOUND_API_KEY
|
||||
valueFrom:
|
||||
secretKeyRef:
|
||||
name: calendars-django-secret
|
||||
key: CALDAV_OUTBOUND_API_KEY
|
||||
- name: CALDAV_INTERNAL_API_KEY
|
||||
valueFrom:
|
||||
secretKeyRef:
|
||||
name: calendars-django-secret
|
||||
key: CALDAV_INTERNAL_API_KEY
|
||||
- name: CALDAV_BASE_URI
|
||||
value: /caldav/
|
||||
- name: CALLBACK_BASE_URL
|
||||
value: http://calendars-backend.lasuite.svc.cluster.local:8000
|
||||
resources:
|
||||
limits:
|
||||
memory: 256Mi
|
||||
cpu: 300m
|
||||
requests:
|
||||
memory: 128Mi
|
||||
cpu: 50m
|
||||
@@ -1,11 +0,0 @@
|
||||
apiVersion: v1
|
||||
kind: Service
|
||||
metadata:
|
||||
name: calendars-caldav
|
||||
namespace: lasuite
|
||||
spec:
|
||||
selector:
|
||||
app: calendars-caldav
|
||||
ports:
|
||||
- port: 80
|
||||
targetPort: 80
|
||||
@@ -1,30 +0,0 @@
|
||||
apiVersion: v1
|
||||
kind: ConfigMap
|
||||
metadata:
|
||||
name: calendars-config
|
||||
namespace: lasuite
|
||||
data:
|
||||
DJANGO_CONFIGURATION: Production
|
||||
DJANGO_SETTINGS_MODULE: calendars.settings
|
||||
DJANGO_ALLOWED_HOSTS: cal.DOMAIN_SUFFIX,calendars-backend.lasuite.svc.cluster.local,localhost
|
||||
DJANGO_CSRF_TRUSTED_ORIGINS: https://cal.DOMAIN_SUFFIX
|
||||
DB_NAME: calendars_db
|
||||
DB_USER: calendars
|
||||
CALDAV_URL: http://calendars-caldav.lasuite.svc.cluster.local:80
|
||||
CALDAV_CALLBACK_BASE_URL: http://calendars-backend.lasuite.svc.cluster.local:8000
|
||||
REDIS_URL: redis://valkey.data.svc.cluster.local:6379/5
|
||||
DRAMATIQ_BROKER_URL: redis://valkey.data.svc.cluster.local:6379/5
|
||||
DRAMATIQ_RESULT_BACKEND_URL: redis://valkey.data.svc.cluster.local:6379/6
|
||||
APP_URL: https://cal.DOMAIN_SUFFIX
|
||||
DEFAULT_FROM_EMAIL: noreply@sunbeam.pt
|
||||
CALENDAR_INVITATION_FROM_EMAIL: calendar@sunbeam.pt
|
||||
CALENDAR_ITIP_ENABLED: "True"
|
||||
LOGIN_REDIRECT_URL: /
|
||||
LOGIN_REDIRECT_URL_FAILURE: /
|
||||
LOGOUT_REDIRECT_URL: /
|
||||
FRONTEND_THEME: sunbeam
|
||||
FRONTEND_HIDE_GAUFRE: "False"
|
||||
NEXT_PUBLIC_VISIO_BASE_URL: https://meet.DOMAIN_SUFFIX
|
||||
FRONTEND_CSS_URL: https://integration.DOMAIN_SUFFIX/api/v2/theme.css
|
||||
OIDC_USERINFO_FULLNAME_FIELDS: given_name,family_name
|
||||
THEME_CUSTOMIZATION_FILE_PATH: /app/theme.json
|
||||
@@ -1,26 +0,0 @@
|
||||
apiVersion: v1
|
||||
kind: ConfigMap
|
||||
metadata:
|
||||
name: calendars-frontend-caddyfile
|
||||
namespace: lasuite
|
||||
data:
|
||||
Caddyfile: |
|
||||
{
|
||||
auto_https off
|
||||
admin off
|
||||
}
|
||||
|
||||
:8080 {
|
||||
root * /srv
|
||||
header X-Frame-Options DENY
|
||||
|
||||
route {
|
||||
try_files {path} {path}.html /index.html
|
||||
file_server
|
||||
}
|
||||
|
||||
handle_errors {
|
||||
rewrite * /404.html
|
||||
file_server
|
||||
}
|
||||
}
|
||||
@@ -1,35 +0,0 @@
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
metadata:
|
||||
name: calendars-frontend
|
||||
namespace: lasuite
|
||||
spec:
|
||||
replicas: 1
|
||||
selector:
|
||||
matchLabels:
|
||||
app: calendars-frontend
|
||||
template:
|
||||
metadata:
|
||||
labels:
|
||||
app: calendars-frontend
|
||||
spec:
|
||||
containers:
|
||||
- name: calendars-frontend
|
||||
image: calendars-frontend
|
||||
ports:
|
||||
- containerPort: 8080
|
||||
volumeMounts:
|
||||
- name: caddyfile
|
||||
mountPath: /etc/caddy/Caddyfile
|
||||
subPath: Caddyfile
|
||||
resources:
|
||||
limits:
|
||||
memory: 128Mi
|
||||
cpu: 100m
|
||||
requests:
|
||||
memory: 64Mi
|
||||
cpu: 10m
|
||||
volumes:
|
||||
- name: caddyfile
|
||||
configMap:
|
||||
name: calendars-frontend-caddyfile
|
||||
@@ -1,11 +0,0 @@
|
||||
apiVersion: v1
|
||||
kind: Service
|
||||
metadata:
|
||||
name: calendars-frontend
|
||||
namespace: lasuite
|
||||
spec:
|
||||
selector:
|
||||
app: calendars-frontend
|
||||
ports:
|
||||
- port: 80
|
||||
targetPort: 8080
|
||||
@@ -1,17 +0,0 @@
|
||||
apiVersion: v1
|
||||
kind: ConfigMap
|
||||
metadata:
|
||||
name: calendars-theme
|
||||
namespace: lasuite
|
||||
data:
|
||||
theme.json: |
|
||||
{
|
||||
"css_url": "https://integration.DOMAIN_SUFFIX/api/v2/theme.css",
|
||||
"waffle": {
|
||||
"apiUrl": "https://integration.DOMAIN_SUFFIX/api/v2/services.json",
|
||||
"widgetPath": "https://integration.DOMAIN_SUFFIX/api/v2/lagaufre.js",
|
||||
"label": "O Estúdio",
|
||||
"closeLabel": "Fechar",
|
||||
"newWindowLabelSuffix": " · nova janela"
|
||||
}
|
||||
}
|
||||
@@ -1,88 +0,0 @@
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
metadata:
|
||||
name: calendars-worker
|
||||
namespace: lasuite
|
||||
spec:
|
||||
replicas: 1
|
||||
selector:
|
||||
matchLabels:
|
||||
app: calendars-worker
|
||||
template:
|
||||
metadata:
|
||||
labels:
|
||||
app: calendars-worker
|
||||
spec:
|
||||
containers:
|
||||
- name: calendars-worker
|
||||
image: calendars-backend
|
||||
command: ["python", "worker.py"]
|
||||
envFrom:
|
||||
- configMapRef:
|
||||
name: calendars-config
|
||||
- configMapRef:
|
||||
name: lasuite-postgres
|
||||
- configMapRef:
|
||||
name: lasuite-oidc-provider
|
||||
env:
|
||||
- name: DB_PASSWORD
|
||||
valueFrom:
|
||||
secretKeyRef:
|
||||
name: calendars-db-credentials
|
||||
key: password
|
||||
- name: DJANGO_SECRET_KEY
|
||||
valueFrom:
|
||||
secretKeyRef:
|
||||
name: calendars-django-secret
|
||||
key: DJANGO_SECRET_KEY
|
||||
- name: SALT_KEY
|
||||
valueFrom:
|
||||
secretKeyRef:
|
||||
name: calendars-django-secret
|
||||
key: SALT_KEY
|
||||
- name: CALDAV_INBOUND_API_KEY
|
||||
valueFrom:
|
||||
secretKeyRef:
|
||||
name: calendars-django-secret
|
||||
key: CALDAV_INBOUND_API_KEY
|
||||
- name: CALDAV_OUTBOUND_API_KEY
|
||||
valueFrom:
|
||||
secretKeyRef:
|
||||
name: calendars-django-secret
|
||||
key: CALDAV_OUTBOUND_API_KEY
|
||||
- name: CALDAV_INTERNAL_API_KEY
|
||||
valueFrom:
|
||||
secretKeyRef:
|
||||
name: calendars-django-secret
|
||||
key: CALDAV_INTERNAL_API_KEY
|
||||
- name: OIDC_RP_CLIENT_ID
|
||||
valueFrom:
|
||||
secretKeyRef:
|
||||
name: oidc-calendars
|
||||
key: CLIENT_ID
|
||||
- name: OIDC_RP_CLIENT_SECRET
|
||||
valueFrom:
|
||||
secretKeyRef:
|
||||
name: oidc-calendars
|
||||
key: CLIENT_SECRET
|
||||
volumeMounts:
|
||||
- name: theme
|
||||
mountPath: /app/theme.json
|
||||
subPath: theme.json
|
||||
- name: translations
|
||||
mountPath: /data/translations.json
|
||||
subPath: translations.json
|
||||
resources:
|
||||
limits:
|
||||
memory: 256Mi
|
||||
cpu: 300m
|
||||
requests:
|
||||
memory: 128Mi
|
||||
cpu: 50m
|
||||
volumes:
|
||||
- name: theme
|
||||
configMap:
|
||||
name: calendars-theme
|
||||
- name: translations
|
||||
configMap:
|
||||
name: calendars-translations
|
||||
@@ -1,88 +0,0 @@
|
||||
# nginx config for drive-frontend.
|
||||
#
|
||||
# /media/ requests are validated via auth_request to the Drive backend before
|
||||
# being proxied to SeaweedFS. This avoids exposing S3 credentials to the browser
|
||||
# while still serving private files through the CDN path.
|
||||
apiVersion: v1
|
||||
kind: ConfigMap
|
||||
metadata:
|
||||
name: drive-frontend-nginx-conf
|
||||
namespace: lasuite
|
||||
data:
|
||||
default.conf: |
|
||||
server {
|
||||
listen 8080;
|
||||
server_name localhost;
|
||||
server_tokens off;
|
||||
|
||||
root /usr/share/nginx/html;
|
||||
|
||||
# Rewrite hardcoded upstream La Gaufre widget and services API URLs to our
|
||||
# integration service. sub_filter doesn't work on gzip-compressed responses.
|
||||
gzip off;
|
||||
sub_filter_once off;
|
||||
sub_filter_types text/html application/javascript;
|
||||
sub_filter 'https://static.suite.anct.gouv.fr/widgets/lagaufre.js'
|
||||
'https://integration.DOMAIN_SUFFIX/api/v2/lagaufre.js';
|
||||
sub_filter 'https://lasuite.numerique.gouv.fr/api/services'
|
||||
'https://integration.DOMAIN_SUFFIX/api/v2/services.json';
|
||||
sub_filter 'https://operateurs.suite.anct.gouv.fr/api/v1.0/lagaufre/services/?operator=9f5624fc-ef99-4d10-ae3f-403a81eb16ef&siret=21870030000013'
|
||||
'https://integration.DOMAIN_SUFFIX/api/v2/services.json';
|
||||
sub_filter '</head>' '<link rel="stylesheet" href="https://integration.DOMAIN_SUFFIX/api/v2/theme.css"></head>';
|
||||
|
||||
# Public file viewer — Next.js static export generates a literal [id].html
|
||||
# template for this dynamic route. Serve it for any file UUID so the
|
||||
# client-side router hydrates the correct FilePage component without auth.
|
||||
location ~ ^/explorer/items/files/[^/]+$ {
|
||||
try_files $uri $uri.html /explorer/items/files/[id].html;
|
||||
}
|
||||
|
||||
# Item detail routes (folders, workspaces, shared items).
|
||||
location ~ ^/explorer/items/[^/]+$ {
|
||||
try_files $uri $uri.html /explorer/items/[id].html;
|
||||
}
|
||||
|
||||
location / {
|
||||
# Try the exact path, then path + .html (Next.js static export generates
|
||||
# e.g. explorer/items/my-files.html), then fall back to index.html for
|
||||
# client-side routes that have no pre-rendered file.
|
||||
try_files $uri $uri.html /index.html;
|
||||
}
|
||||
|
||||
# Protected media: auth via Drive backend, then proxy to S3 with signed headers.
|
||||
# media-auth returns SigV4 Authorization/X-Amz-Date/X-Amz-Content-SHA256
|
||||
# headers signed for the S3 key (item/UUID/file). nginx captures them and
|
||||
# forwards to SeaweedFS. The regex strips /media/ and optional /preview/
|
||||
# so the proxy path matches the signed S3 key exactly.
|
||||
location ~ ^/media/(preview/)?(.*) {
|
||||
set $original_uri $request_uri;
|
||||
set $s3_key $2;
|
||||
resolver kube-dns.kube-system.svc.cluster.local valid=30s;
|
||||
set $s3_backend http://seaweedfs-filer.storage.svc.cluster.local:8333;
|
||||
auth_request /internal/media-auth;
|
||||
auth_request_set $auth_header $upstream_http_authorization;
|
||||
auth_request_set $amz_date $upstream_http_x_amz_date;
|
||||
auth_request_set $amz_content $upstream_http_x_amz_content_sha256;
|
||||
proxy_set_header Authorization $auth_header;
|
||||
proxy_set_header X-Amz-Date $amz_date;
|
||||
proxy_set_header X-Amz-Content-Sha256 $amz_content;
|
||||
proxy_pass $s3_backend/sunbeam-drive/$s3_key;
|
||||
}
|
||||
|
||||
# Internal subrequest: Django checks session and item access, returns S3 auth headers.
|
||||
location = /internal/media-auth {
|
||||
internal;
|
||||
proxy_pass http://drive-backend.lasuite.svc.cluster.local:80/api/v1.0/items/media-auth/;
|
||||
proxy_pass_request_body off;
|
||||
proxy_set_header Content-Length "";
|
||||
proxy_set_header Cookie $http_cookie;
|
||||
proxy_set_header Host drive.DOMAIN_SUFFIX;
|
||||
proxy_set_header X-Original-URL https://drive.DOMAIN_SUFFIX$original_uri;
|
||||
}
|
||||
|
||||
error_page 500 502 503 504 @blank_error;
|
||||
location @blank_error {
|
||||
return 200 '';
|
||||
add_header Content-Type text/html;
|
||||
}
|
||||
}
|
||||
@@ -1,215 +0,0 @@
|
||||
# La Suite Numérique — Drive (drive chart).
|
||||
# Env vars use the chart's dict-based envVars schema:
|
||||
# string value → rendered as env.value
|
||||
# map value → rendered as env.valueFrom (configMapKeyRef / secretKeyRef)
|
||||
# DOMAIN_SUFFIX is substituted by sed at deploy time.
|
||||
#
|
||||
# Required secrets (created by seed script):
|
||||
# oidc-drive — CLIENT_ID, CLIENT_SECRET (created by Hydra Maester)
|
||||
# drive-db-credentials — password (VaultDynamicSecret, DB engine)
|
||||
# drive-django-secret — DJANGO_SECRET_KEY (VaultStaticSecret)
|
||||
# seaweedfs-s3-credentials — S3_ACCESS_KEY, S3_SECRET_KEY (shared)
|
||||
|
||||
fullnameOverride: drive
|
||||
|
||||
backend:
|
||||
livenessProbe:
|
||||
initialDelaySeconds: 15
|
||||
periodSeconds: 10
|
||||
timeoutSeconds: 5
|
||||
failureThreshold: 3
|
||||
readinessProbe:
|
||||
initialDelaySeconds: 15
|
||||
periodSeconds: 10
|
||||
timeoutSeconds: 5
|
||||
failureThreshold: 3
|
||||
createsuperuser:
|
||||
# No superuser — users authenticate via OIDC.
|
||||
# The chart always renders this Job; override command so it exits 0.
|
||||
command: ["true"]
|
||||
|
||||
envVars: &backendEnvVars
|
||||
# ── Database ──────────────────────────────────────────────────────────────
|
||||
DB_NAME: drive_db
|
||||
DB_USER: drive
|
||||
DB_HOST:
|
||||
configMapKeyRef:
|
||||
name: lasuite-postgres
|
||||
key: DB_HOST
|
||||
DB_PORT:
|
||||
configMapKeyRef:
|
||||
name: lasuite-postgres
|
||||
key: DB_PORT
|
||||
# Drive uses psycopg3 backend (no _psycopg2 suffix).
|
||||
DB_ENGINE: django.db.backends.postgresql
|
||||
DB_PASSWORD:
|
||||
secretKeyRef:
|
||||
name: drive-db-credentials
|
||||
key: password
|
||||
|
||||
# ── Redis / Celery ────────────────────────────────────────────────────────
|
||||
REDIS_URL:
|
||||
configMapKeyRef:
|
||||
name: lasuite-valkey
|
||||
key: REDIS_URL
|
||||
# Drive uses DJANGO_CELERY_BROKER_URL (not CELERY_BROKER_URL).
|
||||
DJANGO_CELERY_BROKER_URL:
|
||||
configMapKeyRef:
|
||||
name: lasuite-valkey
|
||||
key: CELERY_BROKER_URL
|
||||
|
||||
# ── S3 (file storage) ─────────────────────────────────────────────────────
|
||||
AWS_STORAGE_BUCKET_NAME: sunbeam-drive
|
||||
AWS_S3_ENDPOINT_URL:
|
||||
configMapKeyRef:
|
||||
name: lasuite-s3
|
||||
key: AWS_S3_ENDPOINT_URL
|
||||
AWS_S3_REGION_NAME:
|
||||
configMapKeyRef:
|
||||
name: lasuite-s3
|
||||
key: AWS_S3_REGION_NAME
|
||||
AWS_DEFAULT_ACL:
|
||||
configMapKeyRef:
|
||||
name: lasuite-s3
|
||||
key: AWS_DEFAULT_ACL
|
||||
# Drive uses AWS_S3_ACCESS_KEY_ID / AWS_S3_SECRET_ACCESS_KEY (with _S3_ prefix).
|
||||
AWS_S3_ACCESS_KEY_ID:
|
||||
secretKeyRef:
|
||||
name: seaweedfs-s3-credentials
|
||||
key: S3_ACCESS_KEY
|
||||
AWS_S3_SECRET_ACCESS_KEY:
|
||||
secretKeyRef:
|
||||
name: seaweedfs-s3-credentials
|
||||
key: S3_SECRET_KEY
|
||||
# Public S3 endpoint for browser-side presigned upload URLs.
|
||||
AWS_S3_DOMAIN_REPLACE: https://s3.DOMAIN_SUFFIX
|
||||
# Base URL for media file references so nginx auth proxy receives full paths.
|
||||
MEDIA_BASE_URL: https://drive.DOMAIN_SUFFIX
|
||||
|
||||
# ── OIDC (Hydra) ──────────────────────────────────────────────────────────
|
||||
OIDC_RP_CLIENT_ID:
|
||||
secretKeyRef:
|
||||
name: oidc-drive
|
||||
key: CLIENT_ID
|
||||
OIDC_RP_CLIENT_SECRET:
|
||||
secretKeyRef:
|
||||
name: oidc-drive
|
||||
key: CLIENT_SECRET
|
||||
OIDC_RP_SIGN_ALGO:
|
||||
configMapKeyRef:
|
||||
name: lasuite-oidc-provider
|
||||
key: OIDC_RP_SIGN_ALGO
|
||||
OIDC_RP_SCOPES:
|
||||
configMapKeyRef:
|
||||
name: lasuite-oidc-provider
|
||||
key: OIDC_RP_SCOPES
|
||||
OIDC_OP_JWKS_ENDPOINT:
|
||||
configMapKeyRef:
|
||||
name: lasuite-oidc-provider
|
||||
key: OIDC_OP_JWKS_ENDPOINT
|
||||
OIDC_OP_AUTHORIZATION_ENDPOINT:
|
||||
configMapKeyRef:
|
||||
name: lasuite-oidc-provider
|
||||
key: OIDC_OP_AUTHORIZATION_ENDPOINT
|
||||
OIDC_OP_TOKEN_ENDPOINT:
|
||||
configMapKeyRef:
|
||||
name: lasuite-oidc-provider
|
||||
key: OIDC_OP_TOKEN_ENDPOINT
|
||||
OIDC_OP_USER_ENDPOINT:
|
||||
configMapKeyRef:
|
||||
name: lasuite-oidc-provider
|
||||
key: OIDC_OP_USER_ENDPOINT
|
||||
OIDC_OP_LOGOUT_ENDPOINT:
|
||||
configMapKeyRef:
|
||||
name: lasuite-oidc-provider
|
||||
key: OIDC_OP_LOGOUT_ENDPOINT
|
||||
OIDC_VERIFY_SSL:
|
||||
configMapKeyRef:
|
||||
name: lasuite-oidc-provider
|
||||
key: OIDC_VERIFY_SSL
|
||||
|
||||
# ── Resource Server (Drive as OAuth2 RS for Messages integration) ─────────
|
||||
OIDC_RESOURCE_SERVER_ENABLED: "True"
|
||||
# Hydra issuer URL — must match the `iss` claim in introspection responses.
|
||||
OIDC_OP_URL: https://auth.DOMAIN_SUFFIX/
|
||||
# Hydra token introspection endpoint (admin port — no client auth required).
|
||||
OIDC_OP_INTROSPECTION_ENDPOINT: http://hydra-admin.ory.svc.cluster.local:4445/admin/oauth2/introspect
|
||||
# Drive authenticates to Hydra introspection using its own OIDC client creds.
|
||||
OIDC_RS_CLIENT_ID:
|
||||
secretKeyRef:
|
||||
name: oidc-drive
|
||||
key: CLIENT_ID
|
||||
OIDC_RS_CLIENT_SECRET:
|
||||
secretKeyRef:
|
||||
name: oidc-drive
|
||||
key: CLIENT_SECRET
|
||||
# Accept bearer tokens from Sunbeam CLI and Messages (server-to-server).
|
||||
# OIDC_RS_ALLOWED_AUDIENCES is set by the sunbeam seed script which reads
|
||||
# the messages client ID from the oidc-messages secret and combines it with
|
||||
# the static sunbeam-cli audience. Stored in vault as secret/drive.
|
||||
OIDC_RS_ALLOWED_AUDIENCES:
|
||||
secretKeyRef:
|
||||
name: drive-rs-audiences
|
||||
key: OIDC_RS_ALLOWED_AUDIENCES
|
||||
|
||||
# ── Django ────────────────────────────────────────────────────────────────
|
||||
DJANGO_SECRET_KEY:
|
||||
secretKeyRef:
|
||||
name: drive-django-secret
|
||||
key: DJANGO_SECRET_KEY
|
||||
DJANGO_CONFIGURATION: Production
|
||||
ALLOWED_HOSTS: drive.DOMAIN_SUFFIX
|
||||
DJANGO_ALLOWED_HOSTS: drive.DOMAIN_SUFFIX
|
||||
DJANGO_CSRF_TRUSTED_ORIGINS: https://drive.DOMAIN_SUFFIX
|
||||
LOGIN_REDIRECT_URL: /
|
||||
LOGOUT_REDIRECT_URL: /
|
||||
SESSION_COOKIE_AGE: "604800"
|
||||
# Session cache TTL must match SESSION_COOKIE_AGE.
|
||||
CACHES_SESSION_TIMEOUT: "604800"
|
||||
# Silent login: when the Django session expires, the frontend redirects
|
||||
# to the OIDC login endpoint which completes instantly (Hydra already
|
||||
# has a session) and bounces the user back. This keeps users logged in
|
||||
# seamlessly as long as their Hydra SSO session is valid.
|
||||
FRONTEND_SILENT_LOGIN_ENABLED: "true"
|
||||
# Redirect unauthenticated visitors at / straight to OIDC login instead of
|
||||
# showing the La Suite marketing landing page. returnTo brings them to
|
||||
# their files after successful auth.
|
||||
FRONTEND_EXTERNAL_HOME_URL: "https://drive.DOMAIN_SUFFIX/api/v1.0/authenticate/?returnTo=https%3A%2F%2Fdrive.DOMAIN_SUFFIX%2Fexplorer%2Fitems%2Fmy-files"
|
||||
|
||||
# Allow Messages to call Drive SDK relay cross-origin.
|
||||
SDK_CORS_ALLOWED_ORIGINS: "https://mail.DOMAIN_SUFFIX"
|
||||
CORS_ALLOWED_ORIGINS: "https://mail.DOMAIN_SUFFIX"
|
||||
|
||||
# Allow all file types — self-hosted instance, no need to restrict uploads.
|
||||
RESTRICT_UPLOAD_FILE_TYPE: "False"
|
||||
|
||||
# ── WOPI / Collabora ──────────────────────────────────────────────────────
|
||||
# Comma-separated list of enabled WOPI client names.
|
||||
# Inject Sunbeam theme CSS from the integration service.
|
||||
FRONTEND_CSS_URL: "https://integration.DOMAIN_SUFFIX/api/v2/theme.css"
|
||||
|
||||
WOPI_CLIENTS: collabora
|
||||
# Discovery XML endpoint — Collabora registers supported MIME types here.
|
||||
WOPI_COLLABORA_DISCOVERY_URL: http://collabora.lasuite.svc.cluster.local:9980/hosting/discovery
|
||||
# Base URL Drive uses when building wopi_src callback URLs for Collabora.
|
||||
WOPI_SRC_BASE_URL: https://drive.DOMAIN_SUFFIX
|
||||
|
||||
themeCustomization:
|
||||
enabled: true
|
||||
file_content:
|
||||
css_url: "https://integration.DOMAIN_SUFFIX/api/v2/theme.css"
|
||||
waffle:
|
||||
apiUrl: "https://integration.DOMAIN_SUFFIX/api/v2/services.json"
|
||||
widgetPath: "https://integration.DOMAIN_SUFFIX/api/v2/lagaufre.js"
|
||||
label: "O Estúdio"
|
||||
closeLabel: "Fechar"
|
||||
newWindowLabelSuffix: " · nova janela"
|
||||
|
||||
ingress:
|
||||
enabled: false
|
||||
|
||||
ingressAdmin:
|
||||
enabled: false
|
||||
|
||||
ingressMedia:
|
||||
enabled: false
|
||||
@@ -1,28 +0,0 @@
|
||||
apiVersion: v1
|
||||
kind: ConfigMap
|
||||
metadata:
|
||||
name: hive-config
|
||||
namespace: lasuite
|
||||
data:
|
||||
config.toml: |
|
||||
[drive]
|
||||
base_url = "http://drive-backend.lasuite.svc.cluster.local:80"
|
||||
workspace = "Game Assets"
|
||||
oidc_client_id = "hive"
|
||||
oidc_token_url = "http://hydra.ory.svc.cluster.local:4444/oauth2/token"
|
||||
# oidc_client_secret_file = "/run/secrets/hive-oidc" # mounted from Secret
|
||||
|
||||
[s3]
|
||||
endpoint = "http://seaweedfs-filer.storage.svc.cluster.local:8333"
|
||||
bucket = "sunbeam-game-assets"
|
||||
region = "us-east-1"
|
||||
# access_key_file = "/run/secrets/seaweedfs-key" # mounted from Secret
|
||||
# secret_key_file = "/run/secrets/seaweedfs-secret" # mounted from Secret
|
||||
|
||||
[postgres]
|
||||
# url_file = "/run/secrets/hive-db-url" # mounted from Secret
|
||||
|
||||
[sync]
|
||||
interval_seconds = 30
|
||||
temp_dir = "/tmp/hive"
|
||||
large_file_threshold_mb = 50
|
||||
@@ -1,45 +0,0 @@
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
metadata:
|
||||
name: hive
|
||||
namespace: lasuite
|
||||
spec:
|
||||
replicas: 1
|
||||
selector:
|
||||
matchLabels:
|
||||
app: hive
|
||||
template:
|
||||
metadata:
|
||||
labels:
|
||||
app: hive
|
||||
spec:
|
||||
automountServiceAccountToken: false
|
||||
containers:
|
||||
- name: hive
|
||||
image: nginx:alpine # placeholder until La Suite Hive image is built
|
||||
volumeMounts:
|
||||
- name: config
|
||||
mountPath: /etc/hive
|
||||
readOnly: true
|
||||
- name: secrets
|
||||
mountPath: /run/secrets
|
||||
readOnly: true
|
||||
resources:
|
||||
limits:
|
||||
memory: 64Mi
|
||||
requests:
|
||||
memory: 32Mi
|
||||
cpu: 25m
|
||||
volumes:
|
||||
- name: config
|
||||
configMap:
|
||||
name: hive-config
|
||||
- name: secrets
|
||||
projected:
|
||||
sources:
|
||||
- secret:
|
||||
name: hive-oidc
|
||||
- secret:
|
||||
name: seaweedfs-s3-credentials
|
||||
- secret:
|
||||
name: hive-db-url
|
||||
@@ -1,15 +0,0 @@
|
||||
# Hive has no inbound HTTP API — it is a reconciliation daemon only.
|
||||
# This Service exists for Linkerd observability (metrics scraping).
|
||||
apiVersion: v1
|
||||
kind: Service
|
||||
metadata:
|
||||
name: hive
|
||||
namespace: lasuite
|
||||
spec:
|
||||
selector:
|
||||
app: hive
|
||||
ports:
|
||||
- name: metrics
|
||||
port: 9090
|
||||
targetPort: 9090
|
||||
protocol: TCP
|
||||
@@ -1,109 +0,0 @@
|
||||
# La Gaufre integration service — O Estúdio app launcher (La Gaufre v2).
|
||||
# Serves the lagaufre.js v2 widget, SVG logos, and the v2 services API.
|
||||
# Apps load gaufre.js which in turn initialises the v2 widget with the
|
||||
# button already rendered by @gouvfr-lasuite/ui-kit.
|
||||
#
|
||||
# Image: src.DOMAIN_SUFFIX/studio/integration:latest
|
||||
# Built from sunbeam/integration-service/ (context: sunbeam/ root)
|
||||
# Baked in: lagaufre.js v2, official La Suite logos, custom logos, gaufre.js, nginx.conf
|
||||
#
|
||||
# ConfigMap: only services.json (v2 format) — the one thing that varies per env
|
||||
# DOMAIN_SUFFIX substituted at deploy time.
|
||||
|
||||
---
|
||||
apiVersion: v1
|
||||
kind: ConfigMap
|
||||
metadata:
|
||||
name: integration-config
|
||||
namespace: lasuite
|
||||
data:
|
||||
services.json: |
|
||||
{
|
||||
"services": [
|
||||
{
|
||||
"name": "Calendar",
|
||||
"url": "https://cal.DOMAIN_SUFFIX",
|
||||
"logo": "https://integration.DOMAIN_SUFFIX/logos/calendar.svg?v=1"
|
||||
},
|
||||
{
|
||||
"name": "Drive",
|
||||
"url": "https://drive.DOMAIN_SUFFIX",
|
||||
"logo": "https://integration.DOMAIN_SUFFIX/logos/drive.svg?v=1"
|
||||
},
|
||||
{
|
||||
"name": "Mail",
|
||||
"url": "https://mail.DOMAIN_SUFFIX",
|
||||
"logo": "https://integration.DOMAIN_SUFFIX/logos/mail.svg?v=1"
|
||||
},
|
||||
{
|
||||
"name": "Meet",
|
||||
"url": "https://meet.DOMAIN_SUFFIX",
|
||||
"logo": "https://integration.DOMAIN_SUFFIX/logos/visio.svg?v=2"
|
||||
},
|
||||
{
|
||||
"name": "Projects",
|
||||
"url": "https://projects.DOMAIN_SUFFIX",
|
||||
"logo": "https://integration.DOMAIN_SUFFIX/logos/projects.svg?v=1"
|
||||
},
|
||||
{
|
||||
"name": "Source Code",
|
||||
"url": "https://src.DOMAIN_SUFFIX",
|
||||
"logo": "https://integration.DOMAIN_SUFFIX/logos/docs.svg?v=1"
|
||||
},
|
||||
{
|
||||
"name": "Account",
|
||||
"url": "https://auth.DOMAIN_SUFFIX",
|
||||
"logo": "https://integration.DOMAIN_SUFFIX/logos/account.svg?v=1"
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
---
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
metadata:
|
||||
name: integration
|
||||
namespace: lasuite
|
||||
spec:
|
||||
replicas: 1
|
||||
selector:
|
||||
matchLabels:
|
||||
app: integration
|
||||
template:
|
||||
metadata:
|
||||
labels:
|
||||
app: integration
|
||||
spec:
|
||||
containers:
|
||||
- name: integration
|
||||
image: integration
|
||||
ports:
|
||||
- name: http
|
||||
containerPort: 80
|
||||
volumeMounts:
|
||||
- name: config
|
||||
mountPath: /etc/integration/services.json
|
||||
subPath: services.json
|
||||
resources:
|
||||
limits:
|
||||
memory: 32Mi
|
||||
requests:
|
||||
memory: 16Mi
|
||||
cpu: 5m
|
||||
volumes:
|
||||
- name: config
|
||||
configMap:
|
||||
name: integration-config
|
||||
---
|
||||
apiVersion: v1
|
||||
kind: Service
|
||||
metadata:
|
||||
name: integration
|
||||
namespace: lasuite
|
||||
spec:
|
||||
selector:
|
||||
app: integration
|
||||
ports:
|
||||
- name: http
|
||||
port: 80
|
||||
targetPort: 80
|
||||
@@ -5,15 +5,9 @@ namespace: lasuite
|
||||
|
||||
resources:
|
||||
- namespace.yaml
|
||||
- postfix-deployment.yaml
|
||||
- hive-config.yaml
|
||||
- hive-deployment.yaml
|
||||
- hive-service.yaml
|
||||
- seaweedfs-buckets.yaml
|
||||
- shared-config.yaml
|
||||
- oidc-clients.yaml
|
||||
- vault-secrets.yaml
|
||||
- integration-deployment.yaml
|
||||
- collabora-deployment.yaml
|
||||
- collabora-service.yaml
|
||||
- meet-config.yaml
|
||||
@@ -23,50 +17,3 @@ resources:
|
||||
- meet-frontend-nginx-configmap.yaml
|
||||
- meet-frontend-deployment.yaml
|
||||
- meet-frontend-service.yaml
|
||||
- drive-frontend-nginx-configmap.yaml
|
||||
- messages-config.yaml
|
||||
- messages-backend-deployment.yaml
|
||||
- messages-backend-service.yaml
|
||||
- messages-frontend-theme-configmap.yaml
|
||||
- messages-frontend-deployment.yaml
|
||||
- messages-frontend-service.yaml
|
||||
- messages-worker-deployment.yaml
|
||||
- messages-mta-in-deployment.yaml
|
||||
- messages-mta-in-service.yaml
|
||||
- messages-mta-out-deployment.yaml
|
||||
- messages-mta-out-service.yaml
|
||||
- messages-mpa-dkim-config.yaml
|
||||
- messages-mpa-deployment.yaml
|
||||
- messages-mpa-service.yaml
|
||||
- messages-socks-proxy-deployment.yaml
|
||||
- messages-socks-proxy-service.yaml
|
||||
- calendars-config.yaml
|
||||
- calendars-theme-configmap.yaml
|
||||
- calendars-backend-deployment.yaml
|
||||
- calendars-backend-service.yaml
|
||||
- calendars-caldav-deployment.yaml
|
||||
- calendars-caldav-service.yaml
|
||||
- calendars-worker-deployment.yaml
|
||||
- calendars-frontend-caddyfile.yaml
|
||||
- calendars-frontend-deployment.yaml
|
||||
- calendars-frontend-service.yaml
|
||||
- projects-config.yaml
|
||||
- projects-deployment.yaml
|
||||
|
||||
patches:
|
||||
# Mount media auth proxy nginx config in drive-frontend
|
||||
- path: patch-drive-frontend-nginx.yaml
|
||||
# Wait for Collabora + run trigger_wopi_configuration on every Drive pod start
|
||||
- path: patch-drive-wopi-init.yaml
|
||||
|
||||
# La Suite Numérique Helm charts.
|
||||
# Charts with a published Helm repo use helmCharts below.
|
||||
# find has no published repo yet — deploy manually when OpenSearch is ready.
|
||||
helmCharts:
|
||||
# helm repo add drive https://suitenumerique.github.io/drive/
|
||||
- name: drive
|
||||
repo: https://suitenumerique.github.io/drive/
|
||||
version: "0.14.0"
|
||||
releaseName: drive
|
||||
namespace: lasuite
|
||||
valuesFile: drive-values.yaml
|
||||
|
||||
@@ -1,183 +0,0 @@
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
metadata:
|
||||
name: messages-backend
|
||||
namespace: lasuite
|
||||
spec:
|
||||
replicas: 1
|
||||
selector:
|
||||
matchLabels:
|
||||
app: messages-backend
|
||||
template:
|
||||
metadata:
|
||||
labels:
|
||||
app: messages-backend
|
||||
spec:
|
||||
initContainers:
|
||||
- name: migrate
|
||||
image: messages-backend
|
||||
command: ["python", "manage.py", "migrate", "--no-input"]
|
||||
envFrom:
|
||||
- configMapRef:
|
||||
name: messages-config
|
||||
- configMapRef:
|
||||
name: lasuite-postgres
|
||||
- configMapRef:
|
||||
name: lasuite-valkey
|
||||
- configMapRef:
|
||||
name: lasuite-s3
|
||||
- configMapRef:
|
||||
name: lasuite-oidc-provider
|
||||
env:
|
||||
- name: DB_PASSWORD
|
||||
valueFrom:
|
||||
secretKeyRef:
|
||||
name: messages-db-credentials
|
||||
key: password
|
||||
- name: DJANGO_SECRET_KEY
|
||||
valueFrom:
|
||||
secretKeyRef:
|
||||
name: messages-django-secret
|
||||
key: DJANGO_SECRET_KEY
|
||||
- name: SALT_KEY
|
||||
valueFrom:
|
||||
secretKeyRef:
|
||||
name: messages-django-secret
|
||||
key: SALT_KEY
|
||||
- name: MDA_API_SECRET
|
||||
valueFrom:
|
||||
secretKeyRef:
|
||||
name: messages-django-secret
|
||||
key: MDA_API_SECRET
|
||||
- name: OIDC_RP_CLIENT_ID
|
||||
valueFrom:
|
||||
secretKeyRef:
|
||||
name: oidc-messages
|
||||
key: CLIENT_ID
|
||||
- name: OIDC_RP_CLIENT_SECRET
|
||||
valueFrom:
|
||||
secretKeyRef:
|
||||
name: oidc-messages
|
||||
key: CLIENT_SECRET
|
||||
- name: AWS_S3_ACCESS_KEY_ID
|
||||
valueFrom:
|
||||
secretKeyRef:
|
||||
name: seaweedfs-s3-credentials
|
||||
key: S3_ACCESS_KEY
|
||||
- name: AWS_S3_SECRET_ACCESS_KEY
|
||||
valueFrom:
|
||||
secretKeyRef:
|
||||
name: seaweedfs-s3-credentials
|
||||
key: S3_SECRET_KEY
|
||||
- name: RSPAMD_PASSWORD
|
||||
valueFrom:
|
||||
secretKeyRef:
|
||||
name: messages-mpa-credentials
|
||||
key: RSPAMD_password
|
||||
- name: OIDC_STORE_REFRESH_TOKEN_KEY
|
||||
valueFrom:
|
||||
secretKeyRef:
|
||||
name: messages-django-secret
|
||||
key: OIDC_STORE_REFRESH_TOKEN_KEY
|
||||
- name: OIDC_RP_SCOPES
|
||||
value: "openid email profile offline_access"
|
||||
resources:
|
||||
limits:
|
||||
memory: 1Gi
|
||||
cpu: 500m
|
||||
requests:
|
||||
memory: 256Mi
|
||||
cpu: 100m
|
||||
containers:
|
||||
- name: messages-backend
|
||||
image: messages-backend
|
||||
command:
|
||||
- gunicorn
|
||||
- -c
|
||||
- /app/gunicorn.conf.py
|
||||
- messages.wsgi:application
|
||||
ports:
|
||||
- containerPort: 8000
|
||||
envFrom:
|
||||
- configMapRef:
|
||||
name: messages-config
|
||||
- configMapRef:
|
||||
name: lasuite-postgres
|
||||
- configMapRef:
|
||||
name: lasuite-valkey
|
||||
- configMapRef:
|
||||
name: lasuite-s3
|
||||
- configMapRef:
|
||||
name: lasuite-oidc-provider
|
||||
env:
|
||||
- name: DB_PASSWORD
|
||||
valueFrom:
|
||||
secretKeyRef:
|
||||
name: messages-db-credentials
|
||||
key: password
|
||||
- name: DJANGO_SECRET_KEY
|
||||
valueFrom:
|
||||
secretKeyRef:
|
||||
name: messages-django-secret
|
||||
key: DJANGO_SECRET_KEY
|
||||
- name: SALT_KEY
|
||||
valueFrom:
|
||||
secretKeyRef:
|
||||
name: messages-django-secret
|
||||
key: SALT_KEY
|
||||
- name: MDA_API_SECRET
|
||||
valueFrom:
|
||||
secretKeyRef:
|
||||
name: messages-django-secret
|
||||
key: MDA_API_SECRET
|
||||
- name: OIDC_RP_CLIENT_ID
|
||||
valueFrom:
|
||||
secretKeyRef:
|
||||
name: oidc-messages
|
||||
key: CLIENT_ID
|
||||
- name: OIDC_RP_CLIENT_SECRET
|
||||
valueFrom:
|
||||
secretKeyRef:
|
||||
name: oidc-messages
|
||||
key: CLIENT_SECRET
|
||||
- name: AWS_S3_ACCESS_KEY_ID
|
||||
valueFrom:
|
||||
secretKeyRef:
|
||||
name: seaweedfs-s3-credentials
|
||||
key: S3_ACCESS_KEY
|
||||
- name: AWS_S3_SECRET_ACCESS_KEY
|
||||
valueFrom:
|
||||
secretKeyRef:
|
||||
name: seaweedfs-s3-credentials
|
||||
key: S3_SECRET_KEY
|
||||
- name: RSPAMD_PASSWORD
|
||||
valueFrom:
|
||||
secretKeyRef:
|
||||
name: messages-mpa-credentials
|
||||
key: RSPAMD_password
|
||||
- name: OIDC_STORE_REFRESH_TOKEN_KEY
|
||||
valueFrom:
|
||||
secretKeyRef:
|
||||
name: messages-django-secret
|
||||
key: OIDC_STORE_REFRESH_TOKEN_KEY
|
||||
- name: OIDC_RP_SCOPES
|
||||
value: "openid email profile offline_access"
|
||||
livenessProbe:
|
||||
httpGet:
|
||||
path: /__heartbeat__/
|
||||
port: 8000
|
||||
initialDelaySeconds: 15
|
||||
periodSeconds: 20
|
||||
readinessProbe:
|
||||
httpGet:
|
||||
path: /__heartbeat__/
|
||||
port: 8000
|
||||
initialDelaySeconds: 10
|
||||
periodSeconds: 10
|
||||
resources:
|
||||
limits:
|
||||
memory: 1Gi
|
||||
cpu: 500m
|
||||
requests:
|
||||
memory: 256Mi
|
||||
cpu: 100m
|
||||
@@ -1,11 +0,0 @@
|
||||
apiVersion: v1
|
||||
kind: Service
|
||||
metadata:
|
||||
name: messages-backend
|
||||
namespace: lasuite
|
||||
spec:
|
||||
selector:
|
||||
app: messages-backend
|
||||
ports:
|
||||
- port: 80
|
||||
targetPort: 8000
|
||||
@@ -1,45 +0,0 @@
|
||||
apiVersion: v1
|
||||
kind: ConfigMap
|
||||
metadata:
|
||||
name: messages-config
|
||||
namespace: lasuite
|
||||
data:
|
||||
DJANGO_CONFIGURATION: Production
|
||||
DJANGO_SETTINGS_MODULE: messages.settings
|
||||
DJANGO_ALLOWED_HOSTS: mail.DOMAIN_SUFFIX,messages-backend.lasuite.svc.cluster.local
|
||||
ALLOWED_HOSTS: mail.DOMAIN_SUFFIX,messages-backend.lasuite.svc.cluster.local
|
||||
DJANGO_CSRF_TRUSTED_ORIGINS: https://mail.DOMAIN_SUFFIX
|
||||
DB_NAME: messages_db
|
||||
DB_USER: messages
|
||||
OPENSEARCH_URL: http://opensearch.data.svc.cluster.local:9200
|
||||
MDA_API_BASE_URL: http://messages-backend.lasuite.svc.cluster.local:80/api/v1.0/
|
||||
MYHOSTNAME: mail.DOMAIN_SUFFIX
|
||||
# rspamd URL (auth token injected separately from messages-mpa-credentials secret)
|
||||
SPAM_RSPAMD_URL: http://messages-mpa.lasuite.svc.cluster.local:8010/_api
|
||||
MESSAGES_FRONTEND_BACKEND_SERVER: messages-backend.lasuite.svc.cluster.local:80
|
||||
STORAGE_MESSAGE_IMPORTS_BUCKET_NAME: sunbeam-messages-imports
|
||||
STORAGE_MESSAGE_IMPORTS_ENDPOINT_URL: http://seaweedfs-filer.storage.svc.cluster.local:8333
|
||||
AWS_STORAGE_BUCKET_NAME: sunbeam-messages
|
||||
IDENTITY_PROVIDER: oidc
|
||||
FRONTEND_THEME: default
|
||||
DRIVE_BASE_URL: https://drive.DOMAIN_SUFFIX
|
||||
LOGIN_REDIRECT_URL: https://mail.DOMAIN_SUFFIX
|
||||
LOGOUT_REDIRECT_URL: https://mail.DOMAIN_SUFFIX
|
||||
OIDC_REDIRECT_ALLOWED_HOSTS: '["https://auth.DOMAIN_SUFFIX"]'
|
||||
MTA_OUT_MODE: direct
|
||||
# Create user accounts on first OIDC login (required — no pre-provisioning)
|
||||
OIDC_CREATE_USER: "True"
|
||||
# Redirect to home on auth failure (avoids HttpResponseRedirect(None) → /callback/None 404)
|
||||
LOGIN_REDIRECT_URL_FAILURE: https://mail.DOMAIN_SUFFIX
|
||||
# Store OIDC tokens in session so the Drive integration can proxy requests on behalf of the user.
|
||||
OIDC_STORE_ACCESS_TOKEN: "True"
|
||||
OIDC_STORE_REFRESH_TOKEN: "True"
|
||||
# Session lives 7 days — long enough to survive overnight/weekend without re-auth.
|
||||
# Default is 43200 (12h) which forces a login after a browser restart.
|
||||
SESSION_COOKIE_AGE: "604800"
|
||||
# Renew the id token 60 s before it expires (access_token TTL = 1h).
|
||||
# Without this the default falls back to SESSION_COOKIE_AGE (7 days), which means
|
||||
# every request sees the 1h token as "expiring within 7 days" and triggers a
|
||||
# prompt=none renewal on every page load — causing repeated auth loops.
|
||||
OIDC_RENEW_ID_TOKEN_EXPIRY_SECONDS: "60"
|
||||
# offline_access scope is set directly in the deployment env (overrides lasuite-oidc-provider envFrom).
|
||||
@@ -1,53 +0,0 @@
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
metadata:
|
||||
name: messages-frontend
|
||||
namespace: lasuite
|
||||
spec:
|
||||
replicas: 1
|
||||
selector:
|
||||
matchLabels:
|
||||
app: messages-frontend
|
||||
template:
|
||||
metadata:
|
||||
labels:
|
||||
app: messages-frontend
|
||||
spec:
|
||||
containers:
|
||||
- name: messages-frontend
|
||||
image: messages-frontend
|
||||
ports:
|
||||
- containerPort: 8080
|
||||
env:
|
||||
- name: MESSAGES_FRONTEND_BACKEND_SERVER
|
||||
value: messages-backend.lasuite.svc.cluster.local:80
|
||||
- name: PORT
|
||||
value: "8080"
|
||||
livenessProbe:
|
||||
httpGet:
|
||||
path: /
|
||||
port: 8080
|
||||
initialDelaySeconds: 10
|
||||
periodSeconds: 20
|
||||
readinessProbe:
|
||||
httpGet:
|
||||
path: /
|
||||
port: 8080
|
||||
initialDelaySeconds: 5
|
||||
periodSeconds: 10
|
||||
volumeMounts:
|
||||
- name: theme
|
||||
mountPath: /app/sunbeam-theme.css
|
||||
subPath: sunbeam-theme.css
|
||||
readOnly: true
|
||||
resources:
|
||||
limits:
|
||||
memory: 256Mi
|
||||
cpu: 250m
|
||||
requests:
|
||||
memory: 64Mi
|
||||
cpu: 50m
|
||||
volumes:
|
||||
- name: theme
|
||||
configMap:
|
||||
name: messages-frontend-theme
|
||||
@@ -1,11 +0,0 @@
|
||||
apiVersion: v1
|
||||
kind: Service
|
||||
metadata:
|
||||
name: messages-frontend
|
||||
namespace: lasuite
|
||||
spec:
|
||||
selector:
|
||||
app: messages-frontend
|
||||
ports:
|
||||
- port: 80
|
||||
targetPort: 8080
|
||||
@@ -1,50 +0,0 @@
|
||||
apiVersion: v1
|
||||
kind: ConfigMap
|
||||
metadata:
|
||||
name: messages-frontend-theme
|
||||
namespace: lasuite
|
||||
data:
|
||||
sunbeam-theme.css: |
|
||||
/*
|
||||
* O Estúdio — runtime brand overrides for messages-frontend.
|
||||
* Loaded via <link href="/sunbeam-theme.css"> injected in _document.tsx.
|
||||
* Override Cunningham v4 --c--globals--* variables (no rebuild for updates).
|
||||
*/
|
||||
@import url('https://fonts.googleapis.com/css2?family=Ysabeau:ital,wght@0,100..900;1,100..900&display=swap');
|
||||
|
||||
:root {
|
||||
--c--globals--font--families--base: 'Ysabeau Variable', Inter, sans-serif;
|
||||
--c--globals--font--families--accent: 'Ysabeau Variable', Inter, sans-serif;
|
||||
|
||||
/* Brand — amber/gold palette */
|
||||
--c--globals--colors--brand-050: #fffbeb;
|
||||
--c--globals--colors--brand-100: #fef3c7;
|
||||
--c--globals--colors--brand-150: #fde9a0;
|
||||
--c--globals--colors--brand-200: #fde68a;
|
||||
--c--globals--colors--brand-250: #fde047;
|
||||
--c--globals--colors--brand-300: #fcd34d;
|
||||
--c--globals--colors--brand-350: #fbcf3f;
|
||||
--c--globals--colors--brand-400: #fbbf24;
|
||||
--c--globals--colors--brand-450: #f8b31a;
|
||||
--c--globals--colors--brand-500: #f59e0b;
|
||||
--c--globals--colors--brand-550: #e8920a;
|
||||
--c--globals--colors--brand-600: #d97706;
|
||||
--c--globals--colors--brand-650: #c26d05;
|
||||
--c--globals--colors--brand-700: #b45309;
|
||||
--c--globals--colors--brand-750: #9a4508;
|
||||
--c--globals--colors--brand-800: #92400e;
|
||||
--c--globals--colors--brand-850: #7c370c;
|
||||
--c--globals--colors--brand-900: #78350f;
|
||||
--c--globals--colors--brand-950: #451a03;
|
||||
|
||||
/* Logo gradient */
|
||||
--c--globals--colors--logo-1: #f59e0b;
|
||||
--c--globals--colors--logo-2: #d97706;
|
||||
--c--globals--colors--logo-1-light: #f59e0b;
|
||||
--c--globals--colors--logo-2-light: #d97706;
|
||||
--c--globals--colors--logo-1-dark: #fcd34d;
|
||||
--c--globals--colors--logo-2-dark: #fbbf24;
|
||||
|
||||
/* PWA theme color */
|
||||
--sunbeam-brand: #f59e0b;
|
||||
}
|
||||
@@ -1,56 +0,0 @@
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
metadata:
|
||||
name: messages-mpa
|
||||
namespace: lasuite
|
||||
spec:
|
||||
replicas: 1
|
||||
selector:
|
||||
matchLabels:
|
||||
app: messages-mpa
|
||||
template:
|
||||
metadata:
|
||||
labels:
|
||||
app: messages-mpa
|
||||
spec:
|
||||
containers:
|
||||
- name: messages-mpa
|
||||
image: messages-mpa
|
||||
ports:
|
||||
- containerPort: 8010
|
||||
env:
|
||||
- name: RSPAMD_password
|
||||
valueFrom:
|
||||
secretKeyRef:
|
||||
name: messages-mpa-credentials
|
||||
key: RSPAMD_password
|
||||
- name: PORT
|
||||
value: "8010"
|
||||
- name: REDIS_HOST
|
||||
value: valkey.data.svc.cluster.local
|
||||
- name: REDIS_PORT
|
||||
value: "6379"
|
||||
volumeMounts:
|
||||
- name: dkim-key
|
||||
mountPath: /etc/rspamd/dkim
|
||||
readOnly: true
|
||||
- name: dkim-signing-conf
|
||||
mountPath: /etc/rspamd/local.d
|
||||
readOnly: true
|
||||
resources:
|
||||
limits:
|
||||
memory: 768Mi
|
||||
cpu: 250m
|
||||
requests:
|
||||
memory: 256Mi
|
||||
cpu: 50m
|
||||
volumes:
|
||||
- name: dkim-key
|
||||
secret:
|
||||
secretName: messages-dkim-key
|
||||
items:
|
||||
- key: dkim-private-key
|
||||
path: default.sunbeam.pt.key
|
||||
- name: dkim-signing-conf
|
||||
configMap:
|
||||
name: messages-mpa-rspamd-config
|
||||
@@ -1,13 +0,0 @@
|
||||
apiVersion: v1
|
||||
kind: ConfigMap
|
||||
metadata:
|
||||
name: messages-mpa-rspamd-config
|
||||
namespace: lasuite
|
||||
data:
|
||||
dkim_signing.conf: |
|
||||
enabled = true;
|
||||
selector = "default";
|
||||
path = "/etc/rspamd/dkim/$domain.$selector.key";
|
||||
sign_authenticated = true;
|
||||
sign_local = true;
|
||||
use_domain = "header";
|
||||
@@ -1,11 +0,0 @@
|
||||
apiVersion: v1
|
||||
kind: Service
|
||||
metadata:
|
||||
name: messages-mpa
|
||||
namespace: lasuite
|
||||
spec:
|
||||
selector:
|
||||
app: messages-mpa
|
||||
ports:
|
||||
- port: 8010
|
||||
targetPort: 8010
|
||||
@@ -1,67 +0,0 @@
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
metadata:
|
||||
name: messages-mta-in
|
||||
namespace: lasuite
|
||||
spec:
|
||||
replicas: 1
|
||||
# Recreate: hostPort 25 blocks RollingUpdate — the new pod can't
|
||||
# schedule while the old one still holds the port.
|
||||
strategy:
|
||||
type: Recreate
|
||||
selector:
|
||||
matchLabels:
|
||||
app: messages-mta-in
|
||||
template:
|
||||
metadata:
|
||||
labels:
|
||||
app: messages-mta-in
|
||||
spec:
|
||||
containers:
|
||||
- name: messages-mta-in
|
||||
image: messages-mta-in
|
||||
ports:
|
||||
- containerPort: 25
|
||||
env:
|
||||
- name: MDA_API_BASE_URL
|
||||
valueFrom:
|
||||
configMapKeyRef:
|
||||
name: messages-config
|
||||
key: MDA_API_BASE_URL
|
||||
- name: MDA_API_SECRET
|
||||
valueFrom:
|
||||
secretKeyRef:
|
||||
name: messages-django-secret
|
||||
key: MDA_API_SECRET
|
||||
- name: MAX_INCOMING_EMAIL_SIZE
|
||||
value: "30000000"
|
||||
# Liveness: verify the delivery milter process is running and the
|
||||
# unix socket exists. The milter is a long-lived Python process that
|
||||
# can hang silently after days of uptime (COE-2026-002 addendum).
|
||||
# Without this probe, postfix returns 451 to all inbound mail and
|
||||
# nobody notices until senders complain.
|
||||
livenessProbe:
|
||||
exec:
|
||||
command:
|
||||
- sh
|
||||
- -c
|
||||
- "test -S /var/spool/postfix/milter/delivery.sock && kill -0 $(cat /var/run/milter.pid 2>/dev/null || pgrep -f delivery_milter.py)"
|
||||
initialDelaySeconds: 15
|
||||
periodSeconds: 30
|
||||
timeoutSeconds: 5
|
||||
failureThreshold: 3
|
||||
readinessProbe:
|
||||
tcpSocket:
|
||||
port: 25
|
||||
initialDelaySeconds: 10
|
||||
periodSeconds: 15
|
||||
securityContext:
|
||||
capabilities:
|
||||
add: ["NET_BIND_SERVICE"]
|
||||
resources:
|
||||
limits:
|
||||
memory: 256Mi
|
||||
cpu: 250m
|
||||
requests:
|
||||
memory: 64Mi
|
||||
cpu: 50m
|
||||
@@ -1,11 +0,0 @@
|
||||
apiVersion: v1
|
||||
kind: Service
|
||||
metadata:
|
||||
name: messages-mta-in
|
||||
namespace: lasuite
|
||||
spec:
|
||||
selector:
|
||||
app: messages-mta-in
|
||||
ports:
|
||||
- port: 25
|
||||
targetPort: 25
|
||||
@@ -1,43 +0,0 @@
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
metadata:
|
||||
name: messages-mta-out
|
||||
namespace: lasuite
|
||||
spec:
|
||||
replicas: 1
|
||||
selector:
|
||||
matchLabels:
|
||||
app: messages-mta-out
|
||||
template:
|
||||
metadata:
|
||||
labels:
|
||||
app: messages-mta-out
|
||||
spec:
|
||||
containers:
|
||||
- name: messages-mta-out
|
||||
image: messages-mta-out
|
||||
ports:
|
||||
- containerPort: 587
|
||||
env:
|
||||
- name: MYHOSTNAME
|
||||
valueFrom:
|
||||
configMapKeyRef:
|
||||
name: messages-config
|
||||
key: MYHOSTNAME
|
||||
- name: SMTP_USERNAME
|
||||
valueFrom:
|
||||
secretKeyRef:
|
||||
name: messages-mta-out-credentials
|
||||
key: SMTP_USERNAME
|
||||
- name: SMTP_PASSWORD
|
||||
valueFrom:
|
||||
secretKeyRef:
|
||||
name: messages-mta-out-credentials
|
||||
key: SMTP_PASSWORD
|
||||
resources:
|
||||
limits:
|
||||
memory: 256Mi
|
||||
cpu: 250m
|
||||
requests:
|
||||
memory: 64Mi
|
||||
cpu: 50m
|
||||
@@ -1,11 +0,0 @@
|
||||
apiVersion: v1
|
||||
kind: Service
|
||||
metadata:
|
||||
name: messages-mta-out
|
||||
namespace: lasuite
|
||||
spec:
|
||||
selector:
|
||||
app: messages-mta-out
|
||||
ports:
|
||||
- port: 587
|
||||
targetPort: 587
|
||||
@@ -1,35 +0,0 @@
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
metadata:
|
||||
name: messages-socks-proxy
|
||||
namespace: lasuite
|
||||
spec:
|
||||
replicas: 1
|
||||
selector:
|
||||
matchLabels:
|
||||
app: messages-socks-proxy
|
||||
template:
|
||||
metadata:
|
||||
labels:
|
||||
app: messages-socks-proxy
|
||||
spec:
|
||||
containers:
|
||||
- name: messages-socks-proxy
|
||||
image: messages-socks-proxy
|
||||
ports:
|
||||
- containerPort: 1080
|
||||
env:
|
||||
- name: PROXY_USERS
|
||||
valueFrom:
|
||||
secretKeyRef:
|
||||
name: messages-socks-credentials
|
||||
key: PROXY_USERS
|
||||
- name: PROXY_SOURCE_IP_WHITELIST
|
||||
value: 10.0.0.0/8
|
||||
resources:
|
||||
limits:
|
||||
memory: 128Mi
|
||||
cpu: 100m
|
||||
requests:
|
||||
memory: 32Mi
|
||||
cpu: 25m
|
||||
@@ -1,11 +0,0 @@
|
||||
apiVersion: v1
|
||||
kind: Service
|
||||
metadata:
|
||||
name: messages-socks-proxy
|
||||
namespace: lasuite
|
||||
spec:
|
||||
selector:
|
||||
app: messages-socks-proxy
|
||||
ports:
|
||||
- port: 1080
|
||||
targetPort: 1080
|
||||
@@ -1,90 +0,0 @@
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
metadata:
|
||||
name: messages-worker
|
||||
namespace: lasuite
|
||||
spec:
|
||||
replicas: 1
|
||||
selector:
|
||||
matchLabels:
|
||||
app: messages-worker
|
||||
template:
|
||||
metadata:
|
||||
labels:
|
||||
app: messages-worker
|
||||
spec:
|
||||
containers:
|
||||
- name: messages-worker
|
||||
image: messages-backend
|
||||
command: ["python", "worker.py", "--loglevel=INFO", "--concurrency=3"]
|
||||
envFrom:
|
||||
- configMapRef:
|
||||
name: messages-config
|
||||
- configMapRef:
|
||||
name: lasuite-postgres
|
||||
- configMapRef:
|
||||
name: lasuite-valkey
|
||||
- configMapRef:
|
||||
name: lasuite-s3
|
||||
- configMapRef:
|
||||
name: lasuite-oidc-provider
|
||||
env:
|
||||
- name: DB_PASSWORD
|
||||
valueFrom:
|
||||
secretKeyRef:
|
||||
name: messages-db-credentials
|
||||
key: password
|
||||
- name: DJANGO_SECRET_KEY
|
||||
valueFrom:
|
||||
secretKeyRef:
|
||||
name: messages-django-secret
|
||||
key: DJANGO_SECRET_KEY
|
||||
- name: SALT_KEY
|
||||
valueFrom:
|
||||
secretKeyRef:
|
||||
name: messages-django-secret
|
||||
key: SALT_KEY
|
||||
- name: MDA_API_SECRET
|
||||
valueFrom:
|
||||
secretKeyRef:
|
||||
name: messages-django-secret
|
||||
key: MDA_API_SECRET
|
||||
- name: OIDC_RP_CLIENT_ID
|
||||
valueFrom:
|
||||
secretKeyRef:
|
||||
name: oidc-messages
|
||||
key: CLIENT_ID
|
||||
- name: OIDC_RP_CLIENT_SECRET
|
||||
valueFrom:
|
||||
secretKeyRef:
|
||||
name: oidc-messages
|
||||
key: CLIENT_SECRET
|
||||
- name: AWS_S3_ACCESS_KEY_ID
|
||||
valueFrom:
|
||||
secretKeyRef:
|
||||
name: seaweedfs-s3-credentials
|
||||
key: S3_ACCESS_KEY
|
||||
- name: AWS_S3_SECRET_ACCESS_KEY
|
||||
valueFrom:
|
||||
secretKeyRef:
|
||||
name: seaweedfs-s3-credentials
|
||||
key: S3_SECRET_KEY
|
||||
- name: RSPAMD_PASSWORD
|
||||
valueFrom:
|
||||
secretKeyRef:
|
||||
name: messages-mpa-credentials
|
||||
key: RSPAMD_password
|
||||
- name: OIDC_STORE_REFRESH_TOKEN_KEY
|
||||
valueFrom:
|
||||
secretKeyRef:
|
||||
name: messages-django-secret
|
||||
key: OIDC_STORE_REFRESH_TOKEN_KEY
|
||||
- name: OIDC_RP_SCOPES
|
||||
value: "openid email profile offline_access"
|
||||
resources:
|
||||
limits:
|
||||
memory: 1Gi
|
||||
cpu: "1"
|
||||
requests:
|
||||
memory: 256Mi
|
||||
cpu: 100m
|
||||
@@ -1,20 +0,0 @@
|
||||
# Patch: mount the nginx ConfigMap into drive-frontend to enable the media
|
||||
# auth_request proxy (validates Drive session before serving S3 files).
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
metadata:
|
||||
name: drive-frontend
|
||||
namespace: lasuite
|
||||
spec:
|
||||
template:
|
||||
spec:
|
||||
containers:
|
||||
- name: drive
|
||||
volumeMounts:
|
||||
- name: nginx-conf
|
||||
mountPath: /etc/nginx/conf.d/default.conf
|
||||
subPath: default.conf
|
||||
volumes:
|
||||
- name: nginx-conf
|
||||
configMap:
|
||||
name: drive-frontend-nginx-conf
|
||||
@@ -1,89 +0,0 @@
|
||||
# Init container that waits for Collabora and configures WOPI on every pod start.
|
||||
#
|
||||
# The Drive chart's configure_wopi Job is designed for ArgoCD PostSync hooks
|
||||
# and only runs on `sunbeam apply`. On server restart, no one re-triggers it,
|
||||
# so WOPI editing silently breaks. This init container fixes that — every time
|
||||
# a Drive backend pod starts (restart, rollout, scale-up), it waits for
|
||||
# Collabora and runs trigger_wopi_configuration before the main container.
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
metadata:
|
||||
name: drive-backend
|
||||
namespace: lasuite
|
||||
spec:
|
||||
template:
|
||||
spec:
|
||||
initContainers:
|
||||
- name: configure-wopi
|
||||
image: lasuite/drive-backend:latest
|
||||
command:
|
||||
- "/bin/sh"
|
||||
- "-c"
|
||||
- |
|
||||
echo "Waiting for Collabora..."
|
||||
for i in $(seq 1 36); do
|
||||
if wget -qO /dev/null --timeout=5 http://collabora.lasuite.svc.cluster.local:9980/hosting/discovery 2>/dev/null; then
|
||||
echo "Collabora ready — configuring WOPI..."
|
||||
python manage.py trigger_wopi_configuration
|
||||
exit $?
|
||||
fi
|
||||
echo "Attempt $i/36: not ready, retrying in 5s..."
|
||||
sleep 5
|
||||
done
|
||||
echo "WARN: Collabora not ready after 3 minutes — starting without WOPI"
|
||||
exit 0
|
||||
env:
|
||||
# Database — minimum needed for Django manage.py
|
||||
- name: DB_ENGINE
|
||||
value: django.db.backends.postgresql
|
||||
- name: DB_NAME
|
||||
value: drive_db
|
||||
- name: DB_USER
|
||||
value: drive
|
||||
- name: DB_HOST
|
||||
valueFrom:
|
||||
configMapKeyRef:
|
||||
name: lasuite-postgres
|
||||
key: DB_HOST
|
||||
- name: DB_PORT
|
||||
valueFrom:
|
||||
configMapKeyRef:
|
||||
name: lasuite-postgres
|
||||
key: DB_PORT
|
||||
- name: DB_PASSWORD
|
||||
valueFrom:
|
||||
secretKeyRef:
|
||||
name: drive-db-credentials
|
||||
key: password
|
||||
# Django
|
||||
- name: DJANGO_CONFIGURATION
|
||||
value: Production
|
||||
- name: DJANGO_SECRET_KEY
|
||||
valueFrom:
|
||||
secretKeyRef:
|
||||
name: drive-django-secret
|
||||
key: DJANGO_SECRET_KEY
|
||||
# Redis/Celery — trigger_wopi_configuration dispatches a Celery task
|
||||
- name: REDIS_URL
|
||||
valueFrom:
|
||||
configMapKeyRef:
|
||||
name: lasuite-valkey
|
||||
key: REDIS_URL
|
||||
- name: DJANGO_CELERY_BROKER_URL
|
||||
valueFrom:
|
||||
configMapKeyRef:
|
||||
name: lasuite-valkey
|
||||
key: CELERY_BROKER_URL
|
||||
# WOPI
|
||||
- name: WOPI_CLIENTS
|
||||
value: collabora
|
||||
- name: WOPI_COLLABORA_DISCOVERY_URL
|
||||
value: http://collabora.lasuite.svc.cluster.local:9980/hosting/discovery
|
||||
- name: WOPI_SRC_BASE_URL
|
||||
value: https://drive.DOMAIN_SUFFIX
|
||||
resources:
|
||||
limits:
|
||||
memory: 128Mi
|
||||
requests:
|
||||
memory: 64Mi
|
||||
cpu: 25m
|
||||
@@ -1,81 +0,0 @@
|
||||
# Postfix MTA for the Messages email platform.
|
||||
#
|
||||
# MTA-out: accepts SMTP from cluster-internal services (Kratos, Messages Django),
|
||||
# signs with DKIM, and relays outbound via Scaleway TEM.
|
||||
#
|
||||
# MTA-in: receives inbound email from the internet (routed via Pingora on port 25).
|
||||
# In local dev, no MX record points here so inbound never arrives.
|
||||
#
|
||||
# Credentials: Secret "postfix-tem-credentials" with keys:
|
||||
# smtp_user — Scaleway TEM SMTP username (project ID)
|
||||
# smtp_password — Scaleway TEM SMTP password (API key)
|
||||
#
|
||||
# DKIM keys: Secret "postfix-dkim" with key:
|
||||
# private.key — DKIM private key for sunbeam.pt (generated once; add DNS TXT record)
|
||||
# selector — DKIM selector (e.g. "mail")
|
||||
#
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
metadata:
|
||||
name: postfix
|
||||
namespace: lasuite
|
||||
spec:
|
||||
replicas: 1
|
||||
selector:
|
||||
matchLabels:
|
||||
app: postfix
|
||||
template:
|
||||
metadata:
|
||||
labels:
|
||||
app: postfix
|
||||
spec:
|
||||
automountServiceAccountToken: false
|
||||
containers:
|
||||
- name: postfix
|
||||
image: boky/postfix:latest
|
||||
ports:
|
||||
- name: smtp
|
||||
containerPort: 25
|
||||
protocol: TCP
|
||||
env:
|
||||
# Accept mail from all cluster-internal pods.
|
||||
- name: MYNETWORKS
|
||||
value: "10.0.0.0/8 172.16.0.0/12 192.168.0.0/16 127.0.0.0/8"
|
||||
# Sending domain — replaced by sed at deploy time.
|
||||
- name: ALLOWED_SENDER_DOMAINS
|
||||
value: "DOMAIN_SUFFIX"
|
||||
# Scaleway TEM outbound relay.
|
||||
- name: RELAYHOST
|
||||
value: "[smtp.tem.scw.cloud]:587"
|
||||
- name: SASL_USER
|
||||
valueFrom:
|
||||
secretKeyRef:
|
||||
name: postfix-tem-credentials
|
||||
key: smtp_user
|
||||
optional: true # allows pod to start before secret exists
|
||||
- name: SASL_PASSWORD
|
||||
valueFrom:
|
||||
secretKeyRef:
|
||||
name: postfix-tem-credentials
|
||||
key: smtp_password
|
||||
optional: true
|
||||
resources:
|
||||
limits:
|
||||
memory: 64Mi
|
||||
requests:
|
||||
memory: 32Mi
|
||||
cpu: 10m
|
||||
---
|
||||
apiVersion: v1
|
||||
kind: Service
|
||||
metadata:
|
||||
name: postfix
|
||||
namespace: lasuite
|
||||
spec:
|
||||
selector:
|
||||
app: postfix
|
||||
ports:
|
||||
- name: smtp
|
||||
port: 25
|
||||
targetPort: 25
|
||||
protocol: TCP
|
||||
@@ -1,44 +0,0 @@
|
||||
apiVersion: v1
|
||||
kind: ConfigMap
|
||||
metadata:
|
||||
name: projects-config
|
||||
namespace: lasuite
|
||||
data:
|
||||
BASE_URL: "https://projects.DOMAIN_SUFFIX"
|
||||
TRUST_PROXY: "1"
|
||||
NODE_ENV: "production"
|
||||
|
||||
# OIDC — Hydra as the identity provider
|
||||
OIDC_ISSUER: "https://auth.DOMAIN_SUFFIX/"
|
||||
OIDC_SCOPES: "openid email profile"
|
||||
OIDC_ENFORCED: "true"
|
||||
OIDC_IGNORE_USERNAME: "true"
|
||||
OIDC_IGNORE_ROLES: "true"
|
||||
OIDC_ADMIN_ROLES: "*"
|
||||
OIDC_FULLNAME_ATTRIBUTES: "given_name,family_name"
|
||||
# Planka defaults to response_mode=fragment, which returns the auth code in the
|
||||
# URL hash (#code=...). The SPA callback handler doesn't parse fragments correctly,
|
||||
# causing a silent auth loop. Use query mode so the code comes as ?code=...
|
||||
OIDC_RESPONSE_MODE: "query"
|
||||
|
||||
# S3 file storage via SeaweedFS
|
||||
S3_ENDPOINT: "http://seaweedfs-filer.storage.svc.cluster.local:8333"
|
||||
S3_BUCKET: "projects"
|
||||
S3_REGION: "us-east-1"
|
||||
S3_FORCE_PATH_STYLE: "true"
|
||||
|
||||
# SMTP via in-cluster Postfix relay
|
||||
SMTP_HOST: "postfix.lasuite.svc.cluster.local"
|
||||
SMTP_PORT: "25"
|
||||
SMTP_SECURE: "false"
|
||||
SMTP_FROM: "Projects <noreply@DOMAIN_SUFFIX>"
|
||||
|
||||
# La Gaufre waffle menu widget
|
||||
REACT_APP_LAGAUFRE_WIDGET_API_URL: "https://integration.DOMAIN_SUFFIX/api/v2/services.json"
|
||||
REACT_APP_LAGAUFRE_WIDGET_PATH: "https://integration.DOMAIN_SUFFIX/api/v2/"
|
||||
|
||||
# Default language for new OIDC users (browser detection fallback if unset)
|
||||
DEFAULT_LANGUAGE: "en-US"
|
||||
|
||||
# Permissions
|
||||
ALLOW_ALL_TO_CREATE_PROJECTS: "true"
|
||||
@@ -1,121 +0,0 @@
|
||||
# Planka-based Kanban project management — single container (SPA bundled into Sails backend).
|
||||
# Image: src.DOMAIN_SUFFIX/studio/projects:latest
|
||||
# Built from projects/Dockerfile
|
||||
#
|
||||
# Secrets injected via env vars:
|
||||
# - projects-db-url (VaultDynamicSecret): DATABASE_URL
|
||||
# - projects-app-secrets (VaultStaticSecret): SECRET_KEY
|
||||
# - oidc-projects (Hydra Maester): CLIENT_ID, CLIENT_SECRET
|
||||
# - seaweedfs-s3-credentials (VaultStaticSecret): S3_ACCESS_KEY, S3_SECRET_KEY
|
||||
---
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
metadata:
|
||||
name: projects
|
||||
namespace: lasuite
|
||||
spec:
|
||||
replicas: 1
|
||||
selector:
|
||||
matchLabels:
|
||||
app: projects
|
||||
template:
|
||||
metadata:
|
||||
labels:
|
||||
app: projects
|
||||
spec:
|
||||
initContainers:
|
||||
- name: db-migrate
|
||||
image: projects
|
||||
command: ["node", "db/init.js"]
|
||||
envFrom:
|
||||
- configMapRef:
|
||||
name: projects-config
|
||||
env:
|
||||
- name: DATABASE_URL
|
||||
valueFrom:
|
||||
secretKeyRef:
|
||||
name: projects-db-url
|
||||
key: url
|
||||
- name: SECRET_KEY
|
||||
valueFrom:
|
||||
secretKeyRef:
|
||||
name: projects-app-secrets
|
||||
key: SECRET_KEY
|
||||
resources:
|
||||
limits:
|
||||
memory: 256Mi
|
||||
requests:
|
||||
memory: 128Mi
|
||||
cpu: 50m
|
||||
containers:
|
||||
- name: projects
|
||||
image: projects
|
||||
command: ["node", "app.js", "--prod"]
|
||||
ports:
|
||||
- name: http
|
||||
containerPort: 1337
|
||||
envFrom:
|
||||
- configMapRef:
|
||||
name: projects-config
|
||||
env:
|
||||
- name: DATABASE_URL
|
||||
valueFrom:
|
||||
secretKeyRef:
|
||||
name: projects-db-url
|
||||
key: url
|
||||
- name: SECRET_KEY
|
||||
valueFrom:
|
||||
secretKeyRef:
|
||||
name: projects-app-secrets
|
||||
key: SECRET_KEY
|
||||
- name: OIDC_CLIENT_ID
|
||||
valueFrom:
|
||||
secretKeyRef:
|
||||
name: oidc-projects
|
||||
key: CLIENT_ID
|
||||
- name: OIDC_CLIENT_SECRET
|
||||
valueFrom:
|
||||
secretKeyRef:
|
||||
name: oidc-projects
|
||||
key: CLIENT_SECRET
|
||||
- name: S3_ACCESS_KEY
|
||||
valueFrom:
|
||||
secretKeyRef:
|
||||
name: seaweedfs-s3-credentials
|
||||
key: S3_ACCESS_KEY
|
||||
- name: S3_SECRET_KEY
|
||||
valueFrom:
|
||||
secretKeyRef:
|
||||
name: seaweedfs-s3-credentials
|
||||
key: S3_SECRET_KEY
|
||||
resources:
|
||||
limits:
|
||||
memory: 512Mi
|
||||
requests:
|
||||
memory: 256Mi
|
||||
cpu: 50m
|
||||
livenessProbe:
|
||||
httpGet:
|
||||
path: /
|
||||
port: http
|
||||
initialDelaySeconds: 15
|
||||
periodSeconds: 30
|
||||
readinessProbe:
|
||||
httpGet:
|
||||
path: /
|
||||
port: http
|
||||
initialDelaySeconds: 10
|
||||
periodSeconds: 10
|
||||
---
|
||||
apiVersion: v1
|
||||
kind: Service
|
||||
metadata:
|
||||
name: projects
|
||||
namespace: lasuite
|
||||
spec:
|
||||
selector:
|
||||
app: projects
|
||||
ports:
|
||||
- name: http
|
||||
port: 80
|
||||
targetPort: 1337
|
||||
@@ -1,45 +0,0 @@
|
||||
apiVersion: batch/v1
|
||||
kind: Job
|
||||
metadata:
|
||||
name: seaweedfs-bucket-init
|
||||
namespace: lasuite
|
||||
annotations:
|
||||
# Run once on first deploy; manually delete to re-run if needed.
|
||||
helm.sh/hook: post-install
|
||||
spec:
|
||||
template:
|
||||
spec:
|
||||
restartPolicy: OnFailure
|
||||
containers:
|
||||
- name: mc
|
||||
image: minio/mc:latest
|
||||
command:
|
||||
- /bin/sh
|
||||
- -c
|
||||
- |
|
||||
set -e
|
||||
ENDPOINT=http://seaweedfs-filer.storage.svc.cluster.local:8333
|
||||
mc alias set weed "$ENDPOINT" "$S3_ACCESS_KEY" "$S3_SECRET_KEY"
|
||||
|
||||
for bucket in \
|
||||
sunbeam-meet \
|
||||
sunbeam-drive \
|
||||
sunbeam-messages \
|
||||
sunbeam-messages-imports \
|
||||
sunbeam-conversations \
|
||||
sunbeam-git-lfs \
|
||||
sunbeam-game-assets \
|
||||
sunbeam-ml-models \
|
||||
sunbeam-stalwart \
|
||||
sunbeam-sccache; do
|
||||
mc mb --ignore-existing "weed/$bucket"
|
||||
echo "Ensured bucket: $bucket"
|
||||
done
|
||||
|
||||
# Enable object versioning on buckets that require it.
|
||||
# Drive's WOPI GetFile response includes X-WOPI-ItemVersion from S3 VersionId.
|
||||
# SeaweedFS doesn't support `mc versioning` — use the S3 API directly.
|
||||
mc versioning enable weed/sunbeam-drive || echo "Versioning not supported by SeaweedFS mc, skipping (filer handles versioning natively)"
|
||||
envFrom:
|
||||
- secretRef:
|
||||
name: seaweedfs-s3-credentials
|
||||
Reference in New Issue
Block a user