Weave Code
Weaver
Helps Laravel developers discover, compare, and choose open-source packages. See popularity, security, maintainers, and scores at a glance to make better decisions.
Feedback
Share your thoughts, report bugs, or suggest improvements.
Subject
Message

Filament Env Editor Laravel Package

geo-sot/filament-env-editor

Filament plugin for viewing and editing your Laravel .env file straight from the admin panel. Manage environment variables through a clean, validated interface with safe saving—no SSH or manual file editing needed.

View on GitHub
Deep Wiki
Context7

Getting Started

What it buys you: a Filament page that parses your .env file into a form of key/value rows and writes changes back to disk. It is an operations convenience, not a configuration system — treat it as a guarded "change these five runtime values without SSH" screen, and nothing more.

Install and wire it up

composer require geo-sot/filament-env-editor
php artisan vendor:publish --tag="filament-env-editor-config"
php artisan optimize:clear

Register the plugin on the panel(s) that should expose it — typically a back-office or admin panel, never a customer-facing one:

// app/Providers/Filament/AdminPanelProvider.php
public function panel(Panel $panel): Panel
{
    return $panel
        // ...
        ->plugins([
            \GeoSot\FilamentEnvEditor\FilamentEnvEditorPlugin::make(),
        ]);
}

Where to look first, in this order

  1. config/filament-env-editor.php — the published config is where the package's real opinion lives (which keys are grouped/hidden/labelled, and how the page is registered). Read it before touching anything else.
  2. The plugin class GeoSot\FilamentEnvEditor\FilamentEnvEditorPlugin — small file; the fluent methods on it are your customization surface (navigation group/label, authorization hook, page class).
  3. The page class and its Blade view under src/ and resources/views/ — this is where save/parse logic lives, and it is short enough to audit fully. With ~24 stars and zero dependents you should absolutely read it rather than assume behavior.
  4. The service provider — confirms how the page is registered and whether any routes/commands are added.

First use case to ship: a staging-only page that lets a release manager rotate third-party API keys and mail credentials (MAIL_HOST, MAIL_USERNAME, MAIL_PASSWORD, STRIPE_KEY, SENTRY_LDSN) without a deploy. Gate it to a super_admin role, exclude everything structural (APP_KEY, DB_*, CACHE_STORE, SESSION_DRIVER), and clear config cache after save. That is 90% of the package's realistic value.


Implementation Patterns

Environment-scoped registration. Only mount the plugin where editing .env is sane — staging and production ops panels, not local (where devs edit the file directly) and never on a tenant panel:

->plugins(array_filter([
    ! app()->isLocal()
        ? \GeoSot\FilamentEnvEditor\FilamentEnvEditorPlugin::make()
            ->navigationGroup('Operations')
        : null,
]))

Authorization is the whole security model. Do the check twice: once at the panel level (FilamentUser::canAccessPanel) and once on the plugin/page, so a future panel change can't silently widen access:

// app/Models/User.php
public function canAccessPanel(Panel $panel): bool
{
    return $this->hasRole('super_admin') && $this->two_factor_confirmed_at !== null;
}

If the plugin exposes an access/authorize callback, bind it to a dedicated Gate (edit-env-file) rather than an inline role string — future-you will want to grant it to one contractor temporarily.

Group keys into human sections. Rather than presenting 80 raw rows, map prefixes into tabs/sections in the config (e.g. APP_* → "Application", MAIL_* → "Mail", AWS_*/S3_* → "Storage"). Use the config's label/description hooks to annotate the dangerous ones: "Changing APP_URL logs everyone out."

Mask secrets. Anything that is a credential should render as a password field with reveal disabled. Values typed into a Filament form travel through the Livewire payload — they are in the browser's network tab and in your server logs if you log requests. Minimise what's rendered in plaintext:

// pseudo-schema — confirm the exact hook in the published config/page class
TextInput::make('MAIL_PASSWORD')->password()->revealable(false)

Audit the change, not the value. Wrap or extend the save action so each edit writes an activity row containing the key names changed, the acting user, and the timestamp — never the values:

activity()
    ->causedBy(auth()->user())
    ->withProperties(['keys' => $changedKeys, 'env' => app()->environment()])
    ->log('env file updated');

