English | Русский
Store selected plugin secrets outside normal Grav config YAML while keeping regular plugin settings in their usual files.
- Loads secrets from private storage files:
- base storage defaults to
user/secrets.yaml - environment storage defaults to
user/secrets.<environment>.yaml
- base storage defaults to
- Overlays those values into Grav runtime config.
- Intercepts Admin saves for protected fields.
- Saves protected fields into private secret files instead of normal plugin config YAML.
- Removes protected keys from plugin config after save.
This is useful when you want to keep:
- normal plugin settings in git
- real secrets outside git
Typical examples:
- OAuth client secrets
- SMTP passwords
- Algolia API keys
Grav already supports configuration overrides through setup.php and server-side environment variables:
There are also plugins built around the environment-variable approach (.env files), for example:
These are valid approaches, but they also have tradeoffs:
- on shared hosting, server-level environment management may be unavailable or inconvenient
.env,setup.php, and server overrides do not integrate with normal Admin and Flex save flows
Secret Split fills that niche: selected plugin secrets are moved out of tracked plugin config YAML into private storage files, while normal Admin editing and save continue to work.
- Download the ZIP archive of this repository.
- Unpack it into
user/plugins/. - Ensure the final plugin directory is:
user/plugins/secret-split
When the plugin is published in the official Grav plugin repository, it can be installed with:
bin/gpm install secret-splitBase private storage default:
user/secrets.yamlEnvironment override default:
user/secrets.<environment>.yamlExamples:
user/secrets.yamluser/secrets.localhost.yamluser/secrets.example.com.yaml
Both paths are configurable via Secret Split plugin settings:
base_storage_fileenvironment_storage_pattern
Behavior is intentionally close to Grav config layering:
- values coming from base plugin config are written to base
user/secrets.yaml - values coming from current env plugin config are written to
user/secrets.<environment>.yaml - returning values back to config restores them into the matching base or current env config layer
- secret files are created again automatically when the corresponding base or current env layer writes back into secrets
- if Grav environment name is empty / undefined, env-specific storage is disabled instead of creating
secrets.unknown.yaml
Secret Split's own plugin configuration lives in:
user/config/plugins/secret-split.yamlThat file stores the protected field list and plugin options.
Actual protected values live in the configured private storage files, which by default are user/secrets.yaml and user/secrets.<environment>.yaml.
The plugin configuration lets you define protected fields grouped by plugin:
- choose a plugin
- choose one or more fields from that plugin
secret-splititself is intentionally excluded from that list, so the plugin cannot protect its own control fields
Field labels are collected from plugin blueprints and shown using their admin-facing names. As soon as a field is selected, the Admin UI also shows its current status and where the value is currently stored.
Password-like fields use Grav's field semantics automatically. Empty values for those fields mean:
- empty value means "keep existing secret"
- non-empty value means "replace secret"
This is needed for fields like:
plugins.email.mailer.smtp.password
because password inputs in Grav Admin render empty by design.
For ordinary non-password protected fields, submitting an explicit empty value removes the stored secret automatically.
Removing a field from protected_fields now removes both:
- the field entry from
secret-splitconfig - the stored secret value from
secrets.yaml/secrets.<env>.yaml
The Admin overview supports two deferred actions:
Move to <secrets file>prepares migration into private storageMove to configprepares returning stored values back into tracked plugin config YAML
After clicking either action, the Admin page immediately updates the visible field statuses and source labels to preview the future result.
Real file changes still happen only after the normal Admin Save.
After Move to config followed by Save:
- current values from the selected secrets file are written back into plugin config YAML
- the corresponding entries are removed from
user/secrets.yaml/user/secrets.<env>.yaml - field status changes from
StoredtoPending - the source label switches to the config YAML file
Fully supported:
- normal plugin config save flow
- Flex configure flow, including
algolia-pro
The Admin page uses live preview for field state, but real file changes are still applied only after the normal Admin Save.
debug_loggingenables verbose plugin-side logging for save, migrate, and Flex flows- environment-specific storage is used only when Grav resolves a non-empty environment name
Internal Grav/Admin/Flex integration details, workarounds, and current limits are documented here:
MIT (see LICENSE).
