Secrets & Limitations
How secrets are handled
A pull exports real records: the settings row, user accounts, flow definitions. If any of those carried a secret value, it would land in JSON files you commit, and git history keeps it forever, in every clone of the repository. Environment Sync strips secret values at export:
- Built-in secret columns (password hashes, tokens, 2FA seeds, license and AI keys) are always deleted from the export.
- Fields you created and marked concealed, hashed, or encrypted are deleted too. Every pull fetches the server's complete field list and drops any flagged value, printing a line naming each dropped field. A field missing from the export reads as protection, not data loss.
Because the field list is fetched separately from the schema, the check also covers pulls scoped to a few collections and pulls that skip schema entirely. And if the check itself cannot run, the pull stops rather than continue unprotected.
The field definition still syncs as schema: the column and its concealed setting arrive on the target. Only the value stays behind; set the real secret on each instance directly.
Why strip instead of sync
The server never hands out the real value for these fields: concealed fields read back as **********, hashed fields as the hash. Exporting that and pushing it would overwrite the target's working secret with a mask. Stripping protects both the repository and the target.
The one blind spot
System collections that do not sync
None of these sync today. Some are shared configuration that a future release could take on; the rest are per-instance data that a sync should never touch.
| Collection | Why it doesn't sync |
|---|---|
directus_presets | Bookmarks, saved layouts, and Insights presets mix shared configuration with personal preference. A future release may sync the shared part. |
directus_extensions | The enabled/disabled state of installed extensions is tied to what is physically deployed on each instance. |
directus_files | File-interface fields sync as schema; file rows and the binaries behind them are their own workstream. |
directus_comments | Content comments; per-instance data. |
directus_activity | The audit log; per-instance data. |
directus_revisions | Change history; per-instance data. |
directus_versions | Content-versioning drafts; per-instance data. |
directus_notifications | User notifications; per-instance data. |
directus_shares | Public share links; per-instance data. |
directus_sessions | Active login sessions; per-instance data. |
directus_migrations | The database migration ledger. The CLI never runs migrations or changes the Directus version. |
directus_webhooks | Deprecated in Directus; superseded by flows. |
What it does not do
| Won't | Because / instead |
|---|---|
| Sync your collections' content (rows) | Environment Sync moves the shape of a project and its configuration. Content sync is deferred to a future release. |
| Undo a push | Git covers configuration; only a database backup covers data. Back up before big pushes. |
| Auto-expand a scoped snapshot | A scope pulls exactly what you name. Dangling references produce a warning; widen --collections yourself. |
| Translate schema across versions | A version mismatch refuses the command; --allow-version-drift overrides the gate but converts nothing. |
| Wrap schema and data in one transaction | Schema applies first, then data. A failed import re-runs data alone; see Diffing & Pushing. |
| Select individual records | Resource selection is by type (--roles), never by row. |
| Model code-first | Model in the Data Studio and pull. Don't hand-author the JSON files. |
| Seal the data plan against target drift | Only the schema apply is sealed against the target changing between preview and apply. The data preview is the server's own dry-run answer, but it is advisory. |
Known limitations
- Translations mirror is opt-in. A server limitation currently breaks
mirrorpushes of translations, so translations are excluded from pulls by default. Opt in with--translations;mergeandaddpushes work normally. - Unlicensed custom permission rules are invisible to the export. On an instance without a license, the API hides custom permission rules, so a pull cannot export them. The pull detects the shortfall and marks the export incomplete:
mergeandaddpush normally,mirrorrefuses. License the source instance to export them. - Users without an email address fail import. The server's import validation rejects a user with no email, so a
--userspush containing one fails before any data applies. Give the account an email on the source, or remove it, first. - Panels can duplicate on a first sync into a look-alike target. Panels have no name to match on, so pushing into a target that already holds equivalent panels (seeded from the same template) can create them a second time. The identity map prevents repeats after that first push.
Get once-a-month release notes & real‑world code tips...no fluff. 🐰
CI & Automation
Run Environment Sync unattended with tokens from environment variables, machine-readable JSON reports on stdout, and explicit flags in place of prompts.
Common Workflows
End-to-end walkthroughs of the most common Environment Sync workflows, from promoting changes to production to recovering a drifted environment and standing up a new one.