I'm working in a Ubuntu 22.04.3 LTS

I'm creating my own apache "arquitecture". I called it "myApache". The idea is that every user can run its own apache listening in its UID as PORT


# Get user UID to use it as apache port.

# Check for pidfile
if [ -f $PIDFILE ] ; then
        PID=`cat $PIDFILE`
        if [ "x$PID" != "x" ] && kill -0 $PID 2>/dev/null ; then
                STATUS="myapache (pid $PID) running"
                STATUS="myapache (pid $PID?) not running"
        STATUS="myapache (no pid file) not running"

case $1 in
                if [ $RUNNING -eq 1 ]; then
                        echo "$0 $ARG: myapache (pid $PID) already running"
                if /usr/sbin/apache2 -c "Listen $PORT" -c "PidFile $PIDFILE" -c "User $USER" -c "Group ubuntu" -c "PassengerUser $USER" -c "PassengerGroup $USER" -c "KeepAlive Off" -c "DirectoryIndex index.html index.cgi index.pl index.php index.xhtml index.htm" -c "DocumentRoot ${HOME}/myapache/" -c "ErrorLog ${HOME}/myapache/logs/error_log" -c "CustomLog ${HOME}/myapache/logs/access_log common" -d "${HOME}/myapache/www" -c "ServerRoot ${HOME}/myapache/config" -f "${HOME}/myapache/config/main.conf" ; then
                        sleep 1
                        PID=`cat $PIDFILE`
                        echo "$0 $ARG: myapache (pid $PID) running on port $PORT to you ($USER)"
                        echo "$0 $ARG: myapache could not be started"
                if [ $RUNNING -eq 0 ]; then
                        echo "$0 $ARG: $STATUS"
                if  kill $(ps -s $PID -o pid=); then
                        echo "$0 $ARG: myapache stopped"
                        echo "$0 $ARG: myapache could not be stopped"

                if [ $RUNNING -eq 1 ]; then
                        echo "$0 $ARG: myapache (pid $PID) already running on port $PORT to you ($USER)"
                        ps auxwww |grep $PID |grep -v grep
                        echo "$0 $ARG: myapache not running to you ($USER)"
                 echo "usage: $0 (start|stop)"
                cat <<EOF

start      - start myapache
stop       - stop myapache
status     - status myapache; if running, show runner port and conf
help       - this myapache




# Se cargan los modules
Include ${HOME}/myapache/config/load_modules.conf

# Se configuran los modules
Include ${HOME}/myapache/config/config_modules.conf
Include ${HOME}/myapache/config/mime.conf

# Se establecen las variables de entorno
Include ${HOME}/myapache/config/env.conf