This is the single highest-value addition you can make; without it, "who changed APP_DEBUG?" is unanswerable.

Clear caches after every save. Whatever the package does internally, verify it. Run php artisan config:clear (and optimize:clear in production, where config is cached) as part of the post-save path, plus queue:restart and octane:reload when those runtimes are in play.

Use it for drift review, not just editing. Point a read-only view at .env.example vs .env and let it flag missing/new keys — this catches the classic "deploy added a var, nobody set it" failure that this package is otherwise a band-aid for.

Keep it out of the deploy path. .env should still be written by your provisioning tooling (Envoyer, Kamal, Ansible, Kubernetes secrets). The panel is for runtime rotation between deploys; if the two ever disagree, the next deploy wins and silently reverts the panel edit. Say so in the page's helper text.


Gotchas and Tips

  • APP_KEY will detonate your app. Rotating it invalidates encrypted sessions, cookies, and any encrypted casts. It has no business being editable in a browser. Exclude it in config, and verify the exclusion by loading the page.
  • Config caching is the #1 "it didn't work". Once php artisan config:cache has run, env() calls inside config files are resolved at boot; editing .env changes nothing until the cache is cleared. If a saved value "doesn't apply," that's almost always the cause — not the package.
  • Long-running processes hold stale env. Queue workers, octane, and scheduler daemons read env at boot. A saved MAIL_PASSWORD won't reach the worker until queue:restart. Build this into the save flow or your on-call runbook.
  • Quoting and multi-line values. Line-based parsers choke on values containing #, =, spaces, or newlines. PEM certificates, JSON service-account blobs, and private keys should live in files referenced by path, never inline in .env. Test round-trips with a value like P@ss#word = "x" before trusting the screen in production.
  • Comments and ordering get destroyed. Save operations typically rewrite the file, dropping comments, blank lines, and grouping. Your .env becomes a generated artefact — so keep .env.example (commented, ordered, in git) as the canonical documentation.
  • Empty string ≠ unset. Setting a key to '' makes env('KEY', 'default') return '', not the default. If you want a default to apply, the key has to be removed, not blanked. Know which behaviour the save action gives you.
  • File ownership and atomicity. The PHP-FPM user must own .env. After running artisan as root, .env often ends up root-owned and saves fail with a permission error (or worse, succeed partially). There is generally no locking — a deploy writing .env while an admin saves can corrupt the file. Take a timestamped backup on every save and keep one deploy's worth of history.
  • APP_DEBUG=true in production is an instant information-disclosure incident. Consider hard-blocking APP_DEBUG and APP_ENV from the editable set entirely, not just labelling them.
  • Access is the security boundary — the URL is not. A hidden route is not a control. Combine canAccessPanel, the plugin's authorization hook, and 2FA. And remember Filament's own error pages / Ignition-style debug output can dump environment values on a misconfigured panel.
  • Zero dependents means zero downstream hardening. Nothing else in the ecosystem is exercising this code, and the last release date is ahead of most of your dependency tree — pin the version in composer.json, read the diff on upgrade, and test the page explicitly after any Filament major bump (v3 → v4 changed page/plugin registration contracts).
  • Extension points worth using: the page class (subclass and register your own via the plugin), the form schema (to enforce masking and read-only keys), and the save action/service (to add backups, audit logging, and cache clearing). All three are small files — prefer overriding them over patching vendor code.
  • In tests, never touch the real file. Point the package at a fixture path (or stub the service) and use putenv()/config() for value assertions; a test suite that writes your local .env will eventually wipe it.
Weaver

How can I help you explore Laravel packages today?

Conversation history is not saved when not logged in.
Prompt
Add packages to context
No packages found.
microsoft/fluentui-system-icons
mmccook/php-json-canonicalization-scheme
middlewares/firewall
qubiqx/montapacking
nyoncode/laravel-package-console
pnscripts/filament-broadquill-lite
pnscripts/laravel-sentfold-lite
vleap/mx-sdk-laravel-internal
twidpay/utils
htetmyathlaing/scout-elasticsearch-driver
artisan-toolbox/front-awesome
ls/client-assistant
users-au/laravel-client
cgv/localized-resource
noith/settings
kda/laravel-package
kda/filament-dynamic-navigation
bypersoft/signbox
pairus/product-data
fayne/laravel-filament-cms-core