-
-
Notifications
You must be signed in to change notification settings - Fork 516
docs(docker): add nginx + PHP-FPM reference configuration to fix login redirect loop #8207
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| @@ -0,0 +1,94 @@ | ||||||||||||||||||||||||||||||||||||
| # PHP-FPM Dockerfile for ChurchCRM (nginx deployments) | ||||||||||||||||||||||||||||||||||||
| # | ||||||||||||||||||||||||||||||||||||
| # Use this image with the nginx configuration in docker/nginx/default.conf. | ||||||||||||||||||||||||||||||||||||
| # For the Apache-based development/CI setup, see Dockerfile.churchcrm-apache-php8. | ||||||||||||||||||||||||||||||||||||
| # | ||||||||||||||||||||||||||||||||||||
| # Build: | ||||||||||||||||||||||||||||||||||||
| # docker build -f Dockerfile.churchcrm-fpm-php8 -t churchcrm/crm:php8-fpm . | ||||||||||||||||||||||||||||||||||||
| # | ||||||||||||||||||||||||||||||||||||
| # Required PHP extensions for ChurchCRM: | ||||||||||||||||||||||||||||||||||||
| # bcmath, curl, exif, gd, gettext, iconv, intl, mbstring, mysqli, | ||||||||||||||||||||||||||||||||||||
| # opcache, pdo_mysql, sodium, xml, zip | ||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||
| FROM php:8-fpm AS base | ||||||||||||||||||||||||||||||||||||
| LABEL maintainer="ChurchCRM" | ||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||
| EXPOSE 9000 | ||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||
| # Install system dependencies required by PHP extensions | ||||||||||||||||||||||||||||||||||||
| RUN apt-get update && \ | ||||||||||||||||||||||||||||||||||||
| apt-get install -y \ | ||||||||||||||||||||||||||||||||||||
| libcurl4-openssl-dev \ | ||||||||||||||||||||||||||||||||||||
| libfreetype6-dev \ | ||||||||||||||||||||||||||||||||||||
| libicu-dev \ | ||||||||||||||||||||||||||||||||||||
| libjpeg-dev \ | ||||||||||||||||||||||||||||||||||||
| libonig-dev \ | ||||||||||||||||||||||||||||||||||||
| libpng-dev \ | ||||||||||||||||||||||||||||||||||||
| libxml2-dev \ | ||||||||||||||||||||||||||||||||||||
| libzip-dev \ | ||||||||||||||||||||||||||||||||||||
| gettext \ | ||||||||||||||||||||||||||||||||||||
| locales \ | ||||||||||||||||||||||||||||||||||||
| locales-all \ | ||||||||||||||||||||||||||||||||||||
| unzip \ | ||||||||||||||||||||||||||||||||||||
| && rm -rf /var/lib/apt/lists/* | ||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||
| # Install and configure PHP extensions | ||||||||||||||||||||||||||||||||||||
| RUN docker-php-ext-configure gd --with-freetype --with-jpeg && \ | ||||||||||||||||||||||||||||||||||||
| docker-php-ext-install -j$(nproc) \ | ||||||||||||||||||||||||||||||||||||
| bcmath \ | ||||||||||||||||||||||||||||||||||||
| curl \ | ||||||||||||||||||||||||||||||||||||
| exif \ | ||||||||||||||||||||||||||||||||||||
| gd \ | ||||||||||||||||||||||||||||||||||||
| gettext \ | ||||||||||||||||||||||||||||||||||||
| iconv \ | ||||||||||||||||||||||||||||||||||||
| intl \ | ||||||||||||||||||||||||||||||||||||
| mbstring \ | ||||||||||||||||||||||||||||||||||||
| mysqli \ | ||||||||||||||||||||||||||||||||||||
| opcache \ | ||||||||||||||||||||||||||||||||||||
| pdo_mysql \ | ||||||||||||||||||||||||||||||||||||
| xml \ | ||||||||||||||||||||||||||||||||||||
| zip | ||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||
| # Sodium is bundled with PHP 7.2+ but needs to be enabled | ||||||||||||||||||||||||||||||||||||
| RUN docker-php-ext-enable sodium | ||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||
| # Configure PHP settings | ||||||||||||||||||||||||||||||||||||
| RUN mv "$PHP_INI_DIR/php.ini-production" "$PHP_INI_DIR/php.ini" && \ | ||||||||||||||||||||||||||||||||||||
| sed -i 's/^upload_max_filesize.*$/upload_max_filesize = 2G/g' $PHP_INI_DIR/php.ini && \ | ||||||||||||||||||||||||||||||||||||
| sed -i 's/^post_max_size.*$/post_max_size = 2G/g' $PHP_INI_DIR/php.ini && \ | ||||||||||||||||||||||||||||||||||||
| sed -i 's/^memory_limit.*$/memory_limit = 256M/g' $PHP_INI_DIR/php.ini && \ | ||||||||||||||||||||||||||||||||||||
| sed -i 's/^max_execution_time.*$/max_execution_time = 120/g' $PHP_INI_DIR/php.ini | ||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||
| # Production stage - minimal runtime | ||||||||||||||||||||||||||||||||||||
| FROM base AS prod | ||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||
| # Dev stage - includes build tools for local development inside the container | ||||||||||||||||||||||||||||||||||||
| FROM base AS dev | ||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||
| # Install development tools | ||||||||||||||||||||||||||||||||||||
| RUN apt-get update && \ | ||||||||||||||||||||||||||||||||||||
| apt-get install -y \ | ||||||||||||||||||||||||||||||||||||
| git \ | ||||||||||||||||||||||||||||||||||||
| make \ | ||||||||||||||||||||||||||||||||||||
| python3 \ | ||||||||||||||||||||||||||||||||||||
| unzip \ | ||||||||||||||||||||||||||||||||||||
| curl \ | ||||||||||||||||||||||||||||||||||||
| && rm -rf /var/lib/apt/lists/* | ||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||
| # Install Xdebug for step-debugging | ||||||||||||||||||||||||||||||||||||
| RUN pecl install xdebug && docker-php-ext-enable xdebug | ||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||
| # Install Composer | ||||||||||||||||||||||||||||||||||||
| RUN php -r "copy('https://getcomposer.org/installer', 'composer-setup.php');" && \ | ||||||||||||||||||||||||||||||||||||
| php composer-setup.php --install-dir=/usr/local/bin --filename=composer && \ | ||||||||||||||||||||||||||||||||||||
| rm composer-setup.php | ||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||
| # Install NVM + Node.js (needed to run npm run deploy inside the container) | ||||||||||||||||||||||||||||||||||||
| RUN curl https://raw.githubusercontent.com/nvm-sh/nvm/v0.39.5/install.sh -o /opt/node-install.sh && \ | ||||||||||||||||||||||||||||||||||||
|
Comment on lines
+83
to
+89
|
||||||||||||||||||||||||||||||||||||
| # Install Composer | |
| RUN php -r "copy('https://getcomposer.org/installer', 'composer-setup.php');" && \ | |
| php composer-setup.php --install-dir=/usr/local/bin --filename=composer && \ | |
| rm composer-setup.php | |
| # Install NVM + Node.js (needed to run npm run deploy inside the container) | |
| RUN curl https://raw.githubusercontent.com/nvm-sh/nvm/v0.39.5/install.sh -o /opt/node-install.sh && \ | |
| # Install Composer (with installer signature verification) | |
| RUN EXPECTED_SIGNATURE="$(curl -s https://composer.github.io/installer.sig)" && \ | |
| php -r "copy('https://getcomposer.org/installer', 'composer-setup.php');" && \ | |
| ACTUAL_SIGNATURE="$(php -r "echo hash_file('sha384', 'composer-setup.php');")" && \ | |
| if [ "$EXPECTED_SIGNATURE" != "$ACTUAL_SIGNATURE" ]; then >&2 echo 'ERROR: Invalid Composer installer signature'; rm composer-setup.php; exit 1; fi && \ | |
| php composer-setup.php --install-dir=/usr/local/bin --filename=composer && \ | |
| rm composer-setup.php | |
| # Install NVM + Node.js (needed to run npm run deploy inside the container) | |
| RUN curl https://raw.githubusercontent.com/nvm-sh/nvm/b3f16ba1f5a1ab3d6a0eef8949b0f9b867951376/install.sh -o /opt/node-install.sh && \ |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,6 +1,18 @@ | ||
| Getting Started with Docker for Development | ||
| Getting Started with Docker for ChurchCRM | ||
| =========================== | ||
|
|
||
| This directory contains two types of Docker configurations: | ||
|
|
||
| | Configuration | Use Case | | ||
| |---------------|----------| | ||
| | `docker-compose.yaml` | Development and testing (Apache + PHP). Used by the automated test suite and local development. | | ||
| | `docker-compose.nginx.yaml` | Self-hosted or production reference (nginx + PHP-FPM). Starting point for your own deployment. | | ||
|
Comment on lines
+6
to
+9
|
||
|
|
||
| --- | ||
|
|
||
| Development & Testing (Apache) | ||
| --- | ||
|
|
||
| ** THIS DOCKER CONFIGURATION IS INTENDED FOR DEVELOPMENT & TESTING PURPOSES ONLY** | ||
|
|
||
| ChurchCRM uses a single `docker-compose.yaml` with profiles to support different environments: | ||
|
|
@@ -117,4 +129,74 @@ WEBSERVER_PORT=80 | |
| ADMINER_PORT=8088 | ||
| MAILSERVER_PORT=1025 | ||
| MAILSERVER_GUI_PORT=8025 | ||
| ``` | ||
| ``` | ||
|
|
||
| --- | ||
|
|
||
| Self-Hosted / Production (nginx + PHP-FPM) | ||
| --- | ||
|
|
||
| The `docker-compose.nginx.yaml` and `nginx/default.conf` files provide a reference | ||
| configuration for deploying ChurchCRM with **nginx + PHP-FPM** instead of Apache. | ||
| This is the setup most commonly used in self-hosted environments (reverse-proxy | ||
| stacks, Kubernetes, etc.). | ||
|
|
||
| ### Why nginx needs explicit routing | ||
|
|
||
| ChurchCRM is structured as multiple independent **Slim 4 PHP applications**, each | ||
| in its own subdirectory with its own `index.php` entry point: | ||
|
|
||
| | URL prefix | Entry point | | ||
| |------------|-------------| | ||
| | `/session/` | `session/index.php` — login, logout, 2FA | | ||
| | `/api/` | `api/index.php` — REST API | | ||
| | `/v2/` | `v2/index.php` — modern MVC pages | | ||
| | `/admin/` | `admin/index.php` — admin panel | | ||
| | `/finance/` | `finance/index.php` — finance module | | ||
| | `/kiosk/` | `kiosk/index.php` — check-in kiosk | | ||
| | `/plugins/` | `plugins/index.php` — plugin system | | ||
| | `/external/` | `external/index.php` — public integrations | | ||
| | `/setup/` | `setup/index.php` — first-run wizard | | ||
| | `/` | `index.php` — legacy PHP pages | | ||
|
|
||
| With **Apache**, each subdirectory's `.htaccess` file automatically routes | ||
| requests to the correct entry point. | ||
|
|
||
| With **nginx**, you must explicitly map each URL prefix to its entry point. | ||
| **Routing all requests to the root `index.php`** (a common mistake) causes an | ||
| infinite redirect loop because unauthenticated users are redirected to | ||
| `/session/begin`, but that path also goes to `index.php`, which redirects again. | ||
|
|
||
| ### Quick start | ||
|
|
||
| ```bash | ||
| # From the docker/ directory: | ||
| docker compose -f docker-compose.nginx.yaml up -d | ||
| ``` | ||
|
|
||
| Visit `http://localhost/` — you will see the setup wizard on first run. | ||
|
|
||
| ### Files | ||
|
|
||
| | File | Description | | ||
| |------|-------------| | ||
| | `docker-compose.nginx.yaml` | Example Compose file (nginx + PHP-FPM + MariaDB) | | ||
| | `nginx/default.conf` | nginx server block with correct per-subdirectory routing | | ||
| | `Dockerfile.churchcrm-fpm-php8` | PHP-FPM image with all required extensions | | ||
|
|
||
| ### Customising the nginx config | ||
|
|
||
| 1. Copy `nginx/default.conf` to your deployment. | ||
| 2. Replace `php-fpm:9000` with your PHP-FPM container hostname/port. | ||
| 3. Set `root` to the path where ChurchCRM's `src/` contents are served from. | ||
| 4. For a **subdirectory install** (e.g. `http://example.com/churchcrm/`): | ||
| - Set `$sRootPath = '/churchcrm'` in `Include/Config.php`. | ||
| - Prefix all `location` paths in the nginx config with `/churchcrm`. | ||
| - See the commented example at the bottom of `nginx/default.conf`. | ||
|
|
||
| ### Required PHP extensions | ||
|
|
||
| `bcmath`, `curl`, `exif`, `gd`, `gettext`, `iconv`, `intl`, `mbstring`, `mysqli`, | ||
| `opcache`, `pdo_mysql`, `sodium`, `xml`, `zip` | ||
|
|
||
| The `Dockerfile.churchcrm-fpm-php8` installs all of these. | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,75 @@ | ||
| # docker-compose.nginx.yaml — Example nginx + PHP-FPM deployment for ChurchCRM | ||
| # | ||
| # This is a REFERENCE CONFIGURATION for self-hosted deployments using nginx + | ||
| # PHP-FPM instead of Apache. It is NOT used by the automated test suite (which | ||
| # uses docker-compose.yaml with Apache). Use this as a starting point for your | ||
| # own production or staging environment. | ||
| # | ||
| # QUICK START | ||
| # ----------- | ||
| # 1. Copy this file and docker/nginx/default.conf to your deployment directory. | ||
| # 2. Copy docker/Config.php to Include/Config.php in your ChurchCRM source tree | ||
| # and set the database connection details to match the values below. | ||
| # 3. Set MYSQL_ROOT_PASSWORD and MYSQL_PASSWORD to strong secrets. | ||
| # 4. Run: docker compose -f docker-compose.nginx.yaml up -d | ||
| # 5. Visit http://localhost/ - you will be redirected to the setup wizard on | ||
| # first run (no Config.php) or to the login page after installation. | ||
| # | ||
| # IMPORTANT: Change all passwords before exposing this to the internet. | ||
|
|
||
| services: | ||
|
|
||
| database: | ||
| image: mariadb:11 | ||
| restart: unless-stopped | ||
| environment: | ||
| MYSQL_ROOT_PASSWORD: ${MYSQL_ROOT_PASSWORD:-changeme_root} | ||
| MYSQL_DATABASE: churchcrm | ||
| MYSQL_USER: churchcrm | ||
| MYSQL_PASSWORD: ${MYSQL_PASSWORD:-changeme} | ||
| volumes: | ||
| - churchcrm-db:/var/lib/mysql | ||
| healthcheck: | ||
| test: ["CMD", "healthcheck.sh", "--connect", "--innodb_initialized"] | ||
| timeout: 20s | ||
| retries: 10 | ||
| hostname: database | ||
|
|
||
| php-fpm: | ||
| build: | ||
| context: . | ||
| dockerfile: Dockerfile.churchcrm-fpm-php8 | ||
| target: prod | ||
| image: churchcrm/crm:php8-fpm | ||
| restart: unless-stopped | ||
| volumes: | ||
| # Mount ChurchCRM source (the contents of src/) here. | ||
| # Options: | ||
| # a) Replace with a bind mount to a local directory: | ||
| # - /path/to/churchcrm/src:/var/www/html | ||
| # b) Copy files into this named volume after the first `docker compose up`: | ||
| # docker cp /path/to/churchcrm/src/. churchcrm-php-fpm-1:/var/www/html/ | ||
| # c) Build a custom image with COPY instructions in your own Dockerfile. | ||
| - churchcrm-www:/var/www/html | ||
| depends_on: | ||
| database: | ||
| condition: service_healthy | ||
| hostname: php-fpm | ||
|
|
||
| webserver: | ||
| image: nginx:stable-alpine | ||
| restart: unless-stopped | ||
| ports: | ||
| - "${WEBSERVER_PORT:-80}:80" | ||
| volumes: | ||
| # Same source volume as php-fpm so nginx can serve static files directly | ||
| - churchcrm-www:/var/www/html:ro | ||
| # Mount the nginx configuration | ||
| - ./nginx/default.conf:/etc/nginx/conf.d/default.conf:ro | ||
| depends_on: | ||
| - php-fpm | ||
| hostname: webserver | ||
|
|
||
| volumes: | ||
| churchcrm-db: | ||
| churchcrm-www: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
docker-php-ext-enable sodiumcan fail on official PHP images when sodium is compiled in (nosodium.soto enable). To make the build reliable, either explicitly install it as a shared extension (docker-php-ext-install sodium) or drop this line if the base image already provides it enabled.