# Administration settings Platform behavior is controlled almost entirely through environment variables read by `saas.provisioner`, rather than an in-app settings screen. This page is the reference for what to set and why. ## Backend selection | Variable | Default | Notes | |---|---|---| | `SAAS_DEFAULT_PROVISION_BACKEND` | `kubernetes` | Used when an instance has no explicit `backend` value | ## Kubernetes backend | Variable | Default | Notes | |---|---|---| | `K8S_DB_HOST` | `postgres.odoo.svc.cluster.local` | Shared Postgres service | | `K8S_DB_PORT` | `5432` | | | `K8S_FILESTORE_STORAGE_CLASS` | `gp3` | Used for both the filestore and custom-addons PVCs | | `K8S_ODOO_IMAGE` | `dkadoh92/dk-business-solutions-odoo:18.0` | | Fixed (not environment-configurable) Kubernetes constants worth knowing: namespace prefix `saas-`, ingress class `alb`, image pull policy `IfNotPresent`, pod UID/GID `100`/`101`, pod-exec timeout 300s with 5 retries at 5s apart. ## Docker backend | Variable | Required | Notes | |---|---|---| | `DOCKER_SAAS_NETWORK` | No (`saas-network` default) | Created automatically if missing | | `DOCKER_ODOO_IMAGE` | No (defaults to the same image as K8s) | | | `DOCKER_DB_HOST` | No (`odoo18-db` default) | | | `DOCKER_DB_PORT` | No (`5432` default) | | | `DOCKER_FILESTORE_HOST_PATH` | **Yes** | Absolute path on the **Docker host's own filesystem** — not a path inside the platform Odoo container. Raises immediately if unset. | | `DOCKER_ADDONS_BASE_PATH` | **Yes** | Same host-filesystem caveat as above | | `DOCKER_TENANT_CONFIG_BASE_PATH` | **Yes** | Where per-tenant `odoo.conf` files (with the master password) are written; must be an absolute path | | `DOCKER_HOST_PUBLIC_ADDRESS` | **Yes**, for DNS | Public IP or hostname used for the Cloudflare A/CNAME record | | `DOCKER_TRAEFIK_CERTRESOLVER` | No (`letsencrypt` default) | | :::{admonition} Why these paths are so strict about "host filesystem" :class: important The platform Odoo module itself runs *inside a container*. Every `docker_client.containers.run()` call in the provisioner talks to the **host's** Docker daemon (over the mounted `docker.sock`), so any volume bind-mount source has to be a real path on the host — not a path that happens to exist inside the platform container. Reusing `FILESTORE_BASE_PATH` (used elsewhere for host resource checks, evaluated *inside* the platform container's own mount namespace) for a Docker bind mount would silently mount the wrong location. This is why the provisioner creates tenant directories via a throwaway container rather than `os.makedirs()` directly. ::: ## Cloudflare | Variable | Required | |---|---| | `CF_DNS_API_TOKEN` | **Yes** — raises immediately if missing | | `CLOUDFLARE_ZONE_ID` | **Yes** — raises immediately if missing | See [Domains](domains.md) for what these are used for.