# Aqui se colocan todos los VirtualHost addinales.
Include ${HOME}/myapache/config/vhosts/*


LoadModule mpm_event_module /usr/lib/apache2/modules/mod_mpm_event.so
LoadModule authz_core_module /usr/lib/apache2/modules/mod_authz_core.so
LoadModule env_module /usr/lib/apache2/modules/mod_env.so
LoadModule dir_module /usr/lib/apache2/modules/mod_dir.so
LoadModule ssl_module /usr/lib/apache2/modules/mod_ssl.so
LoadModule passenger_module /usr/lib/apache2/modules/mod_passenger.so
LoadModule actions_module /usr/lib/apache2/modules/mod_actions.so
LoadModule alias_module /usr/lib/apache2/modules/mod_alias.so
LoadModule mime_module /usr/lib/apache2/modules/mod_mime.so
LoadModule fastcgi_module /usr/lib/apache2/modules/mod_fastcgi.so


# Configuracion del modulo mod_mpm_event.so
<IfModule mpm_event_module>
  StartServers             1
  MinSpareThreads          25
  MaxSpareThreads          75
  ThreadLimit              64
  ThreadsPerChild          25
  MaxRequestWorkers        150
  MaxConnectionsPerChild   0

# Configuracion del modulo mod_passenger.so
<IfModule mod_passenger.c>
  PassengerFriendlyErrorPages on
  PassengerRoot /usr/lib/ruby/vendor_ruby/phusion_passenger/locations.ini
  PassengerDefaultRuby /usr/bin/ruby

# Configuracion del modulo mod_ssl.so
<IfModule mod_ssl.c>
  SSLEngine on

  SSLCertificateFile    ${HOME}/myapache/ssl/my.crt
  SSLCertificateKeyFile ${HOME}/myapache/ssl/my.key
  SSLCertificateChainFile ${HOME}/myapache/ssl/my-ca.crt

# Configuracion de modulo mod_fastcgi.so para fpm
<IfModule mod_fastcgi.c>
  AddHandler php-fcgi .php
  Action php-fcgi /php-fcgi
  Alias /php-fcgi /usr/lib/cgi-bin/php-fcgi
  FastCgiExternalServer /usr/lib/cgi-bin/php-fcgi -host -pass-header Authorization

  <Directory /usr/lib/cgi-bin/php-fcgi>
    Require all granted

  <Directory />
    Require all granted

And here is the thing ...

With user ubuntu all works fine.

With user icalvete (my) I get ..

At the browser: 'File not found.'

At the error log:

[Wed Jul 10 08:53:03.260634 2024] [fastcgi:error] [pid 2819117:tid 129168540931648] [client] FastCGI: server "/usr/lib/cgi-bin/php-fcgi" stderr: Primary script unknown

if I change /usr/lib/cgi-bin/php-fcgi by /tmp/php-fcgi I get exactly the same.

It could be a permission error?

icalvete@f-core-dev01:~/myapache$ id ubuntu
uid=1000(ubuntu) gid=1000(ubuntu) groups=1000(ubuntu),4(adm),20(dialout),24(cdrom),25(floppy),27(sudo),29(audio),30(dip),44(video),46(plugdev),118(netdev),119(lxd)
icalvete@f-core-dev01:~/myapache$ id icalvete
uid=10000(icalvete) gid=1000(ubuntu) groups=1000(ubuntu),5000(docker),27(sudo),20000(operators),20001(developers)

I read https://fastcgi-archives.github.io/mod_fastcgi.html#FastCgiExternalServer and /usr/lib/cgi-bin/php-fcgi does not need to exists but all users have access to /usr/lib/cgi-bin/ that exist.

What could be the solution tu run myApache with any user?

MORE INFO: strace logs....

We can see the write (to the fpm server) and the read (from the fpm server) so we know that the request reach the server at localhost 9000. I delete some info from the write and read for security reasons but both send the same info (or its seems that). The response should a phpinfo() output.

With ubuntu user:

pid 2919511] write(14, "\1\1\0\1\0\10\0\0\0\1"..., 3284) = 3284
[pid 2919511] pselect6(15, [14], [], NULL, {tv_sec=30, tv_nsec=0}, NULL) = 1 (in [14], left {tv_sec=29, tv_nsec=941061310})
[pid 2919511] read(14, "\1\6\0\1\0*\6\0Content-type: text/html; charset=UTF-8\r\n\r\n\0\0\0\0\0\0\1\6\0\1\377\370\0\0", 8192) = 64
[pid 2919511] pselect6(15, [14], [], NULL, {tv_sec=30, tv_nsec=0}, NULL) = 1 (in [14], left {tv_sec=29, tv_nsec=999742086})
[pid 2919511] read(14, "<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Transitional//EN\" \"DTD/xhtml1-transitional.dtd\">\n<html xmlns=\"http://www.w3.org/1999/xhtml\"><head>\n<style type=\"text/css\">\nbody {background-color: #fff; color: #222; font-family: sans-serif;}\npre {margin:

With icalvete user:

[pid 2921747] write(16, "\1\1\0\1\0\10\0\0\0\1\0\0\0\..., 3292) = 3292
[pid 2921747] pselect6(17, [16], [], NULL, {tv_sec=30, tv_nsec=0}, NULL) = 1 (in [16], left {tv_sec=29, tv_nsec=999998428})
[pid 2921746] <... poll resumed>)       = 1 ([{fd=15, revents=POLLIN}])
[pid 2921747] read(16,  <unfinished ...>
[pid 2921746] read(15,  <unfinished ...>
[pid 2921747] <... read resumed>"\1\7\0\1\0\26\2\0Primary script unknown\0\0\1\6\0\1\0Q\7\0Status: 404 Not Found\r\nContent-type: text/html; charset=UTF-8\r\n\r\nFile not found.\n\0\0\0\0\0\0\0\1\3\0\1\0\10\0\0\0\0\0\0\0\0\0\0", 8192) = 144

So the problem is the fpm server.

1 Answer 1


So, the problem is the fpm server can not reach the scripts in the file system because is running as www-data and icalvete home's is full private.

There's two proper fixes for this:

  1. Set permissions appropriately. To cd into a directory, a user needs +x on the directory. To list content, +r is required. Thus chmod 751 /home/$user will allow anyone to traverse, but not list content.
  2. Create a directory outside /home/$user for the web content.

#2 is probably the best solution; securing the users home directory. I would suggest creating /srv/www/$user or similar, with $user as owner, and www-data as group, and permissions something like 750, or rwxr-x---.

The solution proposed in this answer gives every other user root access on the system, as it allows any user able to run PHP scripts access to run commands as root and modify files. In addition to that it will ensure that any remote attacker will pwn the box instantly, increasing damage.

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .