Skip to content

Change one server variable

$ grim env:set MAIL_HOST=smtp.example.com

One value on the server is wrong, or missing: a mail host, an API key that was rotated, APP_DEBUG for ten minutes while you chase a bug. Pulling the whole file, editing it and pushing it back is a lot of ceremony for one line, and it leaves production credentials on your disk. grim env:set changes that one line where it lives and restarts what reads it.

For several values at once, or to remove a line, use the round trip instead: grim env:pull, edit, grim env:push.

Usage

$ grim env:set MAIL_HOST=smtp.example.com          # production
$ grim env:set APP_DEBUG=true staging              # only staging's .env
$ grim env:set "MAIL_FROM_NAME=Shop Support"       # quote it for your shell

Run it from the project directory. The pair comes first and the environment second; with no environment it is production. There is no confirmation: the command acts as soon as you press Enter.

Arguments and options

Set an .env variable on remote server

Usage

grim env:set <pair> [<environment>]

Arguments

Argument Description
pair KEY=VALUE pair to set (required)
environment Target environment (optional, default: production)

What it actually does

  1. Splits the pair at the first =, so a value may contain = itself. Spaces around the key and the value are trimmed.
  2. Finds the server. deploy.environments.<environment> in grim.json, then deploy itself, then your registration in ~/.grim/servers.json. The path falls back to /opt/<project>, or /opt/<project>-<environment> for anything but production: the directory grim server:add-project makes. A top-level deploy.path is production's and is skipped for any other environment.
  3. Reads the server's .env as the deploy user.
  4. Changes one line. The first line that sets the key is replaced, export KEY= lines included. When there is none, KEY=VALUE is added at the end. Every other line stays as it was.
  5. Uploads the file over the old one.
  6. Recreates the PHP services. app, horizon, scheduler and reverb, whichever the project has, because each caches its configuration at start. It prints Recreating PHP services (app, horizon, scheduler)... and the site is away for a few seconds.
  7. Prints a summary. Project, host, key, and whether the key was updated or added. The value is not printed.

How the value is written

You do not have to think about .env quoting. A value with a space, a #, a quote or a backslash is wrapped in double quotes and escaped; anything else is written as it is. URLs and ampersands pass through untouched.

You type The server's .env gets
APP_DEBUG=true APP_DEBUG=true
"MAIL_FROM_NAME=Shop Support" MAIL_FROM_NAME="Shop Support"
CACHE_PREFIX= CACHE_PREFIX=

Your own shell still reads the line first. Put the pair in quotes whenever the value has a space, a $, a & or a !.

Pitfalls

It always restarts

There is no flag to skip the recreation. To stage a value for the next release without touching the running app, use the round trip and grim env:push without --restart.

The key has to look like a variable

Invalid .env key: mail-host means the key has a character other than letters, digits and underscores, or starts with a digit. Nothing was changed on the server. Invalid format. Use: grim env:set KEY=VALUE means there was no = at all.

-v shows the whole file

With -v every SSH command prints its output, and one of them reads the server's .env. Every production credential scrolls through your terminal. Leave verbose off here unless you are alone with the screen.

The value stays in your shell history

A secret typed on the command line is saved by the shell. For a password or a key, the round trip through an editor keeps it out of the history file.

After it finishes

The app is running on the new value. Your local .env.<environment> from an earlier pull knows nothing about it, so pull again before the next push, or that push puts the old value back.

Questions

Can it remove a variable?

No. grim env:set KEY= sets it to an empty value, which is not the same: the app then sees an empty string instead of the default from its config file. To delete the line, pull, edit and push.

Does a commented-out line count as set?

No. # MAIL_HOST=old is left alone and a new MAIL_HOST= line is added at the end of the file.

Recipes that use it