Install the CLI
One phar, and PHP to run it. Modules are installed later, from inside a project.
$ curl -sS https://grim.grimoiry.com/install.sh | bash
Check the machine
Every tool grim expects, and what to do about the missing ones.
$ grim doctor
Runs on
Docker · Traefik · Redis · Horizon · Laravel · PHP
The First Circle
Put grim on a machine, prove it works, start a project.
Start with
grim doctor
11 of 11 inked
Bind your GitHub account
Store a token so grim can fetch private modules, themes and images.
grim auth:login
Log grim in to GitHub
Give grim a GitHub token, from your gh login or a personal access token, and hand the same token to Composer and Docker.
grim auth:whoami
See who grim acts as
Show the GitHub user and the masked token grim holds on this machine.
grim doctor
Check your circle
Check every tool grim expects on this machine, and the project you are standing in, and say what to do about what is missing.
grim setup
Prepare the machine
Put the shared pieces of local development in place, once per machine: the Traefik proxy, a trusted local certificate authority and .test name resolution.
grim hosts:windows
Reach WSL2 from Windows
Write the project's .test domain into the Windows hosts file from inside WSL2, so a Windows browser can open it.
grim create-project
Conjure a project
Create a project directory with a grim.json on the current train and install it, or write the grim.json for an application that already runs.
grim self-update
Update grim itself
Replace the grim phar with the newest release. Projects are not touched.
grim config
Read and write CLI settings
Read, set and remove the per-user settings grim keeps in ~/.grim/config.json.
grim completion
Tab-complete every spell
Print the shell script that makes Tab complete grim's commands and options in bash, zsh and fish.
grim help
Read a command's usage
Print the description, usage, arguments and options of one command, in the terminal.
grim list
See every command
List every command grim has, or only the ones in one namespace.
Daily Practice
The local loop: start, look inside, test, stop.
Start with
grim up
9 of 9 inked
grim up
Raise the stack
Start the project's containers and its Vite dev server, with a trusted certificate and a working address, and say where to open it.
grim down
Lower the stack
Stop the project's containers and its Vite server. Volumes stay unless you say otherwise.
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 logs
Read the logs
Show what the containers have been printing, for one service or all of them, on your machine or on a deployed server.
grim shell
Step inside a container
Open an interactive bash session in the app container, or in another service of the local stack.
grim artisan
Run artisan in the container
Run an artisan command inside the app container, where the app's PHP, extensions and environment are.
grim composer
Run Composer in the container
Run Composer inside the app container, against the PHP version and extensions the app really runs on.
grim test
Run the test suite
Run the project's tests in the app container against a separate test database that grim creates and migrates for you.
grim user
Create an admin user
Create an administrator account in the app, on your machine or on a deployed server, and print the password once.
Summoning
What the project is made of, and why each piece is there.
Start with
grim require
9 of 9 inked
grim require
Summon a module or theme
Add a module or theme to grim.json, install it with everything it depends on, and rewrite grim.lock, all inside the train the project is on.
grim remove
Banish a module
Drop a module from grim.json and delete it from src/ together with every installed module nothing requires any more.
grim install
Assemble the whole project
Turn grim.json into a working project by fetching core, every module and theme, writing grim.lock, building the image and starting the stack.
grim prune
Clear what nothing asks for
Delete the modules under src/ that can no longer be reached from the requires in grim.json.
grim why
Ask why a module is here
Show the chain of requirements that leads from grim.json to an installed module, and what that module requires in turn.
grim search
Search the shelves
Find modules and themes in the catalogue by a word in their name or description, before you build one again.
grim list:available
Survey the whole catalogue
List every module and theme your account can install, grouped by kind, each with the command that adds it.
Read a package’s entry
Description, latest release and README of a module or theme.
grim module:info
Read a module's entry
Show a module's description, latest release, last push and archived status straight from GitHub, with its README on request.
grim theme:info
Read a theme's entry
Show a frontend or admin theme's description, latest release, last push and archived status straight from GitHub, with its README on request.
Chronomancy
Moving a project forward: new trains, new templates.
Start with
grim update --dry-run
2 of 2 inked
grim update
Board the newest train
Move core, every module and every theme onto the newest release train grim.json allows, or a single module within the train it is on.
grim upgrade
Renew the infrastructure files
Rewrite the Docker and nginx files of a project from the templates of the grim you have installed.
Conjuring
Bring new modules and themes into being.
Start with
grim make:module
4 of 4 inked
grim make:module
Forge a new module
Scaffold a module under src/ with a provider, routes, a working admin CRUD and its own GitHub repository.
grim make:theme
Weave a new theme
Scaffold a frontend or admin theme in the project, with its layouts and entry points, and publish it to a GitHub repository of its own.
grim manifest:validate
Check a manifest
Validate module.json, theme.json and core.json against the manifest schema on your machine, before CI does it for you.
grim push
Send a change upstream
Turn the edits you made to one installed module or theme into a pull request against the monorepo it is released from.
Transmutation
A project into an image, an image onto a server.
Start with
grim release
4 of 4 inked
grim build
Forge the production image
Build the project's production Docker image, tag it with the next version, and push it to GHCR when asked.
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.
grim release
Ship in one pass
Test, build, push and deploy the project to an environment with a single command and a single tag.
grim tune
Size the PHP-FPM pool
Generate the PHP-FPM pool config for production, from grim.json or from the CPU and memory of the server itself.
Far Sight
A deployed app, worked from your own terminal.
Start with
grim remote:shell
10 of 10 inked
Change a server’s .env
Pull it, edit it, push it back, or set one value in place.
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:push
Send a .env back
Upload your edited .env.<environment> over the .env of a deployed environment, and optionally recreate the containers that read it.
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.
Keep shared secrets
Credentials stored once in the registry instead of in every .env.
grim secrets:list
See the shared secrets
Show which shared credentials the registry holds, by key and description, without ever showing a value.
grim secrets:set
Store a shared secret
Save a credential in the registry once, so grim install writes it into the .env of every project set up after that.
grim secrets:delete
Remove a shared secret
Delete one credential from the registry so that future installs stop writing it into projects.
Reach into production
Artisan, a shell or any command on the server, without hunting for the SSH string.
grim remote:artisan
Run artisan on the server
Run one artisan command inside the app container of the deployed project, from your own terminal.
grim remote:exec
Run a command on the server
Run one shell command on the server, in the deployed project's directory, without opening an SSH session yourself.
grim remote:shell
Step into a server container
Open an interactive bash session inside a container of the deployed project, the app container unless you name another.
grim error:test
Send a test error
Prove error reporting reaches the registry before you need it to.
Ley Lines
Servers, dev boxes, CI runners and the cloud under them.
Start with
grim server:setup
29 of 29 inked
Raise a production server
Docker, Traefik and a deploy user on a bare VPS, with access to your images.
grim server:setup
Raise a production server
Turn a bare Ubuntu or Debian VPS into a host for deployed projects, with Docker, MySQL, nginx, Traefik and a deploy user.
grim server:ghcr-login
Let a server pull images
Log a server's deploy user in to the GitHub Container Registry, so the server can pull the project's private images.
Give a project a home on a server
Database, vhost and certificate; extra domains, basic auth, and removal.
grim server:add-project
Give a project a home
Prepare one environment of a project on a production server, with its database, nginx vhost, certificate, compose stack and .env.
grim server:add-domain
Add a second domain
Serve a deployed project on one more domain, with the vhost, the Traefik rule and the certificate widened to cover it.
grim server:auth
Put a password on a site
Switch HTTP Basic Auth on or off for a deployed project, in the host nginx that stands in front of it.
grim server:remove-project
Tear a project down
Remove one environment of a project from its server, with its containers, volumes, database, vhost, certificate and directory.
grim server:status
Look over a server
List the servers you have registered, or look at one of them: its containers, its disk, Traefik and its projects.
Bring a server’s config up to date
Re-render compose, nginx and Traefik from the current templates.
grim server:upgrade
Refresh a project's server files
Send the current docker-compose.yml and in-container nginx config to a project's server, without deploying a new image.
grim server:upgrade-traefik
Renew a server's Traefik
Re-render the shared Traefik compose file of a production server from the current template and recreate the container.
grim server:sync-compose
Rebuild a server's compose file
Re-render a project's docker-compose.yml on its server from the current template, keeping the services it already runs, and recreate the containers.
Keep a shared dev box
A VPS or LAN machine developers attach VS Code Remote-SSH to.
grim server:dev:setup
Raise a shared dev box
Turn a bare VPS or LAN machine into a shared development server with Docker, Traefik, one dev user and grim itself.
grim server:dev:add-project
Settle a project on the box
Clone a repository onto a shared dev box, give it a dev .env and domains, and start its stack there.
grim server:dev:keys
Let developers onto the box
List, add and remove the labelled SSH keys that let developers log in as the shared dev user of a dev box.
grim server:dev:ssh-config
Write the SSH block
Print a ready ~/.ssh/config block for a dev box, so ssh and VS Code Remote-SSH reach it under one short name.
grim server:dev:info
Show a project's dev card
Print the URLs, SSH and VS Code commands, database credentials and container states of a project on a dev box.
grim server:dev:reload
Recreate a dev stack
Recreate the containers of a project on a dev box from your own machine, so a changed .env or grim.json takes effect.
grim server:dev:remove
Take a project off the box
Stop a project's stack on a dev box and delete its volumes, its directory and its registration, keeping what you ask to keep.
Host your own CI runners
Ephemeral GitHub Actions runners on a VPS you control.
grim server:runner:setup
Raise a CI runner host
Turn a VPS into a host for ephemeral GitHub Actions runners that register to your organization through a GitHub App.
grim server:runner:status
Check the CI runners
Show the runner containers, cache volume, disk use and GitHub registration of a CI runner host, and fail when runners are missing.
Provision on AWS
An EC2 server, an S3 bucket, alarms, a spend cap and an audit trail.
grim infra:aws-ec2
Raise a server on AWS
Create one EC2 instance with a static address, a firewall and your SSH key in your AWS account, then hand it to grim server:setup.
grim infra:aws-s3
Conjure a private bucket
Create a private S3 bucket and an IAM user that can reach nothing else, then print the .env lines Laravel needs to use it.
grim infra:aws-alarms
Set a watch on a server
Attach two CloudWatch alarms to an EC2 instance, for sustained high CPU and for failed status checks, and have AWS mail you when either fires.
grim infra:aws-budget
Set a spending alarm
Create a monthly AWS budget that mails you at 50, 80 and 100 percent of a limit, and when AWS forecasts the month will end above it.
grim infra:aws-cloudtrail
Keep an account audit trail
Turn on a CloudTrail trail that records API activity in every region of the account into a locked-down S3 bucket, at a level of detail you pick from four presets.
Survey and tear down cloud servers
What grim runs in the cloud, what DNS it wants, and how to remove it.
grim infra:list
Survey what runs on AWS
List every server and AWS resource grim has created, with a monthly cost estimate for each and the ids that infra:destroy takes.
grim infra:dns
Point a domain at a server
Print the two DNS records that point a domain at a server, with step-by-step instructions for Cloudflare or Route 53, and check whether they are live yet.
grim infra:doctor
Check the way to AWS
Check that the aws CLI, terraform and working AWS credentials are in place, and print the setup steps for whatever is missing.
grim infra:destroy
Unmake what grim made
Remove a server or AWS resource that grim created, after checking the account and making you type its name, and stop it from being billed.
grim server:keys
Grant or revoke deploy access
List, add and remove the SSH keys that may log in as a server's deploy user, each under a label you choose.
When one command is not enough
Setting up a server, taking a project to production, getting somebody new onto the dev box. Those run to a dozen commands with decisions in between, so they are written up as recipes instead. The ideas underneath them, trains and manifests, are in the tomes.
Read the recipesDimmed rows
A greyed row is a command that exists but has no page here yet. Until it does,
grim help <command>
prints the real flags. The CLI is the source of truth and this book is catching up to
it.