Commit 6e46512
docs(docker): add nginx + PHP-FPM reference configuration to fix login redirect loop (#8207)
ChurchCRM users deploying with nginx + PHP-FPM hit an infinite redirect
loop (`/session/begin → /session/begin`) because nginx routes everything
to the root `index.php`, which redirects unauthenticated users to
`/session/begin` — which also hits `index.php` — and so on.
The loop happens because ChurchCRM has **9 independent Slim 4 entry
points** (one per subdirectory). Apache resolves this automatically via
per-directory `.htaccess` mod_rewrite rules; nginx requires explicit
`location` blocks per sub-app.
## Changes
- **`docker/nginx/default.conf`** — nginx server block with `location
^~` blocks routing each sub-application prefix to its own `index.php`.
Regex locations for static assets and PHP, security denies for `/logs`,
`/tmp_attach`, and dotfiles. Commented subdirectory-install variant at
the bottom.
```nginx
# Each Slim sub-app gets its own routing block
location ^~ /session {
try_files $uri /session/index.php$is_args$args;
location ~ \.php$ {
fastcgi_pass php-fpm:9000;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
include fastcgi_params;
}
}
# ... repeated for /api, /v2, /admin, /finance, /kiosk, /plugins, /external, /setup
```
- **`docker/Dockerfile.churchcrm-fpm-php8`** — PHP-FPM multi-stage image
(`prod` / `dev`) with all required extensions (`bcmath`, `gd`, `intl`,
`mysqli`, `pdo_mysql`, `sodium`, `zip`, …). Mirrors the existing
`Dockerfile.churchcrm-apache-php8`.
- **`docker/docker-compose.nginx.yaml`** — Self-contained Compose
reference (MariaDB + PHP-FPM + nginx). Not wired into CI; intended as a
starting point for self-hosted deployments.
- **`docker/README.md`** — Added intro table distinguishing dev/CI
(Apache) from self-hosted (nginx), plus a new section explaining the
routing architecture, the loop pitfall, quick-start, and customisation
notes.
<!-- START COPILOT ORIGINAL PROMPT -->
<details>
<summary>Original prompt</summary>
>
> ----
>
> *This section details on the original issue you should resolve*
>
> <issue_title>Question: Docker Installation Challenges</issue_title>
> <issue_description>## How can we help?
>
> Please share briefly:
> - **What you're trying to do**: I'm trying to install ChurchCRM into
an environment that is otherwise manged through docker-compose. Since
ChurchCRM doesn't have a dedicated set of docker containers, I've been
attempting to install it using a combination of nginx, mariadb, and a
custom PHP dockerfile with all the needed PHP extensions. I've made good
progress (and I'm looking to share my procedures once I'm successful),
but I'm running into an issue just a few feet from the finish line.
>
> Specifically, I'm getting a login loop after finishing the initial
setup wizard, 'too many redirects'.
>
> From Claude:
> This is the key finding! Look at what's happening:
>
> ✅ Cookie IS being set — CRM-xxxxx=yyy — so session saving is working
now
> ✅ Only one redirect with curl+cookies — not an infinite loop
> ❌ It's redirecting /session/begin → /session/begin — redirecting to
itself!
>
>
> - **What you've tried**: Steps or settings you've attempted
> This occurs after attempting to go to http://churchcrm.example.com,
once the setup wizard has been completed.
>
> - **Expected behavior**: What you expected to happen
> Getting a login prompt =)
>
> Add environment details only if relevant (version, hosting type,
etc.).
>
> My Docker Compose:
>
> ```version: "3.9"
>
> services:
>
> churchcrm-mariadb:
> image: mariadb:11
> container_name: churchcrm-mariadb
> restart: unless-stopped
> environment:
> MYSQL_ROOT_PASSWORD: 12345
> MYSQL_DATABASE: churchcrm
> MYSQL_USER: churchcrm
> MYSQL_PASSWORD: 12345
> volumes:
> - churchcrm-mariadb:/var/lib/mysql
>
> churchcrm-php:
> image: php84-custom1
> container_name: churchcrm-php
> restart: unless-stopped
> volumes:
> - churchcrm-php:/usr/local/etc/php/conf.d
> - churchcrm-www:/var/www/html
> depends_on:
> - churchcrm-mariadb
>
> churchcrm-nginx:
> image: nginx:stable-alpine
> container_name: churchcrm-nginx
> restart: unless-stopped
> ports:
> - "80:80"
> volumes:
> - churchcrm-www:/var/www/html
> - churchcrm-nginx:/etc/nginx/
> depends_on:
> - churchcrm-php
>
> # =========================
> # PHPMYADMIN
> # =========================
>
> phpmyadmin:
> image: phpmyadmin/phpmyadmin:latest
> container_name: churchcrm-phpmyadmin
> ports:
> - "7381:80"
> environment:
> - PMA_HOST=churchcrm-mariadb
> - PMA_PORT=3306
> - TZ=America/New_York
> restart: ${RESTART_POLICY}
>
> volumes:
> churchcrm-php:
> churchcrm-nginx:
> churchcrm-www:
> churchcrm-mariadb:
> ```
>
> My Dockerfile for my php container:
>
> ```FROM php:8.4-fpm
>
> RUN apt-get update && apt-get install -y \
> libzip-dev \
> libicu-dev \
> libpng-dev \
> libjpeg-dev \
> libfreetype6-dev \
> libxml2-dev \
> libonig-dev \
> unzip \
> git \
> curl \
> && docker-php-ext-configure gd --with-freetype --with-jpeg \
> && docker-php-ext-install \
> pdo_mysql \
> mysqli \
> intl \
> gd \
> zip \
> mbstring \
> xml \
> opcache \
> gettext \
> && apt-get clean
> ```
>
> My php override file:
>
> ```
> session.save_path = /tmp
> upload_max_filesize = 20M
> post_max_size = 25M
> memory_limit = 256M
> ```
>
> My nginx config:
>
> ```
> server {
> listen 80;
> server_name crm.example.org;
> root /var/www/html;
> index index.php index.html;
> client_max_body_size 100M;
>
> location ^~ /setup {
> try_files $uri $uri/ /setup/index.php$is_args$args;
>
> location ~ \.php$ {
> include fastcgi_params;
> fastcgi_pass churchcrm-php:9000;
> fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
> fastcgi_index index.php;
> }
> }
>
> location / {
> try_files $uri $uri/ /index.php?$query_string;
> }
>
> location ~ \.php$ {
> include fastcgi_params;
> fastcgi_pass churchcrm-php:9000;
> fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
> fastcgi_index index.php;
> }
>
> location ~ /\.ht {
> deny all;
> }
> }
> ```
>
> ...I think that's everything =)</issue_description>
>
> <agent_instructions>review the docker setup used for dev/ci/test and
recommend a path forward </agent_instructions>
>
> ## Comments on the Issue (you are @copilot in this section)
>
> <comments>
> </comments>
>
</details>
<!-- START COPILOT CODING AGENT SUFFIX -->
- Fixes #8200
<!-- START COPILOT CODING AGENT TIPS -->
---
💬 We'd love your input! Share your thoughts on Copilot coding agent in
our [2 minute survey](https://gh.io/copilot-coding-agent-survey).
---------
Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
Co-authored-by: DawoudIO <554959+DawoudIO@users.noreply.github.com>
Co-authored-by: George Dawoud <george@dawouds.com>1 parent bdc157c commit 6e46512
File tree
4 files changed
+489
-2
lines changed- docker
- nginx
4 files changed
+489
-2
lines changed| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
| 1 | + | |
| 2 | + | |
| 3 | + | |
| 4 | + | |
| 5 | + | |
| 6 | + | |
| 7 | + | |
| 8 | + | |
| 9 | + | |
| 10 | + | |
| 11 | + | |
| 12 | + | |
| 13 | + | |
| 14 | + | |
| 15 | + | |
| 16 | + | |
| 17 | + | |
| 18 | + | |
| 19 | + | |
| 20 | + | |
| 21 | + | |
| 22 | + | |
| 23 | + | |
| 24 | + | |
| 25 | + | |
| 26 | + | |
| 27 | + | |
| 28 | + | |
| 29 | + | |
| 30 | + | |
| 31 | + | |
| 32 | + | |
| 33 | + | |
| 34 | + | |
| 35 | + | |
| 36 | + | |
| 37 | + | |
| 38 | + | |
| 39 | + | |
| 40 | + | |
| 41 | + | |
| 42 | + | |
| 43 | + | |
| 44 | + | |
| 45 | + | |
| 46 | + | |
| 47 | + | |
| 48 | + | |
| 49 | + | |
| 50 | + | |
| 51 | + | |
| 52 | + | |
| 53 | + | |
| 54 | + | |
| 55 | + | |
| 56 | + | |
| 57 | + | |
| 58 | + | |
| 59 | + | |
| 60 | + | |
| 61 | + | |
| 62 | + | |
| 63 | + | |
| 64 | + | |
| 65 | + | |
| 66 | + | |
| 67 | + | |
| 68 | + | |
| 69 | + | |
| 70 | + | |
| 71 | + | |
| 72 | + | |
| 73 | + | |
| 74 | + | |
| 75 | + | |
| 76 | + | |
| 77 | + | |
| 78 | + | |
| 79 | + | |
| 80 | + | |
| 81 | + | |
| 82 | + | |
| 83 | + | |
| 84 | + | |
| 85 | + | |
| 86 | + | |
| 87 | + | |
| 88 | + | |
| 89 | + | |
| 90 | + | |
| 91 | + | |
| 92 | + | |
| 93 | + | |
| 94 | + | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
1 | | - | |
| 1 | + | |
2 | 2 | | |
3 | 3 | | |
| 4 | + | |
| 5 | + | |
| 6 | + | |
| 7 | + | |
| 8 | + | |
| 9 | + | |
| 10 | + | |
| 11 | + | |
| 12 | + | |
| 13 | + | |
| 14 | + | |
| 15 | + | |
4 | 16 | | |
5 | 17 | | |
6 | 18 | | |
| |||
117 | 129 | | |
118 | 130 | | |
119 | 131 | | |
120 | | - | |
| 132 | + | |
| 133 | + | |
| 134 | + | |
| 135 | + | |
| 136 | + | |
| 137 | + | |
| 138 | + | |
| 139 | + | |
| 140 | + | |
| 141 | + | |
| 142 | + | |
| 143 | + | |
| 144 | + | |
| 145 | + | |
| 146 | + | |
| 147 | + | |
| 148 | + | |
| 149 | + | |
| 150 | + | |
| 151 | + | |
| 152 | + | |
| 153 | + | |
| 154 | + | |
| 155 | + | |
| 156 | + | |
| 157 | + | |
| 158 | + | |
| 159 | + | |
| 160 | + | |
| 161 | + | |
| 162 | + | |
| 163 | + | |
| 164 | + | |
| 165 | + | |
| 166 | + | |
| 167 | + | |
| 168 | + | |
| 169 | + | |
| 170 | + | |
| 171 | + | |
| 172 | + | |
| 173 | + | |
| 174 | + | |
| 175 | + | |
| 176 | + | |
| 177 | + | |
| 178 | + | |
| 179 | + | |
| 180 | + | |
| 181 | + | |
| 182 | + | |
| 183 | + | |
| 184 | + | |
| 185 | + | |
| 186 | + | |
| 187 | + | |
| 188 | + | |
| 189 | + | |
| 190 | + | |
| 191 | + | |
| 192 | + | |
| 193 | + | |
| 194 | + | |
| 195 | + | |
| 196 | + | |
| 197 | + | |
| 198 | + | |
| 199 | + | |
| 200 | + | |
| 201 | + | |
| 202 | + | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
| 1 | + | |
| 2 | + | |
| 3 | + | |
| 4 | + | |
| 5 | + | |
| 6 | + | |
| 7 | + | |
| 8 | + | |
| 9 | + | |
| 10 | + | |
| 11 | + | |
| 12 | + | |
| 13 | + | |
| 14 | + | |
| 15 | + | |
| 16 | + | |
| 17 | + | |
| 18 | + | |
| 19 | + | |
| 20 | + | |
| 21 | + | |
| 22 | + | |
| 23 | + | |
| 24 | + | |
| 25 | + | |
| 26 | + | |
| 27 | + | |
| 28 | + | |
| 29 | + | |
| 30 | + | |
| 31 | + | |
| 32 | + | |
| 33 | + | |
| 34 | + | |
| 35 | + | |
| 36 | + | |
| 37 | + | |
| 38 | + | |
| 39 | + | |
| 40 | + | |
| 41 | + | |
| 42 | + | |
| 43 | + | |
| 44 | + | |
| 45 | + | |
| 46 | + | |
| 47 | + | |
| 48 | + | |
| 49 | + | |
| 50 | + | |
| 51 | + | |
| 52 | + | |
| 53 | + | |
| 54 | + | |
| 55 | + | |
| 56 | + | |
| 57 | + | |
| 58 | + | |
| 59 | + | |
| 60 | + | |
| 61 | + | |
| 62 | + | |
| 63 | + | |
| 64 | + | |
| 65 | + | |
| 66 | + | |
| 67 | + | |
| 68 | + | |
| 69 | + | |
| 70 | + | |
| 71 | + | |
| 72 | + | |
| 73 | + | |
| 74 | + | |
| 75 | + | |
0 commit comments