NAME
pagi-server - PAGI application server
SYNOPSIS
pagi-server [options] [app] [key=value ...]
# Serve current directory (default)
pagi-server
# Serve a specific directory
pagi-server PAGI::App::Directory root=/var/www
# Run a PAGI app file
pagi-server ./app.pl
# With environment modes
pagi-server -E development app.pl # Lint middleware enabled
pagi-server -E production app.pl # No auto-middleware
# With options
pagi-server -p 8080 PAGI::App::Directory root=/var/www
pagi-server --workers 4 ./myapp.pl
DESCRIPTION
pagi-server is the command-line interface for running PAGI applications. It uses PAGI::Runner for application loading and server orchestration, and PAGI::Server as the default server backend.
ENVIRONMENT MODES
pagi-server supports environment modes similar to Plack's -E flag:
- development
-
Auto-enables PAGI::Middleware::Lint with strict mode. This catches specification violations early and provides helpful error messages.
This is the default when running interactively (TTY detected).
- production
-
No middleware is auto-enabled, and access logging is disabled for maximum performance. Use
--access-log FILEto enable logging in production.This is the default when running non-interactively (no TTY, e.g., systemd, docker, cron).
- none
-
Explicit opt-out of all auto-middleware, regardless of TTY detection.
Mode is determined by (in order of precedence):
1. -E / --env command line flag
2. PAGI_ENV environment variable
3. Auto-detection: TTY = development, no TTY = production
After determining the mode, pagi-server sets PAGI_ENV to the resolved value. Your app can check $ENV{PAGI_ENV} to know what mode it's running in, similar to Plack's PLACK_ENV.
OPTIONS
Common Options
These are handled by PAGI::Runner and work with any server backend.
- -I, --lib PATH
-
Add PATH to
@INCbefore loading the app. Can be specified multiple times, similar toperl -I.pagi-server -I ./lib -I ./vendor/lib ./app.pl - -a, --app FILE
-
Path to .pl/.psgi file returning PAGI app coderef. Legacy option for backward compatibility; you can also just pass the file as an argument.
- -e CODE
-
Inline app code, like
perl -e. Must return a PAGI app coderef.# Using a PAGI::App module pagi-server -MPAGI::App::File -e 'PAGI::App::File->new(root => ".")->to_app' - -M MODULE
-
Load MODULE before evaluating
-ecode, likeperl -M. Can be specified multiple times. SupportsModule=import,argssyntax.pagi-server -MPAGI::App::File -e 'PAGI::App::File->new(root => ".")->to_app' - -o, --host HOST
-
Bind address (default: 127.0.0.1, localhost only)
The default only accepts connections from localhost, which is secure by default for development. For remote access:
pagi-server --host 0.0.0.0 ./app.pl # All IPv4 interfaces - -p, --port PORT
-
Bind port (default: 5000)
- -s, --server CLASS
-
Server class to use (default: PAGI::Server). Reserved for future use with pluggable server backends.
- -E, --env MODE
-
Environment mode: development, production, or none.
- -l, --loop BACKEND
-
Event loop backend (Poll, EV, Epoll, UV). Default is auto-detect.
- --access-log FILE
-
Path to access log file (default: STDERR)
- --no-access-log
-
Disable access logging entirely. Improves throughput by 5-15%.
- -D, --daemonize
-
Fork to background and run as a daemon.
- --pid FILE
-
Write the process ID to FILE.
- --user USER
-
After binding, drop privileges to run as USER. Requires root.
- --group GROUP
-
After binding, drop privileges to run as GROUP.
- -q, --quiet
-
Suppress startup banner and development mode message.
- --no-default-middleware
-
Disable auto-middleware even in development mode.
- -v, --version
-
Show version info.
- --help
-
Show help.
PAGI::Server Options
These options are passed through to PAGI::Server.
- -w, --workers NUM
-
Number of worker processes (default: 1, single-process mode)
- --reuseport
-
Enable SO_REUSEPORT mode for multi-worker servers.
- --ssl-cert FILE, --ssl-key FILE
-
Enable HTTPS with the specified certificate and key files.
- --max-requests NUM
-
Maximum requests per worker before restart (default: 0, unlimited)
- --max-connections NUM
-
Maximum concurrent connections per worker (default: auto-detect)
- --max-body-size NUM
-
Maximum request body size in bytes (default: 10MB)
- --timeout NUM
-
Connection idle timeout in seconds (default: 60)
- --shutdown-timeout NUM
-
Graceful shutdown timeout in seconds (default: 30)
- --log-level LEVEL
-
Log verbosity: debug, info, warn, error (default: info)
- -b, --listener-backlog NUM
-
Listen queue size (default: 2048)
- --max-receive-queue NUM
-
Maximum WebSocket receive queue size (default: 1000)
- --max-ws-frame-size NUM
-
Maximum WebSocket frame size in bytes (default: 65536)
- --request-timeout NUM
-
Request stall timeout in seconds (default: 0, disabled)
- --ws-idle-timeout NUM
-
WebSocket idle timeout in seconds (default: 0, disabled)
- --sse-idle-timeout NUM
-
SSE idle timeout in seconds (default: 0, disabled)
- --heartbeat-timeout NUM
-
Worker heartbeat timeout in seconds (default: 50, 0 = disabled). Only active in multi-worker mode. Workers send periodic heartbeats to the parent via a Unix pipe. If a worker's event loop is blocked for longer than this timeout (blocking syscall, deadlock, CPU-bound work), the parent kills it with SIGKILL and respawns a replacement.
This should be larger than the maximum time you expect any single operation to block the event loop. Async operations using
awaitdo not block the event loop and will never trigger this timeout. - --sync-file-threshold NUM
-
Sync file read threshold in bytes (default: 65536)
- --access-log-format FORMAT
-
Access log format string or preset name (default:
clf).Preset names:
clf,combined,common,tiny.Custom format strings use Apache-style atoms:
--access-log-format combined --access-log-format '%h %s %Dms'See "ACCESS LOG FORMAT" in PAGI::Server for the full atoms table.
- --future-xs
-
Enable Future::XS for improved Future performance. Must be installed separately:
cpanm Future::XSCan also be enabled via environment variable:
PAGI_FUTURE_XS=1 - --http2
-
Enable HTTP/2 support. Requires Net::HTTP2::nghttp2.
When combined with
--ssl-cert/--ssl-key, uses ALPN negotiation (h2/http/1.1). Without TLS, enables h2c (cleartext HTTP/2) mode.See PAGI::Server for HTTP/2 protocol tuning options (
h2_max_concurrent_streams,h2_initial_window_size, etc.) which can be passed via the constructor API.
APP SPECIFICATION
Module Name
If the argument contains ::, it's treated as a Perl module name:
pagi-server PAGI::App::Directory root=/var/www
The module must have new() and to_app() methods.
File Path
If the argument contains / or ends with .pl/.psgi:
pagi-server ./app.pl
The file must return a PAGI app coderef.
Default
If no app is specified, serves the current directory:
pagi-server
# equivalent to: pagi-server PAGI::App::Directory root=.
SIGNAL HANDLING
- TERM, INT
-
Graceful shutdown.
- HUP
-
Graceful restart (multi-worker mode only).
- TTIN, TTOU
-
Increase/decrease worker count (multi-worker mode only).
EXAMPLES
# Development (auto-detected from TTY)
pagi-server ./app.pl
# Explicit production mode
pagi-server -E production ./app.pl
PAGI_ENV=production pagi-server ./app.pl
# Multi-worker production
pagi-server --host 0.0.0.0 -p 80 --workers 4 -E production ./app.pl
# With HTTPS
pagi-server --ssl-cert cert.pem --ssl-key key.pem ./app.pl
# Maximum performance
pagi-server --no-access-log --workers 8 -E production ./app.pl
# Using EV event loop
pagi-server --loop EV ./app.pl
ENVIRONMENT
- PAGI_ENV
-
Default environment mode if
-Eis not specified and no TTY detected. - IO_ASYNC_LOOP
-
Preferred IO::Async loop backend.
FUTURE::IO INTEGRATION
pagi-server automatically configures Future::IO to use the IO::Async backend if Future::IO::Impl::IOAsync is installed. This enables seamless use of Future::IO-based libraries in your PAGI applications:
# These just work under pagi-server:
use Async::Redis;
use Some::FutureIO::Database;
# PAGI::SSE->every() also works:
$sse->every(1, sub { $sse->send(data => time) });
In non-production mode, pagi-server will report when Future::IO is configured:
Future::IO configured for IO::Async
If you're using PAGI::Server programmatically (not via pagi-server), you must configure Future::IO yourself. See "LOOP INTEROPERABILITY" in PAGI::Server for details.
SEE ALSO
PAGI::Runner, PAGI::Server, PAGI::Middleware::Lint, Future::IO
AUTHOR
John Napiorkowski <jjnapiork@cpan.org>
LICENSE
This software is licensed under the same terms as Perl itself.