Prepare the machine
$ grim setup
Every project on your machine answers at https://<project>.test, and none of them brings the plumbing for that itself. One Traefik routes all of them, one local certificate authority signs all their certificates, and one rule sends .test names to your own machine. Those belong to the machine, and grim setup puts them there.
Reach for it on a machine that was set up by hand, after the Traefik container has been thrown away, or when a browser has stopped trusting .test pages. It is safe to run again: each step checks what is already there.
Usage
$ grim setup # network, certificate authority, Traefik, DNS
$ grim setup -v # also show Homebrew's output while mkcert installsIt runs from anywhere and asks nothing. Docker has to be running. On macOS expect one sudo prompt the first time.
Arguments and options
Set up local dev environment (Traefik, mkcert, DNS)
Usage
grim setup [--stop-herd]Options
| Option | Description |
|---|---|
--stop-herd |
Stop Laravel Herd when its nginx holds ports 80/443 (never done without this flag) |
What it actually does
Each step prints its name and its result on one line.
- Creates the
traefik-publicDocker network, unless it exists. Every project's stack joins it so Traefik can reach the containers. - Checks for mkcert. On macOS a missing mkcert is installed with Homebrew. On Linux setup prints
sudo apt install mkcertand stops; this is the only step that ends the run. - Installs the mkcert authority into the system trust store with
mkcert -install, and creates~/.grim/traefik/certs. No certificate is made yet. Each project gets its own on its firstgrim up. - Sets up and starts Traefik.
~/.grim/traefik/getsdynamic/,certs/and adocker-compose.ymlrendered for the machine's proxy mode, then the container is started, with its dashboard on127.0.0.1:8099(loopback only, since it shows every router). It routes only containers that are not labelledgrim.proxy=server, so production stacks running on the same Docker are never picked up. In the default mode,traefik, it listens on ports 80 and 443. Inbehind-herdit binds only127.0.0.1:8080(orproxy.port), trusts theX-Forwarded-*headers Herd's nginx sends and carries no certificates; 80 and 443 stay Herd's. The line says which:running (behind-herd, 127.0.0.1:8080). A compose file grim generated earlier is rewritten when the mode or port changed, and the running container is recreated to publish the new ports. One you edited by hand is left alone and named under the line. The mode is set withgrim config set proxy.mode behind-herd. - Points
.testat your machine. On macOS it writes/etc/resolver/testwithnameserver 127.0.0.1, throughsudo, unless the file exists. The file names a DNS server and grim runs none: Herd, Valet or dnsmasq answer there, and on a Mac without themgrim upadds a hosts line per project. On Linux and Windows there is no such wildcard, so it prints the hosts-file line to add instead.
It ends with Local dev environment ready., the dashboard address http://127.0.0.1:8099 and the next command.
Pitfalls
A failed step does not fail the command
When the network or Traefik cannot be set up, that line says failed with Docker's reason under it, and the run still continues to Local dev environment ready. with exit code 0. Read the lines, not the last one. grim doctor afterwards tells you whether Traefik's ports are really bound.
Laravel Herd holds port 80 or 443
Herd's nginx listens on 80 and 443, the ports Traefik needs. On macOS the Traefik step then says failed with Laravel Herd holds :80, :443 (nginx-arm64 (pid 4242)) and grim's Traefik needs them. Run again with --stop-herd … under it. Either grim setup --stop-herd, which runs herd stop for you, or herd stop by hand and grim setup again. Setup never stops Herd without the flag; Herd.app running with its nginx stopped is not in the way. If herd stop itself fails, the step tells you to stop Herd yourself.
Something else holds port 80 or 443
Port(s) 80, 443 are held by a non-Docker process: nginx (pid 910). Free them before running grim (e.g. stop the conflicting service). appears under the Traefik step when a Homebrew nginx or Apache is listening. Stop that service and run setup again.
On Linux the hosts file is yours to keep
Setup only prints the line. In practice you rarely add it by hand: grim create-project and grim up add the project's entry to /etc/hosts through sudo, and on WSL2 grim hosts:windows does the same for the Windows side.
After it finishes
The machine is ready and no project is running yet. Go to a project and start it, or make one with grim create-project.
$ cd shop && grim upRelated spells
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 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 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.
Recipes that use it
Install on macOS
Run the installer, open a fresh terminal, prepare the machine with grim setup, check that .test names resolve, and finish on a clean grim doctor.
Install on Windows
Run one installer in PowerShell, let it seed the Windows certificate authority and hand the rest to the WSL2 distro, then keep the distro's hosts file from being rewritten and finish on a clean grim doctor.