Deploying Django with Apache, mod_wsgi, and PostgreSQL on Windows 11

The Visual Studio Build Tools is the first step because mod_wsgi (and often psycopg2) needs to compile C code to interface with the Python C API and the Apache C headers. Without that specific compiler, pip install will fail every time with the dreaded “Microsoft Visual C++ 14.0 is required” error.

How to set it up correctly:

  • Go to this Visual Studio Installer page, scroll down to the Tools for Visual Studio tab, and download Build Tools for Visual Studio 2026
  • Run the installer and check the Desktop development with C++ in workloads
  • On the right-side summary, ensure MSVC v143 (or latest), Windows 11 SDK, and C++ CMake tools are selected
  • Complete the installation (note: this will take some time as it downloads several GBs) and restart your PC to ensure the compiler is correctly added to your system Path

Project Directory Structure (VM Setup)

We test everything in an isolated Virtual Machine, and we will use C:\project as our root. In this case, I am using Windows 64-bit, so every component I install (Python, Apache, and PostgreSQL) must be the 64-bit version.

Target Layout:

  • C:\project\apache — Apache 2.4 binaries(VS18).
  • C:\project\python — Python environment (3.14.3).
  • C:\project\app — Your Django(6.0.2) project code.
  • C:\project\postgresql — Database installation/binaries(18.1).

Make sure that you have these folders created. Having them ready now prevents “Path not found” errors when we begin extracting the Apache binaries and installing the Python environment.

1 . Installing Python 3.14

Go to python.org and download the latest stable installer for your specific version of Windows (64-bit or 32-bit).

Instead of the default “one-click” setup, we will perform a controlled installation to C:\project\python

  • Run the installer and check Add python.exe to PATH at the bottom
  • Choose Customize installation and click Next through the features
  • Under Advanced Options select Install for all users and change the Customize install location to: C:\project\python
  • After installation, if prompted, click Disable path length limit. This is a life-saver for Django projects with many dependencies

2. Install PostgreSQL

Go to the PostgreSQL Windows Downloads and grab the latest version

  • Run the installer. To keep everything consistent with our “root directory” philosophy, you can change the installation path to C:\project\postgresql
  • Aside from the custom installation path, leave all other settings at their default values (including the Port 5432 and Locale)
  • During setup, you’ll be asked to create a password for the postgres user. Keep this safe. You will need it in a moment to link Django to the database

Preparing the Database

  • Open pgAdmin 4 (the management tool installed with Postgres).
  • Right-click Databases > Create > Database….
  • Name it django and click Save.

3 . Installing Apache

Go to Apache Lounge and download the Win64 version of Apache 2.4.

  • Open the Zip and go into the Apache24 folder
  • Extract everything from inside Apache24 into C:\project\apache

4 . Building the Environment via Native Tools

Click Start, search for “x64 Native Tools Command Prompt for VS”, right-click it, and select Run as Administrator.

We use the x64 Native Tools Command Prompt for VS because it automatically loads the environment variables and paths for the C++ compiler, ensuring mod_wsgi is built specifically for 64-bit architecture

Run this command to enter your root project directory:

cd /d C:\project\app

Create the Virtual Environment: (We use the absolute path to our Python 3.14 installation to be safe)

C:\project\python\python.exe -m venv venv

Activate the Environment:

venv\Scripts\activate

This is a crucial step. By creating a virtual environment, we ensure that the libraries we install for Django don’t interfere with other Python projects or the global Python installation.

A Quick Check: Is your Venv Active?

Before you run the installation command, take a second to look at your Command Prompt. You should see (venv) in parentheses at the very beginning of the line, like this:

(venv) C:\project\app>

Set the Path Variable: This is vital because your Apache isn’t in the default C:\Apache24 location

set "MOD_WSGI_APACHE_ROOTDIR=C:\project\apache"

Install Requirements:

pip install psycopg2 django mod_wsgi

If the installation is correct, and there is no reason why it shouldn’t be if all the previous steps were followed, we will now create our project called myproject

django-admin startproject myproject .

The . at the end is vital. It places manage.py in C:\project\app, keeping your paths clean for the Apache configuration later.

Now run this final command inside your activated virtual environment:

mod_wsgi-express module-config

Copy the output of this command. You will need to paste these three lines into your C:\project\apache\conf\httpd.conf file.

The lines should look like this (though your specific version numbers or user paths might differ slightly, just use the line that your console returned, this is just an example):

LoadFile "C:/project/python/python314.dll"
LoadModule wsgi_module "C:/project/app/venv/Lib/site-packages/mod_wsgi/server/mod_wsgi.cp314-win_amd64.pyd"
WSGIPythonHome "C:/project/app/venv"

Don’t close the command prompt for now. We will use this exact session later to run migrations, create a superuser, and collect static files once the Apache configuration is linked. Keeping it open saves you from having to re-activate the virtual environment.

5 . Apache Configuration

WARNING: CHECK YOUR PATHS CAREFULLY

Before you copy and paste the configuration below, stop and verify your folder names. If you followed every step of this tutorial exactly, your code will look almost identical to the example. However, even a small difference in a folder name or Python version will prevent Apache from starting.

Open C:\project\apache\conf\httpd.conf and scroll to the very bottom. You need to add the mod_wsgi lines you generated earlier, followed by the specific paths for your project.

