hippo has asked for the wisdom of the Perl Monks concerning the following question:

Is there a recommended way to reduce the privilege of processes started with start_server and/or plackup? I am hoping to run webservers on the usual ports (80 and 443) but this of course requires high privilege. Ideally, after binding to these low ports the privileges should drop by switching process ownership to an unprivileged user as most off-the-shelf webservers will do these days. However, I could not immediately spot any simple way to do this either with start_server or with plackup.

What is the best way to achieve this? Currently I am simply running this as root:

start_server --port=80 -- plackup --server=Twiggy /path/to/myapp.psgi

but of course that leaves the app running as root which I would rather avoid. I could just run them unprivileged on a high port and handle the port mapping in netfilter but that seems a little hackish for something intended for production. Any other suggestions welcome.

Replies are listed 'Best First'.
Re: Privilege reduction with start_server / plackup
by haukex (Archbishop) on Apr 16, 2020 at 21:50 UTC

    Does it have to be Twiggy? Starman supports --user and --group options... here is a script I wrote that additionally uses Daemon::Control to set up Starman as a daemon.

      It's Twiggy for the non-blocking. If Starman can do that just as well then I'd be happy enough to switch but from a cursory look through the docs that might not be the case, unfortunately.

        It's Twiggy for the non-blocking.

        Ah, yes, I see, and I think you're right that Starman doesn't support that. It looks like neither Server::Starter or Twiggy support changing the UID/GID natively. What I learned in writing the script I linked to was that it basically has to be done by the server itself, and not by some tool launching that server, because it first needs to open the ports, and then reduce its privileges. You could of course consider putting the server behind an nginx proxy, but that's also an extra component to maintain. Here's a sub I wrote once to manually set the UID and GID with as much error checking as possible.

Re: Privilege reduction with start_server / plackup
by Corion (Patriarch) on Apr 17, 2020 at 08:36 UTC

    I think for Twiggy, you will have to create your own Twiggy subclass (or monkeypatch it) to override Twiggy::Server->start_listen:

    sub Twiggy::Server::start_listen { my ($self, $app) = @_; my @listen = @{$self->{listen} || [ ($self->{host} || '') . ":" . +($self->{port} || 0) ]}; for my $listen (@listen) { push @{$self->{listen_guards}}, $self->_create_tcp_server($lis +ten, $app); } # XXX drop privileges here }

      You are probably right. It is surprising that Miyagawa didn't incorporate something like this already and it makes me wonder what everyone else does when using Twiggy. Do they just run it as root and not care about the security aspects? Do they hide it on a high port behind a reverse proxy? Or do they offer it publicly but on a non-standard high port?

      Thanks for thinking of and sharing this approach.

        Do they hide it on a high port behind a reverse proxy?

        At $WORK, we do that, plus the Twiggy server itself is containerized.

A reply falls below the community's threshold of quality. You may see it by logging in.
A reply falls below the community's threshold of quality. You may see it by logging in.