README.adoc in puma-daemon-0.1.0 vs README.adoc in puma-daemon-0.1.1

- old
+ new

@@ -1,30 +1,137 @@ = Puma::Daemon +:toc: +:toclevels: 4 +:sectnums: +:icons: font -Welcome to your new gem! In this directory, you'll find the files you need to be able to package up your Ruby library into a gem. Put your Ruby code in the file `lib/puma/daemon`. To experiment with that code, run `bin/console` for an interactive prompt. +image:https://github.com/kigster/puma-daemon/workflows/Ruby/badge.svg[link=https://github.com/kigster/puma-daemon/actions?query=workflow%3ARuby] image:https://codecov.io/gh/kigster/puma-daemon/branch/master/graph/badge.svg?token=asxarMSGbz[link=https://codecov.io/gh/kigster/puma-daemon] -TODO: Delete this and the text above, and describe your gem +In version 5.0 of the popular Ruby HTTP server https://github.com/puma/puma[Puma] the developers chose to https://github.com/puma/puma/pull/2170/files[drop the daemonization] support from Puma. They did that because the code wasn't actively maintained. Other and perhaps better options now exist (such as `systemd`, etc), not to mention that many people have switched to Kubernetes and Docker, where you generally want to start all servers in the foreground. +And yet, on occasion, it was rather useful and straightforward to use the built-in daemonization feature that was cross-platform and is now gone. Some folks are still using this feature and are therefore stuck with Puma version 4, or must wrap Puma either in the `systemd` manifest or `launchctl plist` on Mac OS-X, or a Docker container. Well, **not anymore!** + +NOTE: Add this gem to your dependencies, and make a one line change either in your `config/puma.rb` file, or use `pumad` binary to start Puma as per usual, and you can even leave `-d` flags there (they are ignored when started via `pumad`, and Puma always goes to the background when started that way). + +One of the nice features of the old daemonization functionality was that it worked across all platforms. + +So, if you want to use the latest and greatest Puma 5+, but have it self-daemonize, this gem is for you. + +== Compatility + +We did not restore the daemonization code for JRuby; so at the moment this will work with the MRI distribution, and possibly others that support `Process.daemon(true)`. + +We currently run CI suite on Github Actions against + + * MRI Ruby 3.0.0 + * MRI Ruby 2.7.2 + * MRI Ruby 2.6.6 + * MRI Ruby 2.5.7 + + +== Design Decisions + +This gem's goal was to surgically augment Puma's source code to restore daemonization by merely requiring `puma/daemon`. We almost got there, but not quite. + +While this was an admirable goal, it has not been accomplished in the current version. The internals of Puma isn't very easy to monkey-patch or augment. For example, we couldn't think of a way to add back the `-d` flags to the Option Parsing method without having to override the entire method: — which is _not a good solution_, because — what if Puma developers add a new flag in the future? We would have to keep this overridden method frequently updated and potentially choose a different version depending on what version of Puma you are using. That sounds like a nightmare. + +It is why instead, we took an approach that requires you — the user — to make a couple of small changes in your Puma configuration to bring daemonization back, or in your scripts, change `puma` to `pumad`, and everything should work. If you run into problems, please https://github.com/kigster/puma-daemon/issues/new[submit an issue]. + == Installation Add this line to your application's Gemfile: [source,ruby] ---- -gem 'puma-daemon' +gem 'puma-daemon', require: false +gem 'puma', '~> 5' ---- And then execute: $ bundle install -Or install it yourself as: +== Usage - $ gem install puma-daemon +There were two ways you could daemonize Puma in the past: -== Usage + 1. By specifying `daemonize` or `daemonize(true)` in your config file. + 2. Or, by passing a `-d` or `--daemonize` command line flag. -Work in progress. +This gem allows you to daemonize using both ways, but with a small caveat in each case. + +Please note that both ways require you to include this gem in your Gemfile, but you may specify it as `require: false` — it will only activate if you explicitly require it, or use `pumad` executable. + +=== Daemonizing via the Config File + +If you want to specify `daemonize` in your config file, simply include `require 'puma/daemon'` at the top of your config file: + +[source,ruby] +---- +# file: config/puma.rb +require 'puma/daemon' + +port 3001 +workers 3 +threads 2,3 +# accepts true or false, and if false is passed will NOT daemonize +daemonize +---- + +With this method you can continue using the standard `puma` executable to get it started, but (and this is important) — **you must remove any `-d` or `--daemonize` from the command line**, or Puma v5 and above will fail with an error. + +Here is an example of daemonizing via the config file shown above, and using the regular `puma` binary: + +[source,bash] +---- +❯ gem install puma-daemon puma -N +❯ puma -C config/puma.rb config.ru + +[98795] Puma starting in cluster mode... +[98795] * Puma version: 5.1.1 (ruby 2.7.2-p137) ("At Your Service") +[98795] * Min threads: 2 +[98795] * Max threads: 3 +[98795] * Environment: production +[98795] * Master PID: 98795 +[98795] * Workers: 3 +[98795] * Restarts: (✔) hot (✔) phased +[98795] * Listening on http://0.0.0.0:3001 +[98795] * Puma Daemon: Daemonizing (puma-daemon v0.1.1)... +---- + +Note that using this method you can decide whether to daemonize or not by passing true or false to the `daemonize` method. + +=== Daemonizing on the Command Line + +If you prefer to make a decision whether to daemonize or not on the command line, you only have to make one chance: replace `puma` with `pumad`. + +NOTE: We did not want to conflict with the `puma` gem by introducing another executable under the same name. The executable this gem provides is called `pumad` (where 'd' stands for daemon, and follows standard UNIX convention, as in eg `sshd`, `ftpd`, etc). + +If you replace `puma` with `pumad` — you no longer need to pass any aditional command line flag t ocontinue passing it `-d` or you can remove it (both `-d` and `--daemonize` are stripped out before ARGV is passed onto Puma's CLI parser.) + +[source,bash] +---- +❯ gem install puma --version 5.1.1 -N +❯ gem install puma-daemon -N + +❯ pumad -C config/puma.rb spec/rackup/bind.ru + +[98795] Puma starting in cluster mode... +[98795] * Puma version: 5.1.1 (ruby 2.7.2-p137) ("At Your Service") +[98795] * Min threads: 2 +[98795] * Max threads: 8 +[98795] * Environment: production +[98795] * Master PID: 98795 +[98795] * Workers: 3 +[98795] * Restarts: (✔) hot (✔) phased +[98795] * Listening on http://0.0.0.0:3000 +[98795] * Puma Daemon: Daemonizing (puma-daemon v0.1.1)... +---- + +As you can see, at the end it says "Daemonizing". + +If you start puma this way, you can still specify `daemonize(false)` in the configuration file to turn it off, but the default is to daemonize. Also, if you start with `pumad` you do not need to include `require 'puma/daemon'` in your configuration file, as the `pumad` binary loads all dependencies prior to parsing the config. + == Development After checking out the repo, run `bin/setup` to install dependencies. Then, run `rake spec` to run the tests. You can also run `bin/console` for an interactive prompt that will allow you to experiment.