Skip to content

Switching From Pow To Puma for Rails development

Thanks to the recent changes with how Chrome handles the Google-owned .dev TLD, it is no longer recommended to run Ruby on Rails apps with Pow in development in OSX/macOS. Pow doesn’t support HTTPS and Basecamp have ceased development of it after 7 years, so it’s time to move on.

I’ve researched a few alternatives (eg. powproxInvoker, docker, nginx), but the most effective one by far for quickly switching from Pow is Puma-dev. This operates in a similar way to Pow, but uses the Rails-recommended Puma to serve your app in development. The guide below is designed specifically for migrating from Pow to Puma-dev with minimal impact to your environment, so if you’re starting fresh you may want to review their suggested defaults instead.

This guide will assume you have been using Pow, but haven’t tried any other ways of supporting HTTPS on your dev machine (such as Powprox or Invoker). If you have, please make sure you have removed any files they may have installed as there is a potential for conflicts here. You will also need Homebrew installed.

Onwards!

1. Uninstall Pow

This is important! It also means all your current projects will need migrating at the same time, so make sure anyone else working on a project is also ready to follow this guide. Here’s the rather-sketchy uninstall command for a standard Pow installation:

curl get.pow.cx/uninstall.sh | sh

It was also possible to install Pow with Homebrew, so you did that, you’ll need:

brew uninstall pow

2. Add Puma to your Rails app

Update your project’s Gemfile to include gem 'puma' in the development group – newer Rails apps will have this by default. You should remove any existing dev server, such as Unicorn. Be sure not to change anything that will affect your production environment!

Run bundle install to get the gem and its dependencies.

3. Install puma-dev

The following commands do the install and will make sure the DNS resolver can be set up properly later. It also generates the root CA certificate that will be used to seamlessly generate valid SSL certificates for your projects.

brew install puma/puma/puma-dev
sudo puma-dev -setup

4. Start puma-dev

We’re going to install Puma-dev as a background service, using the .dev extension, and refer to the ~/.pow/ directory for matching domain names to project folders.

If you’d rather run Puma-dev only when you need it, then don’t pass the -install option. Make yourself a simple bash script or alias instead, to ensure you always start with the correct options.

puma-dev -install -d dev -dir ~/.pow/

Note: Because we’re trying to achieve the simplest migration with the fewest changes, we are continuing to use the .dev TLD – you may want to take this opportunity to change to using a more appropriate .test or .localhost TLD. You will definitely want to do this if your project doesn’t support SSL.

4a. How to link new projects in future

As with Pow, Puma-dev needs to know where to find the app code for each domain you want to use. If you used the -dir ~/.pow/ option above then your existing Pow projects are already linked. For all new projects, a helper method is provided:

cd ~/projects/my-project
puma-dev link

This will link my-project.dev to the app in ~/projects/my-project. To use a different domain or project path, there are two options, eg.

puma-dev link -n other-name ~/projects/other-path

This will link other-name.dev to ~/projects/other-path.

5. Tail the log

To see debug information about Puma-dev’s operation, you can tail the log:

tail -f ~/Library/Logs/puma-dev.log

6. Environment variables

Your project’s environment variables will be loaded (in order, using source) from the following files in the project root path: .env, .powrc, and .powenv.

It will also source ~/.powconfig first if it exists. Note that any POW_* variables you may have used in the past will have no effect on Puma-dev’s operation.

You can configure the Puma server by setting the following variables in your ~/.powconfig file: CONFIG, THREADS, WORKERS.

These don’t appear to have any effect when set per project, just globally for all Puma instances started by Puma-dev. So what should these be set to? In short, I only recommend setting THREADS=3 and leaving the other two unset.

Note: I tried setting CONFIG=config/puma.rb and WORKERS=3 and ran into system stability problems which I think was related to too many fsevent_watch processes running after a few hours of development work, preventing any forking. This may be something to do with ActiveSupport::EventedFileUpdateChecker and how the listen gem monitors changes to your source code per process. With WORKERS set to zero, there’s no real need to set CONFIG either (for example to the Rails-provided config/puma.rb). If you really want to use workers, be sure to read the comments in your config/puma.rb file relating to pre/post fork actions – but it’s probably overkill for most apps.

7. Refresh DNS and SSL

To ensure Puma-dev can capture and serve your web requests, now do the following:

  1. Toggle your WiFi/Ethernet off and on to force an update the DNS resolver
  2. Fully quit your web browser and re-open it to get the updated root certificate
  3. Visit one of your project domains, eg. https://my-project.dev

8. Success?

If everything is working, after a short delay for the app to boot first-time (watch this happening by tailing the log) your project homepage should now be loaded with a valid SSL certificate.

If you have problems, here are how I solved the ones I ran into…

Troubleshooting

Invalid SSL certificate

If your browser complains about an untrusted root certificate, please do the following:

  1. Open Keychain Access
  2. Click the ‘login’ keychain in the left pane, then find the ‘Puma-dev CA’ certificate in the right pane
  3. Double-click it and expand the ‘Trust’ section, and make sure it says ‘Always Trust’
  4. Drag it into the ‘System’ keychain in the left pane
  5. Restart your computer
  6. Try https://my-project.dev again!

 

“Unexpected exit”

If you get this message on a blank page, check the Puma-dev log and the Rails log for errors preventing the app from booting. Perhaps you forgot to install the Puma gem? I know I definitely didn’t forget to do that the first time round.

“Unknown app”

If you get this message on a blank page, then the URL you are using isn’t linked to a project path. Go to ~/.pow/ and make sure there is a symlink (of the same name as your URL, excluding the .dev) to a valid project path.

Browser timeout / no response

If you don’t get a response, check the state of Puma-dev:

curl -H "Host: puma-dev" localhost/status

You should get a bit of JSON back, read that for more details. If you get an error, make sure Puma-dev is active by re-running the install command from Step 4 and monitoring the log for errors.

 

Good luck!