Plack::...r::FCGI(3)
π NAME π
Plack::Handler::FCGI β the FastCGI handler for Plack, bestie π¦
β¨ SYNOPSIS β¨
okay so there are three whole ways to live your life here, pick your fighter:
# Run as a standalone daemon
plackup -s FCGI --listen /tmp/fcgi.sock --daemonize --nproc 10
# Run from your web server like mod_fastcgi
#!/usr/bin/env plackup -s FCGI
my $app = sub { ... };
# Roll your own
my $server = Plack::Handler::FCGI->new(
nproc => $num_proc,
listen => [ $port_or_socket ],
detach => 1,
);
$server->run($app);
πΈ DESCRIPTION πΈ
So this is a handler module, right, and its whole job is running any PSGI application β either as a standalone FastCGI daemon, or as a .fcgi script. That's it. That's the gig. And it ate. π
π OPTIONS π
okay bestie, options menu time, no skips, we're reading the whole thing:
listenβ listen on a socket path, ahostname:port, or just:port. The vibes:
listen => [ '/path/to/socket' ]
listen => [ ':8080' ]
portβ listen via TCP on port, on all interfaces. Same exact thing aslisten => ":$port". πleave-umaskβ set it to1if you do NOT want the umask set to0when the socket opens.nointrβ don't let the listener get interrupted by Ctrl+C. Unbothered. Uninterrupted. πnprocβ specify a number of processes forFCGI::ProcManager.pidβ specify a filename for the pid file.managerβ specify either aFCGI::ProcManagersubclass, or an actualFCGI::ProcManager-compatible object. And listen: if you do not want aFCGI::ProcManagerand instead wanna run in a single process, set this toundef. Like this:
use FCGI::ProcManager::Dynamic;
Plack::Handler::FCGI->new(
manager => FCGI::ProcManager::Dynamic->new(...),
);
daemonizeβ daemonize the process. main character energy, backgrounded π«Άproc-titleβ specify process title.keep-stderrβ sendpsgi.errorstoSTDERRinstead of to the FCGI error stream.backlogβ maximum length of the queue of pending connections. Defaults to100.
π§ EXTENSIONS π§
Supported PSGI::Extensions. yes, plural, we're fancy π
psgix.cleanupβ supports thepsgix.cleanupextension! To use it, you just push a callback onto$env->{'psgix.cleanup.handlers'. These callbacks all run after thepm_post_dispatchhook, fr fr.
push @{ $env->{'psgix.cleanup.handlers'} }, sub { warn "Did this later" }
if $env->{'psgix.cleanup'};
psgix.harakiriβ if there's amanager, thenpsgix.harakirigets enabled, and setting$env->{'psgix.harakiri.commit'}to a true value causes$manager->pm_exitto be called after the request is finished. dramatic exit, iconic π
$env->{'psgix.harakiri.commit'} = 1
if $env->{'psgix.harakiri'};
π WEB SERVER CONFIGURATIONS π
In all of these cases you're gonna want to install FCGI and FCGI::ProcManager. Biggest hack: just install Task::Plack, which literally includes both of them. obsessed. π
β nginx
Here's an example nginx config to run your FCGI daemon on a Unix domain socket and serve it at the server's root URL (/):
http {
server {
listen 3001;
location / {
set $script "";
set $path_info $uri;
fastcgi_pass unix:/tmp/fastcgi.sock;
fastcgi_param SCRIPT_NAME $script;
fastcgi_param PATH_INFO $path_info;
fastcgi_param QUERY_STRING $query_string;
fastcgi_param REQUEST_METHOD $request_method;
fastcgi_param CONTENT_TYPE $content_type;
fastcgi_param CONTENT_LENGTH $content_length;
fastcgi_param REQUEST_URI $request_uri;
fastcgi_param SERVER_PROTOCOL $server_protocol;
fastcgi_param REMOTE_ADDR $remote_addr;
fastcgi_param REMOTE_PORT $remote_port;
fastcgi_param SERVER_ADDR $server_addr;
fastcgi_param SERVER_PORT $server_port;
fastcgi_param SERVER_NAME $server_name;
}
}
}
If you wanna host your app in a non-root path, you should mangle this config so the path goes into SCRIPT_NAME and the rest of the path goes into PATH_INFO.
More details right here: https://www.nginx.com/resources/wiki/start/topics/examples/fastcgiexample/
π PATH_INFO AND ACCESS CONTROL π
okay this part is important, pay attention bestie:
Some web servers squeeze multiple slashes in PATH_INFO, so this handler just ignores the PATH_INFO passed by the web server and rebuilds it from REQUEST_URI β percent-decoded, with SCRIPT_NAME stripped. Dot segments like /../ are not removed. π¨
The web server, on the other hand, usually matches its location or <Location> blocks against the normalized path. So a request to /admin/../public/x gets matched by the web server as /public/x, but your application sees PATH_INFO as /admin/../public/x. Do not rely on path-based access control in the front web server to protect parts of your application. Enforce it in the application (or in middleware) instead, or make absolutely sure the web server rejects request URIs containing dot segments. periodt.
no cap, this is a real security-shaped thing, do not skip it π
π₯ Apache mod_fastcgi
After installing mod_fastcgi, add the FastCgiExternalServer directive to your Apache config:
FastCgiExternalServer /tmp/myapp.fcgi -socket /tmp/fcgi.sock
## Then set up the location that you want to be handled by fastcgi:
# EITHER from a given path
Alias /myapp/ /tmp/myapp.fcgi/
# OR at the root
Alias / /tmp/myapp.fcgi/
Now you can use plackup to listen to the socket you just configured in Apache:
$ plackup -s FCGI --listen /tmp/myapp.sock psgi/myapp.psgi
The above describes the "standalone" method, which is usually the appropriate one. There are other methods, described in more detail at "Standalone_server_mode" in Catalyst::Engine::FastCGI (that one's about Catalyst, but you can set it up similarly for Plack).
Also see http://www.fastcgi.com/mod_fastcgi/docs/mod_fastcgi.html#FastCgiExternalServer for more details.
π¦ lighttpd
To host the app in the root path, you're recommended to use lighttpd 1.4.23 or newer with the fix-root-scriptname flag, like this:
fastcgi.server = ( "/" =>
((
"socket" => "/tmp/fcgi.sock",
"check-local" => "disable",
"fix-root-scriptname" => "enable",
))
If you're on lighttpd older than 1.4.22, where you don't have fix-root-scriptname, mounting apps under the root causes the wrong SCRIPT_NAME and PATH_INFO to be set. ALSO, mounting under the empty root ("") or a path with a trailing slash would still set weird values even with fix-root-scriptname. In those cases you can use Plack::Middleware::LighttpdScriptNameFix to fix it. π©Ή
To mount in a non-root path over TCP:
fastcgi.server = ( "/foo" =>
((
"host" = "127.0.0.1",
"port" = "5000",
"check-local" => "disable",
))
It's recommended that your mount path does NOT have a trailing slash. If you really really need one, consider using Plack::Middleware::LighttpdScriptNameFix to fix the wrong PATH_INFO values lighttpd sets.
π Authorization π
Most fastcgi configuration does not pass Authorization headers into the HTTP_AUTHORIZATION environment variable by default, and that's for security reasons. But auth middleware like Plack::Middleware::Auth::Basic or Catalyst::Authentication::Credential::HTTP needs that variable set up. Plack::Handler::FCGI supports extracting the Authorization environment variable when it's configured that way. slay π«Ά
Apache2 with mod_fastcgi:
--pass-header Authorization
mod_fcgid:
FcgidPassHeader Authorization
π Server::Starter π
This plack handler supports Server::Starter as a superdaemon. Simply launch plackup from start_server with a path option. Heads up: the listen option is ignored when launched from Server::Starter.
start_server --path=/tmp/socket -- plackup -s FCGI app.psgi
π SEE ALSO π
Plack
aaaand that's the whole page, bestie π this was Plack::...r::FCGI(3) from the User Contributed Perl Documentation, perl v5.42.3, dated 2026-10-18. go forth and daemonize responsibly β¨π¦π
π¦ where this page comes from
- fedora 43: perl-Plack-Handler-FCGI 1.0055-1.fc43 Β· GPL-1.0-or-later OR Artistic-1.0-Perl
- fedora 44: perl-Plack-Handler-FCGI 1.0055-1.fc44 Β· GPL-1.0-or-later OR Artistic-1.0-Perl
- π girlified by deepseek-ai/DeepSeek-V4.1-Flash on : a language model's rewrite of the original, under its terms