presire
presire

Reputation: 71

Nginx + PHP-FPM containers using Podman cannot be linked

I used Podman and Podman-Compose to create Nginx and PHP-FPM with openSUSE Tumbleweed images.

The Containerfile for that Nginx container-file and the PHP-FPM container-file is shown below.

# Start with PHP 8 FPM (FastCGI Process Manager)
FROM registry.opensuse.org/opensuse/bci/php-fpm:latest

# Install PHP extensions
RUN zypper -n install   \
    curl            \
    wget            \
    nano            \
    iputils         \
    netcat-openbsd  \
    net-tools       \
    git             \
    php8            \
    php8-devel      \
    php8-curl       \
    php8-zip        \
    php8-mbstring   \
    php8-fileinfo   \
    php8-gd         \
    php8-mysql      \
    php8-fpm        \
    php8-xdebug

# Add PHP config
COPY ./php-fpm/www.conf     /etc/php8/fpm/php-fpm.d/www.conf
COPY ./php-fpm/php-fpm.conf /etc/php8/fpm/php-fpm.conf
COPY ./php-fpm/php.ini      /etc/php8/fpm/php.ini

# Create nginx user, group
RUN groupadd -g 101 nginx && \
    useradd  -u 1001 -g nginx -s /sbin/nologin -M nginx

# Set permissions after adding files
RUN mkdir -p /srv/www/htdocs            && \
    chmod -R 755 /srv/www/htdocs        && \
    chmod 1777 /tmp                     # sticky bit for /tmp

# Set working directory.
WORKDIR /srv/www/htdocs

# Set volumes.
ADD ["htdocs", "/srv/www/htdocs"]

# What command to run
CMD ["php-fpm", "-F"]

# Document that we use port 9000, 9003
EXPOSE 9000 9003
## Set master image.
FROM registry.opensuse.org/opensuse/nginx:latest

# Install NginX.
RUN zypper -n install   \
    curl            \
    wget            \
    nano            \
    iputils         \
    netcat-openbsd  \
    net-tools       \
    nginx

# Add nginx user and group if they don't exist
RUN getent group nginx  || groupadd -r nginx && \
    getent passwd nginx || useradd -r -g nginx nginx

# Add NginX config
COPY ./nginx/nginx.conf /etc/nginx/nginx.conf

# Create directories
RUN mkdir -p /srv/www/htdocs        && \
    chmod -R 755 /srv/www/htdocs

# Set working directory.
WORKDIR /srv/www/htdocs

# Set volumes.
ADD ["htdocs", "/srv/www/htdocs"]

# Expose port 80, 443.
EXPOSE 80 443

# Start NginX through bash terminal.
CMD ["/bin/bash", "-c", "nginx -g 'daemon off;'"]

Also, run these Containerfile with the podman-compose command.

podman-compose -f ./podman-compose.yml up -d

version: '3.8'

services:
  # PHP-FPM Service
  php:
    build:
      context: .                        # Build context is current directory
      dockerfile: Containerfile_PHP-FPM
    image: tw-phpfpm:latest             # Image name
    container_name: phpfpm              # Name our container
    ports:
      - "9003:9003"                     # Map port 8080 on our PC to 80 in container
    volumes:
      - ./htdocs:/srv/www/htdocs:Z      # Mount document root
      - ./php-fpm/www.conf:/etc/php8/fpm/php-fpm.d/www.conf:Z
      - ./php-fpm/php-fpm.conf:/etc/php8/fpm/php-fpm.conf:Z
      - ./php-fpm/php.ini:/etc/php8/fpm/php.ini:Z
    privileged: true
    networks:
      - web_network                     # Connect to our network
    #environment:
    #  PHP_IDE_CONFIG: serverName=Podman # For Xdebug
    restart: unless-stopped             # Make container restart unless stopped manually
    security_opt:
      - apparmor=unconfined

  # Nginx Service
  nginx:
    build:
      context: .                        # Build context is current directory
      dockerfile: Containerfile_NginX
    image: tw-nginx:latest              # Image name
    container_name: nginx
    ports:
      - "8080:80"                       # Map port 8080 on our PC to 80 in container
    volumes:
      - ./htdocs:/srv/www/htdocs:Z      # Mount same source code
      - ./nginx/nginx.conf:/etc/nginx/nginx.conf:Z
    depends_on:
      - php                             # Wait for PHP container
    links:
      - php
    privileged: true
    networks:
      - web_network
    restart: unless-stopped
    security_opt:
      - apparmor=unconfined

