Skip to content

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 installs

It 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.

  1. Creates the traefik-public Docker network, unless it exists. Every project's stack joins it so Traefik can reach the containers.
  2. Checks for mkcert. On macOS a missing mkcert is installed with Homebrew. On Linux setup prints sudo apt install mkcert and stops; this is the only step that ends the run.
  3. 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 first grim up.
  4. Sets up and starts Traefik. ~/.grim/traefik/ gets dynamic/, certs/ and a docker-compose.yml rendered for the machine's proxy mode, then the container is started, with its dashboard on 127.0.0.1:8099 (loopback only, since it shows every router). It routes only containers that are not labelled grim.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. In behind-herd it binds only 127.0.0.1:8080 (or proxy.port), trusts the X-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 with grim config set proxy.mode behind-herd.
  5. Points .test at your machine. On macOS it writes /etc/resolver/test with nameserver 127.0.0.1, through sudo, 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 them grim up adds 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 up

Recipes that use it