Send a .env back
$ grim env:push --restart
You pulled a server's .env, changed a handful of values in your editor, and now the server has to get them. grim env:push is the second half of that round trip: it takes .env.<environment> from the project directory and puts it where the deployed app reads its .env.
Reach for it when several values change together, or when a line has to go away. For one value, grim env:set is shorter and never leaves a copy of production credentials on your disk. The first half is grim env:pull.
Usage
$ grim env:push # .env.production, asks before it overwrites
$ grim env:push --restart # the same, then the app picks the values up
$ grim env:push staging --restart # .env.staging to the staging server
$ grim env:push --force --restart # no question, for scriptsRun it from the project directory, where both grim.json and the .env.<environment> file are. With no argument the environment is production.
Arguments and options
Push .env to remote server
Usage
grim env:push [--force] [--restart] [--] [<environment>]Arguments
| Argument | Description |
|---|---|
environment |
Target environment (optional, default: production) |
Options
| Option | Description |
|---|---|
--force |
Skip confirmation prompt |
--restart |
Restart app and clear config cache after push |
What it actually does
- Looks for the local file.
.env.<environment>in the project directory. The argument picks the file and the server at once, sostagingcan never upload.env.production. - Finds the server. The same way
grim env:pulldoes:deploy.environments.<environment>ingrim.json, thendeployitself, then your registration in~/.grim/servers.json. The path falls back to/opt/<project>, or/opt/<project>-<environment>for anything but production: the directorygrim server:add-projectmakes. A top-leveldeploy.pathis production's and is skipped for any other environment. - Asks.
Push .env.production (42 variables) to 203.0.113.10:/opt/shop/.env?and waits fory. Anything else printsAborted.and changes nothing.--forceskips the question. - Uploads the file. As the
deployuser, over the.envon the server. The whole file is replaced; nothing is merged and no backup is kept. - Recreates the PHP services, only with
--restart. See below. - Prints a summary. Project, host, source, target and the number of variables.
What --restart restarts
More than the option's description says. The .env is mounted into every PHP container of the stack, and each of them caches its configuration when it starts. So --restart recreates all of them that the project has: app, horizon, scheduler and reverb. nginx and Redis are left running.
Without --restart the new file is on the server and the app keeps running on the old values, for as long as its containers live. That is useful when you want the change to arrive with the next release. It is confusing when you forget.
Recreating the containers takes the site away for a few seconds. On a busy shop, push without --restart and let the next grim release pick the values up.
Pitfalls
The server's file is replaced, not merged
A value a colleague set with grim env:set yesterday is not in the copy you pulled last week, and after your push it is not on the server either. There is no backup on the server to go back to. Pull right before you edit, and push soon after.
The guessed path is only a guess
With a host and no path, the target is /opt/<project> for production and /opt/<project>-staging for staging, which is where grim server:add-project puts them. A stack that was moved, or set up by hand somewhere else, is not found by guessing. Read the target in the question before you answer y, and write deploy.environments.<environment>.path into grim.json when it is wrong.
The question cannot be answered in a script
Run with --no-interaction, the question answers itself with no, and the command prints Aborted. and exits successfully. A pipeline that pushes needs --force.
There is nothing to push yet
.env.staging not found. means the local copy does not exist. Pull it first with grim env:pull staging, or write the file by hand when the environment is new.
After it finishes
With --restart the app is already running on the new values. Check the one you changed from inside the container. grim remote:artisan takes no environment and talks to the one registered on your machine, production in the usual case.
$ grim remote:artisan tinker --execute="echo config('mail.mailers.smtp.host');"Then delete the local copy, or at least do not let it age. It holds production credentials, and the next person to push a stale one undoes somebody's work.
Related spells
grim env:pull
Fetch a server's .env
Copy the .env of a deployed environment into the project as .env.<environment>, to read it or to edit and push back.
grim env:set
Change one server variable
Set a single KEY=VALUE in the .env of a deployed environment and recreate the containers so the app runs on it at once.
grim reload
Apply a changed .env
Recreate every container of the project and clear the config cache, so the app reads the .env as it is now.
grim deploy
Send an image to a server
Roll a pushed image tag out to one environment over SSH, verify the app answers, and fall back to the previous tag when it does not.
Recipes that use it
Staging to production, one image
Register a staging environment next to production, name both in grim.json, release to staging, look at it, then send the same tag to production without building again.
Change config on a live app
Set one value in a server's .env, confirm the app reads it, change many values through a pull and a push, rotate a secret the whole team shares, and apply an edit on a stack you run yourself.