# OdooSky v3 instance-template-v3 — default values. # # Per-tenant overlay repos override only the keys that differ from these # defaults. Keep this file as the single source of truth for what an # Odoo instance looks like by default; do not duplicate defaults in the # overlay schema or in Tower-Go. instance: # Short slug used in K8s object names + as the Helm release name. # Must be DNS-safe (lowercase, no underscores, <= 40 chars). code: demo # The full HTTPS hostname this instance answers on. # Tenants live under *.tenants.odoosky.org (covered by wildcard DNS A). domain: demo.tenants.odoosky.org # Named size — looked up against the `sizes` table below to derive # CPU / memory limits + Odoo workers. Per-tenant overlays only need # `instance.size: medium` (etc); they don't have to know the numbers. size: small # The named-size table. Single source of truth for what each instance # tier actually gets. Adjust here, ALL future instances pick up the # new defaults on next reconcile. Existing instances keep their # previously-rendered manifests until ArgoCD re-syncs. # # Numbers are TOTAL across Odoo + Postgres containers. Odoo/PG split # is roughly 70/30 (matches v2 production tuning). Workers follow # the standard `(cpus*2 - 1)` heuristic capped by RAM headroom. # # tier total RAM total CPU PVC (fs/db) workers use case # tiny 1.5 GB 1.0 5/5 GB 0 sandbox/dev only — NOT recommended for production # small 3 GB 2.0 10/10 GB 1 5–15 users — RECOMMENDED MINIMUM # medium 6 GB 4.0 20/20 GB 2 15–50 users # large 12 GB 8.0 50/50 GB 4 50–150 users # custom operator operator operator operator HA / enterprise — wizard collects all fields sizes: tiny: odoo: requests: { memory: 384Mi, cpu: 200m } limits: { memory: 1Gi, cpu: 700m } postgres: requests: { memory: 128Mi, cpu: 100m } limits: { memory: 512Mi, cpu: 300m } storage: filestore: 5Gi database: 5Gi small: odoo: requests: { memory: 1Gi, cpu: 500m } limits: { memory: 2Gi, cpu: "1" } postgres: requests: { memory: 512Mi, cpu: 250m } limits: { memory: 1Gi, cpu: "1" } storage: filestore: 10Gi database: 10Gi medium: odoo: requests: { memory: 2Gi, cpu: "1" } limits: { memory: 4Gi, cpu: "2" } postgres: requests: { memory: 1Gi, cpu: 500m } limits: { memory: 2Gi, cpu: "2" } storage: filestore: 25Gi database: 25Gi large: odoo: requests: { memory: 4Gi, cpu: "2" } limits: { memory: 8Gi, cpu: "5" } postgres: requests: { memory: 2Gi, cpu: "1" } limits: { memory: 4Gi, cpu: "3" } storage: filestore: 50Gi database: 100Gi # imageMirror — air-gap support (audit B.10). When `registry` is # set, the chart prepends it to .Values.odoo.image AND # .Values.postgres.image references at template-render time. So an # air-gapped customer pointing at e.g. registry.example.com/dh-mirror # renders Odoo as registry.example.com/dh-mirror/odoo:18.0 instead # of Docker Hub's docker.io/library/odoo:18.0. Addon images already # pull from the cluster-local registry (registry.odoosky-system) by # Tower's image-build pipeline; this block covers the upstream Odoo # + Postgres images that bypass that pipeline. # # `pullSecret` names a K8s Secret in the instance namespace that # carries credentials for the mirror. Empty = anonymous pull (the # default; Docker Hub's library images don't need auth). # # Default empty = same behaviour as before this addition — Odoo + # Postgres images come from Docker Hub. imageMirror: registry: "" pullSecret: "" odoo: image: odoo tag: "18.0" # Filestore PVC size (Odoo's /var/lib/odoo). filestoreSize: 10Gi # Addons selected for this instance. Each entry is a tagged image in # the cluster-local registry (deployed by cluster-platform-v3 chart). # The chart renders one initContainer per entry that copies the # addon's content into a shared volume; the Odoo container reads from # /mnt/extra-addons/. # # Tower owns this list — it commits new entries to the tenant overlay # AFTER ensuring the corresponding image exists in the destination # cluster's registry (spawning a build Job from Gitea source if not). # # Schema: # addons: # - code: odoosky_demo # version: "18.0.1.0.0" # source: platform # platform | tenant # image: registry.odoosky-system.svc.cluster.local:5000/addons/odoosky_demo # # Empty list = no extra addons; only Odoo's built-in modules. addons: [] # Path inside the Odoo container where addons are materialized. # Odoo's addons_path includes this dir; one folder per addon code. # Override only if you need a non-standard layout. addonsMountPath: /mnt/extra-addons postgres: image: postgres tag: "16-alpine" user: odoo database: postgres # If empty, the chart auto-generates on first install and re-reads # the existing Secret on subsequent upgrades (lookup pattern). password: "" storage: 10Gi backups: enabled: true # Cron schedule for the automatic backup job. Default 03:00 UTC # daily — quiet hour for most timezones, non-business in EU/US/AS. schedule: "0 3 * * *" # How many dumps to retain in S3. The backup job prunes older # objects matching the instance's prefix on every successful run. retain: 7 # S3-compatible destination. The endpoint + region + bucket are # NON-secret and live in this committed values.yaml; the AWS # credentials live in a K8s Secret named by `credentialsSecret`, # provisioned out-of-band by Tower's bootstrap script (which reads # from OpenBao). The chart never sees access/secret keys directly. s3: endpoint: https://s3.eu-central-1.s4.mega.io region: eu-central-1 bucket: odoosky-v3-backups # Per-instance S3 key prefix. Each instance writes under its own # code/ subdirectory inside the shared bucket. prefix: "{{ .Values.instance.code }}" # Name of the K8s Secret holding AWS_ACCESS_KEY_ID + # AWS_SECRET_ACCESS_KEY. Mounted via envFrom on the backup Job. credentialsSecret: s3-backup-creds ingress: # Traefik entrypoint name (set on the Traefik install in the # `traefik` namespace). entryPoint: websecure # The pre-provisioned wildcard cert for *.tenants.odoosky.org — # one Certificate resource issued ONCE in the chart's release # namespace, then every instance's IngressRoute references the # resulting Secret. Avoids Let's Encrypt's per-week certificate # issuance ceiling (50/week/registered-domain) as we scale to # many tenants. # # See infrastructure/cluster/wildcard-cert.yaml for the # provisioning manifest. tlsSecret: tenants-wildcard-tls # useTenantsDefaults — when true, the IngressRoute references the # cluster-level `tenants-default-retry` Middleware (rendered by the # cluster-platform-v3 chart in the same `tenants` namespace). # Default true matches the standard platform shape; flip to false # only when running on a cluster whose Traefik install isn't # paired with the platform's defaults Middleware set (e.g. an # externally-managed Traefik, or cluster-platform-v3's # `traefik.enabled` is false). Audit B.11. useTenantsDefaults: true