Django/Apache/mod_wsgi Deployment Issue: Internal Server Error & Redirect Loop on cPanel (AlmaLinux 9)

I'm an intern trying to deploy a Django application on a cPanel server, and I've run into a persistent "Internal Server Error" coupled with an Apache redirect loop. I've been troubleshooting for over two days with various AI helpers, but I can't pinpoint the exact cause. Any fresh perspectives ??


My Setup:

  • Server OS : AlmaLinux 9.6 (Sage Margay)
  • Hosting Environment: cPanel (My cPanel account does not have the "Setup Python App" option, which is why I'm using a manual Apache/mod_wsgi configuration.)
  • Django Deployment: Apache + mod_wsgi
  • No .htaccess content at all.
  • Project Structure: I have two Django instances (production and staging) for CI/CD,

each with its own settings, environment variables, database, and domain.

  • validator/settings/base.py

  • validator/settings/production.py (inherits from base)

  • validator/settings/staging.py (inherits from base)

  • Environment files are stored in /etc/validator/envs

  • WSGI files are stored in /etc/validator/wsgi/

  • Django project roots: /home/<username>/<app_name>/ (prod) and /home/<username>/<app_name_test>/ (staging).

  • Python Version: My virtual environments are running Python 3.12.9, and my WSGI files assert this.


The Problem:

When I try to access either domain.in (production) or test.domain.in (staging), I receive an "Internal Server Error". My Apache error log (specifically /var/log/httpd/error_log) shows the following critical error message:

[Fri May 30 00:26:38.624027 2025] [core:error] [pid 253617:tid 253705] [client 45.115.89.80:26970] AH00124: Request exceeded the limit of 10 internal redirects due to probable configuration error. Use 'LimitInternalRecursion' to increase the limit if necessary. Use 'LogLevel debug' to get a backtrace.

This started after a server expiration/renewal and then when I configured new databases for staging and production, updating the respective .env files. Previously, it worked (sharing a database).


My Apache configuration:

I understand cPanel uses a "Direct Include Style" for Apache configs, where httpd.conf includes files from directories like /etc/apache2/conf.d/userdata/.... My custom Django configurations are placed in these included directories.

  1. Production Domain Custom Apache Config (/etc/apache2/conf.d/userdata/std/2_4/<username>/<domain.in>/<filename>.conf):
ServerName <domain>.in
ServerAlias www.<domain>.in
ServerAlias <server_ip>

WSGIDaemonProcess django_app python-home=/home/<username>/app/venv python-path=/home/<username>/app user=<apache_user> group=<group_user>
WSGIProcessGroup app

WSGIScriptAlias / /etc/validator/wsgi/production.wsgi 

Alias /static/ /home/<username>/app/staticfiles/

<Directory /home/<username>/app/staticfiles>
        Require all granted
</Directory>

<Directory /etc/validator/wsgi>
        <Files production.wsgi>
            Require all granted
        </Files>
</Directory>

ErrorLog /home/<username>/app/error.log
CustomLog /home/<username>/app/access.log combined
  1. Staging Domain Custom Apache Config (similar path for test.domain.in):
ServerName test.<domain>.in
ServerAlias www.test.<domain>.in

WSGIDaemonProcess test_app python-home=/home/<username>/app_test/venv python-path=/home/<username>/app_test user=<apache_user> group=<group_user>
WSGIProcessGroup app_test

WSGIScriptAlias / /etc/validator/wsgi/staging.wsgi 

Alias /static/ /home/<username>/app_test/staticfiles/

<Directory /home/<username>/app_test/staticfiles>
        Require all granted
</Directory>

<Directory /etc/validator/wsgi>
        <Files production.wsgi>
            Require all granted
        </Files>
</Directory>

ErrorLog /home/<username>/app_test/error.log
CustomLog /home/<username>/app_test/access.log combined

3.Production Environment File (/etc/validator/envs/production.env):

DBUSER=<dbuser>
DBPASSWORD=<dbpasswd>
DBNAME=<dbname>
DBHOST=localhost
DBPORT=3306
  1. Production WSGI File (/etc/validator/wsgi/production.wsgi):
import os
import sys
from pathlib import Path
from dotenv import load_dotenv

ENV_FILE = Path('/etc/validator/envs/production.env')
load_dotenv(dotenv_path=ENV_FILE)

os.environ.setdefault('DJANGO_SETTINGS_MODULE', '<django_root_app>.settings.production')

from django.core.wsgi import get_wsgi_application
application = get_wsgi_application()
  1. Django settings/prod.py (similar structure for settings/staging.py):
import os
from .base import *

DEBUG = False

ALLOWED_HOSTS = [
    "domain",
    "www.domain",
    "server_ip",
]

DATABASES = {
    "default": {
        "ENGINE": "django.db.backends.<sql>",
        "USER": os.environ["DBUSER"],
        "PASSWORD": os.environ["DBPASSWORD"],
        "NAME": os.environ["DBNAME"],
        "HOST": os.environ["DBHOST"],
        "PORT": os.environ["DBPORT"],
    }
}

Troubleshooting Steps I've Already Taken:

  1. Checked Apache Error Logs: The main Apache log (/var/log/httpd/error_log) consistently shows the "Request exceeded the limit of 10 internal redirects" error. My Django app's custom logs (/home//app/error.log and _test/error.log) are empty or show no relevant errors, often indicating a problem before Django's logger can even kick in.

  2. Permissions: I've meticulously checked and set chown -R medivali:webapps and chmod permissions (755 for directories, 644 for files, 664 for logs) on /home//app/, /home//app_test/, /etc/validator/envs/, and /etc/validator/wsgi/.

  3. WSGIDaemonProcess User/Group: I've tried user=nobody group=webapps (as in config) and user=medivali group=medivali. Neither resolves the issue.

  4. Python Version Assertion: Confirmed venv/bin/python --version is 3.12+ for both environments.

  5. proxy_fcgi_module Conflict: I've added <FilesMatch ".(phtml|php[0-9]*)$">SetHandler None to my validator_conf.conf files to try and prevent the cPanel PHP-FPM handler from interfering.

  6. DocumentRoot vs. WSGIScriptAlias: I understand WSGIScriptAlias / should override DocumentRoot for Django, but I've also tried creating an index.html in /home/medivali/public_html (the default DocumentRoot in the main VHost) to test basic Apache serving, but it still leads to the redirect loop or internal server error.

  7. Database Credentials: I've triple-checked the DBUSER, DBPASSWORD, DBNAME, DBHOST, DBPORT in both .env files. I can connect to the databases directly from the server using mysql client.

  8. ALLOWED_HOSTS: Confirmed correct domain names are in ALLOWED_HOSTS for both production and staging settings.

  9. AI Consultations: Spent 2.5 days consulting ChatGPT, Gemini, Claude, and DeepSeek, trying various suggestions, but without success.

Вернуться на верх