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": [
{
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.