eurooffice
EuroOffice collaborative document suite — Postgres persistence, S3 blob storage, LibreOffice conversions, SMTP delivery and websocket collaboration
@r8s/eurooffice
Components (1)
EuroOffice
EuroOffice — collaborative document suite.
import { Platform } from '@r8s/recipes'
import { EuroOffice } from '@r8s/eurooffice'
export default (
<Platform secrets={{ backend: 'openbao', mount: 'kv', path: 'apps' }}>
<EuroOffice
name="docs"
host="docs.example.com"
objectStorage={{
endpoint: 'https://s3.internal.example.com',
bucket: 'docs-blobs',
credentialsSecret: 'docs-blobs-credentials',
}}
smtp={{ host: 'smtp.example.com', port: 587, from: 'no-reply@${env:MAIL_DOMAIN}' }}
/>
</Platform>
)
namestringOptional—Resource name (defaults to 'eurooffice')
namespacestringOptional—Kubernetes namespace (defaults to 'default')
versionstringOptional—Container image tag (defaults to 'latest' — pin a version in production)
hoststringRequired—Public hostname for the document suite (required)
replicasnumberOptional—Number of app replicas. With websockets enabled (the default) this defaults to 1: websocket sessions are pinned to the pod that accepted the connection and the workload has no session affinity, so >1 replicas means collaborators on different pods stop seeing each other live. An explicitly set replicas is rendered as asked — pair it with a sticky-session (source-IP) ingress strategy for live co-editing. With websockets: false the default is 2 (the app is stateless — scale freely).
websocketsbooleanOptional—Collaborative editing over websockets (default: true). Disable only for single-user or read-only deployments — document presence, cursor sharing and live co-editing all rely on websockets.
objectStorage{ endpoint: string, bucket: string, credentialsSecret: string, region?: string }Required—S3-compatible object storage for document blobs and attachments (RustFS in the platform). Required — reference a bucket whose credentials live in a Secret provisioned by the secrets backend (keys: accessKey, secretKey) — never plaintext.
smtp{ host: string, port?: number, from?: string }Optional—Outgoing SMTP for invitations and notifications. The SMTP password is delivered via secretKeyRef from the ${name}-secrets bundle (key: smtpPassword) — never plaintext.
conversionsbooleanOptional—LibreOffice headless document-conversion workers (same app image, which must include soffice). Adds a ${name}-soffice Deployment + Service; the app reaches it at SOFFICE_HOST:SOFFICE_PORT. Workers serve the UNO socket (TCP), not HTTP — their probes probe the socket.
conversionWorkersnumberOptional—LibreOffice conversion worker replicas (defaults to 1, only used with conversions)
secretsNamestringOptional—Name of an existing Secret holding secretKey and smtpPassword. Required unless a secrets backend (openbao/vault) is configured on the surrounding Platform — the backend then provisions them. Plaintext values are not supported.
resources{ requests?: { cpu?: string, memory?: string }, limits?: { cpu?: string, memory?: string } }Optional—Requested app resources
tls{ secretName: string, clusterIssuer: string }Optional—TLS configuration (defaults to letsencrypt-prod cluster issuer)