Let's face it: secret management isn't the most thrilling part of development, but it's crucial. Even though it's very tempting to manage environment variables and secrets by sshing into a server and typingvi .env, better, and more secure alternatives are available. Let's look at some options, why we chose the 1Password CLI and how to set it up.
Why should I care?

Secret management goes beyond just keeping things secure - it's also about access control and avoiding accidents. Not everyone needs (all) the keys to the kingdom. You might want to give your junior dev access to the staging environment, but keep the production credentials under stricter control. In corporate speak this is called "implementing the principle of least privilege for effective risk mitigation in secret management", but we'll call it common sense.
The right tool for the right job
Before jumping right to the HashiCorp Vaults of this world, you might want to consider these more accessible options for your small to medium size Laravel application:
| Product | Git Compatibility | Granular User Access | Encryption |
|---|---|---|---|
| artisan env:encrypt | ❌ | ❌ | ✔️ |
| git-secret | ❌ | ✔️ | ✔️ |
| 1Password CLI | ✔️ | ✔️ | ✔️ |
As you can see, env:encrypt and git-secret are both effective tools for securely storing your environment variables. However, they save the encrypted secrets as binary files, which makes merging them with Git impossible. By using the 1Password CLI, we can manage .env files for all our application's environments without any of the downsides.
1Password to rule them all

For as long as I can remember, we’ve relied on 1Password to securely share passwords, secrets, and API keys with the Spatie team. It feels like a logical progression to also use their developer tools for integrating those very secrets into our deployments. Did I mention there's excellent JetBrains and VS Code plugins as well, that make working with 1Password references in your config and .env files even easier?
Generating .env files with 1Password
1Password's CLI, op, has a couple of useful commands. We'll be using op inject to inject some secrets from 1Password entries into a template file.
The .env.template file:
APP_KEY=op://Flare/Environment/APP_KEY
# and other variables...
Executing this command will output a new .env file with the 1Password references replaces with their actual values:
op inject -i .env.template -o .env
The outputted .env file looks like this:
APP_KEY=123abc
# and other variables...
Simple, yet effective.
One template, many environments
Typically, you'll have different environment variables for your staging and production environment. Maybe you even want to share a set of local environment variables with your team to make local development easier.
For this, we'll create separate entries in our 1Password vault for each of these environments. Be sure to include the environment name in the entry title, as we'll use that to link it to the APP_ENV.

[!TIP]
Keep the set of variables consistent across environments. TheopCLI will complain if you use a 1Password reference that doesn't exist in your 1Password entry.
Next, you can use the $APP_ENV variable in your 1Password references to access the correct entries (or vaults):
# The $APP_ENV will be replaced with "staging" or "production"
APP_KEY=op://Flare/$APP_ENV-env/APP_KEY
By setting the APP_ENV before running the op inject command, we can generate an .env file using a specific 1Password entry, for a specific environment:
APP_ENV=staging op inject -i .env.template -o .env
[!WARNING]
Instead of creating separate entries in 1Password for each environment, you should create different Vaults. This approach allows you to manage access to each environment's secrets separately.
Integrating 1Password in your deploy process
Depending on your deployment process, there's two options to consider when integrating the 1Password CLI:
- generating the
.envdirectly on your production server(s) - generating the
.envfile on your local machine (or CI) and copying it to the production server(s)
We prefer the first option, this way we never have to store any secrets on your local machine or CI.
To access the 1Password vault on your production or staging servers, you'll need to create a 1Password service account. The op CLI and service account also need to be configured on your production or staging servers. It's best to only configure this service account during the deployment process. This way the op CLI is useless for any bad actor that might gain direct access to the server.
In Laravel Envoy this looks like this:
@setup
// Get the service account token using the local 1Password CLI
$opServiceAccount = shell_exec('op read "op://Flare/service-account/credential"');
$environment ??= 'staging';
@endsetup
...
@task('updateEnvironment', ['on' => $environment])
# Configure the service account only for this shell session
export OP_SERVICE_ACCOUNT_TOKEN={{ $opServiceAccount }}
// Set the APP_ENV based on the $environment and generate the .env
APP_ENV={{ $environment }} op inject -i .env.1pass -o .env
@endtask
In the @setup block, we're loading the service account credentials from our local op CLI. Once we're ready to generate the .env file on our remote server, the updateEnvironment task will configure the service account token and run the op inject command for the current environment.
If you're using GitHub actions to build or deploy your application, there's this excellent GitHub action to install, configure and use the op CLI in your GH actions.
Wrapping up
And there you have it - using the 1Password CLI for your Laravel .env files makes secret management less of a headache and more secure.
Continue reading
Lessons from the deep end
20 months ago, we started building Performance Monitoring as Flare’s next big feature, never expecting Laravel’s rapid commercial growth to put us in direct competition with their own tools. This is our honest take on those 20 months went, how we’re adapting to this new reality, and where we’re heading next while staying true to who we are. A dive into the deep end, without knowing how far down it goes.
Alex
Connect your AI agent to Flare to automatically fix production and performance problems in PHP and Laravel projects
You can now use our MCP server to connect your AI agent to Flare. This way your AI has all context it needs to diagnose and fix production and performance problems.
Freek
Subscribe to Backtrace, our quarterly Flare newsletter
No spam, just news & product updates