main e4dc2dce397e cached
38 files
354.2 KB
76.0k tokens
1 requests
Download .txt
Showing preview only (371K chars total). Download the full file or copy to clipboard to get everything.
Repository: tiredofit/docker-nginx-php-fpm
Branch: main
Commit: e4dc2dce397e
Files: 38
Total size: 354.2 KB

Directory structure:
gitextract_43589cx1/

├── .dockerignore
├── .github/
│   ├── FUNDING.yml
│   ├── ISSUE_TEMPLATE/
│   │   ├── bug_report.md
│   │   └── feature_request.md
│   ├── config.yml
│   └── workflows/
│       ├── build_manual.yml
│       ├── build_push.yml
│       └── image_build.yml
├── .gitignore
├── CHANGELOG.md
├── Containerfile
├── LICENSE
├── README.md
├── examples/
│   ├── .gitignore
│   ├── .gitkeep
│   └── compose.yml
├── rootfs/
│   ├── container/
│   │   ├── data/
│   │   │   ├── nginx/
│   │   │   │   └── templates/
│   │   │   │       ├── server/
│   │   │   │       │   └── http-fastcgi_hide_header_xpowered.template
│   │   │   │       └── site/
│   │   │   │           └── location-php-block.template
│   │   │   └── php-fpm/
│   │   │       ├── cli/
│   │   │       │   └── php.ini
│   │   │       ├── conf.available/
│   │   │       │   ├── apcu.ini
│   │   │       │   └── opcache.ini
│   │   │       ├── fpm/
│   │   │       │   ├── default.logformat
│   │   │       │   ├── json.logformat
│   │   │       │   └── php.ini
│   │   │       └── opcache/
│   │   │           ├── opcache-settings.php
│   │   │           └── opcache-status.php
│   │   ├── defaults/
│   │   │   ├── 20-php-fpm
│   │   │   └── _20-php-fpm/
│   │   │       ├── 20-php-fpm
│   │   │       └── 20-php-fpm.advanced
│   │   ├── functions/
│   │   │   ├── 20-php-fpm
│   │   │   └── 20-php-fpm.advanced
│   │   ├── init/
│   │   │   └── init.d/
│   │   │       └── 20-php-fpm
│   │   └── run/
│   │       └── available/
│   │           └── 20-php-fpm/
│   │               └── run
│   ├── etc/
│   │   ├── fluent-bit/
│   │   │   └── parsers.d/
│   │   │       └── phpfpm.conf
│   │   └── zabbix/
│   │       └── zabbix_agentd.conf.d/
│   │           └── php-fpm.conf
│   └── usr/
│       └── local/
│           └── bin/
│               └── php-ext
└── zabbix_templates/
    ├── app-php_fpm.json
    └── app-php_opcache.json

================================================
FILE CONTENTS
================================================

================================================
FILE: .dockerignore
================================================
examples/


================================================
FILE: .github/FUNDING.yml
================================================
github: [tiredofit]


================================================
FILE: .github/ISSUE_TEMPLATE/bug_report.md
================================================
---
name: Bug report
about: If something isn't working right..
title: ''
labels: bug
assignees: ''

---

### Summary

<!-- Summarize the bug encountered -->


### Steps to reproduce

<!-- Describe how one can reproduce the issue - this is very important. Please use an ordered list. -->


### What is the expected *correct* behavior?

<!-- Describe what should be seen instead. -->


### Relevant logs and/or screenshots

