Skip to content

docs(docker): add nginx + PHP-FPM reference configuration to fix login redirect loop#8207

Draft
Copilot wants to merge 2 commits intomasterfrom
copilot/fix-login-loop-churchcrm
Draft

docs(docker): add nginx + PHP-FPM reference configuration to fix login redirect loop#8207
Copilot wants to merge 2 commits intomasterfrom
copilot/fix-login-loop-churchcrm

Conversation

Copy link
Contributor

Copilot AI commented Mar 6, 2026

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.
# 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.

Original prompt

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:


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:


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)


💬 We'd love your input! Share your thoughts on Copilot coding agent in our 2 minute survey.

Co-authored-by: DawoudIO <554959+DawoudIO@users.noreply.github.com>
Copilot AI changed the title [WIP] Fix login loop issue after ChurchCRM setup docs(docker): add nginx + PHP-FPM reference configuration to fix login redirect loop Mar 6, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Question: Docker Installation Challenges

2 participants