class Puma::DSL


| after_refork | :after_refork | inside |
| before_refork | :before_refork | inside |
| before_worker_shutdown | :before_worker_shutdown | inside, after |
| before_worker_boot | :before_worker_boot | inside, before |
| DSL Method | Options Key | Fork Block Location |
The following hooks have been updated:
before the worker that need to be passed to the hook when the worker is shutdown.
parameter. This allows storage of data, typically objects that are created
hook blocks/procs. If a key name is specified, a hash is passed as the last
Previously, the worker index and the LogWriter instance were passed to the
{Puma::Cluster::Worker#run} method.
hooks that run inside the forked workers. All the hooks run inside the
Puma v6 adds the option to specify a key name (String or Symbol) to the
test/config.
You can also find many examples being used by the test suite in
puts config.options # => “tcp://127.0.0.1:3002”
config.clamp
config = Configuration.new(config_file: “puma_config.rb”)
Resulting configuration:
port 3002
$ cat puma_config.rb
Used to load file:
puts config.options # => “tcp://127.0.0.1:3001”
config.clamp
end
user_config.port 3001
config = Configuration.new({}) do |user_config|
Used manually (via CLI class):
internally.
These same methods are used in Puma cli and the rack handler
The methods that are available for use inside the configuration file.

def self.ssl_bind_str(host, port, opts)

Other tags:
    See: ssl_bind -
def self.ssl_bind_str(host, port, opts)
  verify = opts.fetch(:verify_mode, 'none').to_s
  tls_str =
    if opts[:no_tlsv1_1]  then '&no_tlsv1_1=true'
    elsif opts[:no_tlsv1] then '&no_tlsv1=true'
    else ''
    end
  ca_additions = "&ca=#{Puma::Util.escape(opts[:ca])}" if ['peer', 'force_peer'].include?(verify)
  low_latency_str = opts.key?(:low_latency) ? "&low_latency=#{opts[:low_latency]}" : ''
  backlog_str = opts[:backlog] ? "&backlog=#{Integer(opts[:backlog])}" : ''
  if defined?(JRUBY_VERSION)
    cipher_suites = opts[:ssl_cipher_list] ? "&ssl_cipher_list=#{opts[:ssl_cipher_list]}" : nil # old name
    cipher_suites = "#{cipher_suites}&cipher_suites=#{opts[:cipher_suites]}" if opts[:cipher_suites]
    protocols = opts[:protocols] ? "&protocols=#{opts[:protocols]}" : nil
    keystore_additions = "keystore=#{opts[:keystore]}&keystore-pass=#{opts[:keystore_pass]}"
    keystore_additions = "#{keystore_additions}&keystore-type=#{opts[:keystore_type]}" if opts[:keystore_type]
    if opts[:truststore]
      truststore_additions = "&truststore=#{opts[:truststore]}"
      truststore_additions = "#{truststore_additions}&truststore-pass=#{opts[:truststore_pass]}" if opts[:truststore_pass]
      truststore_additions = "#{truststore_additions}&truststore-type=#{opts[:truststore_type]}" if opts[:truststore_type]
    end
    "ssl://#{host}:#{port}?#{keystore_additions}#{truststore_additions}#{cipher_suites}#{protocols}" \
      "&verify_mode=#{verify}#{tls_str}#{ca_additions}#{backlog_str}"
  else
    ssl_cipher_filter = opts[:ssl_cipher_filter] ? "&ssl_cipher_filter=#{opts[:ssl_cipher_filter]}" : nil
    ssl_ciphersuites = opts[:ssl_ciphersuites] ? "&ssl_ciphersuites=#{opts[:ssl_ciphersuites]}" : nil
    v_flags = (ary = opts[:verification_flags]) ? "&verification_flags=#{Array(ary).join ','}" : nil
    cert_flags = (cert = opts[:cert]) ? "cert=#{Puma::Util.escape(cert)}" : nil
    key_flags = (key = opts[:key]) ? "&key=#{Puma::Util.escape(key)}" : nil
    password_flags = (password_command = opts[:key_password_command]) ? "&key_password_command=#{Puma::Util.escape(password_command)}" : nil
    reuse_flag =
      if (reuse = opts[:reuse])
        if reuse == true
          '&reuse=dflt'
        elsif reuse.is_a?(Hash) && (reuse.key?(:size) || reuse.key?(:timeout))
          val = +''
          if (size = reuse[:size]) && Integer === size
            val << size.to_s
          end
          if (timeout = reuse[:timeout]) && Integer === timeout
            val << ",#{timeout}"
          end
          if val.empty?
            nil
          else
            "&reuse=#{val}"
          end
        else
          nil
        end
      else
        nil
      end
    "ssl://#{host}:#{port}?#{cert_flags}#{key_flags}#{password_flags}#{ssl_cipher_filter}#{ssl_ciphersuites}" \
      "#{reuse_flag}&verify_mode=#{verify}#{tls_str}#{ca_additions}#{v_flags}#{backlog_str}#{low_latency_str}"
  end
end

def _load_from(path)

def _load_from(path)
  if path
    @path = path
    instance_eval(File.read(path), path, 1)
  end
ensure
  _offer_plugins
end

def _offer_plugins

def _offer_plugins
  @plugins.each do |o|
    if o.respond_to? :config
      @options.shift
      o.config self
    end
  end
  @plugins.clear
end

def activate_control_app(url="auto", opts={})


activate_control_app 'unix:///var/run/pumactl.sock', { no_token: true, data_only: true}
@example
activate_control_app 'unix:///var/run/pumactl.sock', { no_token: true }
@example
activate_control_app 'unix:///var/run/pumactl.sock', { auth_token: '12345' }
@example
activate_control_app 'unix:///var/run/pumactl.sock'
@example

Check out {Puma::App::Status} to see what the app has available.

simple authentication.
will need to include that token as a query parameter. This allows for
provide an authentication token, so all requests to the control server
be communicated with to control the main server. Additionally, you can
Start the Puma control rack application on +url+. This application can
def activate_control_app(url="auto", opts={})
  if url == "auto"
    path = Configuration.temp_path
    @options[:control_url] = "unix://#{path}"
    @options[:control_url_temp] = path
  else
    @options[:control_url] = url
  end
  if opts[:no_token]
    # We need to use 'none' rather than :none because this value will be
    # passed on to an instance of OptionParser, which doesn't support
    # symbols as option values.
    #
    # See: https://github.com/puma/puma/issues/1193#issuecomment-305995488
    auth_token = 'none'
  else
    auth_token = opts[:auth_token]
    auth_token ||= Configuration.random_token
  end
  @options[:control_auth_token] = auth_token
  @options[:control_url_umask] = opts[:umask] if opts[:umask]
  @options[:control_data_only] = opts[:data_only] if opts[:data_only]
end

def add_pem_values_to_options_store(opts)


options[:store] from where Puma binder knows how to find and extract them.
To avoid adding cert_pem and key_pem as URI params, we store them on the
def add_pem_values_to_options_store(opts)
  return if defined?(JRUBY_VERSION)
  @options[:store] ||= []
  # Store cert_pem and key_pem to options[:store] if present
  [:cert, :key].each do |v|
    opt_key = :"#{v}_pem"
    if opts[opt_key]
      index = @options[:store].length
      @options[:store] << opts[opt_key]
      opts[v] = "store:#{index}"
    end
  end
end

def after_booted(&block)


end
puts 'After booting...'
after_booted do
@example

Code to run after puma is booted (works for both single and cluster modes).
def after_booted(&block)
  Puma.deprecate_method_change :on_booted, __callee__, __method__
  @config.events.after_booted(&block)
end

def after_refork(key = nil, &block)

Other tags:
    Note: - Cluster mode with `fork_worker` enabled only.
def after_refork(key = nil, &block)
  process_hook :after_refork, key, block
end

def after_stopped(&block)


end
puts 'After stopping...'
after_stopped do
@example

Code to run after puma is stopped (works for both: single and clustered)
def after_stopped(&block)
  Puma.deprecate_method_change :on_stopped, __callee__, __method__
  @config.events.after_stopped(&block)
end

def after_worker_fork(&block)

Other tags:
    Note: - Cluster mode only.
def after_worker_fork(&block)
  process_hook :after_worker_fork, nil, block, cluster_only: true
end

def after_worker_shutdown(&block)

Other tags:
    Note: - Cluster mode only.
def after_worker_shutdown(&block)
  process_hook :after_worker_shutdown, nil, block, cluster_only: true
end

def app(obj=nil, &block)

Other tags:
    See: Puma::Configuration#app -
def app(obj=nil, &block)
  obj ||= block
  raise "Provide either a #call'able or a block" unless obj
  @options[:app] = obj
end

def before_fork(&block)

Other tags:
    Note: - Cluster mode only.
def before_fork(&block)
  process_hook :before_fork, nil, block, cluster_only: true
end

def before_refork(key = nil, &block)

Other tags:
    Version: - 5.0.0

Other tags:
    Note: - Cluster mode with `fork_worker` enabled only.
def before_refork(key = nil, &block)
  Puma.deprecate_method_change :on_refork, __callee__, __method__
  process_hook :before_refork, key, block, cluster_only: true
end

def before_restart(&block)


end
puts 'On restart...'
before_restart do
@example

This can be called multiple times to add code each time.

close log files, database connections, etc.
Code to run before doing a restart. This code should
def before_restart(&block)
  Puma.deprecate_method_change :on_restart, __callee__, __method__
  process_hook :before_restart, nil, block
end

def before_thread_exit(&block)


end
puts 'On thread exit...'
before_thread_exit do
@example

This can be called multiple times to add several hooks.

is trimmed.
This hook is useful for cleaning up thread local resources when a thread

Raising an exception will log a warning.
Return values are ignored.

It does not run when a thread dies due to exceptions or any other cause.
This hook only runs when a thread in the threadpool is trimmed by Puma.

blocked, so no new requests will be picked up.
pool. Be careful: while this block executes, Puma's main loop is
Provide a block to be executed after a thread is trimmed from the thread
def before_thread_exit(&block)
  Puma.deprecate_method_change :on_thread_exit, __callee__, __method__
  process_hook :before_thread_exit, nil, block
end

def before_thread_start(&block)


end
puts 'On thread start...'
before_thread_start do
@example

This can be called multiple times to add several hooks.

This hook is useful for doing something when the thread pool grows.

Raising an exception will log a warning.
Return values are ignored.

the threadpool until the provided block returns.
probably a request will have to wait too! The new thread will not be added to
pool. Be careful: while the block executes, thread creation is delayed, and
Provide a block to be executed just before a thread is added to the thread
def before_thread_start(&block)
  Puma.deprecate_method_change :on_thread_start, __callee__, __method__
  process_hook :before_thread_start, nil, block
end

def before_worker_boot(key = nil, &block)

Other tags:
    Note: - Cluster mode only.
def before_worker_boot(key = nil, &block)
  Puma.deprecate_method_change :on_worker_boot, __callee__, __method__
  process_hook :before_worker_boot, key, block, cluster_only: true
end

def before_worker_fork(&block)

Other tags:
    Note: - Cluster mode only.
def before_worker_fork(&block)
  Puma.deprecate_method_change :on_worker_fork, __callee__, __method__
  process_hook :before_worker_fork, nil, block, cluster_only: true
end

def before_worker_shutdown(key = nil, &block)

Other tags:
    Note: - Cluster mode only.
def before_worker_shutdown(key = nil, &block)
  Puma.deprecate_method_change :on_worker_shutdown, __callee__, __method__
  process_hook :before_worker_shutdown, key, block, cluster_only: true
end

def bind(url)

Other tags:
    See: Puma::Cluster#run -
    See: Puma::Runner#load_and_bind -

Other tags:
    Example: Socket permissions -
    Example: Disable optimization for low latency -
    Example: SSL cert for mutual TLS (mTLS) -
    Example: SSL cert -
    Example: Backlog depth -
def bind(url)
  @options[:binds] ||= []
  @options[:binds] << url
end

def bind_to_activated_sockets(bind=true)

Other tags:
    Example: Only bind to systemd activated sockets, ignoring other binds -
    Example: Use any systemd activated sockets as well as configured binds -
def bind_to_activated_sockets(bind=true)
  @options[:bind_to_activated_sockets] = bind
end

def clear_binds!

def clear_binds!
  @options[:binds] = []
end

def cluster(&block)

Other tags:
    Note: - Cluster mode only.
def cluster(&block)
  raise ArgumentError, "A block must be provided to `cluster`" unless block
  @options[:cluster] ||= []
  @options[:cluster] << block
end

def custom_logger(custom_logger)


custom_logger Logger.new('t.log')
@example

Pass in a custom logging class instance
def custom_logger(custom_logger)
  @options[:custom_logger] = custom_logger
end

def debug


debug
@example

The default is +false+.

Show debugging info
def debug
  @options[:debug] = true
end

def default_host

def default_host
  @options[:default_host] || Configuration.default_tcp_host
end

def directory(dir)


directory '/u/apps/lolcat'
@example

The default is the current directory.

The directory to operate out of.
def directory(dir)
  @options[:directory] = dir.to_s
end

def drain_on_shutdown(which=true)

Other tags:
    See: Puma::Server#graceful_shutdown -
def drain_on_shutdown(which=true)
  @options[:drain_on_shutdown] = which
end

def early_hints(answer=true)


early_hints
@example

The default is +nil+.

Enable HTTP 103 Early Hints responses.
def early_hints(answer=true)
  @options[:early_hints] = answer
end

def enable_keep_alives(enabled=true)


enable_keep_alives false
@example

The default is +true+.

The trade-off is that the number of TCP operations required will increase.
variance and eliminating long-tail outliers caused by keep-alive behavior.
will be processed in the order they are fully received, decreasing response
client to open a new request. Disabling this setting guarantees that requests
When `false`, Puma closes the connection after each request, requiring the

times for some processed requests.
outliers will exist. Those long-tail outliers may significantly affect response
means that the overall average of response times might not change, but more
increasing overall response time variance. Increased response time variance
enabling the keep-alive behavior may result in processing requests out-of-order,
When Puma receives more incoming connections than available Puma threads,

times for connections that can send multiple requests in a single connection.
Enabling this setting reduces the number of TCP operations, reducing response
When `true`, keep-alive connections are maintained on inbound requests.
def enable_keep_alives(enabled=true)
  @options[:enable_keep_alives] = enabled
end

def environment(environment)


environment 'production'
@example

The default is "development".

a string.
Set the environment in which the rack's app will run. The value must be
def environment(environment)
  @options[:environment] = environment
end

def extra_runtime_dependencies(answer = [])

Other tags:
    See: Puma::Launcher#extra_runtime_deps_directories -
def extra_runtime_dependencies(answer = [])
  @options[:extra_runtime_dependencies] = Array(answer)
end

def fiber_per_request(which=true)


fiber_per_request
@example

The default is +false+.

Puma internal stack frames.
locals and fiber storage. Also provides a cleaner backtrace with less
Use a clean fiber per request which ensures a clean slate for fiber
def fiber_per_request(which=true)
  @options[:fiber_per_request] = which
end

def first_data_timeout(seconds)

Other tags:
    See: Puma::Server.new -
def first_data_timeout(seconds)
  @options[:first_data_timeout] = Integer(seconds)
end

def force_shutdown_after(val=:forever)

Other tags:
    See: Puma::Server#graceful_shutdown -
def force_shutdown_after(val=:forever)
  i = case val
      when :forever
        -1
      when :immediately
        0
      else
        Float(val)
      end
  @options[:force_shutdown_after] = i
end

def fork_worker(after_requests=1000)

Other tags:
    Note: - Cluster mode only.
    Note: - This is experimental.
def fork_worker(after_requests=1000)
  @options[:fork_worker] = Integer(after_requests)
end

def get(key,default=nil)

def get(key,default=nil)
  @options[key.to_sym] || default
end

def http_content_length_limit(limit)


http_content_length_limit 2_000_000_000
@example

The default is +nil+.

size of the body of the request.
When no Content-Length http header is present, it is compared against the

HTTP 413 status code is returned.
If the payload size (CONTENT_LENGTH) is larger than http_content_length_limit,
This limit is compared against Content-Length HTTP header.
Specify how big the request payload should be, in bytes.
def http_content_length_limit(limit)
  @options[:http_content_length_limit] = limit
end

def idle_timeout(seconds)

Other tags:
    See: Puma::Server.new -
def idle_timeout(seconds)
  @options[:idle_timeout] = Integer(seconds)
end

def initialize(options, config)

def initialize(options, config)
  @config  = config
  @options = options
  @plugins = []
end

def inject(&blk)

def inject(&blk)
  instance_eval(&blk)
end

def io_selector_backend(backend)

Other tags:
    See: https://github.com/socketry/nio4r/blob/main/lib/nio/selector.rb -
def io_selector_backend(backend)
  @options[:io_selector_backend] = backend.to_sym
end

def load(file)


load 'config/puma/production.rb'
@example

Files get loaded later via Configuration#load.
Load additional configuration from a file.
def load(file)
  @options[:config_files] ||= []
  @options[:config_files] << file
end

def log_formatter(&block)

def log_formatter(&block)
  @options[:log_formatter] = block
end

def log_requests(which=true)


log_requests
@example

The default is +false+.

Enable request logging, the inverse of `quiet`.
def log_requests(which=true)
  @options[:log_requests] = which
end

def lowlevel_error_handler(obj=nil, &block)


end
[200, {}, ["error page"]]
lowlevel_error_handler do |err|
@example

configuration file to change the default error on the server.
Use +obj+ or +block+ as the low level error handler. This allows the
def lowlevel_error_handler(obj=nil, &block)
  obj ||= block
  raise "Provide either a #call'able or a block" unless obj
  @options[:lowlevel_error_handler] = obj
end

def max_fast_inline(num_of_requests)

Deprecated:
  • Use {#max_keep_alive} instead.
def max_fast_inline(num_of_requests)
  Puma.deprecate_method_change :max_fast_inline, __method__, :max_keep_alive
  @options[:max_keep_alive] ||= Float(num_of_requests) unless num_of_requests.nil?
end

def max_io_threads(max)

allows for 3 regular threads and 7 IO threads for example.
Any IO thread over the limit is counted as a regular thread, hence the above configuration also
The above example allows for 5 regular threads and 5 IO threads to process requests concurrently.

max_io_threads 5
threads 5
@example

Threads marked as IO bound are allowed to go over the max thread limit.

of CPU, they can mark the current request as IO bound using env["puma.mark_as_io_bound"].
When request handlers know the current requests will no longer use a significant amount

Configure the max number of IO threads.
def max_io_threads(max)
  max = Integer(max)
  if max < 0
    raise "The maximum number of IO threads (#{max}) must be a positive number"
  end
  @options[:max_io_threads] = max
end

def max_keep_alive(num_of_requests)


max_keep_alive 20
@example

The default is 999.

number or Float::INFINITY.
Note that some applications (server to server) may benefit from a very high
The number of requests a keep-alive client can submit before being closed.
def max_keep_alive(num_of_requests)
  @options[:max_keep_alive] = Float(num_of_requests) unless num_of_requests.nil?
end

def mutate_stdout_and_stderr_to_sync_on_write(enabled=true)


mutate_stdout_and_stderr_to_sync_on_write false
@example

The default is +true+.

operating system and is not buffered internally
Ensures +STDOUT+ and +STDERR+ is immediately flushed to the underlying
def mutate_stdout_and_stderr_to_sync_on_write(enabled=true)
  @options[:mutate_stdout_and_stderr_to_sync_on_write] = enabled
end

def out_of_band(&block)


This can be called multiple times to add several hooks.

or scheduling asynchronous tasks to execute after a response.
This hook is useful for running out-of-band garbage collection

The worker doesn't accept new requests until this code finishes.
processing and there are no busy threads on the worker.
These hooks run immediately after a request has finished
Code to run out-of-band when the worker is idle.
def out_of_band(&block)
  process_hook :out_of_band, nil, block
end

def persistent_timeout(seconds)

Other tags:
    See: Puma::Server.new -
def persistent_timeout(seconds)
  @options[:persistent_timeout] = Integer(seconds)
end

def pidfile(path)


pidfile '/u/apps/lolcat/tmp/pids/puma.pid'
@example

Store the pid of the server in the file at "path".
def pidfile(path)
  @options[:pidfile] = path.to_s
end

def plugin(name)


plugin :tmp_restart
@example

Load the named plugin for use by this configuration.
def plugin(name)
  @plugins << @config.load_plugin(name)
end

def port(port, host=nil)


port 3000
@example

The default is +9292+.

Define the TCP port to bind to. Use `bind` for more advanced options.
def port(port, host=nil)
  host ||= default_host
  bind URI::Generic.build(scheme: 'tcp', host: host, port: Integer(port)).to_s
end

def preload_app!(answer=true)

Other tags:
    Note: - When using `fork_worker`, this only applies to worker 0.
    Note: - Cluster mode only.
def preload_app!(answer=true)
  @options[:preload_app] = answer
end

def process_hook(options_key, key, block, cluster_only: false)

def process_hook(options_key, key, block, cluster_only: false)
  raise ArgumentError, "expected #{options_key} to be given a block" unless block
  @config.hooks[options_key] = true
  @options[options_key] ||= []
  hook_options = { block: block, cluster_only: cluster_only }
  hook_options[:id] = if ON_WORKER_KEY.include?(key.class)
    key.to_sym
  elsif key.nil?
    nil
  else
    raise "'#{options_key}' key must be String or Symbol"
  end
  @options[options_key] << hook_options
end

def prune_bundler(answer=true)

Other tags:
    See: extra_runtime_dependencies -

Other tags:
    Note: - This is only supported for RubyGems 2.2+
    Note: - This is incompatible with +preload_app!+.
    Note: - Cluster mode only.
def prune_bundler(answer=true)
  @options[:prune_bundler] = answer
end

def queue_requests(answer=true)

Other tags:
    See: Puma::Server -
def queue_requests(answer=true)
  @options[:queue_requests] = answer
end

def quiet(which=true)


quiet
@example

The default is +true+.

Disable request logging, the inverse of `log_requests`.
def quiet(which=true)
  @options[:log_requests] = !which
end

def rack_url_scheme(scheme=nil)


Normal values are 'http' or 'https'.
Only necessary if X-Forwarded-Proto is not being set by your proxy
Allows setting `env['rack.url_scheme']`.
def rack_url_scheme(scheme=nil)
  @options[:rack_url_scheme] = scheme
end

def rackup(path)


rackup '/u/apps/lolcat/config.ru'
@example

The default is "config.ru".

Load +path+ as a rackup file.
def rackup(path)
  @options[:rackup] ||= path.to_s
end

def raise_exception_on_sigterm(answer=true)

Other tags:
    See: Puma::Cluster#setup_signals -
    See: Puma::Launcher#setup_signals -
def raise_exception_on_sigterm(answer=true)
  @options[:raise_exception_on_sigterm] = answer
end

def restart_command(cmd)


restart_command '/u/app/lolcat/bin/restart_puma'
@example

to Puma, as those are the same as the original process.
load Puma itself (ie. 'ruby -Ilib bin/puma'), not the arguments
Command to use to restart Puma. This should be just how to
def restart_command(cmd)
  @options[:restart_cmd] = cmd.to_s
end

def set_default_host(host)

def set_default_host(host)
  @options[:default_host] = host
end

def set_remote_address(val=:socket)


set_remote_address :localhost
@example

The default is +:socket+.

entirely in your hands.
you wish. Because Puma never uses this field anyway, it's format is
5. **\** - this allows you to hardcode remote address to any value
protocol attached to it, will fall back to :socket
HAproxy PROXY protocol, version 1. If the request does not have the PROXY
4. **proxy_protocol: :v1**- set the remote address to the value read from the
Puma will fall back to the behavior of :socket
headers such as X-Forwarded-For to be used as well. If this header is absent,
Only the first word (as separated by spaces or comma) is used, allowing
`set_remote_address header: "X-Real-IP"`.
provided http header. For instance:
3. **header: **- set the remote address to the value of the
2. **:localhost** - set the remote address to "127.0.0.1"
system call), Puma will return "0.0.0.0"
if the peer disconnects between the connection being accepted and the getpeername
syscall. This is the normal behavior. If this fails for any reason (e.g.,
1. **:socket** - read the peername from the socket using the

There are 5 possible values:

slows down the handling significantly.
a kernel syscall is required which for very fast rack handlers
is configurable because to calculate the true socket peer address
Control how the remote address of the connection is set. This
def set_remote_address(val=:socket)
  case val
  when :socket
    @options[:remote_address] = val
  when :localhost
    @options[:remote_address] = :value
    @options[:remote_address_value] = "127.0.0.1".freeze
  when String
    @options[:remote_address] = :value
    @options[:remote_address_value] = val
  when Hash
    if hdr = val[:header]
      @options[:remote_address] = :header
      @options[:remote_address_header] = "HTTP_" + hdr.upcase.tr("-", "_")
    elsif protocol_version = val[:proxy_protocol]
      @options[:remote_address] = :proxy_protocol
      protocol_version = protocol_version.downcase.to_sym
      unless [:v1].include?(protocol_version)
        raise "Invalid value for proxy_protocol - #{protocol_version.inspect}"
      end
      @options[:remote_address_proxy_protocol] = protocol_version
    else
      raise "Invalid value for set_remote_address - #{val.inspect}"
    end
  else
    raise "Invalid value for set_remote_address - #{val}"
  end
end

def shutdown_debug(val = true, on_force: false)

Other tags:
    See: force_shutdown_after -
def shutdown_debug(val = true, on_force: false)
  @options[:shutdown_debug] = val && on_force ? :on_force : val
end

def silence_fork_callback_warning


silence_fork_callback_warning
@example

The default is +false+.

Disable warning message when running single mode with callback hook defined.
def silence_fork_callback_warning
  @options[:silence_fork_callback_warning] = true
end

def silence_single_worker_warning

Other tags:
    Note: - Cluster mode only.
def silence_single_worker_warning
  @options[:silence_single_worker_warning] = true
end

def single(&block)

Other tags:
    Note: - Single mode only.
def single(&block)
  raise ArgumentError, "A block must be provided to `single`" unless block
  @options[:single] ||= []
  @options[:single] << block
end

def ssl_bind(host, port, opts = {})

Other tags:
    Example: For JRuby, two keys are required: +keystore+ & +keystore_pass+ -
    Example: Alternatively, you can provide +cert_pem+ and +key_pem+: -
    Example: Using self-signed certificate with the +localhost+ gem: -
def ssl_bind(host, port, opts = {})
  add_pem_values_to_options_store(opts)
  bind self.class.ssl_bind_str(host, port, opts)
end

def state_path(path)


state_path '/u/apps/lolcat/tmp/pids/puma.state'
@example

used by +pumactl+ to query and control the server.
Use +path+ as the file to store the server info state. This is
def state_path(path)
  @options[:state] = path.to_s
end

def state_permission(permission)


state_permission 0600
@example

+permission+ is an octal number (e.g. `0640` or `0o640`).
Use +permission+ to restrict permissions for the state file. By convention,
def state_permission(permission)
  @options[:state_permission] = permission
end

def stdout_redirect(stdout=nil, stderr=nil, append=false)


stdout_redirect '/app/lolcat/log/stdout', '/app/lolcat/log/stderr', true
@example
stdout_redirect '/app/lolcat/log/stdout', '/app/lolcat/log/stderr'
@example

The default is +false+.

specifies whether the output is appended.
Redirect +STDOUT+ and +STDERR+ to files specified. The +append+ parameter
def stdout_redirect(stdout=nil, stderr=nil, append=false)
  @options[:redirect_stdout] = stdout
  @options[:redirect_stderr] = stderr
  @options[:redirect_append] = append
end

def supported_http_methods(methods)

Other tags:
    Example: Allows any method -
    Example: Restricts methods to the methods in the IANA Registry -
    Example: Restricts methods to the array elements -
    Example: Adds 'PROPFIND' to existing supported methods -

Other tags:
    Note: - If the `methods` value is `:any`, no method check with be performed,
def supported_http_methods(methods)
  if methods == :any
    @options[:supported_http_methods] = :any
  elsif Array === methods && methods == (ary = methods.grep(String).uniq) &&
    !ary.empty?
    @options[:supported_http_methods] = ary
  else
    raise "supported_http_methods must be ':any' or a unique array of strings"
  end
end

def tag(string)


tag ''
@example
tag 'app name'
@example

The default is the current file or directory base name.

to add a tag, use an empty string.
If you do not specify a tag, Puma will infer it. If you do not want Puma

Additional text to display in process listing.
def tag(string)
  @options[:tag] = string.to_s
end

def threads(min, max = min)


threads 5, 5
@example
threads 0, 16
@example
threads 5
@example

If these environment variables aren't set, the default is "0, 5" in MRI or "0, 16" for other interpreters.

(or +MIN_THREADS+ / +MAX_THREADS+ if the +PUMA_+ variables aren't set).
The default is the environment variables +PUMA_MIN_THREADS+ / +PUMA_MAX_THREADS+

It can be a single fixed number, or a +min+ and a +max+.

Configure the number of threads to use to answer requests.
def threads(min, max = min)
  min = Integer(min)
  max = Integer(max)
  if min > max
    raise "The minimum (#{min}) number of threads must be less than or equal to the max (#{max})"
  end
  if max < 1
    raise "The maximum number of threads (#{max}) must be greater than 0"
  end
  @options[:min_threads] = min
  @options[:max_threads] = max
end

def wait_for_less_busy_worker(val=0.005)

Other tags:
    See: Puma::ThreadPool#wait_for_less_busy_worker -
    See: Puma::Server#handle_servers -

Other tags:
    Note: - Interpreters with forking support only.
    Note: - Cluster mode with >= 2 workers only.
def wait_for_less_busy_worker(val=0.005)
  @options[:wait_for_less_busy_worker] = val.to_f
end

def worker_boot_timeout(timeout)

Other tags:
    See: Puma::Cluster::Worker#ping_timeout -

Other tags:
    Note: - Cluster mode only.
def worker_boot_timeout(timeout)
  @options[:worker_boot_timeout] = Integer(timeout)
end

def worker_check_interval(interval)

Other tags:
    See: Puma::Cluster#check_workers -

Other tags:
    Note: - Cluster mode only.
def worker_check_interval(interval)
  @options[:worker_check_interval] = Integer(interval)
end

def worker_culling_strategy(strategy)

Other tags:
    See: Puma::Cluster#cull_workers -

Other tags:
    Note: - Cluster mode only.
def worker_culling_strategy(strategy)
  strategy = strategy.to_sym
  if ![:youngest, :oldest].include?(strategy)
    raise "Invalid value for worker_culling_strategy - #{strategy}"
  end
  @options[:worker_culling_strategy] = strategy
end

def worker_shutdown_timeout(timeout)

Other tags:
    See: Puma::Cluster::Worker#term -

Other tags:
    Note: - Cluster mode only.
def worker_shutdown_timeout(timeout)
  @options[:worker_shutdown_timeout] = Integer(timeout)
end

def worker_timeout(timeout)

Other tags:
    See: Puma::Cluster::Worker#ping_timeout -

Other tags:
    Note: - Cluster mode only.
def worker_timeout(timeout)
  timeout = Integer(timeout)
  min = @options.fetch(:worker_check_interval, Configuration::DEFAULTS[:worker_check_interval])
  if timeout <= min
    raise "The minimum worker_timeout must be greater than the worker reporting interval (#{min})"
  end
  @options[:worker_timeout] = timeout
end

def workers(count)

Other tags:
    See: Puma::Cluster -
def workers(count)
  @options[:workers] = count.nil? ? 0 : @config.send(:parse_workers, count)
end