# 1. Paste your specific mod_wsgi lines here first:
LoadFile "C:/project/python/python314.dll"
LoadModule wsgi_module "C:/project/app/venv/Lib/site-packages/mod_wsgi/server/mod_wsgi.cp314-win_amd64.pyd"
WSGIPythonHome "C:/project/app/venv"

# 2. Map the path to your Django project's wsgi.py file
WSGIScriptAlias / "C:/project/app/myproject/wsgi.py"
WSGIPythonPath "C:/project/app"
WSGIApplicationGroup %{GLOBAL}

# 3. Grant Apache permission to access the project folder
<Directory "C:/project/app/myproject">
    <Files wsgi.py>
        Require all granted
    </Files>
</Directory>

# 4. (Optional) Point to your static files
Alias /static "C:/project/app/static"
<Directory "C:/project/app/static">
    Require all granted
</Directory>

In the same configuration file, find the line starting with Define SRVROOT and point it to your project folder. This tells Apache where its own binaries and logs are.

Change like this:

Define SRVROOT "C:/project/apache"
ServerRoot "${SRVROOT}"

Find ServerName. If it’s commented out with a #, remove the # and set it to localhost so Apache doesn’t complain about reliable domain names:

ServerName localhost:80

Final Verification (The “Syntax OK” Moment)

Now, go back to your still-open x64 Native Tools Command Prompt (where your venv is active) and run the diagnostic tool:

C:\project\apache\bin\httpd.exe -t

You should receive “Syntax OK” as the response.

You must first install Apache as a Windows service. In that same command prompt, run:

C:\project\apache\bin\httpd.exe -k install -n "Apache2.4"

When you run httpd.exe for the first time (either by installing the service or starting it manually), a Windows Security Alert popup will appear.

Do not ignore this! * Click the “Allow access” button immediately.

Ensure both “Private networks” and “Public networks” (if applicable to your VM setup) are checked to allow Apache to communicate through the network.

Run this command in your open terminal to start Apache as a service:

C:\project\apache\bin\httpd.exe -k start -n "Apache2.4"

Now, we are modifying the settings in our project to set the path for static files and to configure which database we are using.

This is a critical step because we are moving away from default testing settings (SQLite) toward a professional environment using PostgreSQL and Apache.

Open C:\project\app\myproject\settings.py and ensure STATIC_ROOT is defined:

STATIC_URL = 'static/'
STATIC_ROOT = BASE_DIR / 'static'

In the same file, locate the DATABASES section. We will replace the default SQLite configuration with your PostgreSQL connection parameters.

Make sure to change the settings below with the actual name of your database and the password you set for the postgres user during installation:

DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.postgresql',
        'NAME': 'django',
        'USER': 'postgres',
        'PASSWORD': 'your_password_here',
        'HOST': '127.0.0.1',
        'PORT': '5432',
    }
}

Updating ALLOWED_HOSTS because by default, Django only trusts localhost. Since we are moving to Apache, we need to tell Django which IP addresses or domains it is allowed to “talk” to. If the incoming request doesn’t match one of these, Django will return a 400 Bad Request.

ALLOWED_HOSTS = [
    '127.0.0.1',
    'localhost',
    '192.168.1.50',  # Replace with your actual local network IP
    'yourdomain.com' # Replace with your actual domain
]

This step is important if you want to access the website from a domain or from another computer on your network. However, if you only intend to perform local tests on this machine, you can leave this configuration as is, because localhost will work by default.

6 . Creating a Superuser

Once Apache is installed and the service is started, you have reached a major milestone. If you open your browser and navigate to http://localhost, you should be greeted by the Django landing page. However, a landing page is just the beginning. To truly test if your environment is production-ready, we take it a step further by creating a superuser and collecting static files.

Since you still have your x64 Native Tools Command Prompt open and your virtual environment (venv) is already active, you are in the perfect position to finalize the setup:

python manage.py collectstatic
python manage.py migrate

Creating Your Admin Account

python manage.py createsuperuser

Follow the prompts for usernameemail, and password(Note: Windows terminals won’t show the password as you type it—just type it blindly and hit Enter!)

Once you have completed the database migration and configured your static files, it is time to verify the connection. Open your web browser and navigate to http://localhost/admin (or use your server’s IP).

Try to log in with the superuser account you created earlier. If you can access the dashboard and see the interface clearly, it means the connection between Django, PostgreSQL, and Apache is working perfectly.

Security & Production Disclaimer

This setup is designed as a functional local playground. While it successfully connects all the professional components of a stack, it is not yet “hardened” for the public internet.

Before moving this project to a live server, you must follow official security guides and address these critical points:

  • Django Hardening: Change your SECRET_KEY, set DEBUG = False, and configure ALLOWED_HOSTS.
  • Apache Security: You must configure Apache more strictly by disabling unnecessary headers, setting up a firewall (like Windows Firewall or WAF), and implementing SSL/HTTPS (using certificates).
  • Database Safety: Ensure PostgreSQL is protected with a strong, unique password and is not accessible from outside your local network.
  • Follow the Experts: Always consult the official Django Deployment Checklist and Apache security best practices before going live.

Comments

Leave a Reply

Your email address will not be published. Required fields are marked *