Operate

Production Readiness

The checklist for running a self-managed ObjectOS deployment safely in production — headers, secrets, rate limits, CORS, boot guards, scheduled work and retention.

Use this checklist before exposing ObjectOS to production traffic. It holds for Community and Enterprise alike; the Enterprise adds section at the end lists the items the licensed image brings with it.

HTTP hardening

The runtime sends conservative security headers on its routes by default. Verify the final response, after any proxy that rewrites headers:

  • Content-Security-Policy;
  • X-Content-Type-Options;
  • X-Frame-Options;
  • Referrer-Policy;
  • Permissions-Policy;
  • Cross-Origin-Resource-Policy;
  • HSTS, which the runtime does not send by default: add it at your proxy once TLS is confirmed.
curl -I https://app.example.com

Secrets

Store these in a secret manager, and inject them at runtime:

SecretPurpose
OS_AUTH_SECRETSession signing base secret. Identical on every replica — replicas with different values reject each other's sessions.
OS_SECRET_KEYThe key every stored secret is encrypted under. Required in a container, where a self-minted key dies with the filesystem. Back it up with the database: one without the other cannot decrypt anything.
Database credentialsBusiness database access
OIDC client secretSingle sign-on
Provider API keysEmail, storage, AI, integrations

Never bake secrets into artifacts or images.

A deployment bound to a control plane holds a runtime token as well, but that one is not a secret you configure: it is minted during the binding and persisted by the runtime. There is no deployment-level API key to distribute for it.

Rate limiting

The runtime has a built-in token-bucket rate limiter, off until the app declares a budget (server.security.rateLimit in its stack). An over-budget caller is answered 429 with Retry-After. The bucket is keyed by the signed-in user, and by the caller's address for anonymous traffic.

Behind a reverse proxy, the caller's address is the proxy's unless the app sets server.trustProxy: true — and set that only behind a proxy that overwrites X-Forwarded-For on every request, or callers can choose their own address. The counters are kept in memory, per process. Sign-in can take its own, tighter budget in Setup → Authentication.

Where the limit belongs at the edge instead — an ingress or gateway — start from budgets like these:

TrafficExample limit
Auth endpoints10/min/IP
Write requests60/min/IP
Read requests600/min/IP

CORS

With no OS_CORS_ORIGIN, the runtime admits no cross-origin caller — and needs none while the Console and the API share the public origin. A front end served from another origin is listed explicitly, comma-separated:

OS_CORS_ORIGIN=https://portal.example.com,https://admin.example.com

* is refused at boot while credentials are on.

Boot guards stay on

Two escape hatches exist for development. Neither belongs in production:

  • OS_ALLOW_DRIVER_CONNECT_FAILURE is unset. A database that cannot connect at startup refuses the boot, so a bad OS_DATABASE_URL, a rotated password or a closed network path is a failed deploy — not a "started" server that answers 500 to every request. The flag boots without the database and never reconnects.
  • OS_ALLOW_DEGRADED_TENANCY is unset. A deployment that asks for several organizations without the organizations runtime refuses to boot; this flag lets it boot with the isolation missing.

Scheduled work is a decision

Scheduled work that apps and packages declare — time-triggered flows and packaged cron jobs — is off until the deployment sets OS_AUTOMATION_SCHEDULED_WORK_ENABLED=true. A deployment that expects a digest, a sweep or a reminder to fire must turn it on. Leaving it off is a legitimate answer too; make it on purpose. Confirm the effective value with os doctor, and read the startup summary: work listed there as disabled by deployment policy is not broken, it is switched off. See Environment Variables.

Retention is set before go-live

The platform deletes telemetry on a schedule: activity after 14 days, job runs after 30, notifications after 90, and audit records leave hot storage after 90. If your compliance regime needs longer, extend the windows through the lifecycle.retention_overrides setting before go-live — data deleted by policy is gone from every backup taken afterwards.

Go-live checklist

  • TLS is terminated at the edge or ingress.
  • Security headers are present on the final response.
  • HSTS is enabled after TLS validation.
  • OS_AUTH_URL and OS_TRUSTED_ORIGINS match the public address.
  • CORS admits exactly the cross-origin front ends you serve.
  • Rate limits protect sign-in and write endpoints.
  • OS_AUTH_SECRET and OS_SECRET_KEY are strong, stored as secrets, and escrowed.
  • The first administrator registered before the address was shared.
  • OIDC callback URLs match the public domain.
  • OS_ALLOW_DRIVER_CONNECT_FAILURE and OS_ALLOW_DEGRADED_TENANCY are unset.
  • OS_AUTOMATION_SCHEDULED_WORK_ENABLED is a decision somebody made.
  • Retention windows match your policy.
  • Business database backup and restore are tested — see Backup.
  • Audit logs are retained according to your policy.
  • Monitoring alerts on 5xx rate and readiness — see Observability.
  • Rollback plan covers both the image version and the app artifact version.

Enterprise adds

  • OS_LICENSE_KEY — the deployment's entitlement — is stored as a secret.
  • OS_CLOUD_URL is declared, and it matches the license mode. An ordinary license with off is refused at startup; see Air-gapped.
  • The image is pinned by digest, and its signature, SBOM and provenance were verified (Docker).
  • On several replicas, OS_AUTH_SECRET and OS_SECRET_KEY are identical on every one of them.
  • On a multi-organization posture: the membership policy and the mounted AI agents are declared, OS_PLATFORM_OWNER_EMAIL names more than one verified administrator, and cross-organization negative access tests pass.