networks:
  web_network:
    driver: bridge                  # Standard Podman network type

The nginx.conf file used is shown below.

# nginx.conf

events {
    worker_connections  1024;
    use epoll;
}


http {
    include       mime.types;
    default_type  application/octet-stream;

    log_format  main  '$remote_addr - $remote_user [$time_local] "$request" '
                      '$status $body_bytes_sent "$http_referer" '
                      '"$http_user_agent" "$http_x_forwarded_for"';

    sendfile        on;

    keepalive_timeout  65;

    client_max_body_size 10M;

    gzip  on;
    gzip_types text/plain text/css application/json application/x-javascript text/xml application/xml application/xml+rss text/javascript;

    include conf.d/*.conf;

    server {
        listen       80;
        server_name  localhost;

        root   /srv/www/htdocs;
        index  index.php;

        # Basic security headers
        add_header X-Frame-Options "SAMEORIGIN";
        add_header X-XSS-Protection "1; mode=block";
        add_header X-Content-Type-Options "nosniff";

        location / {
            root        /srv/www/htdocs/;
            index       index.php;
            try_files   $uri $uri/ /index.php?$query_string;
        }

        error_page  404              /404.html;

        # redirect server error pages to the static page /50x.html
        #
        error_page   500 502 503 504  /50x.html;
        location = /50x.html {
            root   /srv/www/htdocs/;
        }

        # PHP-FPM configuration
        location ~ \.php$ {
            try_files               $uri =404;
            fastcgi_split_path_info ^(.+\.php)(/.+)$;
            fastcgi_pass            php:9000;
            fastcgi_index           index.php;
            include                 fastcgi_params;

            fastcgi_param   PATH_INFO           $fastcgi_path_info;
            fastcgi_param   PHP_ADMIN_VALUE     "open_basedir=$document_root:/tmp/:/proc/";
            fastcgi_param   PHP_VALUE           "upload_max_filesize=10M \n post_max_size=10M";
            fastcgi_param   SCRIPT_FILENAME     $document_root$fastcgi_script_name;
        }

        # Deny access to .htaccess files
        location ~ /\.ht {
            deny  all;
        }
    }

    include vhosts.d/*.conf;
}

The www.conf file used by PHP-FPM is shown below.

# www.conf

[www]
user = wwwrun
group = www
listen = php:9000

php_value[session.save_path] = /var/lib/php8/sessions

pm = dynamic
pm.max_children = 5
pm.start_servers = 2
pm.min_spare_servers = 1
pm.max_spare_servers = 3

catch_workers_output = yes
decorate_workers_output = no

When accessing "http://localhost:8080/index.php", the web page displays "Access Denied.".
However, "http://localhost:8080/index.html" is displayed normally.

At this time, if you check the logs of the Nginx container and PHP-FPM container, you will see the following error.

$ podman logs phpfpm

[26-Nov-2024 02:58:24] NOTICE: fpm is running, pid 1
[26-Nov-2024 02:58:24] NOTICE: ready to handle connections
[26-Nov-2024 02:58:24] NOTICE: systemd monitor interval set to 10000ms
NOTICE: PHP message: PHP Warning:  PHP Request Startup: Failed to open stream: Permission denied in Unknown on line 0
ERROR: Unable to open primary script: /srv/www/htdocs/index.php (Permission denied)
10.89.4.23 -  26/Nov/2024:02:58:35 +0000 "GET /index.php" 403

$ podman logs nginx

2024/11/26 03:00:54 [error] 7#7: *1 FastCGI sent in stderr: "PHP message: PHP Warning:  PHP Request Startup: Failed to open stream: Permission denied
in Unknown on line 0; Unable to open primary script: /srv/www/htdocs/index.php (Permission denied)" while reading response header from upstream, clien
t: 10.89.4.27, server: localhost, request: "GET / HTTP/1.1", upstream: "fastcgi://10.89.4.26:9000", host: "localhost:8080"
10.89.4.27 - - [26/Nov/2024:03:00:54 +0000] "GET / HTTP/1.1" 403 46 "-" "Mozilla/5.0 (X11; Linux x86_64; rv:132.0) Gecko/20100101 Firefox/132.0"
10.89.4.27 - - [26/Nov/2024:03:00:54 +0000] "GET /favicon.ico HTTP/1.1" 200 318 "http://localhost:8080/" "Mozilla/5.0 (X11; Linux x86_64; rv:132.0) Gecko/20100101 Firefox/132.0"

What is causing this error?
And how can it be made to work properly using openSUSE container?

Note that this container is openSUSE Tumbleweed, so it does not contain SELinux, etc.

Apparmor is installed on the host.

Update

The following settings were added or edited.

user nginx;  
user = nginx
group = nginx
listen = php:9000

Added nginx user and nginx group to PHP-FPM container.

$ podman exec phpfpm cat /etc/shadow
root:*:20050::::::
nobody:!:19986::::::
wwwrun:!:20050::::::
nginx:!:20053:0:99999:7:::

$ podman exec phpfpm cat /etc/group
root:x:0:
shadow:x:15:
trusted:x:42:
users:x:100:
nogroup:x:65533:
nobody:x:65534:
www:x:499:wwwrun
wwwrun:!:498:
nginx:x:101:

$ podman exec nginx cat /etc/shadow
root:*:20050::::::
nobody:!:19986::::::
nginx:!:20050::::::

$ podman exec nginx cat /etc/group
root:x:0:
shadow:x:15:
trusted:x:42:
users:x:100:
nogroup:x:65533:
nobody:x:65534:
nginx:!:499:

When I access the .php file, I still get "Access Denied".

$ podman logs phpfpm
[26-Nov-2024 02:58:24] NOTICE: fpm is running, pid 1
[26-Nov-2024 02:58:24] NOTICE: ready to handle connections
[26-Nov-2024 02:58:24] NOTICE: systemd monitor interval set to 10000ms
NOTICE: PHP message: PHP Warning:  PHP Request Startup: Failed to open stream: Permission denied in Unknown on line 0
ERROR: Unable to open primary script: /srv/www/htdocs/index.php (Permission denied)
10.89.4.23 -  26/Nov/2024:02:58:35 +0000 "GET /index.php" 403

$ podman logs nginx
2024/11/26 03:00:54 [error] 7#7: *1 FastCGI sent in stderr: "PHP message: PHP Warning:  PHP Request Startup: Failed to open stream: Permission denied
in Unknown on line 0; Unable to open primary script: /srv/www/htdocs/index.php (Permission denied)" while reading response header from upstream, clien
t: 10.89.4.27, server: localhost, request: "GET / HTTP/1.1", upstream: "fastcgi://10.89.4.26:9000", host: "localhost:8080"
10.89.4.27 - - [26/Nov/2024:03:00:54 +0000] "GET / HTTP/1.1" 403 46 "-" "Mozilla/5.0 (X11; Linux x86_64; rv:132.0) Gecko/20100101 Firefox/132.0"
10.89.4.27 - - [26/Nov/2024:03:00:54 +0000] "GET /favicon.ico HTTP/1.1" 200 318 "http://localhost:8080/" "Mozilla/5.0 (X11; Linux x86_64; rv:132.0) Gecko/20100101 Firefox/132.0"

Upvotes: 0

Views: 128

Answers (1)

Dorado
Dorado

Reputation: 431

In your php-fpm configuration, you have the wwwrun/www set as user and group. That is likely the reason the NGINX process does not share similar group permissions to execute PHP scripts.

You may be able to resolve your NGINX configuration simply by adding user nginx; to have the web server run as a Nginx user. The question is whether that Nginx user could read and write to php-fpm sockets at a /var location.

A group permission could resolve this.

Upvotes: 0

Related Questions