Getting your Rails dev environment ready for passkeys

I spent the whole day digging through WebKit bug reports & wrangling with puma-dev , but finally have a working solution.

The gist is: while Chrome, Firefox, and non-macOS implementations of WebKit support *.localhost subdomains (and register them as a Secure Context, see: This MDN article ), WebKit on macOS does not, because of underlying macOS networking APIs. There’s a whole set of bugs about it:

So your Rails development environment needs to run with HTTPS, which requires a certificate, which is a whole mess.

puma-dev to the Rescue

puma-dev solves the HTTPS issue elegantly, but I’ve never liked how it runs as a daemon process by default. macOS does not have good daemon support; and for execution environments as volatile as development, daemons aren’t the right answer.

Update: Arrrgf; turns out that puma-dev only listens to 127.0.0.1 when run in the foreground, so it has to run as a daemon if you need cross-device testing (such as through VMs or on mobile devices).

However, I really don’t want to lose the ability to quickly kill & reboot my development environment. Again, the problem of macOS not having good daemon support and development being too volatile of an execution environment for daemons to be practical. So I ended up writing a script that:

  1. Force stops the puma-dev daemon
  2. Prints out some text to help with attaching the debugger
  3. Starts tailing puma’s daemon logs.
#!/bin/bash

set -e

echo "make sure to attach a debugger with (or alias): rdbg -A"
echo "force-stopping puma-dev"
puma-dev -stop
echo "watching puma with: tail -f ~/Library/Logs/puma-dev.log"
echo "============"
tail -f ~/Library/Logs/puma-dev.log

The ideal solution would be for puma-dev to add a flag to specify what hosts to listen on. There’s a PR for some of this, but a customizable command-line flag (like for ports) would be a great solution; since it allows for flexibility: https://github.com/puma/puma-dev/issues/306

In case it’s useful for anyone, I’ve kept my original version at the end of this post. It’s a good example of how you can hook in Ruby’s built-in debugger as part of a larger buildchain.


puma-dev has the option to run in a foreground mode. But since puma-dev doesn’t support TTY for its child processes, you lose the ability to use the built-in Ruby debugger.

Thankfully, Ruby’s built-in debugger has a special wrapper command that we can use to automatically get an optional debugger for any process spawned by puma-dev .

The commands

The command to run puma-dev in the foreground with the debugger hooks is:

rdbg --nonstop -O -c -- bundle exec puma-dev

To attach the debugger process, run:

rdbg -A

Which is…cumbersome. I prefer using an alias:

alias attachdebugger='rdbg -A'