My Path to a Production Setup
While most of the web runs on Linux, my latest project faced a specific challenge: it had to run on Windows. I quickly realized that the “standard” deployment advice (like using Gunicorn) doesn’t apply here. Being limited to a Windows environment meant I had to find a different way to ensure stability and performance. After plenty of trial and error, I built a stack that actually works: Django + Waitress + Nginx + PostgreSQL.
For this setup, I have created a dedicated root directory on the C: drive(project) that encapsulates the entire environment, including the Python runtime, the Nginx web server, and the Django application source code.
1 . Install Python
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 Nginx
Go to the nginx.org download page and grab the latest stable Windows version (it will be a .zip file).
- Extract the ZIP contents directly to C:\project\nginx to match the Python folder structure; no installation is required
- To start Nginx, open Command Prompt as Administrator, navigate to the directory using
cd C:\project\nginx, and executestart nginx, then verify it’s running by visitinghttp://localhostin your browser to see the welcome page - When you run this command for the first time, a Windows Defender Firewall prompt will appear; make sure to click “Allow Access” to permit Nginx to communicate over your network.
cd C:\project\nginx
start nginx
3 . Install PostgreSQL
In my journey, the choice to move away from SQLite was simple. While SQLite is perfect for those first few hours of coding, I knew that even for a small project, I wanted a setup that felt “real” and production-ready from day one. PostgreSQL was the obvious choice—it’s robust, handles data much more professionally, and is the undisputed industry standard for Django.
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
5432and Locale) - During setup, you’ll be asked to create a password for the
postgresuser. 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
djangoand click Save.
Moving forward in “My Path to a Production Setup”, we now need a home for our code and a way to keep our Python dependencies from making a mess of the system. This is where the project directory and the Virtual Environment (venv) come into play.
4 . Setting Up the Project Workspace
Within our C:\project root, we need a specific folder for the Django source code. This keeps our application logic separate from the Nginx, Python and PostgreSQL we’ve already installed.
Create the Application Folder: Open your Command Prompt and run:
mkdir C:\project\app
cd C:\project\app
The Virtual Environment (venv): 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.
Run the following command while inside C:\project\app:
python -m venv venv
Once created, you must “enter” this environment whenever you want to work on your app or install new packages.
Run the following command while inside C:\project\app:
venv\Scripts\activate
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>
Now that we are inside our isolated (venv), we can safely install our tools. In this step, we’ll bring in the framework itself and the production-grade server that will bridge the gap between Django and Nginx on Windows.
5 . Installing Django and Waitress
Run the following command in your terminal:
pip install django waitress
Initialize the Project: Run this command inside your app folder. The dot . at the end is crucial—it tells Django to create the project files right here in our current directory, keeping our structure clean:
django-admin startproject my_site .
To allow our Django to talk to PostgreSQL, we need a specific bridge
pip install psycopg2
Fire Up the Development Server: Django comes with a built-in server specifically for testing. While we won’t use this for our final production setup, it is the perfect tool for a “pulse check.” Run:
python manage.py runserver
The Moment of Truth
Once the server is running, you’ll see a message saying Starting development server at http://127.0.0.1:8000/.
- Open your browser and go to
http://127.0.0.1:8000. - The Result: If everything is set up correctly, you’ll be greeted by the iconic Django rocket ship page and the message: “The install worked successfully! Congratulations!”
This confirms that our Python installation, our virtual environment, and the Django framework are all communicating perfectly. When you’re finished admiring the rocket, go back to your Command Prompt and press Ctrl + C to stop the development server.
6 . Connecting the Gears
This is the moment where we transform individual pieces into a single, unified machine. We are going to link the database, configure the Waitress “engine,” and set Nginx as our primary gateway.
The first step is to tell Django to look toward PostgreSQL instead of SQLite. Open C:\project\app\my_site\settings.py and update the database block with your credentials:
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.postgresql',
'NAME': 'django',
'USER': 'postgres',
'PASSWORD': 'your_password_here',
'HOST': '127.0.0.1',
'PORT': '5432',
}
}
To run the application professionally on Windows, we create a script named run_server.py in C:\project\app. This script instructs Waitress to host our Django application on an internal port:
import os
import sys
from waitress import serve
# Add the current directory to the Python path
sys.path.append(os.path.dirname(os.path.abspath(__file__)))
# Now import the WSGI application
try:
from my_site.wsgi import application
except ModuleNotFoundError:
print("Error: Could not find 'my_site'. Make sure the folder name matches exactly.")
sys.exit(1)
if __name__ == '__main__':
print("Waitress is starting on http://127.0.0.1:8080")
serve(application, host='127.0.0.1', port=8080)
Nginx sits in front of Waitress, handling security and serving static files. Edit C:\project\nginx\conf\nginx.conf to direct traffic like this:
server {
listen 80;
server_name localhost;
# Static files (CSS, Images)
location /static/ {
alias C:/project/app/static/;
}
# Pass all other traffic to Waitress
location / {
proxy_pass http://127.0.0.1:8080;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}
}
This is the final touch for a truly professional “Playground.” Instead of juggling multiple command prompts, we will create a central control script. Since Windows uses .bat files for automation, we’ll build a Manager Script that can start, stop, and refresh the entire stack.
Create a file named refresh_stack.bat in your root folder C:\project and paste the following code:
@echo off
SET NGINX_PATH=C:\project\nginx
SET APP_PATH=C:\project\app
echo ==========================================
echo REFRESHING DJANGO PRODUCTION STACK
echo ==========================================
:: 1. Kill any existing instances to avoid port conflicts
echo [1/3] Cleaning up existing processes...
taskkill /IM python.exe /F >nul 2>&1
cd /d %NGINX_PATH%
nginx -s stop >nul 2>&1
:: 2. Start Nginx
echo [2/3] Starting Nginx...
start nginx
:: 3. Start Waitress
echo [3/3] Starting Waitress...
cd /d %APP_PATH%
start "Waitress Server" venv\Scripts\python run_server.py
echo ==========================================
echo STACK IS REFRESHED AND LIVE!
echo ==========================================
timeout /t 5
The All-in-One Manager
This script acts as a universal switch for your environment; you can use it to start the entire stack from scratch, restart services to apply code or configuration changes, or reset everything if a process hangs, all with a single double-click.
Important Note: Once the script finishes, a separate window will remain open running the Waitress server; do not close this window, as it must stay active for your website to remain accessible.
In a production setup (Nginx + Waitress), Django stops serving CSS and Images automatically for performance reasons. We need to gather all those files into one folder so Nginx can find them.
Open and ensure C:\project\app\my_site\settings.pySTATIC_ROOT is defined:
STATIC_URL = 'static/'
STATIC_ROOT = BASE_DIR / 'static'
A Quick Reminder on the Terminal
Before we run the next commands, we need to go back to our “Control Center.” As we did in the previous steps when we installed Django and ran our first migrations, you must ensure your terminal is active and inside the virtual environment.
Pro Tip: You’ll know you’re ready when you see the
(venv)prefix at the start of your command line. If you don’t see it, simply runvenv\Scripts\activateagain. This ensures that the commands below use the specific tools we’ve tucked away in ourC:\project\app\venvfolder
In your active terminal, run:
python manage.py collectstatic
Type yes when prompted. This will “copy-paste” all necessary files into a new folder called static.
Until now, our PostgreSQL database was just an empty “bucket.” By migrating, Django automatically creates the structure (the tables) where your users, sessions, and project data will be stored.
python manage.py migrate
Creating Your Admin Account
python manage.py createsuperuser
Follow the prompts for username, email, and password. (Note: Windows terminals won’t show the password as you type it—just type it blindly and hit Enter!)
Congratulations! You have successfully navigated the path from a raw Django project to a professional-grade production environment on Windows. You’ve bridged Nginx (the gateway), Waitress (the engine), and PostgreSQL (the memory) into one automated system.
The Grand Finale
To see your hard work in action:
- Run your
C:\project\refresh_stack.batscript to ensure all services are synchronized. - Open your browser and head to:http://localhost/admin/
Log in with the Superuser credentials you created. If you see the beautifully styled Django dashboard, it means Nginx is correctly serving your static files and your database is communicating perfectly with your code.
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, setDEBUG = False, and configureALLOWED_HOSTS. - Nginx Security: You must configure Nginx more strictly by disabling unnecessary headers, setting up a firewall, and implementing SSL/HTTPS (using Let’s Encrypt or similar).
- 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 Nginx security best practices before going live.
Leave a Reply