<!-- Paste any relevant logs - please use code blocks (```) to format console output, logs, and code as it's tough to read otherwise. -->

### Environment
<!--Your Configuration (please complete the following information): -->

- Image version / tag:
- Host OS:

<details>
<summary>Any logs | compose.yml</summary>
</details>

<!-- Include anything additional -->

### Possible fixes
<!-- If you can, provide details to the root cause that might be responsible for the problem. -->


================================================
FILE: .github/ISSUE_TEMPLATE/feature_request.md
================================================
---
name: Feature request
about: Suggest an idea or feature
title: ''
labels: enhancement
assignees: ''

---

---
name: Feature Request
about: Suggest an idea for this project

---

**Description of the feature**
<!-- A clear description of the feature you'd like implemented  -->

**Benefits of feature**
<!-- Explain the measurable benefits this feature would achieve. -->

**Additional context**
<!--Add any other context or screenshots about the feature request here. -->


================================================
FILE: .github/config.yml
================================================
blank_issues_enabled: false


================================================
FILE: .github/workflows/build_manual.yml
================================================
name: "MANUAL - Build all images"

on:
  workflow_dispatch:
    inputs:
      Manual Build:
        description: 'Manual Build'
        required: false

jobs:
  prepare:
    uses: nfrastack/gha/.github/workflows/artifacts-encrypt.yml@main
    secrets: inherit
  build:
    needs: prepare
    uses: ./.github/workflows/image_build.yml
    secrets: inherit
  cleanup:
    needs: [build]
    uses: nfrastack/gha/.github/workflows/artifacts-remove.yml@main
    secrets: inherit



================================================
FILE: .github/workflows/build_push.yml
================================================
name: "PUSH - Build on repository Push"
on:
  push:
    paths:
      - '**'
      - '!/CHANGELOG.md'
      - '!/examples/*'
      - '!LICENSE'
      - '!README.md'
      - '!/zabbix_templates/*'
jobs:
  prepare:
    uses: nfrastack/gha/.github/workflows/artifacts-encrypt.yml@main
    secrets: inherit
  build:
    needs: prepare
    uses: ./.github/workflows/image_build.yml
    secrets: inherit
  cleanup:
    needs: [build]
    uses: nfrastack/gha/.github/workflows/artifacts-remove.yml@main
    secrets: inherit



================================================
FILE: .github/workflows/image_build.yml
================================================
name: build

on:
  workflow_call

jobs:
  build:
    strategy:
      fail-fast: false
      matrix:
        build:
          - { php_version: "8.5", php_version_latest: "true", distro: "alpine", distro_variant: "3.23", latest: "true", distro_latest: "true", arch: "linux/amd64,linux/arm64" }
          - { php_version: "8.4", php_version_latest: "true", distro: "alpine", distro_variant: "3.23", latest: "false", distro_latest: "true", arch: "linux/amd64,linux/arm64" }
          - { php_version: "8.4", php_version_latest: "false", distro: "alpine", distro_variant: "3.22", latest: "false", distro_latest: "false", arch: "linux/amd64,linux/arm64" }
          - { php_version: "8.3", php_version_latest: "true", distro: "alpine", distro_variant: "3.23", latest: "false", distro_latest: "true", arch: "linux/amd64,linux/arm64" }
          - { php_version: "8.3", php_version_latest: "false", distro: "alpine", distro_variant: "3.22", latest: "false", distro_latest: "false", arch: "linux/amd64,linux/arm64" }
          - { php_version: "8.2", php_version_latest: "true", distro: "alpine", distro_variant: "3.22", latest: "false", distro_latest: "true", arch: "linux/amd64,linux/arm64" }
          - { php_version: "8.1", php_version_latest: "true", distro: "alpine", distro_variant: "3.19", latest: "false", distro_latest: "true", arch: "linux/amd64,linux/arm64" }
          - { php_version: "8.0", php_version_latest: "true", distro: "alpine", distro_variant: "3.16", latest: "false", distro_latest: "true", arch: "linux/amd64" }
          - { php_version: "7.4", php_version_latest: "true", distro: "alpine", distro_variant: "3.15", latest: "false", distro_latest: "true", arch: "linux/amd64,linux/arm64" }
          - { php_version: "7.3", php_version_latest: "true", distro: "alpine", distro_variant: "3.12", latest: "false", distro_latest: "true", arch: "linux/amd64" }
          - { php_version: "8.5", php_version_latest: "false", distro: "debian", distro_variant: "trixie", latest: "false", distro_latest: "true", arch: "linux/amd64,linux/arm64" }
          - { php_version: "8.4", php_version_latest: "false", distro: "debian", distro_variant: "trixie", latest: "false", distro_latest: "true", arch: "linux/amd64,linux/arm64" }
          - { php_version: "8.4", php_version_latest: "false", distro: "debian", distro_variant: "bookworm", latest: "false", distro_latest: "false", arch: "linux/amd64,linux/arm64" }
          - { php_version: "8.3", php_version_latest: "false", distro: "debian", distro_variant: "trixie", latest: "false", distro_latest: "true", arch: "linux/amd64,linux/arm64" }
          - { php_version: "8.3", php_version_latest: "false", distro: "debian", distro_variant: "bookworm", latest: "false", distro_latest: "false", arch: "linux/amd64,linux/arm64" }
          - { php_version: "8.2", php_version_latest: "false", distro: "debian", distro_variant: "trixie", latest: "false", distro_latest: "true", arch: "linux/amd64,linux/arm64" }
          - { php_version: "8.2", php_version_latest: "false", distro: "debian", distro_variant: "bookworm", latest: "false", distro_latest: "false", arch: "linux/amd64,linux/arm64" }
        image_variant:
          - core
          - faflopza
          - faflopzaze
    uses: nfrastack/gha/.github/workflows/container-build_phpfpm.yml@main
    with:
      base_image: "ghcr.io/nfrastack/container-nginx"
      base_image_version: ${{ matrix.build.base_image_version || '' }}
      php_version: ${{ matrix.build.php_version }}
      php_version_latest: ${{ matrix.build.php_version_latest }}
      distro: ${{ matrix.build.distro }}
      distro_variant: ${{ matrix.build.distro_variant }}
      image_variant: ${{ matrix.image_variant }}
      latest: ${{ matrix.build.latest || 'false' }}
      distro_latest: ${{ matrix.build.distro_latest || 'false' }}
      platforms: ${{ matrix.build.arch || 'linux/amd64,linux/arm64' }}
    secrets: inherit


================================================
FILE: .gitignore
================================================
/build-assets/*
!/build-assets/.empty



================================================
FILE: CHANGELOG.md
================================================
## 8.1.0 2026-05-11 <code at nfrastack dot com>

   ### Added
      - Add PHPFPM_POOL_<NAME>_INCLUDES to add external include configuration
      - Add ..._LISTEN_TYPE=both support spawning shadow pools with -tcp suffix

   ### Changed
      - Migrate to write_file for remaining tee commands


## 8.0.6 2026-05-10 <code at nfrastack dot com>

   ### Changed
      - Add --remove destination to limit downstream image configurations destroying source of truth


## 8.0.5 2026-04-22 <code at nfastack dot com>

   ### Changed
      - Fix abliity to use downstream images with 8.0.4


## 8.0.4 2026-04-22 <code at nfastack dot com>

   ### Changed
      - Fix sisues with Zabbix monitoring (ping/php-fpm_status) URLs
      - Rework Opcache Monitoring scripts to be dynamically created in /usr/share/zabbix/php-opcache instead of zabbix permission locked config folder


## 8.0.3 2026-04-20 <code at nfastack dot com>

   ### Changed
      - Tag to support changes in nfrastack/containre-nginx:8.0.7


## 8.0.2 2026-03-26 <code at nfastack dot com>

   ### Added
      - Support BUILD_ENV

   ### Changed
      - Rewrite php-ext operations
      - Repair monitoring configuration routines
      - Support upstream base image features better


## 8.0.1 2026-02-24 <code at nfastack dot com>

   ### Changed
      - Upstream and index placeholder repairs


## 8.0.0 2026-02-23 <code at nfastack dot com>

   ### Added
      - Supporting PHP 8.5 and Alpine 3.23
      - Multiple Pool Support
      - Many differnet customization options
      - Dynamic configuration of PHP location block
      - Uses nfrastack/container-nginx:8.x.x as base image


## 7.7.20 2025-08-16 <dave at tiredofit dot ca>

   ### Changed
      - Change php8.1-alpine to use alpine 3.18 base with prebuilt images


## 7.7.19 2025-04-27 <dave at tiredofit dot ca>

   ### Added
      - Pin to tiredofit/nginx:6.5.18


## 7.7.18 2025-04-25 <dave at tiredofit dot ca>

   ### Added
      - Pin to tiredofit/nginx:6.5.17


## 7.7.17 2024-12-19 <dave at tiredofit dot ca>

   ### Reverted
      - Remove php84-spell component to support building under Alpine


## 7.7.16 2024-12-12 <dave at tiredofit dot ca>

   ### Added
      - Pin to tiredofit/nginx:6.5.10


## 7.7.15 2024-12-09 <dave at tiredofit dot ca>

   ### Added
      - Alpine pin to tiredofit/nginx:6.5.8


## 7.7.14 2024-12-07 <dave at tiredofit dot ca>

   ### Added
      - Add PHP 8.4 Support

   ### Changed
      - Switch PHP 8.3 and PHP 8.2 to use Alpine 3.21 as base


## 7.7.13 2024-10-22 <dave at tiredofit dot ca>

   ### Added
      - Pin to tiredofit/nginx:6.5.4


## 7.7.12 2024-10-04 <dave at tiredofit dot ca>

   ### Added
      - Pin to tiredofit/alpine:6.5.3


## 7.7.11 2024-09-26 <dave at tiredofit dot ca>

   ### Changed
      - Cleanup php-ext script
      - Pin to tiredofit/nginx:6.5.2


## 7.7.10 2024-09-25 <dave at tiredofit dot ca>

   ### Added
      - Add php-ext disable reset statement to refresh environments


## 7.7.9 2024-09-25 <dave at tiredofit dot ca>

   ### Changed
      - Remove stray cat command in Dockerfile

## 7.7.8 2024-05-01 <dave at tiredofit dot ca>

   ### Changed
      - Change sury.org GPG key for Debian installations


## 7.7.7 2024-04-16 <dave at tiredofit dot ca>

   ### Added
      - Add php83 extensions: ds,event,grpc,imagick,opentelemetry,pcov,rdkafka,smblient,ssh2
      - Add php82 extensions: decimal,ds,event,grpc,mailparse,mcrypt,opentelemetry,pcov,rdkafka,smbclient,ssh2,timezonedb,vips,xlswriter
      - Add php81 extensions: decimal,ds,luasandbox,mcrypt,opentelemetry,pcov,smbclient


## 7.7.6 2024-02-16 <dave at tiredofit dot ca>

   ### Changed
      - Remove Suhosin from hp5.6 variant


## 7.7.5 2024-01-26 <dave at tiredofit dot ca>

   ### Reverted
      - Remove lz4 extension from Debian variant


## 7.7.4 2023-12-08 <dave at tiredofit dot ca>

   ### Changed
      - Add alpine:3.19


## 7.7.3 2023-12-05 <dave at tiredofit dot ca>

   ### Changed
      - Change build for Alpine PHP 8.3 to not include 4 PECL extensions


## 7.7.2 2023-11-28 <dave at tiredofit dot ca>

   ### Reverted
      - Drop php-lua extension


## 7.7.1 2023-11-28 <dave at tiredofit dot ca>

   ### Changed
      - Remove `BOTH` Option for PHP_FPM_LISTEN_TYPE


## 7.7.0 2023-11-25 <dave at tiredofit dot ca>

   ### Added
      - Allow listening on Unix Socket or TCP Socket (default Unix Socket)
      - Add host/ip restrictions for TCP listening
      - Add PHP_FPM_USER and PHP_FPM_GROUP variables to create isolation from upstream image (default NGINX_ or UNIT_ USER|GROUP)


## 7.6.16 2023-11-22 <dave at tiredofit dot ca>

   ### Added
      - Introduce PHP 8.3 support


## 7.6.15 2023-09-13 <dave at tiredofit dot ca>

   ### Changed
      - Fix PHP_TIMEOUT not affecting php-cli operations causing unnecessary Signal 15s in some cases


## 7.6.14 2023-09-05 <fermion2020@github>

   ### Changed
      - Fixed not working LLNG handler authentification
      - Fixed creating a default index page

## 7.6.13 2023-07-28 <dave at tiredofit dot ca>

   ### Reverted
      - Remove php-decimal extension from Debian variant


## 7.6.12 2023-07-28 <dave at tiredofit dot ca>

   ### Added
      - Add support for Debian Bookworm

   ### Changed
      - Cleanup some PHP directories that shouldn't exist on Debian variants


## 7.6.11 2023-07-25 <dave at tiredofit dot ca>

   ### Changed
      - Change environment variable case


## 7.6.10 2023-07-06 <dave at tiredofit dot ca>

   ### Added
      - Source defaults from upstream nginx container to avoid having to use NGINX_ENABLE_APPLICATION_CONFIGURATION=TRUE variable


## 7.6.9 2023-06-21 <dave at tiredofit dot ca>

   ### Changed
      - Fix case introduced with 7.6.8 where authentication takes over default settings


## 7.6.8 2023-06-20 <dave at tiredofit dot ca>

   ### Changed
      - Restructure authentication routines when no NGINX_SITE_ENABLED being used to properly allow NGINX_AUTHENTICATION_TYPE=LLNG to be used.


## 7.6.6 2023-06-19 <dave at tiredofit dot ca>

   ### Changed
      - Stop building gnupg extension for <PHP 8.1


## 7.6.5 2023-05-30 <dave at tiredofit dot ca>

   ### Changed
      - Drop requirement of gnu-libiconv for < PHP 8.0 on alpine


## 7.6.4 2023-05-12 <dave at tiredofit dot ca>

   ### Reverted
      - Remove php82-pecl-phalcon for Alpine 3.18


## 7.6.3 2023-05-12 <dave at tiredofit dot ca>

   ### Changed
      - Strip pecl packages that no longer exist in Arch 3.18 repository for PHP 8.2


## 7.6.2 2023-05-10 <dave at tiredofit dot ca>

   ### Changed
      - Change PHP 8.2 to build with Alpine 3.18 Base
      - Change PHP 8.1 to build with Alpine 3.18 Base
      - Drop PHP 3.17 base variant


## 7.6.1 2023-04-04 <dave at tiredofit dot ca>

   ### Reverted
      - Remove spx extension from PHP 8.2 alpine


## 7.6.0 2023-03-24 <dave at tiredofit dot ca>

   ### Added
      - Added dozens of extra modules for Alpine PHP 8.0, 8.1, 8.2 variants


## 7.5.6 2023-03-23 <dave at tiredofit dot ca>

   ### Changed
      - Load MSGPACK when loading Redis module


## 7.5.5 2023-03-23 <dave at tiredofit dot ca>

   ### Added
      - Add more OPCache options and fix broken options


## 7.5.4 2023-03-23 <dave at tiredofit dot ca>

   ### Added
      - Add testing repository for PHP 8.2-alpine


## 7.5.3 2023-03-23 <dave at tiredofit dot ca>

   ### Added
      - Introduce PHP_HIDE_X_POWERED_BY variable


## 7.5.2 2023-03-20 <dave at tiredofit dot ca>

   ### Added
      - Add gnu-libconv package


## 7.5.1 2023-03-16 <dave at tiredofit dot ca>

   ### Changed
      - Change log_errors_max_len to 0 in php.ini from 1024

   ### Reverted
      - Strip php_admin_value[log_errors_max_len] from fpm config


## 7.5.0 2023-03-15 <dave at tiredofit dot ca>

   ### Changed
      - Quiet down output when loading defaults (xxx is already loaded! warnings)
      - Rework initialization
      - Fix a weird opcache issue


## 7.4.2 2023-02-21 <radarsymphony@github>

   ### Changed
      - Fix for LLNG_AUTHENTICATION_TYPE not reading variables properly


## 7.4.1 2023-01-16 <dave at tiredofit dot ca>

   ### Changed
      - Fix for 7.4.0


## 7.4.0 2023-01-15 <dave at tiredofit dot ca>

   ### Added
      - Add JIT Compilation support by means of PHP_OPCACHE_JIT_MODE and PHP_OPCACHE_BUFFER_SIZE variables (8.x only)

   ### Changed
      - Minor formatting fixes


## 7.3.4 2023-01-11 <dave at tiredofit dot ca>

   ### Changed
      - Convert alias to function in php-ext for non interactive sessions


## 7.3.3 2023-01-10 <dave at tiredofit dot ca>

   ### Changed
      - Fix for `php-ext` not reading modules with underscores properly (credit timoschwarzer@github)


## 7.3.2 2022-12-14 <dave at tiredofit dot ca>

   ### Changed
      - Fix PHP_BASE issue with modules not loading introduced with 7.3.0


## 7.3.1 2022-12-13 <dave at tiredofit dot ca>

   ### Changed
      - Patchup for 8.2.x on Alpine systems


## 7.3.0 2022-12-11 <dave at tiredofit dot ca>

   ### Added
      - Introduce PHP 8.2 Support

   ### Changed
      - Rework Dockerfiles


## 7.2.1 2022-11-23 <dave at tiredofit dot ca>

   ### Changed
      - Switch PHP 8.1 base to Alpine 3.17


## 7.2.0 2022-10-13 <dave at tiredofit dot ca>

   ### Added
      - Introduce customizable Opcache and APC environment variables


## 7.1.1 2022-10-05 <dave at tiredofit dot ca>

   ### Changed
      - Remvoe /var/log entries in Dockerfile build


## 7.1.0 2022-10-01 <dave at tiredofit dot ca>

   ### Added
      - Convert to using update_template functions when configuring

   ### Changed
      - Fix an error where sample php file wasn't being created properly


## 7.0.11 2022-09-16 <dave at tiredofit dot ca>

   ### Changed
      - Change the way PHP_DISPLAY_ERRORS works in code - True / False actually works


## 7.0.10 2022-08-17 <dave at tiredofit dot ca>

   ### Changed
      - Switch to using exec to have process take over pid


## 7.0.9 2022-08-08 <dave at tiredofit dot ca>

   ### Changed
      - Additional fixes to 7.0.8


## 7.0.8 2022-08-08 <dave at tiredofit dot ca>

   ### Changed
      - Fix for Kitchen Sink mode showing pathnames on print_notice command
      - Stop using log_length parameter for < PHP-FPM 7.3


## 7.0.7 2022-07-18 <dave at tiredofit dot ca>

   ### Changed
      - Fix for keepalives in upstream


## 7.0.6 2022-07-09 <dave at tiredofit dot ca>

   ### Changed
      - Escape document_root for FastCGI default scripts


## 7.0.5 2022-07-06 <dave at tiredofit dot ca>

   ### Changed
      - Fix for blank configuration not passing proper fastcgi_params
      - Stop throwing an error for openssl if it doesn't exist in the slightest


## 7.0.4 2022-07-06 <dave at tiredofit dot ca>

   ### Changed
      - Debian: Switch to PHP_BASE versioned msgpack module


## 7.0.3 2022-07-05 <dave at tiredofit dot ca>

   ### Changed
      - Add ARG for easier build argument shifting with CI and command line


## 7.0.2 2022-07-04 <dave at tiredofit dot ca>

   ### Changed
      - Bugfix when there is no default.conf file available


## 7.0.1 2022-07-03 <dave at tiredofit dot ca>

   ### Added
      - Add PHP_FPM_OUTPUT_BUFFER_SIZE environment variable


## 7.0.0 2022-06-23 <dave at tiredofit dot ca>

   ### Added
      - Rewrote entire image and split into functions to be reused in descendent images
      - Rework to support tiredofit/nginx:6.0.0 and its changes

   ### Changed
      - Rename CONTAINER_MODE variable
      - Quiet down output on extension loading/unloading


## 6.4.10 2022-05-24 <dave at tiredofit dot ca>

   ### Added
      - Alpine: Switch PHP 8 and 8.1 to Alpine 3.16 base


## 6.4.9 2022-04-12 <unlink@github>

   ### Changed
      - Add support for debugging with PHPStorm

## 6.4.8 2022-04-11 <unlink@github>

   ### Changed
      - Fix for open brace in if statement
      - Revamp Xdebug options for PHP 7.2 and higher


## 6.4.7 2022-04-06 <dave at tiredofit dot ca>

   ### Changed
      - Adjust defaults to use proper if statements as opposed to shortcuts


## 6.4.6 2022-03-18 <dave at tiredofit dot ca>

   ### Changed
      - Fix for Debian images not including redis extension


## 6.4.5 2022-03-11 <dave at tiredofit dot ca>

   ### Changed
      - Sanity checks to be able to survive "warm" restarts


## 6.4.4 2022-03-08 <dave at tiredofit dot ca>

   ### Added
      - Remove php74-embed


## 6.4.3 2022-03-04 <dave at tiredofit dot ca>

   ### Changed
      - Change the way that upstream blocks are being added - stop relying on default.conf, instead put them in nginx.conf


## 6.4.2 2022-03-03 <dave at tiredofit dot ca>

   ### Changed
      - Patchup for 6.4.1


## 6.4.1 2022-03-02 <dave at tiredofit dot ca>

   ### Added
      - Add PHP_FPM_POST_INIT_SCRIPT variable to execute scripts before php-fpm process starts
      - Add PHP_FPM_POST_INIT_COMMAND variable to execute command before php-fpm-process starts


## 6.4.0 2022-02-23 <dave at tiredofit dot ca>

   ### Added
      - Add multiple PHP upstream hosts by default
      - Update LLNG Authentication to use Upstream Hosts

   ### Changed
      - Code Cleanup, refactoring


## 6.3.7 2022-02-22 <dave at tiredofit dot ca>

   ### Added
      - Patchup Alpine Mono Dockerfile to properly build PHP 8.1 variants


## 6.3.6 2022-02-09 <dave at tiredofit dot ca>

   ### Changed
      - Fixes for builds showing up as PHP 8.1 instead of what they should be
      - Base image updates

   ### Reverted


## 6.3.5 2021-12-28 <dave at tiredofit dot ca>

   ### Changed
      - Fixup for LibTidy throwing errors


## 6.3.4 2021-12-27 <dave at tiredofit dot ca>

   ### Changed
      - Fix for Zabbix Opcache monitoring


## 6.3.3 2021-12-16 <dave at tiredofit dot ca>

   ### Changed
      - Cleanup some of the autodiscover routines should Nginx or PHP-FPM be running in 'standalone' mode


## 6.3.2 2021-12-14 <dave at tiredofit dot ca>

   ### Changed
      - Fix for Docker Mono repo for PHP < 7.3 failing


## 6.3.1 2021-12-10 <dave at tiredofit dot ca>

   ### Changed
      - Fix for 6.3.0 Zabbix Templates and switch to User Parameters


## 6.3.0 2021-12-07 <dave at tiredofit dot ca>

   ### Changed
      - Rework Zabbix Monitoring scripts and templates


## 6.2.15 2021-12-01 <dave at tiredofit dot ca>

   ### Changed
      - Stop OpenSSL warning in PHP 8.1


## 6.2.14 2021-11-24 <dave at tiredofit dot ca>

   ### Added
      - Change PHP 7.4 and 8.0 to use Alpine 3.15 as base


## 6.2.13 2021-11-16 <dave at tiredofit dot ca>

   ### Changed
      - Fix for Zabbix PHP-FPM Metrics not functioning when AUTHENTICATION_TYPE=LLNG


## 6.2.12 2021-11-16 <dave at tiredofit dot ca>

   ### Changed
      - Fix for XDebug Log Path


## 6.2.11 2021-11-16 <dave at tiredofit dot ca>

   ### Changed
      - Adjustment to Log Level integer


## 6.2.10 2021-11-10 <dave at tiredofit dot ca>

   ### Changed
      - Change the way that access logs are being configured on startup for those who don't stop and destroy a container completely


## 6.2.9 2021-10-28 <dave at tiredofit dot ca>

   ### Changed
      - Debian: Fix for pulling in MariaDB repository


## 6.2.8 2021-10-28 <dave at tiredofit dot ca>

   ### Changed
      - Fix with pulling in MariaDB Repository


## 6.2.7 2021-10-20 <dave at tiredofit dot ca>

   ### Added
      - Add mariadb-connector-c to fix SHA2 problems with connecting to MariaDB 8.0 systems


## 6.2.6 2021-10-19 <dave at tiredofit dot ca>

   ### Added
      - Add PHP_LOG_LIMIT environment variable to ensure single line log levels in access/error.log


## 6.2.5 2021-09-04 <dave at tiredofit dot ca>

   ### Changed
      - Redo how logrotate files were created


## 6.2.4 2021-09-04 <dave at tiredofit dot ca>

   ### Changed
      - Opcache key removal for Zabbix monitoring


## 6.2.3 2021-09-04 <dave at tiredofit dot ca>

   ### Changed
      - Fix for monitoring PHP-FPM


## 6.2.2 2021-09-01 <dave at tiredofit dot ca>

   ### Changed
      - Fix for logformats


## 6.2.1 2021-09-01 <dave at tiredofit dot ca>

   ### Changed
      - Fix for msmtp not working due to a change in upstream base images


## 6.2.0 2021-08-29 <dave at tiredofit dot ca>

   ### Added
      - Added Access Log support with standard/default string output or json output
      - Fluent-Bit Log Parsing support


## 6.1.21 2021-08-19 <dave at tiredofit dot ca>

   ### Changed
      - Change the way dependent modules are loaded in defaults


## 6.1.20 2021-08-18 <dave at tiredofit dot ca>

   ### Changed
      - Change to PECL http package


## 6.1.19 2021-08-18 <dave at tiredofit dot ca>

   ### Changed
      - Change to PHP Memcached plugin for debian


## 6.1.18 2021-08-05 <dave at tiredofit dot ca>

   ### Added
      - Add another value for socket timeout
      - Cleanup some opcache console annoyances


## 6.1.17 2021-07-12 <dave at tiredofit dot ca>

   ### Changed
      - Move around some LLNG Authentication blocks


## 6.1.16 2021-07-05 <dave at tiredofit dot ca>

   ### Added
      - Support upstream image changes

## 6.1.15 2021-06-08 <dave at tiredofit dot ca>

   ### Added
      - Add Hook to load IGBINARY when PHP_ENABLE_MEMCACHED=TRUE


## 6.1.14 2021-06-04 <dave at tiredofit dot ca>

   ### Added
      - Enable APC Caching for CLI


## 6.1.13 2021-05-29 <dave at tiredofit dot ca>

   ### Changed
      - Final permissions fix for MSMTP


## 6.1.12 2021-05-25 <dave at tiredofit dot ca>

   ### Changed
      - Additional checks for msmtp usage - If ENABLE_SMTP=FALSE then don't execute permissions settings


## 6.1.11 2021-05-25 <dave at tiredofit dot ca>

   ### Changed
      - Change the way that LLNG authentication gets loaded


## 6.1.10 2021-05-24 <dave at tiredofit dot ca>

   ### Changed
      - Fix for 6.1.9 permissions


## 6.1.9 2021-05-24 <dave at tiredofit dot ca>

   ### Changed
      - Update msmtprc file with nginx user/group permissions to allow php-fpm to send
      - Shuffle XDebug environment variables and configuraiton around


## 6.1.8 2021-05-19 <dave at tiredofit dot ca>

   ### Added
      - Add gpgme package (Alpine)

   ### Changed
      - Fix for php-ext enable script to stop loading json if PHP > 8
      - GPG extension loading fix


## 6.1.7 2021-05-05 <dave at tiredofit dot ca>

   ### Changed
      - Force OPENSSL extension to be activated by default to fix composer errors


## 6.1.6 2021-05-04 <dave at tiredofit dot ca>

   ### Changed
      - Fix for opcache being loaded twice in some scenarios


## 6.1.5 2021-05-03 <dave at tiredofit dot ca>

   ### Changed
      - Fix for enabling json warning under php8


## 6.1.4 2021-05-03 <dave at tiredofit dot ca>

   ### Changed
      - Fix for JSON for <php7


## 6.1.3 2021-05-03 <dave at tiredofit dot ca>

   ### Changed
      - Add PHP_ENABLE_SESSION=TRUE to defaults
      - Set PHP_ENABLE_IGBINARY=TRUE when PHP_ENABLE_REDIS=TRUE


## 6.1.2 2021-05-01 <dave at tiredofit dot ca>

   ### Changed
      - Fixes to php extension script specifically under Alpine


## 6.1.1 2021-05-01 <dave at tiredofit dot ca>

   ### Changed
      - Fix for determining PHP version on runtime


## 6.1.0 2021-04-22 <dave at tiredofit dot ca>

   ### Changed
      - Unified Script for Alpine and Debian
      - Merged all changes up to 6.xx into Alpine build

## 6.0.1 2021-04-16 <dave at tiredofit dot ca>

   ### Changed
      - Fix PHP Extension script
      - Opcache seems to want to load twice for some reason, dirty hack enabled
      - Composer wasn't installing properly


## 6.0.0 2021-04-16 <dave at tiredofit dot ca>

   ### Added
      - Merged Debian branches into one - Use Build Argument of PHP_BASE to build `7.3` `7.4` or `8.0`
      - Composer 2.x
      - Massively revamped module loading. Try `php-env` from the command line to enable, disable, see modules available per version
      - Building for Stretch and Buster, ready for Bullseye
      - Building and amd64, arm7, arm64

## 5.6.0 2020-10-26 <dave at tiredofit dot ca>

   ### Added
      - Add composer version declaration (pinning to 1.10.16)


## 5.5.3 2020-08-29 <dave at tiredofit dot ca>

   ### Added
      - Add ENABLE_PHP_FPM environment variable


## 5.5.2 2020-08-10 <dave at tiredofit dot ca>

   ### Changed
      - Fix to regex for LLNG Authentication


## 5.5.1 2020-07-16 <dave at tiredofit dot ca>

   ### Changed
      - Fix logrotate for PHP-FPM


## 5.5.0 2020-06-09 <dave at tiredofit dot ca>

   ### Added
      - Update to support tiredofit/debian 5.0.0 base image


## 5.4.1 2020-06-05 <dave at tiredofit dot ca>

   ### Changed
      - Move /etc/s6/services to /etc/services.d


## 5.4.0 2020-05-13 <dave at tiredofit dot ca>

   ### Added
      - PHP 7.3 - Debian Buster Variant


## 5.3.7 2020-04-21 <dave at tiredofit dot ca>

   ### Changed
      - Remove extra logrotate.d file added by packages


## 5.3.6 2020-04-21 <dave at tiredofit dot ca>

   ### Changed
      - Fix for PHP Plugins not enabling correctly


## 5.3.5 2020-04-18 <dave at tiredofit dot ca>

   ### Added
      - Update to support tiredofit/alpine 4.5.1 base image


## 5.3.4 2020-03-16 <dave at tiredofit dot ca>

   ### Changed
      - Change msmtp configuration


## 5.3.3 2020-03-04 <dave at tiredofit dot ca>

   ### Added
      - Update image to support new tiredofit/alpine:4.4.0 base image

## 5.3.1 2020-01-20 <dave at tiredofit dot ca>

   ### Changed
      - Change the way PHP XDebug is being called


## 5.3.0 2020-01-04 <dave at tiredofit dot ca>

   ### Added
      - Add new `CONTAINER_MODE` environment variable to allow standalone operation for load balancing
      - Add new `PHP_WEBROOT` environment variable when `CONTAINER_MODE` set to `php-fpm`


## 5.2.2 2020-01-03 <dave at tiredofit dot ca>

   ### Added
      - ADD PHP_POST_MAX_SIZE environment variable

   ### Changed
      - Cleanup with LLNG Authentication
      - Properly assign PHP_UPLOAD_MAX_SIZE and PHP_POST_MAX_SIZE variables


## 5.2.0 2019-12-31 <dave at tiredofit dot ca>

   ### Added
      - Move defaults to /assets/functions files

   ### Changed
      - Change warnings to notices


## 5.1.0 2019-12-29 <dave at tiredofit dot ca>

   ### Added
      - Update to support new tiredofit/alpine base image


## 5.0.4 2019-12-19 <dave at tiredofit dot ca>

   ### Changed
      - Change to LLNG Authentication Auto Configuration Routines


## 5.0.3 2019-12-18 <dave at tiredofit dot ca>

   ### Changed
      - Fixed error with display errors configuration

## 5.0.2 2019-12-18 <dave at tiredofit dot ca>

   ### Changed
      - Change to support dynamic webserver user/group


## 5.0.1 2019-12-04 <dave at tiredofit dot ca>

   ### Changed
      - Make MySQL Default Enabled


## 5.0.0 2019-12-04 <dave at tiredofit dot ca>

   ### Added
      - Reworked entire image
      - Added many new variables
      - Basing off of tiredofit/nginx
      - Code Cleanup


## 4.4.2 2019-11-18 <dave at tiredofit dot ca>

   ### Changed
      - Update Nginx proxy temp location


## 4.4.1 2019-07-08 <dave at tiredofit dot ca>

* Add tmp folder during startup to avoid bootloop

## 4.4 2019-06-19 <dave at tiredofit dot ca>

* PHP 7.3
* Alpine 3.10

## 4.3 2019-03-03 <dave at tiredofit dot ca>

* Move Alpine base to 3.9

## 4.2 2018-12-17 <dave at tiredofit dot ca>

* Add Nginx tmp cache directory

## 4.1 2018-11-28 <dave at tiredofit dot ca>

* Fix Timezone setting for php.ini

## 4.0.1 2018-11-19 <dave at tiredofit dot ca>

* Update further LLNG

## 4.0 2018-04-28 <dave at tiredofit dot ca>

* Ability to protect service via basic authentication or using LemonLDAP:NG Handlers


## 3.7 2018-04-22 <dave at tiredofit dot ca>

* Tweak SMTP to always route through msmtp based on new Base Image Changes

## 3.6 2018-04-02 <dave at tiredofit dot ca>

* Added MAINTENANCE environment variable to move system to maintenance mode. Also maintenance script (off/on/sleep 60) inside container.

## 2018-03-18 3.5 <dave at tiredofit dot ca>

* Add `STAGE` variable to be passed to PHP for Development/Production Purposes

## 2018-02-20 3.4 <dave at tiredofit dot ca>

* Add Reverse Proxy Detection

## 2018-02-14 3.3 <dave at tiredofit dot ca>

* Remove Redundant Entrypoint
* Fix Paths for enabled php modules

## 2018-02-01 3.2 <dave at tiredofit dot ca>

* Fix PHP Timezone Issue
* Add Zabbix Scripts

## 2017-11-30 edge-3.1 <dave at tiredofit dot ca>

* Switched to Edge Base


## 2017-09-17 3.1 <dave at tiredofit dot ca>

* Fix Issue with PHP XDebug
* Added Imagick Extension

## 2017-08-27 3.0 <dave at tiredofit dot ca>

* Big change (in image size) due to adding all available PHP Extensions
* Debug Mode via XDebug set via Environment Variables
* All PHP Extensions able to be enabled of disabled via Environment Variables

## 2017-07-12 2.6 <dave at tiredofit dot ca>

* Added Checking to wait to start services in sequence

## 2017-07-12 2.5 <dave at tiredofit dot ca>

* Added Composer, memcached, and sqlite extensions

## 2017-07-06 2.4 <dave at tiredofit dot ca>

* Added proper logging for php-fpm

## 2017-07-06 2.3 <dave at tiredofit dot ca>

* Add PHP_TIMEOUT

## 2017-07-03 2.2 <dave at tiredofit dot ca>

* Added Logrotate

## 2017-07-01 2.1 <dave at tiredofit dot ca>

* Sanity Check and write initialization state to /tmp/.container/*service name
* Added MSMTP to take place of sendmail


## 2017-06-23 2.0 <dave at tiredofit dot ca>

* s6.d Process Seperation
* PHP-FPM run as NGINX
* Nginx Zabbix Checks set to port 73
* Nginx Uses conf.d file for Loading Site


## 2017-05-29 1.3 <dave at tiredofit dot ca>

* Tracking Alpine 3.4
* PHP 5.6

## 2017-04-07 1.2 <dave at tiredofit dot ca>

* Rebase

## 2017-02-08 1.1 <dave at tiredofit dot ca>

* Added mariadb-client

## 2017-02-08 1.0 <dave at tiredofit dot ca>

* Initial Release
* Alpine:edge
* PHP7
* Zabbix



================================================
FILE: Containerfile
================================================
# SPDX-FileCopyrightText: © 2026 Nfrastack <code@nfrastack.com>
#
# SPDX-License-Identifier: MIT

ARG BASE_IMAGE

FROM ${BASE_IMAGE}

LABEL \
        org.opencontainers.image.title="Nginx PHP-FPM" \
        org.opencontainers.image.description="PHP Interpreter w/Web server" \
        org.opencontainers.image.url="https://hub.docker.com/r/nfrastack/nginx-php-fpm" \
        org.opencontainers.image.documentation="https://github.com/nfrastack/container-nginx-php-fpm/blob/main/README.md" \
        org.opencontainers.image.source="https://github.com/nfrastack/container-nginx-php-fpm.git" \
        org.opencontainers.image.authors="Nfrastack <code@nfrastack.com>" \
        org.opencontainers.image.vendor="Nfrastack <https://www.nfrastack.com>" \
        org.opencontainers.image.licenses="MIT"

ARG \
    PHP_BASE

ENV \
    CONTAINER_ENABLE_MESSAGING=TRUE \
    IMAGE_NAME="nfrastack/nginx-php-fpm" \
    IMAGE_REPO_URL="https://github.com/nfrastack/container-nginx-php-fpm/"

COPY CHANGELOG.md /usr/src/container/CHANGELOG.md
COPY LICENSE /usr/src/container/LICENSE
COPY README.md /usr/src/container/README.md

RUN echo "" && \
    BUILD_ENV=" \
                10-nginx/NGINX_CREATE_SAMPLE_HTML=FALSE \
                10-nginx/NGINX_INDEX_FILE=index.php \
                20-php-fpm/PHP_MODULE_ENABLE_APCU=TRUE \
                20-php-fpm/PHP_MODULE_ENABLE_BCMATH=TRUE \
                20-php-fpm/PHP_MODULE_ENABLE_BZ2=TRUE \
                20-php-fpm/PHP_MODULE_ENABLE_CTYPE=TRUE \
                20-php-fpm/PHP_MODULE_ENABLE_CURL=TRUE \
                20-php-fpm/PHP_MODULE_ENABLE_DOM=TRUE \
                20-php-fpm/PHP_MODULE_ENABLE_EXIF=TRUE \
                20-php-fpm/PHP_MODULE_ENABLE_FILEINFO=TRUE \
                20-php-fpm/PHP_MODULE_ENABLE_GD=TRUE \
                20-php-fpm/PHP_MODULE_ENABLE_ICONV=TRUE \
                20-php-fpm/PHP_MODULE_ENABLE_IMAP=TRUE \
                20-php-fpm/PHP_MODULE_ENABLE_INTL=TRUE \
                20-php-fpm/PHP_MODULE_ENABLE_MBSTRING=TRUE \
                20-php-fpm/PHP_MODULE_ENABLE_MYSQLI=TRUE \
                20-php-fpm/PHP_MODULE_ENABLE_MYSQLND=TRUE \
                20-php-fpm/PHP_MODULE_ENABLE_OPCACHE=TRUE \
                20-php-fpm/PHP_MODULE_ENABLE_OPENSSL=TRUE \
                20-php-fpm/PHP_MODULE_ENABLE_PDO=TRUE \
                20-php-fpm/PHP_MODULE_ENABLE_PDO_MYSQL=TRUE \
                20-php-fpm/PHP_MODULE_ENABLE_PGSQL=TRUE \
                20-php-fpm/PHP_MODULE_ENABLE_PHAR=TRUE \
                20-php-fpm/PHP_MODULE_ENABLE_SESSION=TRUE \
                20-php-fpm/PHP_MODULE_ENABLE_SIMPLEXML=TRUE \
                20-php-fpm/PHP_MODULE_ENABLE_TOKENIZER=TRUE \
                20-php-fpm/PHP_MODULE_ENABLE_XML=TRUE \
                20-php-fpm/PHP_MODULE_ENABLE_XMLREADER=TRUE \
                20-php-fpm/PHP_MODULE_ENABLE_XMLWRITER=TRUE \
                20-php-fpm/PHPFPM_USER=[env:NGINX_USER] \
                20-php-fpm/PHPFPM_GROUP=[env:NGINX_GROUP] \
                " \
                && \
    PHP_BUILD_DEPS_ALPINE="  \
                                build-base \
                                php${PHP_BASE/./}-dev \
                                " \
                                && \
    PHP_BUILD_DEPS_DEBIAN="  \
                          " \
                          && \
    PHP_RUN_DEPS_ALPINE="  \
                            mariadb-client \
                            mariadb-connector-c \
                            postgresql-client \
                        " \
                        && \
    PHP_8_5_RUN_DEPS_ALPINE=" \
                                gnu-libiconv \
                                mariadb-connector-c \
                            " && \
    \
    PHP_8_4_RUN_DEPS_ALPINE=" \
                                gnu-libiconv \
                                mariadb-connector-c \
                            " && \
    \
    PHP_8_3_RUN_DEPS_ALPINE=" \
                                gnu-libiconv \
                                mariadb-connector-c \
                            " && \
    \
    PHP_8_2_RUN_DEPS_ALPINE=" \
                                gnu-libiconv \
                                mariadb-connector-c \
                            " && \
    \
     PHP_8_1_RUN_DEPS_ALPINE=" \
                                gnu-libiconv \
                                mariadb-connector-c \
                            " && \
    \
    PHP_8_0_RUN_DEPS_ALPINE=" \
                                gnu-libiconv \
                                mariadb-connector-c \
                            " && \
    \
    PHP_7_4_RUN_DEPS_ALPINE=" \
                                mariadb-connector-c \
                            " && \
    \
    PHP_7_3_RUN_DEPS_ALPINE=" \
                                mariadb-connector-c \
                            " && \
    \
    PHP_7_2_RUN_DEPS_ALPINE=" \
                            " && \
    \
    PHP_7_1_RUN_DEPS_ALPINE=" \
                            " && \
    \
    PHP_7_0_RUN_DEPS_ALPINE=" \
                            " && \
    \
    PHP_5_6_RUN_DEPS_ALPINE=" \
                            " && \
    \
    PHP_RUN_DEPS_DEBIAN=" \
                            ca-certificates \
                            git \
                            mariadb-client \
                            php-pear \
                            postgresql-client \
                        " \
    PHP_8_5_RUN_DEPS_DEBIAN=" \
                            " && \
    \
    PHP_8_4_RUN_DEPS_DEBIAN=" \
                            " && \
    \
    PHP_8_3_RUN_DEPS_DEBIAN=" \
                            " && \
    \
    PHP_8_2_RUN_DEPS_DEBIAN=" \
                            " && \
    \
    PHP_8_1_RUN_DEPS=_DEBIAN" \
                            " && \
    \
    PHP_8_0_RUN_DEPS_DEBIAN=" \
                            " && \
    \
    PHP_7_4_RUN_DEPS_DEBIAN=" \
                            " && \
    \
    PHP_7_3_RUN_DEPS_DEBIAN=" \
                            " && \
    \
    source /container/base/functions/container/build && \
    container_build_log image && \
    create_user php 9000 www-data && \
    add_user_group php www-data && \
    case "$(container_info distro)" in \
        "alpine" ) \
            case "${PHP_BASE}" in \
                8.[1-9] ) \
                        export _php_folder="/etc/php${PHP_BASE/./}" ; \
                        export _php_version="${PHP_BASE/./}" ; \
                        export build_gnupg=true ; \
                    ;; \
                8.0 | *  ) \
                        export _php_folder="/etc/php${PHP_BASE:0:1}" ; \
                        export _php_version="${PHP_BASE:0:1}" ; \
                        export build_gnupg=false ; \
                    ;; \
            esac \
        ;; \
        "debian" ) \
            export _php_version="${PHP_BASE}" ; \
            export _php_folder="/etc/php/${PHP_BASE}" ; \
            package repo add mariadb ; \
            package repo add postgres ; \
            package repo key https://packages.sury.org/php/apt.gpg suryphp.gpg ; \
            package repo add suryphp "https://packages.sury.org/php/ $(cat /etc/os-release |grep "VERSION=" | awk 'NR>1{print $1}' RS='(' FS=')') main" suryphp.gpg ; \
        ;; \
    esac ; \
    package update && \
    package upgrade && \
    package install \
                    PHP_BUILD_DEPS \
                    PHP_${PHP_BASE/./_}_BUILD_DEPS \
                    PHP_RUN_DEPS \
                    PHP_${PHP_BASE/./_}_RUN_DEPS \
                    && \
    \
    case "$(container_info distro)" in \
        "alpine" ) \
            package install $(apk search -q php${_php_version} | grep "^php${_php_version}" | sed -e "/-cgi/d" -e "/-apache2/d" -e "/-doc/d" -e "/-dbg/d") ; \
            sed -i "s|;cgi.fix_pathinfo=1|cgi.fix_pathinfo=0|g" ${_php_folder}/php.ini ; \
        ;; \
        "debian" ) \
            package install $(apt-cache search php${_php_version} | awk '{print $1}' | sed -e "/-cgi/d" -e "/-dbgsym/d" -e "/-dev/d" -e "/-gmagick/d"  -e "/libapache2-mod/d" -e "/-libvirt/d" -e "/-yac/d") ; \
            sed -i "s|;cgi.fix_pathinfo=1|cgi.fix_pathinfo=0|g" ${_php_folder}/cli/php.ini ; \
        ;; \
    esac ; \
    \
    if [ -f /usr/sbin/php-fpm"${_php_version}" ] ; then ln -sf /usr/sbin/php-fpm"${_php_version}" /usr/sbin/php-fpm ; fi ; \
    if [ -f /usr/sbin/php-fpm"${PHP_BASE}" ] ; then ln -sf /usr/sbin/php-fpm"${PHP_BASE}" /usr/sbin/php-fpm ; fi ; \
    if [ -f /usr/bin/pecl"${_php_version}" ] ; then ln -sf /usr/bin/pecl"${_php_version}" /usr/sbin/pecl; fi ; \
    if [ -f /usr/bin/php"${_php_version}" ] ; then ln -sf /usr/bin/php"${_php_version}" /usr/sbin/php ; fi ; \
    if [ -f /usr/bin/phpize"${_php_version}" ] ; then ln -sf /usr/bin/phpize"${_php_version}" /usr/sbin/phpize ; fi ; \
    curl -sSLk https://getcomposer.org/installer | php -- --install-dir=/usr/local/bin --filename=composer && \
    \
    rm -rf \
            "${_php_folder}"/environment/* \
            "${_php_folder}"/php-fpm.d/* \
            "${_php_folder}"/pools.d/* \
            && \
    \
    if [ "${_php_version}" = "5" ] ; then echo "suhosin.executor.include.whitelist = phar" >> "${_php_folder}"/php.ini ; fi ;  \
    \
    case "$(container_info distro)" in \
        "alpine" ) \
            #### Disabling any but core extensions - When using this image as a base for other images, you'll want to turn turn them on before running composer with the inverse of phpdisomd (phpenmod) to keep things clean
            mkdir -p "${_php_folder}"/conf.available/ && \
            for module in "${_php_folder}"/conf.d/*.ini; do \
                if [ ! -L "${module}" ] ; then \
                    if [ "$(echo $(basename $module) | grep -c '^[0-9][0-9].*')" = "0" ] ; then \
                        mv "${module}" "$(dirname ${module})/20_$(basename ${module})" ; \
                        module="$(dirname ${module})/20_$(basename ${module})"; \
                    fi ; \
                    if ! grep -w -i -q ";priority" "$module"; then \
                        echo ";priority=$(basename $module .ini | cut -d _ -f1)" >> $module ; \
                        mv "${module}" "${_php_folder}"/conf.available/$(basename "${module}" .ini | cut -c 4-).ini; \
                    fi; \
                fi; \
            done; \
            rm -rf "${_php_folder}"/conf.d/* ; \
            sed -i "s|;priority=00|;priority=10|g" "${_php_folder}"/conf.available/opcache.ini ; \
            php_env_modules_enabled="$(set -o posix; set | sort | grep "^PHP_MODULE_ENABLE_.*=" | grep -i TRUE | cut -d _ -f 4 | cut -d = -f 1 |  tr [A-Z] [a-z])" ; \
            for module in $php_env_modules_enabled ; do \
                if [ -f "${_php_folder}"/conf.available/"${module}".ini ] ; then \
                    priority=$(cat "${_php_folder}"/conf.available/"${module}".ini | grep ";priority" | cut -d = -f2) ; \
                    ln -sf "${_php_folder}"/conf.available/"${module}".ini "${_php_folder}"/conf.d/"${priority}"-"${module}".ini ; \
                fi ; \
            done ; \
            if [ "${_php_version}" != "8" ] ; then \
                if [ -f "${_php_folder}"/conf.available/json.ini ] ; then \
                          priority=$(cat "${_php_folder}"/conf.available/json.ini | grep ";priority" | cut -d = -f2) ; \
                    ln -sf "${_php_folder}"/conf.available/json.ini "${_php_folder}"/conf.d/"${priority}"-json.ini ; \
                fi ; \
            fi ; \
        ;; \
        "debian" ) \
            update-alternatives --set php /usr/bin/php${PHP_BASE} ; \
            for f in /etc/php/${PHP_BASE}/mods-available/*.ini; do phpdismod $(basename $f .ini); done; \
            php_env_modules_enabled="$(set -o posix; set | sort | grep "^PHP_MODULE_ENABLE_.*=" | grep -i TRUE | cut -d _ -f 4 | cut -d = -f 1 |  tr A-Z a-z)" ; \
            for module in $php_env_modules_enabled ; do phpenmod ${module} ; done ; \
            if [ "${PHP_BASE}" = "7.3" ] || [ "${PHP_BASE}" = "7.4" ]; then phpenmod json ; fi ; \
            find /etc/php/ -mindepth 1 -maxdepth 1 -type d -not -name ${PHP_BASE} -exec rm -rf '{}' \; 2>/dev/null ; \
        ;; \
    esac ; \
    \
    package remove \
                    PHP_BUILD_DEPS \
                    PHP_${PHP_BASE/./_}_BUILD_DEPS \
                    && \
    package cleanup && \
    rm -rf \
            /root/.composer

COPY rootfs /


================================================
FILE: LICENSE
================================================
The MIT License (MIT)

Copyright (c) 2026 Nfrastack

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.


================================================
FILE: README.md
================================================
# nfrastack/container-nginx-php-fpm

## About

This repository will build a [Nginx](https://www.nginx.org) w/[PHP-FPM](https://php.net) container image, suitable for serving PHP scripts, or utilizing as a base image for installing additional software.

* Tracking PHP 5.3-8.5
* Easily enable / disable extensions based on your use case
* Automatic Log rotation
* Composer Included
* XDebug capability
* Caching via APC, opcache
* Includes client libraries for [MariaDB](https://www.mariadb.org) and [Postgresql](https://www.postgresql.org)
* Multiple pool support

## Maintainer

* [Nfrastack](https://www.nfrastack.com)

## Table of Contents

* [About](#about)
* [Maintainer](#maintainer)
* [Table of Contents](#table-of-contents)
* [Installation](#installation)
  * [Prebuilt Images](#prebuilt-images)
  * [Quick Start](#quick-start)
  * [Persistent Storage](#persistent-storage)
* [Configuration](#configuration)
  * [Environment Variables](#environment-variables)
    * [Base Images used](#base-images-used)
    * [Core Configuration](#core-configuration)
  * [Users and Groups](#users-and-groups)
  * [Networking](#networking)
* [Maintenance](#maintenance)
  * [Shell Access](#shell-access)
* [Support & Maintenance](#support--maintenance)
* [License](#license)
* [References](#references)

## Installation

### Prebuilt Images

Feature limited builds of the image are available on the [Github Container Registry](https://github.com/nfrastack/container-nginx-php-fpm/pkgs/container/container-nginx-php-fpm) and [Docker Hub](https://hub.docker.com/r/nfrastack/nginx-php-fpm).

To unlock advanced features, one must provide a code to be able to change specific environment variables from defaults. Support the development to gain access to a code.

To get access to the image use your container orchestrator to pull from the following locations:

```
ghcr.io/nfrastack/container-nginx-php-fpm:(image_tag)
docker.io/nfrastack/nginx-php-fpm:(image_tag)
```

Image tag syntax is:

`<image>:<optional tag>-<optional phpversion>-<optional distro>-<optional distro_variant>`

Example:

`ghcr.io/nfrastack/container-nginx-php-fpm:latest` or

`ghcr.io/nfrastack/container-nginx-php-fpm:1.0-8.4-debian_trixie`

* `latest` will be the most recent commit

* An optional `tag` may exist that matches the [CHANGELOG](CHANGELOG.md) - These are the safest

| PHP version | Alpine Base | Tag            | Debian Base | Tag                    |
| ----------- | ----------- | -------------- | ----------- | ---------------------- |
| latest      | edge        | `:alpine-edge` |             |                        |
| 8.5.x       | 3.23        | `:8.5-alpine`  |             |                        |
| 8.4.x       | 3.23        | `:8.4-alpine`  | Trixie      | `:8.4-debian`          |
|             |             |                | Bookworm    | `:8.4-debian_bookworm` |
| 8.3.x       | 3.23        | `:8.3-alpine`  | Bookworm    | `:8.3-debian_trixie`   |
|             |             |                | Trixie      | `:8.3-debian`          |
| 8.2.x       | 3.22        | `:8.2-alpine`  | Trixie      | `:8.2-debian`          |
|             |             |                | Bookworm    | `:8.2-debian_bookworm` |
| 8.1.x       | 3.19        | `:8.1-alpine`  |             |                        |
| 8.0.x       | 3.16        | `:8.0-alpine`  |             |                        |


Have a look at the container registries and see what tags are available.

#### Multi-Architecture Support

Images are built for `amd64` by default, with optional support for `arm64` and other architectures.

### Quick Start

* The quickest way to get started is using [docker-compose](https://docs.docker.com/compose/). See the examples folder for a working [compose.yml](examples/compose.yml) that can be modified for your use.

* Map [persistent storage](#persistent-storage) for access to configuration and data files for backup.
* Set various [environment variables](#environment-variables) to understand the capabilities of this image.

Refer to the nginx upstream readme for configuration. If you do not create any configuration files for the sites, a default PHP location block will be added to your site

```nginx
location ~ [^/]\.php(/|$) {
    try_files $fastcgi_script_name =404; # Fail if script missing
    {{php_upstream}};
    fastcgi_split_path_info ^(.+\.php)(/.+)$;
    fastcgi_index {{php_index_file}};
    {{fastcgi_params}};
}
```

{{php_upstream}} will get replaced on container start with your PHP POOL value, and {{fastcgi_params}} will get replaced with the location of your nginx fastcgi_params.

### Persistent Storage

The following directories/files should be mapped for persistent storage in order to utilize the container effectively.

| Directory       | Description                |
| --------------- | -------------------------- |
| `/www/html`     | Root Directory             |
| `/logs/php-fpm` | Nginx and php-fpm logfiles |

### Environment Variables

#### Base Images used

This image relies on a customized base image in order to work.
Be sure to view the following repositories to understand all the customizable options:

| Image                                                   | Description     |
| ------------------------------------------------------- | --------------- |
| [OS Base](https://github.com/nfrastack/container-base/) | Base Image      |
| [Nginx](https://github.com/nfrastack/container-nginx/)  | Nginx Webserver |

Below is the complete list of available options that can be used to customize your installation.

* Variables showing an 'x' under the `Advanced` column can only be set if the containers advanced functionality is enabled.

#### Core Configuration

| Variable                | Description                         | Default                             |
| ----------------------- | ----------------------------------- | ----------------------------------- |
| `ENABLE_PHP_FPM`        | Enable PHP-FPM container mode       | `TRUE`                              |
| `PHPFPM_CONTAINER_MODE` | Container mode for PHP-FPM          | `nginx-php-fpm`                     |
| `PHP_CREATE_SAMPLE_PHP` | Create a sample PHP page on startup | `TRUE`                              |
| `PHP_HIDE_X_POWERED_BY` | Hide X-Powered-By header            | `TRUE`                              |
| `PHP_KITCHENSINK`       | Enable all PHP extensions           | `FALSE`                             |
| `PHP_MEMORY_LIMIT`      | PHP memory limit                    | `128M`                              |
| `PHP_POST_MAX_SIZE`     | Maximum POST size                   | `2G`                                |
| `PHP_TIMEOUT`           | Script execution timeout            | `180`                               |
| `PHP_UPLOAD_MAX_SIZE`   | Maximum upload size                 | `2G`                                |
| `PHP_WEBROOT`           | Webroot directory                   | `/www/html` (or `${NGINX_WEBROOT}`) |

#### PHP Environment

| Variable            | Description              | Default                                                        |
| ------------------- | ------------------------ | -------------------------------------------------------------- |
| `PHPFPM_ENV_TEMP`   | PHP-FPM temp directory   | `/tmp`                                                         |
| `PHPFPM_ENV_TMP`    | PHP-FPM tmp directory    | `/tmp`                                                         |
| `PHPFPM_ENV_TMPDIR` | PHP-FPM tmpdir           | `/tmp`                                                         |
| `PHPFPM_ENV_PATH`   | PHP-FPM PATH environment | `/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin` |

#### PHP Pools

You can define multiple PHP-FPM pools using environment variables. The default pool uses variables prefixed with `PHPFPM_POOL_DEFAULT_`. To add additional pools, use the pattern:

`PHPFPM_POOL_<POOLNAME>_<SETTING>`

For example, to add a pool named `api`:

```env
PHPFPM_POOL_API_LISTEN_TYPE=tcp
PHPFPM_POOL_API_LISTEN_TCP_PORT=9001
PHPFPM_POOL_API_USER=www-data
PHPFPM_POOL_API_GROUP=www-data
```

Each pool will be configured in `/etc/php.../pools.d/<poolname>.conf` inside the container.

If no pool is defined then a default `www` pool will be created with the following default settings

Default pool settings:

| Variable                                      | Description                                     | Default                             |
| --------------------------------------------- | ----------------------------------------------- | ----------------------------------- |
| `PHPFPM_POOL_DEFAULT_LISTEN_UNIX_GROUP`       | Default UNIX group for pool                     | `${NGINX_GROUP}`                    |
| `PHPFPM_POOL_DEFAULT_LISTEN_UNIX_USER`        | Default UNIX user for pool                      | `${NGINX_USER}`                     |
| `PHPFPM_POOL_DEFAULT_USER`                    | Default pool user                               | `${NGINX_USER}`                     |
| `PHPFPM_POOL_DEFAULT_GROUP`                   | Default pool group                              | `${NGINX_GROUP}`                    |
| `PHPFPM_POOL_DEFAULT_CATCH_WORKERS_OUTPUT`    | Catch workers output                            | `true`                              |
| `PHPFPM_POOL_DEFAULT_ENABLE_LOG`              | Enable pool logging                             | `TRUE`                              |
| `PHPFPM_POOL_DEFAULT_PING_PATH`               | Pool ping path                                  | `/ping`                             |
| `PHPFPM_POOL_DEFAULT_DISPLAY_ERRORS`          | Display errors                                  | `TRUE`                              |
| `PHPFPM_POOL_DEFAULT_LISTEN_IP`               | Pool listen IP                                  | `0.0.0.0`                           |
| `PHPFPM_POOL_DEFAULT_LISTEN_TYPE`             | Pool listen type `unix` `tcp` `both` - See note | `unix`                              |
| `PHPFPM_POOL_DEFAULT_LISTEN_PORT`             | Pool listen port                                | `9000`                              |
| `PHPFPM_POOL_DEFAULT_LISTEN_TCP_IP`           | Pool listen TCP IP                              | `0.0.0.0`                           |
| `PHPFPM_POOL_DEFAULT_LISTEN_TCP_IP_ALLOWED`   | Allowed TCP IPs                                 | `127.0.0.1`                         |
| `PHPFPM_POOL_DEFAULT_LISTEN_TCP_PORT`         | Pool listen TCP port                            | `9000`                              |
| `PHPFPM_POOL_DEFAULT_LISTEN_UNIX_SOCKET`      | Pool UNIX socket                                | `/var/lib/php-fpm/run/default.sock` |
| `PHPFPM_POOL_DEFAULT_ENV`                     | Default pool environment variables              | `PATH,TEMP,TMP,TMPDIR`              |
| `PHPFPM_POOL_DEFAULT_LOG_ACCESS_FILE`         | Pool access log file                            | `default-access.log`                |
| `PHPFPM_POOL_DEFAULT_LOG_ACCESS_FORMAT`       | Pool access log format                          | `default`                           |
| `PHPFPM_POOL_DEFAULT_LOG_PATH`                | Pool log path                                   | `/logs/php-fpm/`                    |
| `PHPFPM_POOL_DEFAULT_MAX_CHILDREN`            | Max children                                    | `75`                                |
| `PHPFPM_POOL_DEFAULT_MAX_INPUT_NESTING_LEVEL` | Max input nesting level                         | `256`                               |
| `PHPFPM_POOL_DEFAULT_MAX_INPUT_VARS`          | Max input vars                                  | `10000`                             |
| `PHPFPM_POOL_DEFAULT_MAX_REQUESTS`            | Max requests                                    | `0`                                 |
| `PHPFPM_POOL_DEFAULT_MAX_SPARE_SERVERS`       | Max spare servers                               | `3`                                 |
| `PHPFPM_POOL_DEFAULT_MEMORY_LIMIT`            | Pool memory limit                               | `${PHP_MEMORY_LIMIT}`               |
| `PHPFPM_POOL_DEFAULT_MIN_SPARE_SERVERS`       | Min spare servers                               | `1`                                 |
| `PHPFPM_POOL_DEFAULT_OUTPUT_BUFFER_SIZE`      | Output buffer size                              | `0`                                 |
| `PHPFPM_POOL_DEFAULT_POST_MAX_SIZE`           | Pool POST max size                              | `${PHP_POST_MAX_SIZE}`              |
| `PHPFPM_POOL_DEFAULT_PROCESS_IDLE_TIMEOUT`    | Process idle timeout                            | `10s`                               |
| `PHPFPM_POOL_DEFAULT_PROCESS_MANAGER`         | Process manager                                 | `dynamic`                           |
| `PHPFPM_POOL_DEFAULT_START_SERVERS`           | Start servers                                   | `2`                                 |
| `PHPFPM_POOL_DEFAULT_STATUS_PATH`             | Status path                                     | `/php-fpm_status`                   |
| `PHPFPM_POOL_DEFAULT_TIMEOUT`                 | Pool timeout                                    | `${PHP_TIMEOUT}`                    |
| `PHPFPM_POOL_DEFAULT_UPLOAD_MAX_SIZE`         | Pool upload max size                            | `${PHP_UPLOAD_MAX_SIZE}`            |

#### Listening on both Unix socket and TCP at once

PHP-FPM does not allow multiple `listen` directives in a single pool — each pool owns exactly one endpoint. To accept FastCGI on both a Unix socket and a TCP port simultaneously, set:

```yaml
- PHPFPM_POOL_<NAME>_LISTEN_TYPE=both
```

The image then writes two pool configs:

* Primary pool `[<NAME>]` — listens on the Unix socket (using `PHPFPM_POOL_<NAME>_LISTEN_UNIX_*` variables). This is the pool the image's nginx upstream is wired to.
* Shadow pool `[<NAME>-tcp]` — listens on TCP (using `PHPFPM_POOL_<NAME>_LISTEN_TCP_*` variables). Inherits the same process-manager, log, environment, override, and includes settings as the primary.

#### Logging

| Variable                | Description    | Default             |
| ----------------------- | -------------- | ------------------- |
| `PHPFPM_LOG_ERROR_FILE` | Error log file | `error.log`         |
| `PHPFPM_LOG_ERROR_PATH` | Error log path | `/var/log/php-fpm/` |
| `PHPFPM_LOG_LEVEL`      | Log level      | `notice`            |
| `PHPFPM_LOG_LIMIT`      | Log limit      | `3072`              |

### Modules

#### Enabling / Disabling Specific Modules

Enable extensions by using the PHP extension name ie redis as `PHP_MODULE_ENABLE_REDIS=TRUE`. Core extensions are enabled by default are:

| Parameter                     | Default |
| ----------------------------- | ------- |
| `PHP_MODULE_ENABLE_APCU`      | `TRUE`  |
| `PHP_MODULE_ENABLE_BCMATH`    | `TRUE`  |
| `PHP_MODULE_ENABLE_BZ2`       | `TRUE`  |
| `PHP_MODULE_ENABLE_CTYPE`     | `TRUE`  |
| `PHP_MODULE_ENABLE_CURL`      | `TRUE`  |
| `PHP_MODULE_ENABLE_DOM`       | `TRUE`  |
| `PHP_MODULE_ENABLE_EXIF`      | `TRUE`  |
| `PHP_MODULE_ENABLE_FILEINFO`  | `TRUE`  |
| `PHP_MODULE_ENABLE_GD`        | `TRUE`  |
| `PHP_MODULE_ENABLE_ICONV`     | `TRUE`  |
| `PHP_MODULE_ENABLE_IMAP`      | `TRUE`  |
| `PHP_MODULE_ENABLE_INTL`      | `TRUE`  |
| `PHP_MODULE_ENABLE_JSON`      | `TRUE`  |
| `PHP_MODULE_ENABLE_MBSTRING`  | `TRUE`  |
| `PHP_MODULE_ENABLE_MYSQLI`    | `TRUE`  |
| `PHP_MODULE_ENABLE_MYSQLND`   | `TRUE`  |
| `PHP_MODULE_ENABLE_OPCACHE`   | `TRUE`  |
| `PHP_MODULE_ENABLE_OPENSSL`   | `TRUE`  |
| `PHP_MODULE_ENABLE_PDO`       | `TRUE`  |
| `PHP_MODULE_ENABLE_PDO_MYSQL` | `TRUE`  |
| `PHP_MODULE_ENABLE_PGSQL`     | `TRUE`  |
| `PHP_MODULE_ENABLE_PHAR`      | `TRUE`  |
| `PHP_MODULE_ENABLE_SESSION`   | `TRUE`  |
| `PHP_MODULE_ENABLE_SIMPLEXML` | `TRUE`  |
| `PHP_MODULE_ENABLE_TOKENIZER` | `TRUE`  |
| `PHP_MODULE_ENABLE_XML`       | `TRUE`  |
| `PHP_MODULE_ENABLE_XMLREADER` | `TRUE`  |
| `PHP_MODULE_ENABLE_XMLWRITER` | `TRUE`  |

To enable all modules in image use `PHP_KITCHENSINK=TRUE`. Head inside the image and see what extensions are available by typing `php-ext list all`

###### APCu Options

| Variable                  | Description             | Default |
| ------------------------- | ----------------------- | ------- |
| `PHP_MODULE_APC_SHM_SIZE` | APCu shared memory size | `128M`  |
| `PHP_MODULE_APC_TTL`      | APCu time to live       | `7200`  |

###### OPCache Options

| Variable                                     | Description                     | Default     |
| -------------------------------------------- | ------------------------------- | ----------- |
| `PHP_MODULE_OPCACHE_MEM_SIZE`                | Opcache memory size             | `128`       |
| `PHP_MODULE_OPCACHE_INTERNED_STRINGS_BUFFER` | Opcache interned strings buffer | `8`         |
| `PHP_MODULE_OPCACHE_JIT_BUFFER_SIZE`         | Opcache JIT buffer size         | `50M`       |
| `PHP_MODULE_OPCACHE_JIT_MODE`                | Opcache JIT mode                | `1255`      |
| `PHP_MODULE_OPCACHE_MAX_ACCELERATED_FILES`   | Opcache max accelerated files   | `10000`     |
| `PHP_MODULE_OPCACHE_MAX_FILE_SIZE`           | Opcache max file size           | `0`         |
| `PHP_MODULE_OPCACHE_MAX_WASTED_PERCENTAGE`   | Opcache max wasted percentage   | `5`         |
| `PHP_MODULE_OPCACHE_OPTIMIZATION_LEVEL`      | Opcache optimization level      | `0x7FFFBFF` |
| `PHP_MODULE_OPCACHE_REVALIDATE_FREQ`         | Opcache revalidate frequency    | `2`         |
| `PHP_MODULE_OPCACHE_SAVE_COMMENTS`           | Opcache save comments           | `1`         |
| `PHP_MODULE_OPCACHE_VALIDATE_TIMESTAMPS`     | Opcache validate timestamps     | `1`         |

###### XDebug Options

To enable XDebug set `PHP_MODULE_ENABLE_XDEBUG=TRUE`. Visit the [PHP XDebug Documentation](https://xdebug.org/docs/all_settings#remote_connect_back) to understand what these options mean.
If you debug a PHP project in PHPStorm, you need to set server name using `PHP_IDE_CONFIG` to the same value as set in PHPStorm. Usual value is localhost, i.e. `PHP_IDE_CONFIG="serverName=localhost"`.

For Xdebug 2 (php <= 7.1) you should set:
| Parameter                                   | Description                                | Default         |
| ------------------------------------------- | ------------------------------------------ | --------------- |
| `PHP_MODULE_XDEBUG_PROFILER_PATH`           | Xdebug profiler path                       | `/logs/xdebug/` |
| `PHP_MODULE_XDEBUG_PROFILER_ENABLE`         | Enable Profiler                            | `0`             |
| `PHP_MODULE_XDEBUG_PROFILER_ENABLE_TRIGGER` | Enable Profiler Trigger                    | `0`             |
| `PHP_MODULE_XDEBUG_REMOTE_AUTOSTART`        | Enable Autostarting as opposed to GET/POST | `1`             |
| `PHP_MODULE_XDEBUG_REMOTE_CONNECT_BACK`     | Enbable Connection Back                    | `0`             |
| `PHP_MODULE_XDEBUG_REMOTE_ENABLE`           | Enable Remote Debugging                    | `1`             |
| `PHP_MODULE_XDEBUG_REMOTE_HANDLER`          | XDebug Remote Handler                      | `dbgp`          |
| `PHP_MODULE_XDEBUG_REMOTE_HOST`             | Set this to your IP Address                | `127.0.0.1`     |
| `PHP_MODULE_XDEBUG_REMOTE_PORT`             | XDebug Remote Port                         | `9090`          |

* * *

For Xdebug 3 (php >= 7.2) you should set:
| Parameter                                | Description                                                          | Default         |
| ---------------------------------------- | -------------------------------------------------------------------- | --------------- |
| `PHP_MODULE_XDEBUG_PROFILER_PATH`        | Xdebug profiler path                                                 | `/logs/xdebug/` |
| `PHP_MODULE_XDEBUG_MODE`                 | This setting controls which Xdebug features are enabled.             | `develop`       |
| `PHP_MODULE_XDEBUG_START_WITH_REQUEST`   | Enable Autostarting as opposed to GET/POST                           | `default`       |
| `PHP_MODULE_XDEBUG_DISCOVER_CLIENT_HOST` | Xdebug will try to connect to the client that made the HTTP request. | `1`             |
| `PHP_MODULE_XDEBUG_CLIENT_HOST`          | Set this to your IP Address                                          | `127.0.0.1`     |
| `PHP_MODULE_XDEBUG_CLIENT_PORT`          | XDebug Remote Port                                                   | `9003`          |

###### Including operator-supplied config files

| Parameter                     | Description                                                                       | Default |
| ----------------------------- | --------------------------------------------------------------------------------- | ------- |
| `PHPFPM_POOL_<NAME>_INCLUDES` | Comma-separated paths appended as `include = <path>` lines to the pool's `.conf`. |         |

#### Routing an nginx site to a specific PHP pool

When configuring a site, the image picks which PHP pool to wire it to via this resolution chain:

1. `NGINX_SITE_<SITENAME>_PHP_UPSTREAM` - per-site override (highest priority)
2. `NGINX_PHP_UPSTREAM` - global default for all sites
3. `www` - hardcoded fallback if neither is set

The value is the pool name (e.g. `www`, `api` (or `www-tcp` to target the shadow generated by `LISTEN_TYPE=both`).

| Parameter                            | Description                                                  | Default |
| ------------------------------------ | ------------------------------------------------------------ | ------- |
| `NGINX_SITE_<SITENAME>_PHP_UPSTREAM` | Pool name this site's nginx config should `fastcgi_pass` to. | `www`   |
| `NGINX_PHP_UPSTREAM`                 | Default pool name used when no per-site override is set.     | `www`   |

## Users and Groups

| Type  | Name       | ID     |
| ----- | ---------- | ------ |
| User  | `php`      | `9000` |
| Group | `php`      | `9000` |
| Group | `www-data` | `82`   |

### Networking

| Port   | Protocol | Description |
| ------ | -------- | ----------- |
| `9000` | tcp      | PHP-FPM     |

* * *

## Maintenance

### Shell Access

For debugging and maintenance, `bash` and `sh` are available in the container.

## Support & Maintenance

* For community help, tips, and community discussions, visit the [Discussions board](/discussions).
* For personalized support or a support agreement, see [Nfrastack Support](https://nfrastack.com/).
* To report bugs, submit a [Bug Report](issues/new). Usage questions will be closed as not-a-bug.
* Feature requests are welcome, but not guaranteed. For prioritized development, consider a support agreement.
* Updates are best-effort, with priority given to active production use and support agreements.

## License

This project is licensed under the MIT License - see the [LICENSE](LICENSE) file for details.


================================================
FILE: examples/.gitignore
================================================
!compose.yml


================================================
FILE: examples/.gitkeep
================================================


================================================
FILE: examples/compose.yml
================================================
services:
  npf-app:
    image: docker.io/nfrastack/nginx-php-fpm/8.5-alpine
    container_name: npf-app
    labels:
      - traefik.enable=true
      - traefik.http.routers.npf.rule=Host(`npf.example.com`)
      - traefik.http.services.npf.loadbalancer.server.port=80
    volumes:
      - ./data/:/www/html
      - ./logs/:/logs
    environment:
      - TIMEZONE=America/Vancouver
    networks:
      - services
      - proxy
    restart: always

networks:
  proxy:
    external: true
  services:
    external: true



================================================
FILE: rootfs/container/data/nginx/templates/server/http-fastcgi_hide_header_xpowered.template
================================================
# SPDX-FileCopyrightText: © 2026 Nfrastack <code@nfrastack.com>
#
# SPDX-License-Identifier: MIT

fastcgi_hide_header X-Powered-By;


================================================
FILE: rootfs/container/data/nginx/templates/site/location-php-block.template
================================================
# SPDX-FileCopyrightText: © 2026 Nfrastack <code@nfrastack.com>
#
# SPDX-License-Identifier: MIT

location ~ [^/]\.php(/|$) {
    try_files $fastcgi_script_name =404; # Fail if script missing
    {{php_upstream}};
    fastcgi_split_path_info ^(.+\.php)(/.+)$;
    fastcgi_index {{php_index_file}};
    {{fastcgi_params}};
}

================================================
FILE: rootfs/container/data/php-fpm/cli/php.ini
================================================
; SPDX-FileCopyrightText: © 2026 Nfrastack <code@nfrastack.com>
;
; SPDX-License-Identifier: MIT

[PHP]
engine = On
allow_url_fopen = On
allow_url_include = Off
asp_tags = Off
auto_append_file =
auto_globals_jit = On
auto_prepend_file =
cgi.discard_path = 1
cgi.fix_pathinfo=0
default_charset = "UTF-8"
default_mimetype = "text/html"
default_socket_timeout = 180
disable_classes =
disable_functions =
display_errors = Off
display_startup_errors = Off
doc_root =
enable_dl = Off
error_reporting = E_ALL & ~E_DEPRECATED & ~E_STRICT
expose_php = On
file_uploads = On
html_errors = On
ignore_repeated_errors = Off
ignore_repeated_source = Off
implicit_flush = Off
log_errors = On
log_errors_max_len = 0
max_execution_time = 30
max_file_uploads = 20
max_input_time = 180
memory_limit = 128M
output_buffering = 4096
post_max_size = 2G
precision = 14
register_argc_argv = Off
report_memleaks = On
request_order = "GP"
serialize_precision = 17
short_open_tag = Off
track_errors = Off
unserialize_callback_func =
upload_max_filesize = 2G
user_dir =
variables_order = "GPCS"
zend.enable_gc = On
zlib.output_compression = Off

[CLI Server]
cli_server.color = On

[Date]
date.timezone = UTC

[filter]

[iconv]

[intl]

[sqlite3]

[Pcre]

[Pdo]

[Pdo_mysql]
pdo_mysql.cache_size = 2000
pdo_mysql.default_socket=

[Phar]

[mail function]
SMTP = localhost
smtp_port = 25
;sendmail_path =
mail.add_x_header = On

[SQL]
sql.safe_mode = Off

[ODBC]
odbc.allow_persistent = On
odbc.check_persistent = On
odbc.max_persistent = -1
odbc.max_links = -1
odbc.defaultlrl = 4096
odbc.defaultbinmode = 1


[Interbase]
ibase.allow_persistent = 1
ibase.max_persistent = -1
ibase.max_links = -1
ibase.timestampformat = "%Y-%m-%d %H:%M:%S"
ibase.dateformat = "%Y-%m-%d"
ibase.timeformat = "%H:%M:%S"

[MySQL]
mysql.allow_local_infile = On
mysql.allow_persistent = On
mysql.cache_size = 2000
mysql.max_persistent = -1
mysql.max_links = -1
mysql.default_port =
mysql.default_socket =
mysql.default_host =
mysql.default_user =
mysql.default_password =
mysql.connect_timeout = 60
mysql.trace_mode = Off

[MySQLi]
mysqli.max_persistent = -1
mysqli.allow_persistent = On
mysqli.max_links = -1
mysqli.cache_size = 2000
mysqli.default_port = 3306
mysqli.default_socket =
mysqli.default_host =
mysqli.default_user =
mysqli.default_pw =
mysqli.reconnect = Off

[mysqlnd]
mysqlnd.collect_statistics = On
mysqlnd.collect_memory_statistics = Off

[OCI8]

[PostgreSQL]
pgsql.allow_persistent = On
pgsql.auto_reset_persistent = Off
pgsql.max_persistent = -1
pgsql.max_links = -1
pgsql.ignore_notice = 0
pgsql.log_notice = 0

[Sybase-CT]
sybct.allow_persistent = On
sybct.max_persistent = -1
sybct.max_links = -1
sybct.min_server_severity = 10
sybct.min_client_severity = 10

[bcmath]
bcmath.scale = 0

[browscap]

[Session]
session.save_handler = files
session.use_strict_mode = 0
session.use_cookies = 1
session.use_only_cookies = 1
session.name = PHPSESSID
session.auto_start = 0
session.cookie_lifetime = 0
session.cookie_path = /
session.cookie_domain =
session.cookie_httponly =
session.serialize_handler = php
session.gc_probability = 1
session.gc_divisor = 1000
session.gc_maxlifetime = 1440
session.referer_check =
session.cache_limiter = nocache
session.cache_expire = 180
session.use_trans_sid = 0
session.hash_function = 0
session.hash_bits_per_character = 5
url_rewriter.tags = "a=href,area=href,frame=src,input=src,form=fakeentry"

[MSSQL]
mssql.allow_persistent = On
mssql.max_persistent = -1
mssql.max_links = -1
mssql.min_error_severity = 10
mssql.min_message_severity = 10
mssql.compatibility_mode = Off
mssql.secure_connection = Off

[Assertion]

[COM]

[mbstring]

[gd]

[exif]

[Tidy]
tidy.clean_output = Off

[soap]
soap.wsdl_cache_enabled=1
soap.wsdl_cache_dir="/tmp"
soap.wsdl_cache_ttl=86400
soap.wsdl_cache_limit = 5

[sysvshm]

[ldap]
ldap.max_links = -1

[mcrypt]

[dba]

[opcache]

[curl]

[openssl]



================================================
FILE: rootfs/container/data/php-fpm/conf.available/apcu.ini
================================================
; SPDX-FileCopyrightText: © 2026 Nfrastack <code@nfrastack.com>
;
; SPDX-License-Identifier: MIT

extension=apcu.so
apc.enabled=1
apc.shm_size=128M
apc.ttl=7200
apc.enable_cli=1
;priority=20


================================================
FILE: rootfs/container/data/php-fpm/conf.available/opcache.ini
================================================
; SPDX-FileCopyrightText: © 2026 Nfrastack <code@nfrastack.com>
;
; SPDX-License-Identifier: MIT

zend_extension=opcache.so
opcache.enable=1
opcache.enable_cli=1
opcache.memory_consumption=128
opcache.interned_strings_buffer=8
opcache.max_accelerated_files=10000
opcache.max_wasted_percentage=5
opcache.validate_timestamps=1
opcache.revalidate_freq=2
opcache.save_comments=1
opcache.optimization_level=0x7FFFBFFF
opcache.max_file_size=0
opcache.jit_buffer_size=0
opcache.jit=1255
;priority=10

================================================
FILE: rootfs/container/data/php-fpm/fpm/default.logformat
================================================
; SPDX-FileCopyrightText: © 2026 Nfrastack <code@nfrastack.com>
;
; SPDX-License-Identifier: MIT

access.format='%{%Y-%m-%dT%H:%M:%S%z}T %{HTTP_X_FORWARDED_FOR}e %R %u %s %m "%{REQUEST_URI}e" %{HTTP_X_REQUEST_ID}e %{SERVER_PROTOCOL}e %l "%{HTTP_REFERER}e" "%{HTTP_USER_AGENT}e" %M %C %d'

================================================
FILE: rootfs/container/data/php-fpm/fpm/json.logformat
================================================
; SPDX-FileCopyrightText: © 2026 Nfrastack <code@nfrastack.com>
;
; SPDX-License-Identifier: MIT

access.format='{"time":"%{%Y-%m-%dT%H:%M:%S%z}T","remote_addr":"%{HTTP_X_FORWARDED_FOR}","client_ip":"%R","remote_user":"%u","status":"%s","request_method":"%m","request_uri":"%{REQUEST_URI}e","request_id":"%{HTTP_X_REQUEST_ID}e","server_protocol":"%{SERVER_PROTOCOL}e","body_bytes_sent":"%l","http_referrer":"%{HTTP_REFERER}e","http_user_agent":"%{HTTP_USER_AGENT}e","memory_usage":"%M","cpu_usage":"%C","duration":"%d"}'

================================================
FILE: rootfs/container/data/php-fpm/fpm/php.ini
================================================
; SPDX-FileCopyrightText: © 2026 Nfrastack <code@nfrastack.com>
;
; SPDX-License-Identifier: MIT

[PHP]
engine = On
allow_url_fopen = On
allow_url_include = Off
asp_tags = Off
auto_append_file =
auto_globals_jit = On
auto_prepend_file =
cgi.discard_path = 1
cgi.fix_pathinfo=0
default_charset = "UTF-8"
default_mimetype = "text/html"
default_socket_timeout = 180
disable_classes =
disable_functions =
display_errors = Off
display_startup_errors = Off
doc_root =
enable_dl = Off
error_reporting = E_ALL & ~E_DEPRECATED & ~E_STRICT
expose_php = On
file_uploads = On
html_errors = On
ignore_repeated_errors = Off
ignore_repeated_source = Off
implicit_flush = Off
log_errors = On
log_errors_max_len = 1024
max_execution_time = 30
max_file_uploads = 20
max_input_time = 180
memory_limit = 128M
output_buffering = 4096
post_max_size = 2G
precision = 14
register_argc_argv = Off
report_memleaks = On
request_order = "GP"
serialize_precision = 17
short_open_tag = Off
track_errors = Off
unserialize_callback_func =
upload_max_filesize = 2G
user_dir =
variables_order = "GPCS"
zend.enable_gc = On
zlib.output_compression = Off

[CLI Server]
cli_server.color = On

[Date]
date.timezone = UTC

[filter]

[iconv]

[intl]

[sqlite3]

[Pcre]

[Pdo]

[Pdo_mysql]
pdo_mysql.cache_size = 2000
pdo_mysql.default_socket=

[Phar]

[mail function]
SMTP = localhost
smtp_port = 25

;sendmail_path =

mail.add_x_header = On

[SQL]
sql.safe_mode = Off

[ODBC]
odbc.allow_persistent = On
odbc.check_persistent = On
odbc.max_persistent = -1
odbc.max_links = -1
odbc.defaultlrl = 4096
odbc.defaultbinmode = 1


[Interbase]
ibase.allow_persistent = 1
ibase.max_persistent = -1
ibase.max_links = -1
ibase.timestampformat = "%Y-%m-%d %H:%M:%S"
ibase.dateformat = "%Y-%m-%d"
ibase.timeformat = "%H:%M:%S"

[MySQL]
mysql.allow_local_infile = On
mysql.allow_persistent = On
mysql.cache_size = 2000
mysql.max_persistent = -1
mysql.max_links = -1
mysql.default_port =
mysql.default_socket =
mysql.default_host =
mysql.default_user =
mysql.default_password =
mysql.connect_timeout = 60
mysql.trace_mode = Off

[MySQLi]
mysqli.max_persistent = -1
mysqli.allow_persistent = On
mysqli.max_links = -1
mysqli.cache_size = 2000
mysqli.default_port = 3306
mysqli.default_socket =
mysqli.default_host =
mysqli.default_user =
mysqli.default_pw =
mysqli.reconnect = Off

[mysqlnd]
mysqlnd.collect_statistics = On
mysqlnd.collect_memory_statistics = Off

[OCI8]

[PostgreSQL]
pgsql.allow_persistent = On
pgsql.auto_reset_persistent = Off
pgsql.max_persistent = -1
pgsql.max_links = -1
pgsql.ignore_notice = 0
pgsql.log_notice = 0

[Sybase-CT]
sybct.allow_persistent = On
sybct.max_persistent = -1
sybct.max_links = -1
sybct.min_server_severity = 10
sybct.min_client_severity = 10

[bcmath]
bcmath.scale = 0

[browscap]

[Session]
session.save_handler = files
session.use_strict_mode = 0
session.use_cookies = 1
session.use_only_cookies = 1
session.name = PHPSESSID
session.auto_start = 0
session.cookie_lifetime = 0
session.cookie_path = /
session.cookie_domain =
session.cookie_httponly =
session.serialize_handler = php
session.gc_probability = 1
session.gc_divisor = 1000
session.gc_maxlifetime = 1440
session.referer_check =
session.cache_limiter = nocache
session.cache_expire = 180
session.use_trans_sid = 0
session.hash_function = 0
session.hash_bits_per_character = 5
url_rewriter.tags = "a=href,area=href,frame=src,input=src,form=fakeentry"

[MSSQL]
mssql.allow_persistent = On
mssql.max_persistent = -1
mssql.max_links = -1
mssql.min_error_severity = 10
mssql.min_message_severity = 10
mssql.compatibility_mode = Off
mssql.secure_connection = Off

[Assertion]

[COM]

[mbstring]

[gd]

[exif]

[Tidy]
tidy.clean_output = Off

[soap]
soap.wsdl_cache_enabled=1
soap.wsdl_cache_dir="/tmp"
soap.wsdl_cache_ttl=86400
soap.wsdl_cache_limit = 5

[sysvshm]

[ldap]
ldap.max_links = -1

[mcrypt]

[dba]

[opcache]

[curl]

[openssl]



================================================
FILE: rootfs/container/data/php-fpm/opcache/opcache-settings.php
================================================
<?php
    $configuration = opcache_get_configuration();
    echo "opcache.enable: " ; print ($configuration['directives']['opcache.enable']); echo "\n" ;
    echo "opcache.enable_cli: " ; print ($configuration['directives']['opcache.enable_cli']); echo "\n" ;
    echo "opcache.use_cwd: " ; print ($configuration['directives']['opcache.use_cwd']); echo "\n" ;
    echo "opcache.validate_timestamps: " ; print ($configuration['directives']['opcache.validate_timestamps']); echo "\n" ;
    echo "opcache.validate_permission: " ; print ($configuration['directives']['opcache.validate_permission']); echo "\n" ;
    echo "opcache.validate_root: " ; print ($configuration['directives']['opcache.validate_root']); echo "\n" ;
    echo "opcache.dups_fix: " ; print ($configuration['directives']['opcache.dups_fix']); echo "\n" ;
    echo "opcache.revalidate_path: " ; print ($configuration['directives']['opcache.revalidate_path']); echo "\n" ;
    echo "opcache.log_verbosity_level: " ; print ($configuration['directives']['opcache.log_verbosity_level']); echo "\n" ;
    echo "opcache.memory_consumption: " ; print ($configuration['directives']['opcache.memory_consumption']); echo "\n" ;
    echo "opcache.interned_strings_buffer: " ; print ($configuration['directives']['opcache.interned_strings_buffer']); echo "\n" ;
    echo "opcache.max_accelerated_files: " ; print ($configuration['directives']['opcache.max_accelerated_files']); echo "\n" ;
    echo "opcache.max_wasted_percentage: " ; print ($configuration['directives']['opcache.max_wasted_percentage']); echo "\n" ;
    echo "opcache.consistency_checks: " ; print ($configuration['directives']['opcache.consistency_checks']); echo "\n" ;
    echo "opcache.force_restart_timeout: " ; print ($configuration['directives']['opcache.force_restart_timeout']); echo "\n" ;
    echo "opcache.revalidate_freq: " ; print ($configuration['directives']['opcache.revalidate_freq']); echo "\n" ;
    echo "opcache.preferred_memory_model: " ; print ($configuration['directives']['opcache.preferred_memory_model']); echo "\n" ;
    echo "opcache.blacklist_filename: " ; print ($configuration['directives']['opcache.blacklist_filename']); echo "\n" ;
    echo "opcache.max_file_size: " ; print ($configuration['directives']['opcache.max_file_size']); echo "\n" ;
    echo "opcache.error_log: " ; print ($configuration['directives']['opcache.error_log']); echo "\n" ;
    echo "opcache.protect_memory: " ; print ($configuration['directives']['opcache.protect_memory']); echo "\n" ;
    echo "opcache.save_comments: " ; print ($configuration['directives']['opcache.save_comments']); echo "\n" ;
    echo "opcache.record_warnings: " ; print ($configuration['directives']['opcache.record_warnings']); echo "\n" ;
    echo "opcache.enable_file_override: " ; print ($configuration['directives']['opcache.enable_file_override']); echo "\n" ;
    echo "opcache.optimization_level: " ; print ($configuration['directives']['opcache.optimization_level']); echo "\n" ;
    echo "opcache.lockfile_path: " ; print ($configuration['directives']['opcache.lockfile_path']); echo "\n" ;
    echo "opcache.file_cache: " ; print ($configuration['directives']['opcache.file_cache']); echo "\n" ;
    echo "opcache.file_cache_only: " ; print ($configuration['directives']['opcache.file_cache_only']); echo "\n" ;
    echo "opcache.file_cache_consistency_checks: " ; print ($configuration['directives']['opcache.file_cache_consistency_checks']); echo "\n" ;
    echo "opcache.file_update_protection: " ; print ($configuration['directives']['opcache.file_update_protection']); echo "\n" ;
    echo "opcache.opt_debug_level: " ; print ($configuration['directives']['opcache.opt_debug_level']); echo "\n" ;
    echo "opcache.restrict_api: " ; print ($configuration['directives']['opcache.restrict_api']); echo "\n" ;
    echo "opcache.huge_code_pages: " ; print ($configuration['directives']['opcache.huge_code_pages']); echo "\n" ;
    echo "opcache.preload: " ; print ($configuration['directives']['opcache.preload']); echo "\n" ;
    echo "opcache.preload_user: " ; print ($configuration['directives']['opcache.preload_user']); echo "\n" ;
    echo "opcache.jit: " ; print ($configuration['directives']['opcache.jit']); echo "\n" ;
    echo "opcache.jit_buffer_size: " ; print ($configuration['directives']['opcache.jit_buffer_size']); echo "\n" ;
    echo "opcache.jit_debug: " ; print ($configuration['directives']['opcache.jit_debug']); echo "\n" ;
    echo "opcache.jit_bisect_limit: " ; print ($configuration['directives']['opcache.jit_bisect_limit']); echo "\n" ;
    echo "opcache.jit_blacklist_root_trace: " ; print ($configuration['directives']['opcache.jit_blacklist_root_trace']); echo "\n" ;
    echo "opcache.jit_blacklist_side_trace: " ; print ($configuration['directives']['opcache.jit_blacklist_side_trace']); echo "\n" ;
    echo "opcache.jit_hot_func: " ; print ($configuration['directives']['opcache.jit_hot_func']); echo "\n" ;
    echo "opcache.jit_hot_loop: " ; print ($configuration['directives']['opcache.jit_hot_loop']); echo "\n" ;
    echo "opcache.jit_hot_return: " ; print ($configuration['directives']['opcache.jit_hot_return']); echo "\n" ;
    echo "opcache.jit_hot_side_exit: " ; print ($configuration['directives']['opcache.jit_hot_side_exit']); echo "\n" ;
    echo "opcache.jit_max_exit_counters: " ; print ($configuration['directives']['opcache.jit_max_exit_counters']); echo "\n" ;
    echo "opcache.jit_max_loop_unrolls: " ; print ($configuration['directives']['opcache.jit_max_loop_unrolls']); echo "\n" ;
    echo "opcache.jit_max_polymorphic_calls: " ; print ($configuration['directives']['opcache.jit_max_polymorphic_calls']); echo "\n" ;
    echo "opcache.jit_max_recursive_calls: " ; print ($configuration['directives']['opcache.jit_max_recursive_calls']); echo "\n" ;
    echo "opcache.jit_max_recursive_returns: " ; print ($configuration['directives']['opcache.jit_max_recursive_returns']); echo "\n" ;
    echo "opcache.jit_max_root_traces: " ; print ($configuration['directives']['opcache.jit_max_root_traces']); echo "\n" ;
    echo "opcache.jit_max_side_traces: " ; print ($configuration['directives']['opcache.jit_max_side_traces']); echo "\n" ;
    echo "opcache.jit_prof_threshold: " ; print ($configuration['directives']['opcache.jit_prof_threshold']); echo "\n" ;
?>

================================================
FILE: rootfs/container/data/php-fpm/opcache/opcache-status.php
================================================
<?php
  $status = opcache_get_status(false);
  echo json_encode($status);
  echo "\n";
?>

================================================
FILE: rootfs/container/defaults/20-php-fpm
================================================
# SPDX-FileCopyrightText: © 2026 Nfrastack <code@nfrastack.com>
#
# SPDX-License-Identifier: MIT

ENABLE_PHP_FPM=${ENABLE_PHP_FPM:-"TRUE"}
PHPFPM_CONTAINER_MODE=${PHPFPM_CONTAINER_MODE:-"nginx-php-fpm"}
PHP_VERSION="$(php -v 2>/dev/null | grep "^PHP " | head -n 1 | awk '{print $2}')"
PHP_BASE="${PHP_VERSION%.*}"

PHP_ENABLE_CREATE_SAMPLE_PHP=${PHP_ENABLE_CREATE_SAMPLE_PHP:-"TRUE"}
PHP_HIDE_X_POWERED_BY=${PHP_HIDE_X_POWERED_BY:-"TRUE"}
PHP_KITCHENSINK=${PHP_KITCHENSINK:-"FALSE"}
PHP_MEMORY_LIMIT=${PHP_MEMORY_LIMIT:-"128M"}

PHP_MODULE_APC_SHM_SIZE=${PHP_MODULE_APC_SHM_SIZE:-"128M"}
PHP_MODULE_APC_TTL=${PHP_MODULE_APC_TTL:-"7200"}
PHP_MODULE_OPCACHE_INTERNED_STRINGS_BUFFER=${PHP_MODULE_OPCACHE_INTERNED_STRINGS_BUFFER:-"8"}
PHP_MODULE_OPCACHE_JIT_BUFFER_SIZE=${PHP_MODULE_OPCACHE_JIT_BUFFER_SIZE:-"50M"}
PHP_MODULE_OPCACHE_JIT_MODE=${PHP_MODULE_OPCACHE_JIT_MODE:-"1255"}
PHP_MODULE_OPCACHE_MAX_ACCELERATED_FILES=${PHP_MODULE_OPCACHE_MAX_ACCELERATED_FILES:-"10000"}
PHP_MODULE_OPCACHE_MAX_FILE_SIZE=${PHP_MODULE_OPCACHE_MAX_FILE_SIZE:-"0"}
PHP_MODULE_OPCACHE_MAX_WASTED_PERCENTAGE=${PHP_MODULE_OPCACHE_MAX_WASTED_PERCENTAGE:-"5"}
PHP_MODULE_OPCACHE_MEM_SIZE=${PHP_MODULE_OPCACHE_MEM_SIZE:-"128"}
PHP_MODULE_OPCACHE_OPTIMIZATION_LEVEL=${PHP_MODULE_OPCACHE_OPTIMIZATION_LEVEL:-"0x7FFFBFF"}
PHP_MODULE_OPCACHE_REVALIDATE_FREQ=${PHP_MODULE_OPCACHE_REVALIDATE_FREQ:-"2"}
PHP_MODULE_OPCACHE_SAVE_COMMENTS=${PHP_MODULE_OPCACHE_SAVE_COMMENTS:-"1"}
PHP_MODULE_OPCACHE_VALIDATE_TIMESTAMPS=${PHP_MODULE_OPCACHE_VALIDATE_TIMESTAMPS:-"1"}

#Xdebug 2
PHP_MODULE_XDEBUG_PROFILER_PATH=${PHP_MODULE_XDEBUG_PROFILER_PATH:-"/logs/xdebug/"}
PHP_MODULE_XDEBUG_PROFILER_ENABLE=${PHP_MODULE_XDEBUG_PROFILER_ENABLE:-"0"}
PHP_MODULE_XDEBUG_PROFILER_ENABLE_TRIGGER=${PHP_MODULE_XDEBUG_PROFILER_ENABLE_TRIGGER:-"0"}
PHP_MODULE_XDEBUG_REMOTE_AUTOSTART=${PHP_MODULE_XDEBUG_REMOTE_AUTOSTART:-"1"}
PHP_MODULE_XDEBUG_REMOTE_CONNECT_BACK=${PHP_MODULE_XDEBUG_REMOTE_CONNECT_BACK:-"0"}
PHP_MODULE_XDEBUG_REMOTE_ENABLE=${PHP_MODULE_XDEBUG_REMOTE_ENABLE:-"1"}
PHP_MODULE_XDEBUG_REMOTE_HANDLER=${PHP_MODULE_XDEBUG_REMOTE_HANDLER:-"dbgp"}
PHP_MODULE_XDEBUG_REMOTE_HOST=${PHP_MODULE_XDEBUG_REMOTE_HOST:-"127.0.0.1"}
PHP_MODULE_XDEBUG_REMOTE_PORT=${PHP_MODULE_XDEBUG_REMOTE_PORT:-"9090"}

#Xdebug 3
PHP_MODULE_XDEBUG_MODE=${PHP_MODULE_XDEBUG_MODE:-"develop"}
PHP_MODULE_XDEBUG_START_WITH_REQUEST=${PHP_MODULE_XDEBUG_START_WITH_REQUEST:-"default"}
PHP_MODULE_XDEBUG_DISCOVER_CLIENT_HOST=${PHP_MODULE_XDEBUG_DISCOVER_CLIENT_HOST:-"default"}
PHP_MODULE_XDEBUG_CLIENT_HOST=${PHP_MODULE_XDEBUG_CLIENT_HOST:-"127.0.0.1"}
PHP_MODULE_XDEBUG_CLIENT_PORT=${PHP_MODULE_XDEBUG_CLIENT_PORT:-"9003"}

if [ "${PHP_BASE:0:1}" != "8" ] ; then
    PHP_MODULE_ENABLE_JSON=TRUE
fi

if var_true "${PHP_MODULE_ENABLE_MEMCACHED}" || var_true "${PHP_MODULE_ENABLE_REDIS}"; then
    PHP_MODULE_ENABLE_IGBINARY=TRUE
    PHP_MODULE_ENABLE_MSGPACK=TRUE
fi

PHP_POST_MAX_SIZE=${PHP_POST_MAX_SIZE:-"2G"}
PHP_TIMEOUT=${PHP_TIMEOUT:-"180"}
PHP_UPLOAD_MAX_SIZE=${PHP_UPLOAD_MAX_SIZE:-"2G"}

if [ -f "/usr/sbin/unitd" ] ; then
    PHP_WEBROOT=${PHP_WEBROOT:-"${UNIT_WEBROOT}"}
    PHPFPM_POOL_DEFAULT_USER=${PHPFPM_POOL_DEFAULT_USER:-"${UNIT_USER}"}
    PHPFPM_POOL_DEFAULT_GROUP=${PHPFPM_POOL_DEFAULT_GROUP:-"${UNIT_GROUP}"}
    PHPFPM_POOL_DEFAULT_LISTEN_UNIX_GROUP=${PHPFPM_POOL_DEFAULT_LISTEN_UNIX_GROUP:-"${PHPFPM_GROUP}"}
    PHPFPM_POOL_DEFAULT_LISTEN_UNIX_USER=${PHPFPM_POOL_DEFAULT_LISTEN_UNIX_USER:-"${PHPFPM_USER}"}
fi

if [ -f "/usr/sbin/nginx" ] ; then
    PHP_WEBROOT=${PHP_WEBROOT:-"${NGINX_WEBROOT}"}
    PHPFPM_USER=${PHPFPM_USER:-"php"}
    PHPFPM_GROUP=${PHPFPM_GROUP:-"www-data"}
    PHPFPM_POOL_DEFAULT_LISTEN_UNIX_GROUP=${PHPFPM_POOL_DEFAULT_LISTEN_UNIX_GROUP:-"${PHPFPM_GROUP}"}
    PHPFPM_POOL_DEFAULT_LISTEN_UNIX_USER=${PHPFPM_POOL_DEFAULT_LISTEN_UNIX_USER:-"${PHPFPM_USER}"}
    #PHPFPM_USER=${PHPFPM_USER:-"${NGINX_USER}"}
    #PHPFPM_GROUP=${PHPFPM_GROUP:-"${NGINX_GROUP}"}
fi

PHPFPM_ENV_TEMP=${PHPFPM_ENV_TEMP:-"/tmp"}
PHPFPM_ENV_TMP=${PHPFPM_ENV_TMP:-"/tmp"}
PHPFPM_ENV_TMPDIR=${PHPFPM_ENV_TMPDIR:-"/tmp"}
PHPFPM_ENV_PATH=${PHPFPM_ENV_PATH:-"/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin"}
PHPFPM_LOG_ERROR_FILE=${PHPFPM_LOG_ERROR_FILE:-"error.log"}
PHPFPM_LOG_ERROR_PATH=${PHPFPM_LOG_ERROR_PATH:-"/var/log/php-fpm/"}
PHPFPM_LOG_LEVEL=${PHPFPM_LOG_LEVEL:-"notice"}
PHPFPM_LOG_LIMIT=${PHPFPM_LOG_LIMIT:-"3072"}
PHPFPM_POOL_DEFAULT_CATCH_WORKERS_OUTPUT=${PHPFPM_POOL_DEFAULT_CATCH_WORKERS_OUTPUT-"true"}
PHPFPM_POOL_DEFAULT_ENABLE_LOG=${PHPFPM_POOL_DEFAULT_ENABLE_LOG:-"TRUE"}
PHPFPM_POOL_DEFAULT_PING_PATH=${PHPFPM_POOL_DEFAULT_PING_PATH-"/ping"}
PHPFPM_POOL_DEFAULT_DISPLAY_ERRORS=${PHPFPM_POOL_DEFAULT_DISPLAY_ERRORS-"TRUE"}
PHPFPM_POOL_DEFAULT_LISTEN_IP=${PHPFPM_POOL_DEFAULT_LISTEN_IP:-"0.0.0.0"}
PHPFPM_POOL_DEFAULT_LISTEN_TYPE=${PHPFPM_POOL_DEFAULT_LISTEN_TYPE:-"unix"}
PHPFPM_POOL_DEFAULT_LISTEN_PORT=${PHPFPM_POOL_DEFAULT_LISTEN_PORT:-"9000"}
PHPFPM_POOL_DEFAULT_LISTEN_TCP_IP=${PHPFPM_POOL_DEFAULT_LISTEN_TCP_IP:-"${PHPFPM_POOL_DEFAULT_LISTEN_IP}"}
PHPFPM_POOL_DEFAULT_LISTEN_TCP_IP_ALLOWED=${PHPFPM_POOL_DEFAULT_LISTEN_TCP_IP_ALLOWED:-"127.0.0.1"}
PHPFPM_POOL_DEFAULT_LISTEN_TCP_PORT=${PHPFPM_POOL_DEFAULT_LISTEN_TCP_PORT:-"${PHPFPM_POOL_DEFAULT_LISTEN_PORT}"}
PHPFPM_POOL_DEFAULT_LISTEN_UNIX_SOCKET=${PHPFPM_POOL_DEFAULT_LISTEN_UNIX_SOCKET:-"/var/lib/php-fpm/run/default.sock"}
PHPFPM_POOL_DEFAULT_ENV=${PHPFPM_POOL_DEFAULT_ENV:-"PATH,TEMP,TMP,TMPDIR"}
PHPFPM_POOL_DEFAULT_LOG_ACCESS_FILE=${PHPFPM_POOL_DEFAULT_LOG_ACCESS_FILE:-"default-access.log"}
PHPFPM_POOL_DEFAULT_LOG_ACCESS_FORMAT=${PHPFPM_POOL_DEFAULT_LOG_ACCESS_FORMAT:-"default"}
PHPFPM_POOL_DEFAULT_LOG_PATH=${PHPFPM_POOL_DEFAULT_LOG_PATH:-"/logs/php-fpm/"}
PHPFPM_POOL_DEFAULT_MAX_CHILDREN=${PHPFPM_MAX_CHILDREN:-"75"}
PHPFPM_POOL_DEFAULT_MAX_INPUT_NESTING_LEVEL=${PHPFPM_MAX_INPUT_NESTING_LEVEL:-"256"}
PHPFPM_POOL_DEFAULT_MAX_INPUT_VARS=${PHPFPM_MAX_INPUT_VARS:-"10000"}
PHPFPM_POOL_DEFAULT_MAX_REQUESTS=${PHPFPM_MAX_REQUESTS:-"0"}
PHPFPM_POOL_DEFAULT_MAX_SPARE_SERVERS=${PHPFPM_MAX_SPARE_SERVERS:-"3"}
PHPFPM_POOL_DEFAULT_MEMORY_LIMIT=${PHPFPM_MEMORY_LIMIT:-"${PHP_MEMORY_LIMIT}"}
PHPFPM_POOL_DEFAULT_MIN_SPARE_SERVERS=${PHPFPM_MIN_SPARE_SERVERS:-"1"}
PHPFPM_POOL_DEFAULT_OUTPUT_BUFFER_SIZE=${PHPFPM_OUTPUT_BUFFER_SIZE:-"0"}
PHPFPM_POOL_DEFAULT_POST_MAX_SIZE=${PHPFPM_POOL_POST_MAX_SIZE:-"${PHP_POST_MAX_SIZE}"}
PHPFPM_POOL_DEFAULT_PROCESS_IDLE_TIMEOUT=${PHPFPM_PROCESS_IDLE_TIMEOUT:-"10s"}
PHPFPM_POOL_DEFAULT_PROCESS_MANAGER=${PHPFPM_PROCESS_MANAGER:-"dynamic"}
PHPFPM_POOL_DEFAULT_START_SERVERS=${PHPFPM_START_SERVERS:-"2"}
PHPFPM_POOL_DEFAULT_STATUS_PATH=${PHPFPM_STATUS_PATH:-"/php-fpm_status"}
PHPFPM_POOL_DEFAULT_TIMEOUT=${PHPFPM_TIMEOUT:-"${PHP_TIMEOUT}"}
PHPFPM_POOL_DEFAULT_UPLOAD_MAX_SIZE=${PHPFPM_UPLOAD_MAX_SIZE:-"${PHP_UPLOAD_MAX_SIZE}"}

get_defaults_advanced

================================================
FILE: rootfs/container/defaults/_20-php-fpm/20-php-fpm
================================================
# SPDX-FileCopyrightText: © 2026 Nfrastack <code@nfrastack.com>
#
# SPDX-License-Identifier: MIT



================================================
FILE: rootfs/container/defaults/_20-php-fpm/20-php-fpm.advanced
================================================
# SPDX-FileCopyrightText: © 2026 Nfrastack <code@nfrastack.com>
#
# SPDX-License-Identifier: MIT


================================================
FILE: rootfs/container/functions/20-php-fpm
================================================
# SPDX-FileCopyrightText: © 2026 Nfrastack <code@nfrastack.com>
#
# SPDX-License-Identifier: MIT

phpfpm_bootstrap() {
    case "$(container_info distro)" in
        alpine )
            case "${PHP_BASE}" in
                8*)
                    php_prefix="/etc/php${PHP_BASE/./}/"
                ;;
                * )
                    php_prefix="/etc/php${PHP_VERSION%%.*}/"
                ;;
            esac
        ;;
        "debian" )
            php_root="/etc/php/${PHP_BASE}/"
            php_prefix="/etc/php/${PHP_BASE}/fpm/"
        ;;
    esac
}

phpfpm_nginx_create_location_block() {
    if [ -z "${1:-}" ]; then return 1; fi
    local _sitename="${1}"
    local _site_path="${2:-}"

    if [ -z "${_site_path}" ]; then
        if [ -f "${NGINX_CONFIG_PATH%/}/sites.enabled/${_sitename}.conf" ]; then
            _site_path="${NGINX_CONFIG_PATH%/}/sites.enabled/${_sitename}.conf"
        fi
    fi

    if [ -z "${_site_path}" ]; then
        print_debug "[create_location_block/${_sitename}] No site path available, skipping"
        return 0
    fi

    local site_location="${_site_path%.*}/location"
    local template_src="/container/data/nginx/templates/site/location-php-block.template"

        if [ ! -d "${site_location}" ] || dir_empty "${site_location}" || ! grep -qRniE '^[[:space:]]*location[[:space:]]+[^{}]*php[^{}]*[[:space:]]*\{' "${site_location}" 2>/dev/null ; then
        if [ -f "${template_src}" ]; then
            print_debug "[create_location_block/${_sitename}] Installing php location block into ${site_location}"
            mkdir -p "${site_location}"
            cp -a --remove-destination "${template_src}" "${site_location}/20-php_block.conf"
        else
            print_warn "[create_location_block/${_sitename}] Template ${template_src} not found"
        fi
    else
        print_debug "[create_location_block/${_sitename}] Existing PHP location block found, skipping"
    fi
}

phpfpm_nginx_server_configure_upstream() {
    if [ -n "${1}" ]; then
        local _upstream="${1}"
        local _upstream_file="${NGINX_CONFIG_PATH%/}"/"${NGINX_CONFIG_FILE}".d/php-fpm/${_upstream,,}.conf
        create_folder "$(dirname "${_upstream_file}")" "${NGINX_USER}:${NGINX_GROUP}" 755
        write_file "${_upstream_file}":644 <<EOF
fastcgi_pass            phpfpm-${_upstream,,}-upstream;
fastcgi_read_timeout    ${_pool_max_execution_time};
fastcgi_send_timeout    ${_pool_max_execution_time};
proxy_http_version      1.1;
proxy_set_header        Connection "";
EOF

        if var_true "${CONTAINER_ENABLE_MONITORING}" ; then
            local metrics_conf="${NGINX_CONFIG_PATH%/}/${NGINX_CONFIG_FILE}.d/http/metrics.conf"
            sed -i \
                        -e '/^}/d;}' \
                    "${metrics_conf}"

            if [ "${_upstream,,}" != "www" ]; then
                local _poolsuffix="_${_upstream,,}"
            else
                local _poolsuffix="\$"
            fi

            write_file -a "${metrics_conf}":644 <<EOF

    location ~ ^/(php-fpm_status|ping)${_poolsuffix} {
        access_log off;
        allow 127.0.0.1;
        deny all;
        include ${_upstream_file};
        fastcgi_param REQUEST_METHOD \$request_method;
        fastcgi_param SCRIPT_NAME \$uri;
        fastcgi_param SCRIPT_FILENAME \$document_root\$uri;
    }
EOF

            if var_true "${PHP_MODULE_ENABLE_OPCACHE}" ; then
                case "${CONTAINER_MONITORING_BACKEND,,}" in
                    "zabbix" )
                        local zbx_opcache_module="${ZABBIX_CONFIG_PATH%/}/${ZABBIX_CONFIG_FILE%/}.d/nfrastack-php_module_opcache.conf"
                        local zbx_opcache_scripts="$(dirname "${zbx_opcache_module%/}")/scripts/php-${_upstream,,}/"
                        if [ !  -f "${zbx_opcache_module}" ]; then
                            write_file "${zbx_opcache_module}":644 <<EOF
# Zabbix PHP Opcache Configuration - Automatically Generated
# Find Companion Zabbix Server Templates at https://github.com/nfrastack/container-nginx-php-fpm
# Autoregister=opcache

EOF
                        fi

                        write_file -a "${zbx_opcache_module}":644 <<EOF
UserParameter=php.opcache.get_status,sudo -Eu zabbix php ${zbx_opcache_scripts%/}/opcache-status.php
UserParameter=php.opcache.get_settings,sudo -Eu zabbix php ${zbx_opcache_scripts%/}/opcache-settings.php
EOF

                        write_file -a "${metrics_conf}":644 <<EOF

    location ~ ^/${_upstream,,}/(.+\.php)(/.*)?\$ {
        rewrite ^/${_upstream,,}/(.+)\$ /\$1 break;
        root ${zbx_opcache_scripts%/};
        access_log off;
        allow 127.0.0.1;
        deny all;
        fastcgi_split_path_info ^(.+?\.php)(/.+)\$;
        fastcgi_param PATH_INFO \$fastcgi_path_info;
        include ${_upstream_file};
        fastcgi_param SCRIPT_FILENAME \$document_root\$fastcgi_script_name;
        fastcgi_param SCRIPT_NAME     \$fastcgi_script_name;
        fastcgi_param PATH_INFO       \$fastcgi_path_info;
    }
EOF
                    ;;
                esac

                create_folder "${zbx_opcache_scripts%/}" "zabbix:${NGINX_GROUP}" 755
                cp -a /container/data/php-fpm/opcache/* "${zbx_opcache_scripts%/}"
                chown -R zabbix:${NGINX_GROUP} "${zbx_opcache_scripts%/}"
                chmod -R 0755 "${zbx_opcache_scripts%/}"
            fi

            echo "}" | write_file -a "${metrics_conf}"
        fi

        local _phpfpm_host
## TODO old
        if var_true "${NGINX_ENABLE_UPSTREAM_KEEPALIVE}" ; then
            upstream_keepalive="keepalive ${NGINX_UPSTREAM_KEEPALIVE};"
        fi

        if [ -v NGINX_UPSTREAM_"${_upstream^^}"_HOST ]; then
            _phpfpm_host=$(set -o posix ; set | grep -oE "^NGINX_UPSTREAM_${_upstream^^}_HOST=" | cut -d = -f2-)
        else
            case "${_pool_listen_type,,}" in
                "tcp" )
                    _phpfpm_host="127.0.0.1:${_pool_listen_tcp_port}"
            ;;
                "unix" | "both" )
                    # phpfpm_server_pool_shadow_tcp.
                    _phpfpm_host="${_pool_listen_unix_socket}"
            ;;
            esac
        fi

        create_folder "${NGINX_CONFIG_PATH%/}/${NGINX_CONFIG_FILE}.d/upstream/" "${NGINX_USER}:${NGINX_GROUP}" 755
        local _upstream_conf="${NGINX_CONFIG_PATH%/}/${NGINX_CONFIG_FILE}.d/upstream/upstream-phpfpm-${_upstream,,}.conf"

        {
            echo "upstream phpfpm-${_upstream,,}-upstream {"
            if [ -n "${upstream_keepalive}" ]; then
                echo "    ${upstream_keepalive}"
            fi

            IFS=',' read -r -a _hosts <<< "${_phpfpm_host}"
            for _php_fpm_upstream in "${_hosts[@]}"; do
                _php_fpm_upstream_host_socket_prefix=""
                if [[ "${_php_fpm_upstream}" != *":"* ]]; then
                    _php_fpm_upstream_host_socket_prefix="unix://"
                fi

                _opts="$(set -o posix ; set | grep -E "^PHPFPM_UPSTREAM_${_upstream^^}_OPTIONS=" | cut -d '=' -f2-)"
                echo "    server ${_php_fpm_upstream_host_socket_prefix}${_php_fpm_upstream} ${_opts};"
            done

            echo "}"
        } | write_file "${_upstream_conf}"
    fi
}

phpfpm_nginx_server_hide_header() {
    local dest="${NGINX_CONFIG_PATH%/}"/"${NGINX_CONFIG_FILE%/}".d/http/headers-php.conf
    if var_true "${PHP_HIDE_X_POWERED_BY}" ; then
        cp -a /container/data/nginx/templates/server/http-fastcgi_hide_header_xpowered.template "${dest}"
    else
        rm -f "${dest}"
    fi
}

phpfpm_post_init() {
    case "$(container_info distro)" in
        "alpine" )
            cp -aR /container/data/php-fpm/cli/php.ini "${php_prefix%/}"/
            cp -aR /container/data/php-fpm/conf.available/* "${php_prefix%/}"/conf.available/
        ;;
        "debian" )
            cp -aR /container/data/php-fpm/cli/php.ini "${php_root%/}"/
            cp -aR /container/data/php-fpm/cli/php.ini "${php_prefix%/}"/
        ;;
    esac

    case "$(container_info distro)" in
        "alpine" )
            ### Weird Opcache issue
            if [ -f "${php_prefix%/}/conf.d/10-opcache.ini" ] && [ -f "${php_prefix%/}/conf.d/00-opcache.ini" ] ; then
                rm -rf "${php_prefix%/}"/conf.d/00-opcache.ini
            fi
        ;;
        "debian" )
            ### Weird Opcache issue
            if [ -f "${php_prefix%/}/conf.d/10-opcache.ini" ] && [ -f "${php_prefix%/}/fpm/conf.d/00-opcache.ini" ] ; then
                rm -rf /etc/php/"${PHP_BASE}"/*/conf.d/00-opcache.ini
            fi
        ;;
    esac

    if var_false "${PHP_KITCHENSINK}" ; then
        silent php-ext enable core
        print_debug "PHP-FPM Preparing to start with the following modules enabled: $(set -o posix; set | sort | grep "^PHP_MODULE_ENABLE_.*=" | grep -i TRUE |sed -e 's|PHP_MODULE_ENABLE_||g' -e 's|=TRUE||g' | awk -vRS="" -vOFS=', ' '$1=$1' | tr '[A-Z]' '[a-z]')"
    else
        print_warn "Enabling Kitchen Sink mode and allowing all modules to be active"
        silent php-ext enable all
    fi

    chmod -R 0750 "${php_prefix}"
    chown -R root:"${PHPFPM_GROUP}" "${php_prefix}"
}

phpfpm_server_configure() {
    echo "include = ${php_prefix%/}/php-fpm.d/logging.conf" | write_file "${php_prefix%/}"/php-fpm.conf

    for pools_to_include in "${php_prefix%/}"/pools.d/*.conf ; do
        echo "include = ${pools_to_include}" | write_file -a "${php_prefix%/}"/php-fpm.conf
    done

    if [ -d /override/data/php-fpm/fpm/ ]; then
        for config_to_include in /override/data/php-fpm/fpm/* "${php_prefix%/}"/pools.d/*.conf ; do
            echo "include = ${config_to_include}" | write_file -a "${php_prefix%/}"/php-fpm.conf
        done
    fi

    update_template "${NGINX_CONFIG_PATH%/}"/"${NGINX_CONFIG_FILE}".d/php-fpm/php-fpm.conf PHPFPM_TIMEOUT

    sed -i \
                -e "s#memory_limit = .*#memory_limit = ${PHP_MEMORY_LIMIT}#g" \
                -e "s#max_execution_time = .*#max_execution_time = ${PHP_TIMEOUT}#g" \
                -e "s#max_input_time = .*#max_input_time = ${PHP_TIMEOUT}#g" \
                -e "s#default_socket_timeout = .*#default_socket_timeout = ${PHP_TIMEOUT}#g" \
                -e "s#post_max_size = .*#post_max_size = ${PHP_UPLOAD_MAX_SIZE}#g" \
                -e "s#upload_max_filesize = .*#upload_max_filesize = ${PHP_UPLOAD_MAX_SIZE}#g" \
           /container/data/php-fpm/cli/php.ini

    call phpfpm_server_configure_smtp
    call phpfpm_server_configure_timezone
}

phpfpm_server_configure_environment_variables() {
    mkdir -p "${php_prefix%/}"/environment/
    for phpfpm_env_pair in $(set -o posix ; set | sort | grep "^PHPFPM_ENV_.*=" | sed "s|^PHPFPM_ENV_||g") ; do
        local phpfpm_env_var
        local phpfpm_env_value
        phpfpm_env_var=$(echo "${phpfpm_env_pair}" | cut -d = -f1)
        phpfpm_env_value=$(echo "${phpfpm_env_pair}" | cut -d = -f2-)
        echo "env[${phpfpm_env_var}] = ${phpfpm_env_value}" | write_file "${php_prefix%/}"/environment/"${phpfpm_env_var}"
    done
}

phpfpm_server_configure_logging() {
    mkdir -p \
                "${php_prefix%/}"/php-fpm.d/ \
                "${PHPFPM_LOG_ERROR_PATH}"
    touch "${PHPFPM_LOG_ERROR_PATH%/}"/"${PHPFPM_LOG_ERROR_FILE}"
    chown -R "${PHPFPM_USER}":"${PHPFPM_GROUP}" "${PHPFPM_LOG_ERROR_PATH%/}"
    create_logrotate phpfpm-error "${PHPFPM_LOG_ERROR_PATH%/}"/"${PHPFPM_LOG_ERROR_FILE}" phpfpm-error "${PHPFPM_USER}" "${PHPFPM_GROUP}"

    configure_server_logging="$(cat <<EOF
                                    error_log = ${PHPFPM_LOG_ERROR_PATH%/}/${PHPFPM_LOG_ERROR_FILE}
                                    log_level = ${PHPFPM_LOG_LEVEL}
                                    log_limit = ${PHPFPM_LOG_LIMIT}
EOF
                               )"

    echo "${configure_server_logging}" | sed -e "s|^[ \t]*||" | write_file "${php_prefix%/}"/php-fpm.d/logging.conf

    case "${PHP_BASE}" in
        "5.6" | 7[0-2] )
            sed -i \
                        -e "/^log_limit =/d" \
                    "${php_prefix%/}"/php-fpm.d/logging.conf
        ;;
    esac
}

phpfpm_server_configure_modules() {
    call phpfpm_server_module_apc
    call phpfpm_server_module_opcache
    call phpfpm_server_module_xdebug
}

phpfpm_server_configure_pools() {
    local _phpfpm_pools
    local _phpfpm_pool_vars
    local _phpfpm_pool_prefix

    _transform_phpfpmpool_variable() {
        local _val
        if grep -q -m1 "^PHPFPM_POOL_${1}_${2}=" "${_php_fpm_pool_vars}" && [ "$(grep -m1 "^PHPFPM_POOL_${1}_${2}=" "${_php_fpm_pool_vars}" | cut -d = -f2-)" != "unset" ]; then
            _val=$(grep -m1 "^PHPFPM_POOL_${1}_${2}=" "${_php_fpm_pool_vars}" | cut -d = -f2- | sed "s/^['\"]//; s/['\"]$//")
            export "$3"="${_val}"
            transform_var env "$3"
        elif grep -q -m1 "^PHP_FPM_${2}=" "${_php_fpm_pool_vars}" && [ "$(grep -m1 "^PHP_FPM_${2}=" "${_php_fpm_pool_vars}" | cut -d = -f2-)" != "unset" ]; then
            _val=$(grep -m1 "^PHP_FPM_${2}=" "${_php_fpm_pool_vars}" | cut -d = -f2- | sed "s/^['\"]//; s/['\"]$//")
            export "$3"="${_val}"
            transform_var env "$3"
        elif grep -q -m1 "^PHPFPM_POOL_DEFAULT_${2}=" "${_php_fpm_pool_vars}" && [ "$(grep -m1 "^PHPFPM_POOL_DEFAULT_${2}=" "${_php_fpm_pool_vars}" | cut -d = -f2-)" != "unset" ]; then
            _val=$(grep -m1 "^PHPFPM_POOL_DEFAULT_${2}=" "${_php_fpm_pool_vars}" | cut -d = -f2- | sed "s/^['\"]//; s/['\"]$//")
            export "$3"="${_val}"
            transform_var env "$3"
        fi
    }

    if [ "$(set -o posix ; set | sort | grep "^PHPFPM_POOL_.*" | sed -n "s/^PHPFPM_POOL_\([^_]*\)_.*$/\1/p" | uniq | wc -l)" -eq 1 ] ; then
        export PHPFPM_POOL_WWW_LISTEN_TYPE="${PHPFPM_POOL_DEFAULT_LISTEN_TYPE}"
    fi

    phpfpm_pool_list=$(set -o posix ; set | sort | grep "^PHPFPM_POOL_.*_LISTEN_TYPE" | sed -n 's/^PHPFPM_POOL_\([^_]*\)_.*$/\1/p' | grep -v -E '^DEFAULT$' | tr '\n' ' ')
    for phpfpm_pool in ${phpfpm_pool_list}; do
        _php_fpm_pool_vars="$(mktemp)"
        set -o posix ; set | grep -E "^PHPFPM_POOL_${phpfpm_pool}_|^PHPFPM_POOL_DEFAULT_" | tr " " "\n" | write_file "${_php_fpm_pool_vars}"
        _phpfpm_pool_prefix="${php_prefix%/}/pools.d/${phpfpm_pool,,}"
        mkdir -p "${_phpfpm_pool_prefix}"
        echo "[${phpfpm_pool,,}]" | write_file "${_phpfpm_pool_prefix}".conf
        call phpfpm_server_pool_listener "${phpfpm_pool}"
        call phpfpm_server_pool_log "${phpfpm_pool}"
        call phpfpm_server_pool_processmanagement "${phpfpm_pool}"
        call phpfpm_server_pool_settings "${phpfpm_pool}"
        call phpfpm_server_pool_environment "${phpfpm_pool}"
        call phpfpm_server_pool_override "${phpfpm_pool}"
        call phpfpm_server_pool_includes "${phpfpm_pool}"
        call phpfpm_nginx_server_configure_upstream "${phpfpm_pool}"
        call phpfpm_server_pool_shadow_tcp "${phpfpm_pool}"
        rm "${_php_fpm_pool_vars}"
    done
}

phpfpm_server_configure_smtp() {
    if var_true "${CONTAINER_ENABLE_MESSAGING}" || [ "${CONTAINER_MESSAGING_BACKEND}" = "msmtp" ] ; then
        case "$(container_info distro)" in
            "alpine" )
                  if var_true "${CONTAINER_ENABLE_MESSAGING}" || [ "${CONTAINER_MESSAGING_BACKEND}" = "msmtp" ] ; then
                      echo 'sendmail_path="/usr/bin/msmtp -C /etc/msmtprc -t "' | write_file "${php_prefix%/}"/conf.d/99-smtp.ini
                  fi
              ;;
            "debian" )
                if var_true "${ENABLE_SMTP}" || var_true "${CONTAINER_ENABLE_MESSAGING}" ; then
                    echo 'sendmail_path="/usr/bin/msmtp -C /etc/msmtprc -t "' | write_file "${php_root%/}"/cli/conf.d/99-smtp.ini "${php_prefix%/}"/conf.d/99-smtp.ini
                fi
            ;;
        esac

        if [ -f /etc/msmtprc ]; then
            chown "${PHPFPM_USER}":"${PHPFPM_GROUP}" /etc/msmtprc
            chmod 0600 /etc/msmtprc
        fi
    fi
}

phpfpm_server_configure_socket() {
    :
}

phpfpm_server_configure_timezone() {
     sed -i \
                -e "s#date.timezone = .*#date.timezone = $(cat /etc/timezone)#g" \
            /container/data/php-fpm/cli/php.ini \
            /container/data/php-fpm/fpm/php.ini

    case "$(container_info distro)" in
        "alpine" )
            echo "date.timezone=$(cat /etc/timezone)" | write_file "${php_prefix%/}"/conf.d/99-timezone.ini
        ;;
        "debian" )
            echo "date.timezone=$(cat /etc/timezone)" | write_file "${php_root%/}"/cli/conf.d/99-timezone.ini  "${php_prefix%/}"/conf.d/99-timezone.ini
        ;;
    esac
}

phpfpm_server_module_apc() {
    if [ "${PHP_MODULE_APC_SHM_SIZE}" = "0" ]; then
        sed -i -e "s#apc.enabled=1#apc.enabled=0#g" /container/data/php-fpm/conf.available/acpu.ini
    fi

    sed -i \
            -e "s#apc.shm_size=.*#apc.shm_size=${PHP_MODULE_APC_SHM_SIZE}#g" \
            -e "s#apc.ttl=.*#apc.ttl=${PHP_MODULE_APC_TTL}#g" \
        /container/data/php-fpm/conf.available/apcu.ini
}

phpfpm_server_module_opcache() {
    if [ "${PHP_MODULE_OPCACHE_MEM_SIZE}" = "0" ] || var_false "${PHP_MODULE_ENABLE_OPCACHE}" ; then
        sed -i \
                    -e "s|opcache.enable=1|opcache.enable=0|g" \
                    -e "s|opcache.enable_ci=1|opcache.enable_cli=0|g" \
                /container/data/php-fpm/conf.available/opcache.ini
    else
        sed -i \
                -e "s#opcache.interned_strings_buffer=.*#opcache.interned_strings_buffer=${PHP_MODULE_OPCACHE_INTERNED_STRINGS_BUFFER}#g" \
                -e "s#opcache.max_accelerated_files=.*#opcache.max_accelerated_files=${PHP_MODULE_OPCACHE_MAX_ACCELERATED_FILES}#g" \
                -e "s#opcache.max_file_size=.*#opcache.max_file_size=${PHP_MODULE_OPCACHE_MAX_FILE_SIZE}#g" \
                -e "s#opcache.max_wasted_percentage=.*#opcache.max_wasted_percentage=${PHP_MODULE_OPCACHE_MAX_WASTED_PERCENTAGE}#g" \
                -e "s#opcache.memory_consumption=.*#opcache.memory_consumption=${PHP_MODULE_OPCACHE_MEM_SIZE}#g" \
                -e "s#opcache.optimization_level=.*#opcache.optimization_level=${PHP_MODULE_OPCACHE_OPTIMIZATION_LEVEL}#g" \
                -e "s#opcache.reavalidate_freq=.*#opcache.revalidate_freq=${PHP_MODULE_OPCACHE_REVALIDATE_FREQ}#g" \
                -e "s#opcache.revalidate_freq=.*#opcache.revalidate_freq=${PHP_MODULE_OPCACHE_REVALIDATE_FREQ}#g" \
                -e "s#opcache.save_comments=.*#opcache.save_comments=${PHP_MODULE_OPCACHE_SAVE_COMMENTS}#g" \
                -e "s#opcache.validate_timestamps=.*#opcache.validate_timestamps=${PHP_MODULE_OPCACHE_VALIDATE_TIMESTAMPS}#g" \
            /container/data/php-fpm/conf.available/opcache.ini

        if [ "${PHP_BASE:0:1}" = "7" ] ; then
            sed -i "/opcache.jit/d" /container/data/php-fpm/conf.available/opcache.ini
        else
            sed -i \
                        -e "s#opcache.jit_buffer_size=.*#opcache.jit_buffer_size=${PHP_MODULE_OPCACHE_JIT_BUFFER_SIZE}#g" \
                        -e "s#opcache.jit=.*#opcache.jit=${PHP_MODULE_OPCACHE_JIT_MODE}#g" \
                    /container/data/php-fpm/conf.available/opcache.ini
        fi
    fi
}

phpfpm_server_module_xdebug() {
    if var_true "${PHP_MODULE_ENABLE_XDEBUG}" ; then
        mkdir "${PHP_MODULE_XDEBUG_PROFILER_PATH}"
        chown -R "${PHPFPM_USER}":"${PHPFPM_GROUP}" "${PHP_MODULE_XDEBUG_PROFILER_PATH}"
        if [ "${PHP_BASE:0:1}" = "5" ] || [ "${PHP_BASE:0:3}" = "7.0" ] || [ "${PHP_BASE:0:3}" = "7.1" ] ; then
            write_file -a "${php_prefix}"conf.available/xdebug.ini:644 <<EOF
zend_extension=xdebug.so
xdebug.default_enable = 1
xdebug.profiler_enable= ${PHP_MODULE_XDEBUG_PROFILER_ENABLE}
xdebug.profiler_enable_trigger= ${PHP_MODULE_XDEBUG_PROFILER_ENABLE_TRIGGER}
xdebug.profiler_output_dir='${PHP_MODULE_XDEBUG_PROFILER_DIR}'
xdebug.remote_autostart = ${PHP_MODULE_XDEBUG_REMOTE_AUTOSTART}
xdebug.remote_connect_back = ${PHP_MODULE_XDEBUG_REMOTE_CONNECT_BACK}
xdebug.remote_enable = ${PHP_MODULE_XDEBUG_REMOTE_ENABLE}
xdebug.remote_handler = ${PHP_MODULE_XDEBUG_REMOTE_HANDLER}
xdebug.remote_host = ${PHP_MODULE_XDEBUG_REMOTE_HOST}
xdebug.remote_port = ${PHP_MODULE_XDEBUG_REMOTE_PORT}
EOF
    	else
	    	write_file -a "${php_prefix}"conf.available/xdebug.ini:644 <<EOF
zend_extension=xdebug.so
xdebug.default_enable = 1
xdebug.output_dir = ${PHP_MODULE_XDEBUG_OUTPUT_DIR}
xdebug.mode = ${PHP_MODULE_XDEBUG_MODE}
xdebug.start_with_request = ${PHP_MODULE_XDEBUG_START_WITH_REQUEST}
xdebug.discover_client_host = ${PHP_MODULE_XDEBUG_DISCOVER_CLIENT_HOST}
xdebug.client_host = ${PHP_MODULE_XDEBUG_CLIENT_HOST}
xdebug.client_port = ${PHP_MODULE_XDEBUG_CLIENT_PORT}
EOF
    	fi
        PHP_LOG_LEVEL=debug
        print_notice "DEBUGGING MODE ACTIVATED: Please use your IDE to connect to: ${PHP_MODULE_XDEBUG_REMOTE_HOST}:${PHP_MODULE_XDEBUG_REMOTE_PORT}"
        if [ "${PHP_MODULE_XDEBUG_PROFILER_ENABLE}" = "1" ] || [ "${PHP_MODULE_XDEBUG_MODE,,}" = "trace" ]; then
            print_notice "PROFILING MODE ACTIVATED: Please find the profiler logs at: ${PHP_MODULE_XDEBUG_PROFILER_PATH}"
            mkdir -p "${PHP_MODULE_XDEBUG_PROFILER_PATH}"
            chown -R "${PHPFPM_USER}":"${PHPFPM_GROUP}" "${PHP_MODULE_XDEBUG_PROFILER_PATH}"
        fi
    fi
}

phpfpm_server_pool_environment() {
    _transform_phpfpmpool_variable "${1^^}" ENV _pool_env
    for pool_env in $(echo "${_pool_env}" | tr "," "\n" | uniq); do
        if [ -f "${php_prefix%/}"/environment/"${pool_env}" ]; then
            echo "include = ${php_prefix%/}/environment/${pool_env}" | write_file -a "${_phpfpm_pool_prefix}".conf
        fi
    done
}

phpfpm_server_pool_listener() {
    _transform_phpfpmpool_variable "${1^^}" LISTEN_TYPE _pool_listen_type

    case "${_pool_listen_type}" in
        "tcp" )
            _transform_phpfpmpool_variable "${phpfpm_pool^^}" LISTEN_IP _pool_listen_ip
            _transform_phpfpmpool_variable "${phpfpm_pool^^}" LISTEN_PORT _pool_listen_port
            _transform_phpfpmpool_variable "${phpfpm_pool^^}" LISTEN_TCP_IP _pool_listen_tcp_ip
            _transform_phpfpmpool_variable "${phpfpm_pool^^}" LISTEN_TCP_IP_ALLOWED _pool_listen_tcp_ip_allowed
            _transform_phpfpmpool_variable "${phpfpm_pool^^}" LISTEN_TCP_PORT _pool_listen_tcp_port
            configure_pool="$(cat <<EOF
                                listen                          = ${_pool_listen_tcp_ip}:${_pool_listen_tcp_port}
                                listen.allowed_clients          = ${_pool_listen_tcp_ip_allowed}
EOF
                            )"
        ;;
        "unix" | "both" )
            _transform_phpfpmpool_variable "${phpfpm_pool^^}" LISTEN_UNIX_SOCKET _pool_listen_unix_socket
            _transform_phpfpmpool_variable "${phpfpm_pool^^}" LISTEN_UNIX_GROUP _pool_listen_unix_group
            _transform_phpfpmpool_variable "${phpfpm_pool^^}" LISTEN_UNIX_USER _pool_listen_unix_user

            if [ ! -d "$(dirname "${_pool_listen_unix_socket}")" ]; then
                mkdir -p "$(dirname "${_pool_listen_unix_socket}")"
                chown -R "${_pool_listen_unix_user}":"${_pool_listen_unix_group}" "$(dirname "${_pool_listen_unix_socket}")"
            fi

            if [ "$(basename "${_pool_listen_unix_socket}")" = "default.sock" ] ; then
                _pool_listen_unix_socket="$(dirname "${_pool_listen_unix_socket}")/${1,,}.sock"
            fi

            configure_pool="$(cat <<EOF
                                listen                              = ${_pool_listen_unix_socket}
                                listen.owner                        = ${_pool_listen_unix_user}
                                listen.group                        = ${_pool_listen_unix_group}
EOF
                            )"
        ;;
    esac
    echo "${configure_pool}" | sed -e "s|^[ \t]*||" | write_file "${_phpfpm_pool_prefix}"/"${1,,}-listener.conf"
    echo "include = ${_phpfpm_pool_prefix}/${1,,}-listener.conf" | write_file -a "${_phpfpm_pool_prefix}".conf
}

phpfpm_server_pool_includes() {
    _transform_phpfpmpool_variable "${1^^}" INCLUDES _pool_includes
    if [ -z "${_pool_includes}" ]; then
        return
    fi
    local _inc
    IFS=',' read -ra _pool_includes_arr <<< "${_pool_includes}"
    for _inc in "${_pool_includes_arr[@]}"; do
        _inc=$(echo "${_inc}" | sed 's/^[[:space:]]*//;s/[[:space:]]*$//')
        if [ -n "${_inc}" ]; then
            print_debug "[pool_includes/${1,,}] include = ${_inc}"
            echo "include = ${_inc}" | write_file -a "${_phpfpm_pool_prefix}".conf
        fi
    done
}

phpfpm_server_pool_shadow_tcp() {
    # Create shadow pool when PHPFPM_POOL_<NAME>_LISTEN_TYPE=both
    # Create <NAME>-tcp pool sharing all other options pm/log/env/override/inclues

    _transform_phpfpmpool_variable "${1^^}" LISTEN_TYPE _pool_listen_type
    if [ "${_pool_listen_type,,}" != "both" ]; then
        return
    fi

    local _pool_lower="${1,,}"
    local _primary_conf="${_phpfpm_pool_prefix}.conf"
    local _shadow_conf="${php_prefix%/}/pools.d/${_pool_lower}-tcp.conf"

    if [ ! -f "${_primary_conf}" ]; then
        print_warn "[pool_shadow_tcp/${_pool_lower}] Primary pool .conf not found at '${_primary_conf}' - skipping shadow"
        return
    fi

    # refuse to clobber an user created <pool>-tcp pool
    if echo " ${phpfpm_pool_list} " | grep -qi -- " ${_pool_lower}-tcp " 2>/dev/null; then
        print_warn "[pool_shadow_tcp/${_pool_lower}] An operator-defined '${_pool_lower}-tcp' pool exists - skipping shadow generation"
        return
    fi

    _transform_phpfpmpool_variable "${1^^}" LISTEN_TCP_IP _shadow_tcp_ip
    _transform_phpfpmpool_variable "${1^^}" LISTEN_TCP_PORT _shadow_tcp_port
    _transform_phpfpmpool_variable "${1^^}" LISTEN_TCP_IP_ALLOWED _shadow_tcp_allowed

    : "${_shadow_tcp_ip:=127.0.0.1}"
    : "${_shadow_tcp_port:=9000}"
    : "${_shadow_tcp_allowed:=127.0.0.1}"

    local _shadow_pool="${_pool_lower}-tcp"

    print_notice "[pool_shadow_tcp/${_pool_lower}] Spawning shadow pool '${_shadow_pool}' listening on ${_shadow_tcp_ip}:${_shadow_tcp_port}"

    sed \
        -e "s|^\[${_pool_lower}\]|[${_shadow_pool}]|" \
        -e "\|^include[[:space:]]*=.*${_pool_lower}-listener\.conf$|d" \
        "${_primary_conf}" > "${_shadow_conf}"

    {
        echo "listen                          = ${_shadow_tcp_ip}:${_shadow_tcp_port}"
        echo "listen.allowed_clients          = ${_shadow_tcp_allowed}"
    } >> "${_shadow_conf}"

    local _shadow_upstream_file="${NGINX_CONFIG_PATH%/}/${NGINX_CONFIG_FILE}.d/php-fpm/${_shadow_pool}.conf"
    create_folder "$(dirname "${_shadow_upstream_file}")" "${NGINX_USER}:${NGINX_GROUP}" 755
    write_file "${_shadow_upstream_file}":644 <<EOF
fastcgi_pass            phpfpm-${_shadow_pool}-upstream;
fastcgi_read_timeout    ${_pool_max_execution_time};
fastcgi_send_timeout    ${_pool_max_execution_time};
proxy_http_version      1.1;
proxy_set_header        Connection "";
EOF

    local _shadow_upstream_conf="${NGINX_CONFIG_PATH%/}/${NGINX_CONFIG_FILE}.d/upstream/upstream-phpfpm-${_shadow_pool}.conf"
    create_folder "$(dirname "${_shadow_upstream_conf}")" "${NGINX_USER}:${NGINX_GROUP}" 755
    local _shadow_keepalive=""
    if var_true "${NGINX_ENABLE_UPSTREAM_KEEPALIVE}" ; then
        _shadow_keepalive="    keepalive ${NGINX_UPSTREAM_KEEPALIVE};"
    fi
    {
        echo "upstream phpfpm-${_shadow_pool}-upstream {"
        if [ -n "${_shadow_keepalive}" ]; then
            echo "${_shadow_keepalive}"
        fi
        echo "    server ${_shadow_tcp_ip}:${_shadow_tcp_port};"
        echo "}"
    } | write_file "${_shadow_upstream_conf}"
}

phpfpm_server_pool_log() {
    _transform_phpfpmpool_variable "${1^^}" ENABLE_LOG _pool_enable_log

    if var_true "${_pool_enable_log}" ; then
        _transform_phpfpmpool_variable "${1^^}" LOG_PATH _pool_log_path
        _transform_phpfpmpool_variable "${1^^}" LOG_ACCESS_FILE _pool_log_access_file
        _transform_phpfpmpool_variable "${1^^}" LOG_ACCESS_FORMAT _pool_log_access_format

        create_folder "${_pool_log_path}" "${PHPFPM_USER}:${PHPFPM_GROUP}" 755
        if [ "${_pool_log_access_file}" = "default-access.log" ] ; then _pool_log_access_file="${1,,}-access.log" ; fi
        sudo -u "${PHPFPM_USER}" touch "${_pool_log_path%/}"/"${_pool_log_access_file}"
        chown -R "${PHPFPM_USER}":"${PHPFPM_GROUP}" "${_pool_log_path%/}"
        create_logrotate phpfpm-${1,,}-access "${_pool_log_path%/}"/"${_pool_log_access_file}" phpfpm "${PHPFPM_USER}":"${PHPFPM_GROUP}"

        if [ "${_pool_log_access_format,,}" = "standard" ] ; then
            _pool_log_access_format=default
        fi

        configure_pool="$(cat <<EOF

                            access.log                          = ${_pool_log_path%/}/${_pool_log_access_file}
                            include                             = /container/data/php-fpm/fpm/${_pool_log_access_format,,}.logformat
EOF
                        )"

        echo "${configure_pool}" | sed -e "s|^[ \t]*||" | write_file "${_phpfpm_pool_prefix}"/"${1,,}-log.conf"
        echo "include = ${_phpfpm_pool_prefix}/${1,,}-log.conf" | write_file -a "${_phpfpm_pool_prefix}".conf
    fi
}

phpfpm_server_pool_override() {
    if [ -d /override/php-fpm/pool/"${1,,}" ]; then
        echo "include = /override/php-fpm/pool/${1}/*.conf" | write_file "${_phpfpm_pool_prefix}"/"${1,,}-override.conf"
        echo "include = ${_phpfpm_pool_prefix}/${1,,}-override.conf" | write_file -a "${_phpfpm_pool_prefix}".conf
    fi
}

phpfpm_server_pool_processmanagement() {
    _transform_phpfpmpool_variable "${1^^}" MAX_CHILDREN _pool_pm_max_children
    _transform_phpfpmpool_variable "${1^^}" MAX_REQUESTS _pool_pm_max_requests
    _transform_phpfpmpool_variable "${1^^}" MAX_SPARE_SERVERS _pool_pm_max_spare_servers
    _transform_phpfpmpool_variable "${1^^}" MIN_SPARE_SERVERS _pool_pm_min_spare_servers
    _transform_phpfpmpool_variable "${1^^}" PROCESS_MANAGER _pool_pm_process_manager
    _transform_phpfpmpool_variable "${1^^}" START_SERVERS _pool_pm_start_servers
    _transform_phpfpmpool_variable "${1^^}" STATUS_PATH _pool_pm_status_path
    _transform_phpfpmpool_variable "${1^^}" PROCESS_IDLE_TIMEOUT _pool_pm_process_idle_timeout

    configure_pool="$(cat <<EOF

                        pm                                          = ${_pool_pm_process_manager}
                        pm.max_children                             = ${_pool_pm_max_children}
                        pm.max_requests                             = ${_pool_pm_max_requests}
                        pm.max_spare_servers                        = ${_pool_pm_max_spare_servers}
                        pm.min_spare_servers                        = ${_pool_pm_min_spare_servers}
                        pm.process_idle_timeout                     = ${_pool_pm_process_idle_timeout}
                        pm.start_servers                            = ${_pool_pm_start_servers}
                        pm.status_path                              = ${_pool_pm_status_path}

EOF
                    )"

    echo "${configure_pool}" | sed -e "s|^[ \t]*||" | write_file "${_phpfpm_pool_prefix}"/"${1,,}-pm.conf"
    echo "include = ${_phpfpm_pool_prefix}/${1,,}-pm.conf" | write_file -a "${_phpfpm_pool_prefix}".conf
}

phpfpm_server_pool_settings() {
    _transform_phpfpmpool_variable "${1^^}" OUTPUT_BUFFER_SIZE _pool_output_buffer_size
    _transform_phpfpmpool_variable "${1^^}" TIMEOUT _pool_max_execution_time
    _transform_phpfpmpool_variable "${1^^}" MAX_INPUT_NESTING_LEVEL _pool_max_input_nesting_level
    _transform_phpfpmpool_variable "${1^^}" MAX_INPUT_VARS _pool_max_input_vars
    _transform_phpfpmpool_variable "${1^^}" MEMORY_LIMIT _pool_memory_limit
    _transform_phpfpmpool_variable "${1^^}" POST_MAX_SIZE _pool_post_max_size
    _transform_phpfpmpool_variable "${1^^}" UPLOAD_MAX_SIZE _pool_upload_max_size
    _transform_phpfpmpool_variable "${1^^}" CATCH_WORKERS_OUTPUT _pool_catch_workers_output
    _transform_phpfpmpool_variable "${1^^}" DISPLAY_ERRORS _pool_display_errors
    _transform_phpfpmpool_variable "${1^^}" PING_PATH _pool_ping_path

    configure_pool="$(cat <<EOF

                        php_admin_value[max_execution_time]         = ${_pool_max_execution_time}
                        php_admin_value[max_input_nesting_level]    = ${_pool_max_input_nesting_level}
                        php_admin_value[max_input_vars]             = ${_pool_max_input_vars}
                        php_admin_value[memory_limit]               = ${_pool_memory_limit}
                        php_admin_value[openssl.cafile]             = /etc/ssl/certs/ca-certificates.crt
                        php_admin_value[openssl.capath]             = /etc/ssl/certs
                        php_admin_value[output_buffering]           = ${_pool_output_buffer_size}
                        php_admin_value[post_max_size]              = ${_pool_post_max_size}
                        php_admin_value[upload_max_filesize]        = ${_pool_upload_max_size}
                        php_flag[display_errors]                    = ${_pool_display_errors,,}

                        catch_workers_output                        = ${_pool_catch_workers_output,,}
                        ping.path                                   = ${_pool_ping_path}

EOF
                    )"

    echo "${configure_pool}" | sed -e "s|^[ \t]*||" | write_file "${_phpfpm_pool_prefix}"/"${1,,}-settings.conf"
    echo "include = ${_phpfpm_pool_prefix}/${1,,}-settings.conf" | write_file -a "${_phpfpm_pool_prefix}".conf
}

phpfpm_site_create_default_page() {
    if [ -n "${1}" ] ; then
        local _sitename="${1}"
        local _webroot="${2}"
        local _index="${3}"
        local enable_phpsample_var="PHP_SITE_${_sitename^^}_CREATE_SAMPLE_PHP"
        local enable_phpsample_val
        enable_phpsample_val="$(resolve_site_var "${enable_phpsample_var}" "${PHP_CREATE_SAMPLE_PHP:-${PHP_ENABLE_CREATE_SAMPLE_PHP:-}}" "${allow_defaults}")"
        if [ -z "${enable_phpsample_val}" ] ; then enable_phpsample_val="false"; fi

        if var_true "${enable_phpsample_val}" && [ ! -f "${_index}" ]; then
            print_notice "[configure_site/${_sitename}] [php_create_default_page] Creating sample ${_index} for site at ${_webroot}"
            create_folder "${_webroot}" "${NGINX_USER}:${NGINX_GROUP}" 750
            write_file "${NGINX_USER}":"${NGINX_GROUP}" "${_webroot%/}"/"${_index}":644 <<EOF
<html>
<title>Default Page</title>
<h2>Container is working</h2>
Congratulations! Your ${IMAGE_NAME} $(container_info distro) $(container_info variant) PHP-FPM image is working. You are seeing this because you don't have an index.php file in your ${PHP_WEBROOT} directory.<br />
For more info visit <a href="https://www.nfrastack.com/?ref=container-nginx-php-fpm">https://www.nfrastack.com</a><p>
<?php phpinfo();?>
</html>
EOF
        fi
    fi
}


phpfpm_nginx_site_configure() {
    if var_true "${NGINX_ENABLE_APPLICATION_CONFIGURATION}"; then
        if [ -z "${NGINX_SITE_ENABLED}" ] || [ "${NGINX_SITE_ENABLED,,}" = "null" ] ; then
            NGINX_SITE_ENABLED=default
        fi

        if [ -n "${NGINX_SITE_ENABLED}" ] && [ "${NGINX_SITE_ENABLED,,}" != "null" ] ; then
            sites_to_enable=""
            for site_list in $(echo "${NGINX_SITE_ENABLED}" | tr "," "\n"); do
                case "${site_list}" in
                    "all")
                        site_filelist=$(find "${NGINX_CONFIG_PATH%/}"/"${NGINX_CONFIG_FILE}".d/sites.available/*.conf /container/data/nginx/sites.available/*.conf /override/sites.available/*.conf -type f ! -name *.enc* -maxdepth 1 2>/dev/null || true)
                        for site_path in ${site_filelist}; do
                            sites_to_enable="${sites_to_enable} $(basename "${site_path%.*}")"
                        done
                    ;;
                    *)
                        sites_to_enable="${sites_to_enable} ${site_list}"
                    ;;
                esac
            done

            sites_to_enable=$(echo "${sites_to_enable}" | tr ' ' '\n' | sed '/^$/d' | awk '!seen[$0]++' | tr '\n' ' ')
            for site in ${sites_to_enable}; do
                print_notice "[configure_site/${site}] Configuring PHP settings"
                site_path=""
                for enable_candidate in "${NGINX_CONFIG_PATH%/}/sites.enabled/${site}.conf"; do
                    if [ -f "${enable_candidate}" ]; then
                        site_path="${enable_candidate}"
                        break
                    fi
                done
                local allow_defaults_var_site="NGINX_SITE_${site^^}_ALLOW_DEFAULTS"
                local allow_defaults="${!allow_defaults_var_site}"
                if [ -z "${allow_defaults}" ]; then allow_defaults="${NGINX_ALLOW_DEFAULTS}"; fi
                if [ -z "${allow_defaults}" ]; then allow_defaults=true; fi
                call phpfpm_nginx_site_configure_php "${site}" "${site_path}" "${allow_defaults,,}"
            done
        fi
    else
        print_notice "[application_configuration] Disabled automated PHP site configuration routines"
    fi

    call phpfpm_nginx_server_hide_header
}

phpfpm_nginx_site_configure_php() {
    if [ -n "${1}" ]; then
        local _sitename="${1:-}"
        local site_path="${2:-}"
        local allow_defaults="${3:-true}"

        local _nginxphpupvar="NGINX_SITE_${_sitename^^}_PHP_UPSTREAM"
        local _nginxphpconf=""
        if [ -n "${!_nginxphpupvar:-}" ]; then
            _nginxphpconf="${!_nginxphpupvar}"
        else
            if [ "${allow_defaults,,}" = "true" ] && [ -n "${NGINX_PHP_UPSTREAM:-}" ]; then
                _nginxphpconf="${NGINX_PHP_UPSTREAM}"
            else
                _nginxphpconf=www
            fi
        fi

        create_folder "${NGINX_CONFIG_PATH%/}/${NGINX_CONFIG_FILE}.d/php-fpm" "${NGINX_USER}:${NGINX_GROUP}" 755
        ln -sf "${NGINX_CONFIG_PATH%/}/${NGINX_CONFIG_FILE}.d/php-fpm/${_nginxphpconf}.conf" "${NGINX_CONFIG_PATH%/}/${NGINX_CONFIG_FILE}.d/php-fpm/php-fpm.conf"

        local php_index_file=""
        local _site_index_var="NGINX_SITE_${_sitename^^}_INDEX_FILE"
        if [ -n "${!_site_index_var:-}" ]; then
            _site_index_val="${!_site_index_var}"
            IFS=$', ' read -ra _idx_arr <<< "${_site_index_val}"
            php_index_file="${_idx_arr[0]}"
        else
            if [ "${allow_defaults,,}" = "true" ] && [ -n "${NGINX_INDEX_FILE}" ]; then
                IFS=$', ' read -ra _idx_arr <<< "${NGINX_INDEX_FILE}"
                php_index_file="${_idx_arr[0]}"
            else
                php_index_file="index.php"
            fi
        fi
        local nginx_index_file="${php_index_file}"
        local site_index="${php_index_file}"
        render_template \
                            /container/data/nginx/templates/site/server-index.template \
                            "${NGINX_CONFIG_PATH%/}"/sites.enabled/"${_sitename}"/server-begin/21-index.conf \
                        site_index
        local php_upstream="include ${NGINX_CONFIG_PATH%/}/${NGINX_CONFIG_FILE}.d/php-fpm/${_nginxphpconf}.conf"
        if [ -n "${site_path}" ] && [ -f "${site_path}" ] && [ -f "${NGINX_CONFIG_PATH%/}/${NGINX_CONFIG_FILE}.d/php-fpm/${_nginxphpconf}.conf" ]; then
            while IFS= read -r -d '' _file; do
                if grep -q '{{[[:space:]]*php_[A-Za-z0-9_]*[[:space:]]*}}' "${_file}"; then
                    placeholders=$(grep -oE '{{[[:space:]]*php_[A-Za-z0-9_]*[[:space:]]*}}' "${_file}" \
                        | sed -e 's/^{{[[:space:]]*//' -e 's/[[:space:]]*}}$//' \
                        | awk '{$1=$1;print}' \
                        | sort -u \
                        | tr '\n' ' ')

                    if [ -n "${placeholders}" ]; then
                        print_debug "[configure_site/${_sitename}] [configure_nginx_php] Updating template ${_file} with placeholders: ${placeholders}"
                        set -- ${placeholders}
                        update_template "${_file}" "$@"
                        set --
                    fi
                fi
            done < <( { [ -f "${site_path}" ] && printf '%s\0' "${site_path}"; find -L "$(dirname "${site_path}")" -type f -print0 2>/dev/null; } )
        fi
    fi
}


================================================
FILE: rootfs/container/functions/20-php-fpm.advanced
================================================
# SPDX-FileCopyrightText: © 2026 Nfrastack <code@nfrastack.com>
#
# SPDX-License-Identifier: MIT



================================================
FILE: rootfs/container/init/init.d/20-php-fpm
================================================
#!/command/with-contenv bash
# SPDX-FileCopyrightText: © 2026 Nfrastack <code@nfrastack.com>
#
# SPDX-License-Identifier: MIT

source /container/base/functions/container/init
prepare_service *-nginx single
prepare_service 20-php-fpm single
SERVICE_NAME="php-fpm"

if var_false "${ENABLE_PHPFPM}" ; then
    print_debug "Disabling PHP-FPM Functionality"
    service_stop 20-php-fpm
    rm -rf \
            /container/logrotate/php-fpm* \
            /etc/logrotate.d/php-fpm* \
            /etc/fluent-bit/conf.d/php* \
            /etc/zabbix/*/php*.conf
    liftoff
    exit 0
fi

case "${PHPFPM_CONTAINER_MODE,,}" in
      "nginx")
            print_warn "Setting Container to operate in Nginx standalone mode"
            if [ "${PHP_FPM_HOST}" = "127.0.0.1" ] || [ "${PHP_FPM_HOST}" = "localhost" ] ; then
              print_error "Your PHP_FPM_HOST variable is still set to 'localhost' Please change it to something else"
              exit 1
            fi
            service_stop "$(basename "$0")"
            rm -rf /etc/zabbix/zabbix_agent.conf.d/php-fpm.conf
            liftoff
            exit 0
      ;;
      "php-fpm")
            print_warn "Setting Container to operate in PHP-FPM standalone mode - You will need a seperate container for Nginx or another webserver to serve content"
            mod_service_stop 10-nginx
            print_notice "Setting PHP-FPM to serve from ${PHP_WEBROOT}"
            sed -i "/[www]#/achdir = ${PHP_WEBROOT}" /container/data/php-fpm/fpm/php-fpm.conf
            rm -rf /etc/zabbix/zabbix_agent.conf.d/nginx.conf
      ;;
esac

if check_container_restarted; then
    if var_true "${CONTAINER_ENABLE_MONITORING}" ; then source /container/base/defaults/*-monitoring; fi
    phpfpm_bootstrap
    phpfpm_server_configure_logging
    phpfpm_server_configure_environment_variables
    phpfpm_server_configure_modules
    phpfpm_server_configure_pools
    phpfpm_server_configure
    if [[ "${PHPFPM_CONTAINER_MODE,,}" == *"nginx"* ]] ; then phpfpm_nginx_site_configure ; fi
    phpfpm_post_init
fi
liftoff

================================================
FILE: rootfs/container/run/available/20-php-fpm/run
================================================
#!/command/with-contenv bash
# SPDX-FileCopyrightText: © 2026 Nfrastack <code@nfrastack.com>
#
# SPDX-License-Identifier: MIT

source /container/base/functions/container/init
prepare_service defaults *-nginx
prepare_service single
SERVICE_NAME="php-fpm"

check_container_initialized
check_service_initialized init
liftoff

print_start "Starting php-fpm ${PHP_VERSION}"
silent exec s6-setuidgid ${PHPFPM_USER} php-fpm -F;

================================================
FILE: rootfs/etc/fluent-bit/parsers.d/phpfpm.conf
================================================
[PARSER]
    Name   phpfpm
    Format regex
    Regex ^(?<time>[^ ]*) (?<remote_addr>[^ ]*) (?<host>[^ ]*) (?<remote_user>[^ ]*) (?<status>[^ ]*) (?<request_method>\S+) "(?<request_uri>[^\"]*)" (?<request_id>[^ ]*) (?<server_protocol>[^ ]*) (?<body_bytes_sent>[^ ]*)(?: "(?<referer>[^\"]*)" "(?<agent>[^\"]*)") (?<memory_usage>[^ ]*) (?<cpu_usage>[^ ]*) (?<duration>[^ ]*)$
    Time_Key time
    Time_Format %Y-%m-%dT%H:%M:%S%z

[PARSER]
    Name   phpfpm-error
    Format regex
    Regex ^\[(?<time>[^\]]*)\] (?<severity>[^ ]*): (?<message>.*)
    Time_Key time
    Time_Format %d-%b-%Y %H:%M:%S


================================================
FILE: rootfs/etc/zabbix/zabbix_agentd.conf.d/php-fpm.conf
================================================
# PHP-FPM checking for Zabbix Agent 5.4+
# All data metric collection is handled by the template
# Get the template at https://github.com/nfrastack/container-nginx-php-fpm/
# Autoregister=phpfpm


================================================
FILE: rootfs/usr/local/bin/php-ext
================================================
#!/command/with-contenv bash
# SPDX-FileCopyrightText: © 2026 Nfrastack <code@nfrastack.com>
#
# SPDX-License-Identifier: MIT

source /container/base/functions/container/init
_container_build_env_import silent $(basename $(dirname "$0"))
_container_run_env_import silent $(basename $(dirname "$0"))

php_version=$(php -v 2>/dev/null | grep "^PHP " | head -n 1 | awk '{print $2}')
php_base=${php_version:0:3}

os=$(grep -o '^ID=.*' /etc/os-release | cut -d = -f2)

case "${os}" in
    "alpine" )
        case "${php_version:0:3}" in
            8*)
                php_prefix="/etc/php${php_base/./}/"
            ;;
            * )
                php_prefix="/etc/php${php_version:0:1}/"
            ;;
        esac
        modules_available="${php_prefix}/conf.available/"
    ;;
    "debian" )
        php_prefix="/etc/php/${php_base}/"
        modules_available="${php_prefix}/mods-available/"
    ;;
esac

disable_module() {
    if [ -n "$1" ]; then
        case "$1" in
            "all" )
                echo "**Disabling All Modules"
                for module in "${modules_available}"/*.ini ; do
                    case "${os}" in
                        "alpine" )
                            rm -f "${php_prefix}"/conf.d/$(cat ${module} | grep ";priority" | cut -d = -f 2)-$(basename ${module})
                        ;;
                        "debian" )
                            silent phpdismod $(basename $module .ini)
                        ;;
                    esac
                done
            ;;
            "core" )
                php_env_modules_enabled=$(get_php_env_modules_enabled)
                for module in $php_env_modules_enabled ; do
                    if [ -f "${modules_available}/${module}.ini" ]; then
                        echo "Disabling ${module}"
                        case "${os}" in
                            "alpine" )
                                rm -f ${php_prefix}/conf.d/$(cat ${modules_available}/${module}.ini | grep ";priority" | cut -d = -f 2)-${module}.ini
                            ;;
                            "debian" )
                                silent phpdismod $(basename ${module} .ini)
                                if [ "${php_major_version}" != "8" ] ; then phpdismod json ; fi
                                if [[ "$( ls -l ${php_prefix}/fpm/conf.d/*-opcache.ini |  wc -l )" -ge 1 ]] ; then
                                    rm -f "$(ls ${php_prefix}/fpm/conf.d/*-opcache.ini | tail -1 )"
                                fi
                                if [[ "$( ls -l ${php_prefix}/cli/conf.d/*-opcache.ini |  wc -l )" -ge 1 ]] ; then
                                    rm -f "$(ls ${php_prefix}/cli/conf.d/*-opcache.ini | tail -1 )"
                                fi
                            ;;
                        esac
                        php_script_modules_disabled="${php_actual_modules_disabled} $(basename ${module} .ini)"
                    else
                        echo "[php-ext] WARN Requested disabling ${module} however it doesn't exist!"
                    fi
                done
            ;;
            "optional" )
                php_env_modules_enabled=$(get_php_env_modules_enabled)
                echo "** Disabling Optional Modules"
                for module in ${modules_available}/*.ini; do
                    MATCH=0
                    for plugin in $php_env_modules_enabled ; do
                        if [ "$(basename ${module} .ini)" = "${plugin}" ] ; then
                            (( MATCH+=1 ))
                        fi
                    done

                    if [[ "$MATCH" -lt 1 ]] ; then
                        echo "Disabling $(basename $module .ini)"
                        case "${os}" in
                            "alpine" )
                                rm -f "${php_prefix}"conf.d/$(cat ${module} | grep ";priority" | cut -d = -f 2)-$(basename ${module})
                            ;;
                            "debian" )
                                silent phpdismod $(basename ${module} .ini)
                            ;;
                        esac
                    fi
                done
            ;;
            reset )
                case "${os}" in
                    "alpine" )
                        rm -rf ${php_prefix}conf.d/*
                    ;;
                    "debian" )
                        rm -rf ${php_prefix}/*/conf.d/*
                    ;;
                esac
            ;;
            * )
                if [ -f "${modules_available}/${1}.ini" ]; then
                    echo "Disabling ${1}"
                        case "${os}" in
                            "alpine" )
                                rm -f ${php_prefix}conf.d/$(cat ${modules_available}/${1}.ini | grep ";priority" | cut -d = -f 2)-$1.ini
                            ;;
                            "debian" )
                                silent phpdismod ${1}
                            ;;
                        esac
                else
                    echo "[php-ext] WARN Requested disabling '$1' module however it doesn't exist!"
                fi
            ;;
        esac
    else
       echo "** Disable Module"
       echo "Commands: all | core | optional | (modulename)"
    fi
}

enable_module () {
    if [ -n "${1}" ]; then
        case "${1}" in
                "all" )
                    echo "[php-ext] Enabling All Modules"
                    for module in "${modules_available}"/*.ini; do
                        echo "[php-ext] Enabling ${module}"
                        case "${os}" in
                            "alpine" )
                                ln -sf "${module}" "${php_prefix}"/conf.d/$(cat "${module}" | grep ";priority" | cut -d = -f 2)-$(basename "${module}")
                            ;;
                            "debian" )
                                silent phpenmod $(basename "${module}" .ini)
                            ;;
                        esac
                    done
                ;;
                "core" )
                    php_env_modules_enabled=$(get_php_env_modules_enabled | sed "/^json/d")
                    for module in ${php_env_modules_enabled} ; do
                        if [ -f "${modules_available}"/"${module}".ini ]; then
                            echo "[php-ext] Enabling '$(basename "${module}" .ini)' module"
                            case "${os}" in
                                "alpine" )
                                    ln -sf "${modules_available}/${module}.ini" ${php_prefix}/conf.d/$(cat ${modules_available}/${module}.ini | grep ";priority" | cut -d = -f 2)-${module}.ini
                                    if [ "${php_major_version}" != "8" ] ; then
                                        if [ -f "${modules_available}/json.ini" ]; then
                                            ln -sf "${modules_available}/json.ini" ${php_prefix}/conf.d/$(cat ${modules_available}/json.ini | grep ";priority" | cut -d = -f 2)-json.ini
                                        fi
                                    fi
                                ;;
                                "debian" )
                                    silent phpenmod $(basename $module .ini)
                                    if [ "${php_major_version}" != "8" ] ; then silent phpenmod json ; fi
                                    if [[ "$( ls -l ${php_prefix}/fpm/conf.d/*-opcache.ini |  wc -l )" -gt 1 ]] ; then
                                       rm -f "$(ls ${php_prefix}/fpm/conf.d/*-opcache.ini | tail -1 )"
                                    fi
                                    if [[ "$( ls -l ${php_prefix}/cli/conf.d/*-opcache.ini |  wc -l )" -gt 1 ]] ; then
                                       rm -f "$(ls ${php_prefix}/cli/conf.d/*-opcache.ini | tail -1 )"
                                    fi
                                ;;
                            esac
                            php_script_modules_enabled="${php_actual_modules_enabled} $(basename $module .ini)"
                        else
                            echo "[php-ext] ERROR Requested enabling '$(basename $module .ini)' module however it doesn't exist!"
                        fi
                    done
                ;;
                "optional" )
                    php_env_modules_enabled=$(get_php_env_modules_enabled)
                    echo "** Activating Optional Modules"
                    for module in "${modules_available}"/*.ini; do
                        if ! grep -w -i -q "$(basename ${module} .ini)" "${php_env_modules_enabled}"; then
                            echo "[php-ext] Enabling $(basename ${module} .ini)"
                            case "${os}" in
                                "alpine" )
                                    ln -sf "${module}" ${php_prefix}conf.d/$(cat ${module} | grep ";priority" | cut -d = -f 2)-$(basename ${module})
                                ;;
                                "debian" )
                                    silent phpenmod $(basename ${module} .ini)
                                ;;
                            esac
                            php_script_modules_enabled="${php_actual_modules_enabled} $(basename ${module} .ini)"
                        fi
                    done

                php_env_modules_enabled=$(get_php_env_modules_enabled)
                    echo "** Activating Optional Modules"
                    for module in "${modules_available}"/*.ini; do
                        MATCH=0
                        for plugin in $php_env_modules_enabled ; do
                            if [ "$(basename ${module} .ini)" = "${plugin}" ] ; then
                                (( MATCH+=1 ))
                            fi
                        done

                        if [[ "$MATCH" -lt 1 ]] ; then
                            echo "[php-ext] Enabling $(basename ${module} .ini)"
                            case "${os}" in
                                "alpine" )
                                    ln -sf "${module}" ${php_prefix}conf.d/$(cat ${module} | grep ";priority" | cut -d = -f 2)-$(basename ${module})
                                ;;
                                "debian" )
                                    silent phpdismod $(basename ${module} .ini)
                                ;;
                            esac
                        fi
                    done
                ;;
                * )
                    if [ -f "${modules_available}/$1.ini" ]; then
                        echo "Enabling $1"
                        case "${os}" in
                                "alpine" )
                                    ln -sf "${modules_available}/$1.ini" ${php_prefix}conf.d/$(cat ${modules_available}/${1}.ini | grep ";priority" | cut -d = -f 2)-$1.ini
                                ;;
                                "debian" )
                                    silent phpenmod "$1"
                                ;;
                        esac

                    else
                        echo "[php-ext] ERROR Requested enabling '${1}' module however it doesn't exist!"
                    fi
                ;;
        esac
    else
       echo "** Enable Module"
       echo "Commands: all | core | optional | (modulename)"
    fi
}

info() {
    if [ -n "${1}" ]; then
        case "${1,,}" in
            "base" )
                echo "${php_base}"
            ;;
            "base_alt" )
                echo "${php_base/./}"
            ;;
            "help" )
                echo "Commands: base | modules_path | prefix | version"
            ;;
            "modules_path" )
                echo "${modules_available}"
            ;;
            "prefix" )
                echo "${php_prefix}"
            ;;
            "version" )
                echo "${php_version}"
            ;;
        esac
    else
        echo "** Info"
        echo "Commands: base | modules_path | prefix | version"
    fi
}

list_module() {
    if [ -n "${1}" ]; then
        case "${1,,}" in
            "all" )
                echo "[php-ext] Listing All Modules"
                for module in ${modules_available}/*.ini; do
                    echo "$(basename $module .ini)"
                done
            ;;
            "core"  )
                echo "[php-ext] Listing Core Modules"
                php_env_modules_enabled=$(get_php_env_modules_enabled)
                for module in $php_env_modules_enabled ; do
                    if [ -f "${modules_available}/${module}.ini" ]; then
                        echo "${module}"
                    else
                        echo "** ERROR: '${module}' module enabled but doesn't exist"
                    fi
                done
            ;;
            "optional" )
                echo "[php-ext] Listing Optional Modules"
                php_env_modules_enabled=$(get_php_env_modules_enabled)

                for module in ${modules_available}/*.ini; do
                    MATCH=0
                    for plugin in $php_env_modules_enabled ; do
                        if [ "$(basename ${module} .ini)" = "${plugin}" ] ; then
                            (( MATCH+=1 ))
                        fi
                    done

                    if [[ "$MATCH" -lt 1 ]] ; then
                        echo "$(basename $module .ini)"
                    fi
                done
            ;;
        esac
    else
       echo "** List Modules"
       echo "Commands: all | core | optional"
    fi
}

display_help() {
    cat <<EOF

    PHP Module Tool - Use this to
    Syntax: $(basename $0) <command> <argument>

    Command: enable | disable | list | help
       enable - Enable a module for usage
       disable - Disable a mdule for usage
       info - Get information about the PHP install
       list - List available modules
       help - This is it

    Argument: all | core | optional | <module_name>
       all - Every Module
       core - Modules set via environment variable PHP_MODULE_ENABLE_*=TRUE
       optional - All other modules not explicitly set with PHP_MODULE_ENABLE_*=TRUE
       module_name - The PHP Extension name ie 'zip'
EOF
}

prepare() {
    case "${os}" in
        "alpine" )
            mkdir -p ${modules_available}
            for module in ${php_prefix}/conf.d/*.ini; do
                if [ ! -L "${module}" ] ; then
                    ## Assign Priority 20 to filenames without prefix
                    if ! [[ "$(basename $module .ini)" =~  ^[0-9][0-9] ]] ; then
                        mv "${module}" "$(dirname ${module})/20_$(basename ${module})"
                        module="$(dirname ${module})/20_$(basename ${module})"
                    fi
                    ## Add Priority Comment into file for later use
                    if ! grep -w -i -q ";priority" "$module"; then
                        echo ";priority=$(basename $module .ini | cut -d _ -f1)" >> $module
                        mv "${module}" "${modules_available}"/$(basename ${module} .ini | cut -c 4-).ini
                    fi
                fi
            done
        ;;
    esac
}

get_php_env_modules_enabled() {
    set -o posix; set | sort | grep "^PHP_MODULE_ENABLE_.*=" | grep -i TRUE | cut -d _ -f 4- | cut -d = -f 1 | tr A-Z a-z
}

silent() {
    ## Quiet down output
    if [ "${DEBUG_MODE}" = "true" ] || [ "${SHOW_OUTPUT,,}" = "true" ] || [ "${CONTAINER_LOG_LEVEL,,}" = "debug" ] ;  then
        "$@"
    else
        "$@" > /dev/null 2>&1
    fi
}

if [ "${PHP_MODULE_ENABLE_OPENSSL,,}" = "true" ] && [ ! -f "${modules_available}"/openssl.ini ]; then
    export PHP_MODULE_ENABLE_OPENSSL=FALSE
fi

if [ -n "$1" ] ; then
    case "${1,,}" in
        "enable" )
            enable_module "$2"
            if [[ "$(pgrep -f 'php-fpm: master process')" -ge "1" ]] ; then
                pkill php-fpm
            fi
        ;;
        "disable" )
            disable_module "$2"
            if [[ "$(pgrep -f 'php-fpm: master process')" -ge "1" ]] ; then
                pkill php-fpm
            fi
        ;;
        "info" )
            info "$2"
        ;;
        "list" )
            list_module "$2"
        ;;
        "prepare" )
            prepare
        ;;
        "help" )
            display_help "$2"
        ;;
    esac
else
    echo "PHP Module Tool"
    echo "Commands: enable | disable | list | info | help"
fi


================================================
FILE: zabbix_templates/app-php_fpm.json
================================================
{
    "zabbix_export": {
        "version": "5.4",
        "date": "2021-12-09T00:36:45Z",
        "groups": [
            {
                "uuid": "a571c0d144b14fd4a87a9d9b2aa9fcd6",
                "name": "Templates/Applications"
            }
        ],
        "templates": [
            {
                "uuid": "1cbda0970410425684135884d0cb7090",
                "template": "PHP FPM",
                "name": "PHP FPM",
                "description": "Get PHP-FPM metrics using Zabbix agent running on Linux.\n\nThis template is meant to be used with https://github.com/nfrastack/container-nginx-php-fpm",
                "groups": [
                    {
                        "name": "Templates/Applications"
                    }
                ],
                "items": [
                    {
                        "uuid": "9ae9e2a8203a48a7a482ef6d6ae9886c",
                        "name": "PHP-FPM: Accepted connections per second",
                        "type": "DEPENDENT",
                        "key": "php-fpm.conn_accepted.rate",
                        "delay": "0",
                        "history": "7d",
                        "value_type": "FLOAT",
                        "description": "The number of accepted requests per second.",
                        "preprocessing": [
                            {
                                "type": "JSONPATH",
                                "parameters": [
                                    "$.['accepted conn']"
                                ]
                            },
                            {
                                "type": "CHANGE_PER_SECOND",
                                "parameters": [
                                    ""
                                ]
                            }
                        ],
                        "master_item": {
                            "key": "web.page.get[\"{$PHP_FPM.HOST}\",\"{$PHP_FPM.STATUS.PAGE}?json\",\"{$PHP_FPM.PORT}\"]"
                        },
                        "tags": [
                            {
                                "tag": "Application",
                                "value": "PHP-FPM"
                            }
                        ]
                    },
                    {
                        "uuid": "edc6b68194fe429facfb6b22425ff0d4",
                        "name": "PHP-FPM: Listen queue",
                        "type": "DEPENDENT",
                        "key": "php-fpm.listen_queue",
                        "delay": "0",
                        "history": "7d",
                        "description": "The current number of connections that have been initiated, but not yet accepted.",
                        "preprocessing": [
                            {
                                "type": "JSONPATH",
                                "parameters": [
                                    "$.['listen queue']"
                                ]
                            }
                        ],
                        "master_item": {
                            "key": "web.page.get[\"{$PHP_FPM.HOST}\",\"{$PHP_FPM.STATUS.PAGE}?json\",\"{$PHP_FPM.PORT}\"]"
                        },
                        "tags": [
                            {
                                "tag": "Application",
                                "value": "PHP-FPM"
                            }
                        ]
                    },
                    {
                        "uuid": "2ff9f072b06a4b56afb0e0f44b2c83a4",
                        "name": "PHP-FPM: Listen queue, len",
                        "type": "DEPENDENT",
                        "key": "php-fpm.listen_queue_len",
                        "delay": "0",
                        "history": "7d",
                        "description": "Size of the socket queue of pending connections.",
                        "preprocessing": [
                            {
                                "type": "JSONPATH",
                                "parameters": [
                                    "$.['listen queue len']"
                                ]
                            }
                        ],
                        "master_item": {
                            "key": "web.page.get[\"{$PHP_FPM.HOST}\",\"{$PHP_FPM.STATUS.PAGE}?json\",\"{$PHP_FPM.PORT}\"]"
                        },
                        "tags": [
                            {
                                "tag": "Application",
                                "value": "PHP-FPM"
                            }
                        ]
                    },
                    {
                        "uuid": "2e0a543bee5a46c88085b2aba2f4976f",
                        "name": "PHP-FPM: Listen queue, max",
                        "type": "DEPENDENT",
                        "key": "php-fpm.listen_queue_max",
                        "delay": "0",
                        "history": "7d",
                        "description": "The maximum number of requests in the queue of pending connections since this FPM pool has started.",
                        "preprocessing": [
                            {
                                "type": "JSONPATH",
                                "parameters": [
                                    "$.['max listen queue']"
                                ]
                            }
                        ],
                        "master_item": {
                            "key": "web.page.get[\"{$PHP_FPM.HOST}\",\"{$PHP_FPM.STATUS.PAGE}?json\",\"{$PHP_FPM.PORT}\"]"
                        },
                        "tags": [
                            {
                                "tag": "Application",
                                "value": "PHP-FPM"
                            }
                        ]
                    },
                    {
                        "uuid": "2fabcd55c13449c29a48b70fdce77674",
                        "name": "PHP-FPM: Queue usage",
                        "type": "CALCULATED",
                        "key": "php-fpm.listen_queue_usage",
                        "history": "7d",
                        "value_type": "FLOAT",
                        "units": "%",
                        "params": "last(//php-fpm.listen_queue)/(last(//php-fpm.listen_queue_len)+(last(//php-fpm.listen_queue_len)=0))*100",
                        "description": "Queue utilization",
                        "tags": [
                            {
                                "tag": "Application",
                                "value": "PHP-FPM"
                            }
                        ],
                        "triggers": [
                            {
                                "uuid": "412264f0e1174b7fb81b457dad1a745f",
                                "expression": "min(/PHP FPM/php-fpm.listen_queue_usage,15m)  > {$PHP_FPM.QUEUE.WARN.MAX}",
                                "name": "PHP-FPM: Queue utilization is high (over {$PHP_FPM.QUEUE.WARN.MAX}% for 15m)",
                                "priority": "WARNING",
                                "description": "The queue for this pool reached {$PHP_FPM.QUEUE.WARN.MAX}% of its maximum capacity. Items in queue represent the current number of connections that have been initiated on this pool, but not yet accepted."
                            }
                        ]
                    },
                    {
                        "uuid": "e9d89669cf53492a9d5ef7ff997e1a40",
                        "name": "PHP-FPM: Max children reached",
                        "type": "DEPENDENT",
                        "key": "php-fpm.max_children",
                        "delay": "0",
                        "history": "7d",
                        "description": "The number of times that pm.max_children has been reached since the php-fpm pool started",
                        "preprocessing": [
                            {
                                "type": "JSONPATH",
                                "parameters": [
                                    "$.['max children reached']"
                                ]
                            },
                            {
                                "type": "SIMPLE_CHANGE",
                                "parameters": [
                                    ""
                                ]
                            }
                        ],
                        "master_item": {
                            "key": "web.page.get[\"{$PHP_FPM.HOST}\",\"{$PHP_FPM.STATUS.PAGE}?json\",\"{$PHP_FPM.PORT}\"]"
                        },
                        "tags": [
                            {
                                "tag": "Application",
                                "value": "PHP-FPM"
                            }
                        ]
                    },
                    {
                        "uuid": "830e04be30f03e50ac0fa4783ecdc677",
                        "name": "PHP-FPM: Pool name",
                        "type": "DEPENDENT",
                        "key": "php-fpm.name",
                        "delay": "0",
                        "history": "7d",
                        "trends": "0",
                        "value_type": "CHAR",
                        "description": "The name of current pool.",
                        "preprocessing": [
                            {
                                "type": "JSONPATH",
                                "parameters": [
                                    "$.pool"
                                ]
                            },
                            {
                                "type": "DISCARD_UNCHANGED_HEARTBEAT",
                                "parameters": [
                                    "3h"
                                ]
                            }
                        ],
                        "master_item": {
                            "key": "web.page.get[\"{$PHP_FPM.HOST}\",\"{$PHP_FPM.STATUS.PAGE}?json\",\"{$PHP_FPM.PORT}\"]"
                        },
                        "tags": [
                            {
                                "tag": "Application",
                                "value": "PHP-FPM"
                            }
                        ]
                    },
                    {
                        "uuid": "8ebee5fc8c853a96b34ed743e3dd0154",
                        "name": "PHP-FPM: Processes, active",
                        "type": "DEPENDENT",
                        "key": "php-fpm.processes_active",
                        "delay": "0",
                        "history": "7d",
                        "description": "The total number of active processes.",
                        "preprocessing": [
                            {
                                "type": "JSONPATH",
                                "parameters": [
                                    "$.['active processes']"
                                ]
                            }
                        ],
                        "master_item": {
                            "key": "web.page.get[\"{$PHP_FPM.HOST}\",\"{$PHP_FPM.STATUS.PAGE}?json\",\"{$PHP_FPM.PORT}\"]"
                        },
                        "tags": [
                            {
                                "tag": "Application",
                                "value": "PHP-FPM"
                            }
                        ]
                    },
                    {
                        "uuid": "11cfd028325232a58d61d9e83aee640b",
                        "name": "PHP-FPM: Processes, idle",
                        "type": "DEPENDENT",
                        "key": "php-fpm.processes_idle",
                        "delay": "0",
                        "history": "7d",
                        "description": "The total number of idle processes.",
                        "preprocessing": [
                            {
                                "type": "JSONPATH",
                                "parameters": [
                                    "$.['idle processes']"
                                ]
                            }
                        ],
                        "master_item": {
                            "key": "web.page.get[\"{$PHP_FPM.HOST}\",\"{$PHP_FPM.STATUS.PAGE}?json\",\"{$PHP_FPM.PORT}\"]"
                        },
                        "tags": [
                            {
                                "tag": "Application",
                                "value": "PHP-FPM"
                            }
                        ]
                    },
                    {
                        "uuid": "3858218f90683bb19cbe27fc9aedf404",
                        "name": "PHP-FPM: Processes, max active",
                        "type": "DEPENDENT",
                        "key": "php-fpm.processes_max_active",
                        "delay": "0",
                        "history": "7d",
                        "description": "The highest value that 'active processes' has reached since the php-fpm server started.",
                        "preprocessing": [
                            {
                                "type": "JSONPATH",
                                "parameters": [
                                    "$.['max active processes']"
                                ]
                            }
                        ],
                        "master_item": {
                            "key": "web.page.get[\"{$PHP_FPM.HOST}\",\"{$PHP_FPM.STATUS.PAGE}?json\",\"{$PHP_FPM.PORT}\"]"
                        },
                        "tags": [
                            {
                                "tag": "Application",
                                "value": "PHP-FPM"
                            }
                        ]
                    },
                    {
                        "uuid": "a79af6cf38ec35518055c64aa7f1f5a2",
                        "name": "PHP-FPM: Processes, total",
                        "type": "DEPENDENT",
                        "key": "php-fpm.processes_total",
                        "delay": "0",
                        "history": "7d",
                        "description": "The total number of server processes currently running.",
                        "preprocessing": [
                            {
                                "type": "JSONPATH",
                                "parameters": [
                                    "$.['total processes']"
                                ]
                            }
                        ],
                        "master_item": {
                            "key": "web.page.get[\"{$PHP_FPM.HOST}\",\"{$PHP_FPM.STATUS.PAGE}?json\",\"{$PHP_FPM.PORT}\"]"
                        },
                        "tags": [
                            {
                                "tag": "Application",
                                "value": "PHP-FPM"
                            }
                        ]
                    },
                    {
                        "uuid": "5ab12fc9f4ef39e5bbf7b2c6a840879e",
                        "name": "PHP-FPM: Process manager",
                        "type": "DEPENDENT",
                        "key": "php-fpm.process_manager",
                        "delay": "0",
                        "history": "7d",
                        "trends": "0",
                        "value_type": "CHAR",
                        "description": "The method used by the process manager to control the number of child processes for this pool.",
                        "preprocessing": [
                            {
                                "type": "JSONPATH",
                                "parameters": [
                                    "$.['process manager']"
                                ]
                            },
                            {
                                "type": "DISCARD_UNCHANGED_HEARTBEAT",
                                "parameters": [
                                    "3h"
                                ]
                            }
                        ],
                        "master_item": {
                            "key": "web.page.get[\"{$PHP_FPM.HOST}\",\"{$PHP_FPM.STATUS.PAGE}?json\",\"{$PHP_FPM.PORT}\"]"
                        },
                        "tags": [
                            {
                                "tag": "Application",
                                "value": "PHP-FPM"
                            }
                        ],
                        "triggers": [
                            {
                                "uuid": "231e03bfb6e94f34b790576766244602",
                                "expression": "last(/PHP FPM/php-fpm.process_manager,#1)<>last(/PHP FPM/php-fpm.process_manager,#2)",
                                "name": "PHP-FPM: Manager  changed (new value received: {ITEM.VALUE})",
                                "priority": "INFO",
                                "description": "PHP-FPM manager changed. Ack to close.",
                                "manual_close": "YES"
                            }
                        ]
                    },
                    {
                        "uuid": "4d17b6d89ac93d0880eac6962ebf7347",
                        "name": "PHP-FPM: Slow requests",
                        "type": "DEPENDENT",
                        "key": "php-fpm.slow_requests",
                        "delay": "0",
                        "history": "7d",
                        "description": "The number of requests that exceeded your request_slowlog_timeout value.",
                        "preprocessing": [
                            {
                                "type": "JSONPATH",
                                "parameters": [
                                    "$.['slow requests']"
                                ]
                            },
                            {
                                "type": "SIMPLE_CHANGE",
                                "parameters": [
                                    ""
                                ]
                            }
                        ],
                        "master_item": {
                            "key": "web.page.get[\"{$PHP_FPM.HOST}\",\"{$PHP_FPM.STATUS.PAGE}?json\",\"{$PHP_FPM.PORT}\"]"
                        },
                        "tags": [
                            {
                                "tag": "Application",
                                "value": "PHP-FPM"
                            }
                        ],
                        "triggers": [
                            {
                                "uuid": "f30143d8e92f48aa8fedc2d28b8d7c70",
                                "expression": "min(/PHP FPM/php-fpm.slow_requests,#3)>0",
                                "name": "PHP-FPM: Detected slow requests",
                                "priority": "WARNING",
                                "description": "PHP-FPM detected slow request. A slow request means that it took more time to execute than expected (defined in the configuration of your pool)."
                            }
                        ]
                    },
                    {
                        "uuid": "4e4d6eda8fbb4d32ba7f48fba5723473",
                        "name": "PHP-FPM: Start time",
                        "type": "DEPENDENT",
                        "key": "php-fpm.start_time",
                        "delay": "0",
                        "history": "7d",
                        "units": "unixtime",
                        "description": "The time when this pool was started.",
                        "preprocessing": [
                            {
                                "type": "JSONPATH",
                                "parameters": [
                                    "$.['start time']"
                                ]
                            }
                        ],
                        "master_item": {
                            "key": "web.page.get[\"{$PHP_FPM.HOST}\",\"{$PHP_FPM.STATUS.PAGE}?json\",\"{$PHP_FPM.PORT}\"]"
                        },
                        "tags": [
                            {
                                "tag": "Application",
                                "value": "PHP-FPM"
                            }
                        ]
                    },
                    {
                        "uuid": "2a19b306712a47939e70d3ec30e39b05",
                        "name": "PHP-FPM: Uptime",
                        "type": "DEPENDENT",
                        "key": "php-fpm.uptime",
                        "delay": "0",
                        "history": "7d",
                        "units": "s",
                        "description": "How long has this pool been running.",
                        "preprocessing": [
                            {
                                "type": "JSONPATH",
                                "parameters": [
                                    "$.['start since']"
                                ]
                            }
                        ],
                        "master_item": {
                            "key": "web.page.get[\"{$PHP_FPM.HOST}\",\"{$PHP_FPM.STATUS.PAGE}?json\",\"{$PHP_FPM.PORT}\"]"
                        },
                        "tags": [
                            {
                                "tag": "Application",
                                "value": "PHP-FPM"
                            }
                        ],
                        "triggers": [
                            {
                                "uuid": "bdf9962a3e2049a8aec000b037b94d60",
                                "expression": "nodata(/PHP FPM/php-fpm.uptime,30m)=1",
                                "name": "PHP-FPM: Failed to fetch info data (or no data for 30m)",
                                "priority": "INFO",
                                "description": "Zabbix has not received data for items for the last 30 minutes",
                                "manual_close": "YES",
                                "dependencies": [
                                    {
                                        "name": "PHP-FPM: Process is not running",
                                        "expression": "last(/PHP FPM/proc.num[\"{$PHP_FPM.SERVICE_NAME}\"])=0"
                                    }
                                ]
                            },
                            {
                                "uuid": "c6966a6c33f0452ab4fd112c9299e624",
                                "expression": "last(/PHP FPM/php-fpm.uptime)<10m",
                                "name": "PHP-FPM: has been restarted (uptime < 10m)",
                                "priority": "INFO",
                                "description": "Uptime is less than 10 minutes",
                                "manual_close": "YES"
                            }
                        ]
                    },
                    {
                        "uuid": "a709eaae52ad4128a139c618db6525d2",
                        "name": "PHP-FPM: CPU utilization",
                        "type": "ZABBIX_ACTIVE",
                        "key": "proc.cpu.util[\"{$PHP_FPM.SERVICE_NAME}\"]",
                        "history": "7d",
                        "value_type": "FLOAT",
                        "units": "%",
                        "description": "Process CPU utilization percentage.",
                        "tags": [
                            {
                                "tag": "Application",
                                "value": "PHP-FPM"
                            }
                        ]
                    },
                    {
                        "uuid": "ef771994ec9e482babf372d9f867d500",
                        "name": "PHP-FPM: Memory usage, %",
                        "type": "ZABBIX_ACTIVE",
                        "key": "proc.mem[\"{$PHP_FPM.SERVICE_NAME}\",,,,pmem]",
                        "history": "7d",
                        "value_type": "FLOAT",
                        "units": "%",
                        "description": "Memory used percentage relative to total memory available.",
                        "tags": [
                            {
                                "tag": "Application",
                                "value": "PHP-FPM"
                            }
                        ]
                    },
                    {
                        "uuid": "f55a5ef29f864d0a8c1a325df2372f7c",
                        "name": "PHP-FPM: Memory usage (rss)",
                        "type": "ZABBIX_ACTIVE",
                        "key": "proc.mem[\"{$PHP_FPM.SERVICE_NAME}\",,,,rss]",
                        "history": "7d",
                        "units": "B",
                        "description": "Resident set size memory used by process in bytes.",
                        "tags": [
                            {
                                "tag": "Application",
                                "value": "PHP-FPM"
                            }
                        ]
                    },
                    {
                        "uuid": "ab8dc0d1ce344fe8ae6a23716a168fbd",
                        "name": "PHP-FPM: Number of processes running",
                        "type": "ZABBIX_ACTIVE",
                        "key": "proc.num[\"{$PHP_FPM.SERVICE_NAME}\"]",
                        "history": "7d",
                        "tags": [
                            {
                                "tag": "Application",
                                "value": "PHP-FPM"
                            }
                        ],
                        "triggers": [
                            {
                                "uuid": "21a03d0ada634632ae9089a2cf3b4d70",
                                "expression": "last(/PHP FPM/proc.num[\"{$PHP_FPM.SERVICE_NAME}\"])=0",
                                "name": "PHP-FPM: Process is not running",
                                "priority": "HIGH"
                            }
                        ]
                    },
                    {
                        "uuid": "09ec73291f21417ab8f19f53fda3331f",
                        "name": "PHP-FPM: Get status page",
                        "type": "ZABBIX_ACTIVE",
                        "key": "web.page.get[\"{$PHP_FPM.HOST}\",\"{$PHP_FPM.STATUS.PAGE}?json\",\"{$PHP_FPM.PORT}\"]",
                        "history": "0",
                        "trends": "0",
                        "value_type": "TEXT",
                        "preprocessing": [
                            {
                                "type": "REGEX",
                                "parameters": [
                                    "^[.\\s\\S]*({.+})",
                                    "\\1"
                                ]
                            }
                        ],
                        "tags": [
                            {
                                "tag": "Application",
                                "value": "Zabbix raw items"
                            }
                        ]
                    }
                ],
                "macros": [
                    {
                        "macro": "{$PHP_FPM.HOST}",
                        "value": "localhost",
                        "description": "Hostname or IP of PHP-FPM status host or container."
                    },
                    {
                        "macro": "{$PHP_FPM.PORT}",
                        "value": "73",
                        "description": "The port of PHP-FPM status host or container."
                    },
                    {
                        "macro": "{$PHP_FPM.SERVICE_NAME}",
                        "value": "php-fpm",
                        "description": "PHP-FPM process name"
                    },
                    {
                        "macro": "{$PHP_FPM.QUEUE.WARN.MAX}",
                        "value": "80",
                        "description": "The maximum PHP-FPM queue usage percent for trigger expression."
                    },
                    {
                        "macro": "{$PHP_FPM.STATUS.PAGE}",
                        "value": "php-fpm_status",
                        "description": "The path of PHP-FPM status page."
                    }
                ],
                "dashboards": [
                    {
                        "uuid": "aa710e8b45a14da582a2e8853a944b23",
                        "name": "PHP-FPM",
                        "pages": [
                            {
                                "widgets": [
                                    {
                                        "type": "GRAPH_CLASSIC",
                                        "name": "Accepted Connections per second",
                                        "y": "5",
                                        "width": "12",
                                        "height": "5",
                                        "fields": [
                                            {
                                                "type": "GRAPH",
                                                "name": "graphid",
                                                "value": {
                                                    "name": "PHP-FPM: Accepted Connections per second",
                                                    "host": "PHP FPM"
                                                }
                                            }
                                        ]
                                    },
                                    {
                                        "type": "GRAPH_CLASSIC",
                                        "name": "CPU Utilization",
                                        "width": "12",
                                        "height": "5",
                                        "fields": [
                                            {
                                                "type": "GRAPH",
                                                "name": "graphid",
                                                "value": {
                                                    "name": "PHP-FPM: CPU Utilization",
                                                    "host": "PHP FPM"
                                                }
                                            }
                                        ]
                                    },
                                    {
                                        "type": "GRAPH_CLASSIC",
                                        "name": "Memory Utilization",
                                        "x": "12",
                                        "width": "11",
                                        "height": "5",
                                        "fields": [
                                            {
                                                "type": "GRAPH",
                                                "name": "graphid",
                                                "value": {
                                                    "name": "PHP-FPM: Memory Utilization",
                                                    "host": "PHP FPM"
                                                }
                                            }
                                        ]
                                    },
                                    {
                                        "type": "GRAPH_CLASSIC",
                                        "name": "Processes",
                                        "x": "12",
                                        "y": "5",
                                        "width": "11",
                                        "height": "5",
                                        "fields": [
                                            {
                                                "type": "GRAPH",
                                                "name": "graphid",
                                                "value": {
                                                    "name": "PHP-FPM: Process",
                                                    "host": "PHP FPM"
                                                }
                                            }
                                        ]
                                    },
                                    {
                                        "type": "GRAPH_CLASSIC",
                                        "name": "Queue",
                                        "y": "10",
                                        "width": "12",
                                        "height": "5",
                                        "fields": [
                                            {
                                                "type": "GRAPH",
                                                "name": "graphid",
                                                "value": {
                                                    "name": "PHP-FPM: Queue",
                                                    "host": "PHP FPM"
                                                }
                                            }
                                        ]
                                    }
                                ]
                            }
                        ]
                    }
                ],
                "valuemaps": [
                    {
                        "uuid": "1caa1e7c41e14c7492ab8112f33ea068",
                        "name": "Service state",
                        "mappings": [
                            {
                                "value": "0",
                                "newvalue": "Down"
                            },
                            {
                                "value": "1",
                                "newvalue": "Up"
                            }
                        ]
                    }
                ]
            },
            {
                "uuid": "1cbda0970410435684135884d0cb7090",
                "template": "PHP FPM - Passive",
                "name": "PHP FPM - Passive",
                "description": "Get PHP-FPM metrics using Zabbix agent running on Linux.\n\nThis template is meant to be used with https://github.com/tiredofit/docker-nginx-php-fpm",
                "groups": [
                    {
                        "name": "Templates/Applications"
                    }
                ],
                "items": [
                    {
                        "uuid": "9ae9e2a8003a48a7a482ef6d6ae9886c",
                        "name": "PHP-FPM: Accepted connections per second",
                        "type": "DEPENDENT",
                        "key": "php-fpm.conn_accepted.rate",
                        "delay": "0",
                        "history": "7d",
                        "value_type": "FLOAT",
                        "description": "The number of accepted requests per second.",
                        "preprocessing": [
                            {
                                "type": "JSONPATH",
                                "parameters": [
                                    "$.['accepted conn']"
                                ]
                            },
                            {
                                "type": "CHANGE_PER_SECOND",
                                "parameters": [
                                    ""
                                ]
                            }
                        ],
                        "master_item": {
                            "key": "web.page.get[\"{$PHP_FPM.HOST}\",\"{$PHP_FPM.STATUS.PAGE}?json\",\"{$PHP_FPM.PORT}\"]"
                        },
                        "tags": [
                            {
                                "tag": "Application",
                                "value": "PHP-FPM"
                            }
                        ]
                    },
                    {
                        "uuid": "edc6b68194fe499facfb6b22425ff0d4",
                        "name": "PHP-FPM: Listen queue",
                        "type": "DEPENDENT",
                        "key": "php-fpm.listen_queue",
                        "delay": "0",
                        "history": "7d",
                        "description": "The current number of connections that have been initiated, but not yet accepted.",
                        "preprocessing": [
                            {
                                "type": "JSONPATH",
                                "parameters": [
                                    "$.['listen queue']"
                                ]
                            }
                        ],
                        "master_item": {
                            "key": "web.page.get[\"{$PHP_FPM.HOST}\",\"{$PHP_FPM.STATUS.PAGE}?json\",\"{$PHP_FPM.PORT}\"]"
                        },
                        "tags": [
                            {
                                "tag": "Application",
                                "value": "PHP-FPM"
                            }
                        ]
                    },
                    {
                        "uuid": "aff9f072b06a4b56afb0e0f44b2c83a4",
                        "name": "PHP-FPM: Listen queue, len",
                        "type": "DEPENDENT",
                        "key": "php-fpm.listen_queue_len",
                        "delay": "0",
                        "history": "7d",
                        "description": "Size of the socket queue of pending connections.",
                        "preprocessing": [
                            {
                                "type": "JSONPATH",
                                "parameters": [
                                    "$.['listen queue len']"
                                ]
                            }
                        ],
                        "master_item": {
                            "key": "web.page.get[\"{$PHP_FPM.HOST}\",\"{$PHP_FPM.STATUS.PAGE}?json\",\"{$PHP_FPM.PORT}\"]"
                        },
                        "tags": [
                            {
                                "tag": "Application",
                                "value": "PHP-FPM"
                            }
                        ]
                    },
                    {
                        "uuid": "de0a543bee5a46c88085b2aba2f4976f",
                        "name": "PHP-FPM: Listen queue, max",
                        "type": "DEPENDENT",
                        "key": "php-fpm.listen_queue_max",
                        "delay": "0",
                        "history": "7d",
                        "description": "The maximum number of requests in the queue of pending connections since this FPM pool has started.",
                        "preprocessing": [
                            {
                                "type": "JSONPATH",
                                "parameters": [
                                    "$.['max listen queue']"
                                ]
                            }
                        ],
                        "master_item": {
                            "key": "web.page.get[\"{$PHP_FPM.HOST}\",\"{$PHP_FPM.STATUS.PAGE}?json\",\"{$PHP_FPM.PORT}\"]"
                        },
                        "tags": [
                            {
                                "tag": "Application",
                                "value": "PHP-FPM"
                            }
                        ]
                    },
                    {
                        "uuid": "dfabcd55c13449c29a48b70fdce77674",
                        "name": "PHP-FPM: Queue usage",
                        "type": "CALCULATED",
                        "key": "php-fpm.listen_queue_usage",
                        "history": "7d",
                        "value_type": "FLOAT",
                        "units": "%",
                        "params": "last(//php-fpm.listen_queue)/(last(//php-fpm.listen_queue_len)+(last(//php-fpm.listen_queue_len)=0))*100",
                        "description": "Queue utilization",
                        "tags": [
                            {
                                "tag": "Application",
                                "value": "PHP-FPM"
                            }
                        ],
                        "triggers": [
                            {
                                "uuid": "a11264f0e1174b7fb81b457dad1a745f",
                                "expression": "min(/PHP FPM - Passive/php-fpm.listen_queue_usage,15m)  > {$PHP_FPM.QUEUE.WARN.MAX}",
                                "name": "PHP-FPM: Queue utilization is high (over {$PHP_FPM.QUEUE.WARN.MAX}% for 15m)",
                                "priority": "WARNING",
                                "description": "The queue for this pool reached {$PHP_FPM.QUEUE.WARN.MAX}% of its maximum capacity. Items in queue represent the current number of connections that have been initiated on this pool, but not yet accepted."
                            }
                        ]
                    },
                    {
                        "uuid": "e9d49669cf58492a9d5ef7ff997e1a40",
                        "name": "PHP-FPM: Max children reached",
                        "type": "DEPENDENT",
                        "key": "php-fpm.max_children",
                        "delay": "0",
                        "history": "7d",
                        "description": "The number of times that pm.max_children has been reached since the php-fpm pool started",
                        "preprocessing": [
                            {
                      
Download .txt
gitextract_43589cx1/

├── .dockerignore
├── .github/
│   ├── FUNDING.yml
│   ├── ISSUE_TEMPLATE/
│   │   ├── bug_report.md
│   │   └── feature_request.md
│   ├── config.yml
│   └── workflows/
│       ├── build_manual.yml
│       ├── build_push.yml
│       └── image_build.yml
├── .gitignore
├── CHANGELOG.md
├── Containerfile
├── LICENSE
├── README.md
├── examples/
│   ├── .gitignore
│   ├── .gitkeep
│   └── compose.yml
├── rootfs/
│   ├── container/
│   │   ├── data/
│   │   │   ├── nginx/
│   │   │   │   └── templates/
│   │   │   │       ├── server/
│   │   │   │       │   └── http-fastcgi_hide_header_xpowered.template
│   │   │   │       └── site/
│   │   │   │           └── location-php-block.template
│   │   │   └── php-fpm/
│   │   │       ├── cli/
│   │   │       │   └── php.ini
│   │   │       ├── conf.available/
│   │   │       │   ├── apcu.ini
│   │   │       │   └── opcache.ini
│   │   │       ├── fpm/
│   │   │       │   ├── default.logformat
│   │   │       │   ├── json.logformat
│   │   │       │   └── php.ini
│   │   │       └── opcache/
│   │   │           ├── opcache-settings.php
│   │   │           └── opcache-status.php
│   │   ├── defaults/
│   │   │   ├── 20-php-fpm
│   │   │   └── _20-php-fpm/
│   │   │       ├── 20-php-fpm
│   │   │       └── 20-php-fpm.advanced
│   │   ├── functions/
│   │   │   ├── 20-php-fpm
│   │   │   └── 20-php-fpm.advanced
│   │   ├── init/
│   │   │   └── init.d/
│   │   │       └── 20-php-fpm
│   │   └── run/
│   │       └── available/
│   │           └── 20-php-fpm/
│   │               └── run
│   ├── etc/
│   │   ├── fluent-bit/
│   │   │   └── parsers.d/
│   │   │       └── phpfpm.conf
│   │   └── zabbix/
│   │       └── zabbix_agentd.conf.d/
│   │           └── php-fpm.conf
│   └── usr/
│       └── local/
│           └── bin/
│               └── php-ext
└── zabbix_templates/
    ├── app-php_fpm.json
    └── app-php_opcache.json
Condensed preview — 38 files, each showing path, character count, and a content snippet. Download the .json file or copy for the full structured content (387K chars).
[
  {
    "path": ".dockerignore",
    "chars": 10,
    "preview": "examples/\n"
  },
  {
    "path": ".github/FUNDING.yml",
    "chars": 20,
    "preview": "github: [tiredofit]\n"
  },
  {
    "path": ".github/ISSUE_TEMPLATE/bug_report.md",
    "chars": 904,
    "preview": "---\nname: Bug report\nabout: If something isn't working right..\ntitle: ''\nlabels: bug\nassignees: ''\n\n---\n\n### Summary\n\n<!"
  },
  {
    "path": ".github/ISSUE_TEMPLATE/feature_request.md",
    "chars": 476,
    "preview": "---\nname: Feature request\nabout: Suggest an idea or feature\ntitle: ''\nlabels: enhancement\nassignees: ''\n\n---\n\n---\nname: "
  },
  {
    "path": ".github/config.yml",
    "chars": 28,
    "preview": "blank_issues_enabled: false\n"
  },
  {
    "path": ".github/workflows/build_manual.yml",
    "chars": 475,
    "preview": "name: \"MANUAL - Build all images\"\n\non:\n  workflow_dispatch:\n    inputs:\n      Manual Build:\n        description: 'Manual"
  },
  {
    "path": ".github/workflows/build_push.yml",
    "chars": 517,
    "preview": "name: \"PUSH - Build on repository Push\"\non:\n  push:\n    paths:\n      - '**'\n      - '!/CHANGELOG.md'\n      - '!/examples"
  },
  {
    "path": ".github/workflows/image_build.yml",
    "chars": 3916,
    "preview": "name: build\n\non:\n  workflow_call\n\njobs:\n  build:\n    strategy:\n      fail-fast: false\n      matrix:\n        build:\n     "
  },
  {
    "path": ".gitignore",
    "chars": 39,
    "preview": "/build-assets/*\n!/build-assets/.empty\n\n"
  },
  {
    "path": "CHANGELOG.md",
    "chars": 25715,
    "preview": "## 8.1.0 2026-05-11 <code at nfrastack dot com>\n\n   ### Added\n      - Add PHPFPM_POOL_<NAME>_INCLUDES to add external in"
  },
  {
    "path": "Containerfile",
    "chars": 12413,
    "preview": "# SPDX-FileCopyrightText: © 2026 Nfrastack <code@nfrastack.com>\n#\n# SPDX-License-Identifier: MIT\n\nARG BASE_IMAGE\n\nFROM $"
  },
  {
    "path": "LICENSE",
    "chars": 1076,
    "preview": "The MIT License (MIT)\n\nCopyright (c) 2026 Nfrastack\n\nPermission is hereby granted, free of charge, to any person obtaini"
  },
  {
    "path": "README.md",
    "chars": 22830,
    "preview": "# nfrastack/container-nginx-php-fpm\n\n## About\n\nThis repository will build a [Nginx](https://www.nginx.org) w/[PHP-FPM](h"
  },
  {
    "path": "examples/.gitignore",
    "chars": 13,
    "preview": "!compose.yml\n"
  },
  {
    "path": "examples/.gitkeep",
    "chars": 0,
    "preview": ""
  },
  {
    "path": "examples/compose.yml",
    "chars": 518,
    "preview": "services:\n  npf-app:\n    image: docker.io/nfrastack/nginx-php-fpm/8.5-alpine\n    container_name: npf-app\n    labels:\n   "
  },
  {
    "path": "rootfs/container/data/nginx/templates/server/http-fastcgi_hide_header_xpowered.template",
    "chars": 132,
    "preview": "# SPDX-FileCopyrightText: © 2026 Nfrastack <code@nfrastack.com>\n#\n# SPDX-License-Identifier: MIT\n\nfastcgi_hide_header X-"
  },
  {
    "path": "rootfs/container/data/nginx/templates/site/location-php-block.template",
    "chars": 323,
    "preview": "# SPDX-FileCopyrightText: © 2026 Nfrastack <code@nfrastack.com>\n#\n# SPDX-License-Identifier: MIT\n\nlocation ~ [^/]\\.php(/"
  },
  {
    "path": "rootfs/container/data/php-fpm/cli/php.ini",
    "chars": 3883,
    "preview": "; SPDX-FileCopyrightText: © 2026 Nfrastack <code@nfrastack.com>\n;\n; SPDX-License-Identifier: MIT\n\n[PHP]\nengine = On\nallo"
  },
  {
    "path": "rootfs/container/data/php-fpm/conf.available/apcu.ini",
    "chars": 191,
    "preview": "; SPDX-FileCopyrightText: © 2026 Nfrastack <code@nfrastack.com>\n;\n; SPDX-License-Identifier: MIT\n\nextension=apcu.so\napc."
  },
  {
    "path": "rootfs/container/data/php-fpm/conf.available/opcache.ini",
    "chars": 492,
    "preview": "; SPDX-FileCopyrightText: © 2026 Nfrastack <code@nfrastack.com>\n;\n; SPDX-License-Identifier: MIT\n\nzend_extension=opcache"
  },
  {
    "path": "rootfs/container/data/php-fpm/fpm/default.logformat",
    "chars": 287,
    "preview": "; SPDX-FileCopyrightText: © 2026 Nfrastack <code@nfrastack.com>\n;\n; SPDX-License-Identifier: MIT\n\naccess.format='%{%Y-%m"
  },
  {
    "path": "rootfs/container/data/php-fpm/fpm/json.logformat",
    "chars": 520,
    "preview": "; SPDX-FileCopyrightText: © 2026 Nfrastack <code@nfrastack.com>\n;\n; SPDX-License-Identifier: MIT\n\naccess.format='{\"time\""
  },
  {
    "path": "rootfs/container/data/php-fpm/fpm/php.ini",
    "chars": 3888,
    "preview": "; SPDX-FileCopyrightText: © 2026 Nfrastack <code@nfrastack.com>\n;\n; SPDX-License-Identifier: MIT\n\n[PHP]\nengine = On\nallo"
  },
  {
    "path": "rootfs/container/data/php-fpm/opcache/opcache-settings.php",
    "chars": 6338,
    "preview": "<?php\n    $configuration = opcache_get_configuration();\n    echo \"opcache.enable: \" ; print ($configuration['directives'"
  },
  {
    "path": "rootfs/container/data/php-fpm/opcache/opcache-status.php",
    "chars": 89,
    "preview": "<?php\n  $status = opcache_get_status(false);\n  echo json_encode($status);\n  echo \"\\n\";\n?>"
  },
  {
    "path": "rootfs/container/defaults/20-php-fpm",
    "chars": 6826,
    "preview": "# SPDX-FileCopyrightText: © 2026 Nfrastack <code@nfrastack.com>\n#\n# SPDX-License-Identifier: MIT\n\nENABLE_PHP_FPM=${ENABL"
  },
  {
    "path": "rootfs/container/defaults/_20-php-fpm/20-php-fpm",
    "chars": 98,
    "preview": "# SPDX-FileCopyrightText: © 2026 Nfrastack <code@nfrastack.com>\n#\n# SPDX-License-Identifier: MIT\n\n"
  },
  {
    "path": "rootfs/container/defaults/_20-php-fpm/20-php-fpm.advanced",
    "chars": 97,
    "preview": "# SPDX-FileCopyrightText: © 2026 Nfrastack <code@nfrastack.com>\n#\n# SPDX-License-Identifier: MIT\n"
  },
  {
    "path": "rootfs/container/functions/20-php-fpm",
    "chars": 40313,
    "preview": "# SPDX-FileCopyrightText: © 2026 Nfrastack <code@nfrastack.com>\n#\n# SPDX-License-Identifier: MIT\n\nphpfpm_bootstrap() {\n "
  },
  {
    "path": "rootfs/container/functions/20-php-fpm.advanced",
    "chars": 98,
    "preview": "# SPDX-FileCopyrightText: © 2026 Nfrastack <code@nfrastack.com>\n#\n# SPDX-License-Identifier: MIT\n\n"
  },
  {
    "path": "rootfs/container/init/init.d/20-php-fpm",
    "chars": 2056,
    "preview": "#!/command/with-contenv bash\n# SPDX-FileCopyrightText: © 2026 Nfrastack <code@nfrastack.com>\n#\n# SPDX-License-Identifier"
  },
  {
    "path": "rootfs/container/run/available/20-php-fpm/run",
    "chars": 420,
    "preview": "#!/command/with-contenv bash\n# SPDX-FileCopyrightText: © 2026 Nfrastack <code@nfrastack.com>\n#\n# SPDX-License-Identifier"
  },
  {
    "path": "rootfs/etc/fluent-bit/parsers.d/phpfpm.conf",
    "chars": 597,
    "preview": "[PARSER]\n    Name   phpfpm\n    Format regex\n    Regex ^(?<time>[^ ]*) (?<remote_addr>[^ ]*) (?<host>[^ ]*) (?<remote_use"
  },
  {
    "path": "rootfs/etc/zabbix/zabbix_agentd.conf.d/php-fpm.conf",
    "chars": 195,
    "preview": "# PHP-FPM checking for Zabbix Agent 5.4+\n# All data metric collection is handled by the template\n# Get the template at h"
  },
  {
    "path": "rootfs/usr/local/bin/php-ext",
    "chars": 16501,
    "preview": "#!/command/with-contenv bash\n# SPDX-FileCopyrightText: © 2026 Nfrastack <code@nfrastack.com>\n#\n# SPDX-License-Identifier"
  },
  {
    "path": "zabbix_templates/app-php_fpm.json",
    "chars": 76820,
    "preview": "{\n    \"zabbix_export\": {\n        \"version\": \"5.4\",\n        \"date\": \"2021-12-09T00:36:45Z\",\n        \"groups\": [\n         "
  },
  {
    "path": "zabbix_templates/app-php_opcache.json",
    "chars": 133594,
    "preview": "{\n    \"zabbix_export\": {\n        \"version\": \"5.4\",\n        \"date\": \"2021-12-11T00:34:20Z\",\n        \"groups\": [\n         "
  }
]

About this extraction

This page contains the full source code of the tiredofit/docker-nginx-php-fpm GitHub repository, extracted and formatted as plain text for AI agents and large language models (LLMs). The extraction includes 38 files (354.2 KB), approximately 76.0k tokens. Use this with OpenClaw, Claude, ChatGPT, Cursor, Windsurf, or any other AI tool that accepts text input. You can copy the full output to your clipboard or download it as a .txt file.

Extracted by GitExtract — free GitHub repo to text converter for AI. Built by Nikandr Surkov.

Copied to clipboard!