Step 0. Domain setup.
Before deployment, it’s important to register a domain.
Not an ad, but it could be! There are many registrars on the market, but I chose porkbun — it offered the best price-to-feature ratio. Unlike many services where the first year is cheap and renewals are much more expensive, porkbun offers reasonable renewal rates as well.
The package already includes an SSL certificate you can use for HTTPS at no extra cost.
Tip: before buying, be sure to compare prices for TLDs across different registrars. The same domain in .com, .net, or .io can cost very different amounts depending on the platform.
DNS records configuration.
After purchasing a domain, go to the control panel and open the DNS Records section.
Delete all existing records (if you don’t need them) and create two new A (Address Record) entries:
First record.
Type: A - Address Record
Host: example.com (Your site’s domain)
TTL: 600 (If you want the cache to persist longer, set a larger value. The larger the value, the higher the load on the server.)
Answer/Value: the server’s external IP address (for example, 93.184.216.34)
(you can find it on 2ip.io)
Second record.
Type: A - Address Record
Host: www.example.com (Your site’s domain with www prefix)
TTL: 600 (same value as for the first record)
Answer/Value: the same external IP address
Why this matters: having both records ensures the site works correctly at both example.com and www.example.com.
Connection check.
After saving the records:
- Wait from 5 minutes to 24 hours — this is how long DNS changes can take to propagate (depending on TTL and your provider).
- Check domain availability with the command:
ping example.com
SSL certificate.
Go to the SSL tab and download the key bundle. Later we’ll add them to the project, connect them, and get an HTTPS connection, so don’t lose them.
Step 1. Preparing the server.
We’ll use a home server as the base, a Mikrotik as the router, and a computer to work with it. For virtualization, we’ll choose Hyper-V (included in Windows 10/11 Pro and Windows Server).
Enable Hyper-V
- Open Control Panel → Programs and Features → Turn Windows features on or off.
- Check Hyper-V Platform and Hyper-V Management Tools.
- Restart the computer.
Create a virtual switch:
- Launch Hyper-V Manager.
- In the right menu, choose Virtual Switch Manager.
- Create an External virtual switch and bind it to the NIC through which the server will access the Internet/LAN.
- Save changes.
Create a virtual machine
- In Hyper-V Manager click New → Virtual Machine.
- Specify a name (e.g., WinServer2022).
- Choose Generation 2 (recommended for Windows Server 2022).
- Set RAM — 6144 MB (6 GB) or more if necessary. NOT less than 4 GB (PostgreSQL requirements).
- Select the previously created virtual switch.
- Create a virtual disk of 60 GB (VHDX format, dynamically expanding).
- Specify the Windows Server 2022 ISO image (downloaded in advance from Microsoft’s official site).
- Finish the wizard and start the installation.
Install Windows Server 2022
- Choose Desktop Experience during installation (Windows with GUI).
- Set the administrator password.
- Wait for reboot and the first login.
Configure a static IP
- Open Network settings → Change adapter options.
- Find your network adapter, click Properties.
- Select Internet Protocol Version 4 (TCP/IPv4) → Properties.
- Set:
- IP address: 192.168.6.66 (within your network)
- Subnet mask: 255.255.255.0
- Gateway: 192.168.6.1 (your gateway address)
- DNS: you can set 8.8.8.8 (Google) or a local DNS
Enable RDP access
- Open Control Panel → System and Security → System.
- Click Remote settings.
- In Remote Desktop enable Allow remote connections.
- Add the user who will be allowed to sign in.
- Make sure the firewall allows inbound traffic on port 3389; usually there are no issues with this.
Create a new user and disable Administrator
- Open Control Panel → Administrative Tools → Computer Management → Local Users and Groups.
- In Users, create a new user with a short name (e.g., srvuser).
- Set a strong password (length ≥ 12 characters, mixed case, digits, special characters).
- Add the user to the Administrators group.
- Sign out and sign in under the new user.
- Deactivate the default Administrator account (right-click → Disable), but only if you’re sure the new user has all necessary privileges.
First programs
For convenience, install Notepad++ right away (trust me, you’ll need it; Notepad won’t cut it for later configs):
- Download the installer from the official site.
- Install with default settings.
Create a server snapshot so you can easily roll back in case of a catastrophic error later.
In Hyper-V select the server → right-click → Checkpoint.
Close the server window, switch to the main workstation desktop, choose Remote Desktop or Microsoft Remote Desktop (at the time of writing, Windows App). Connect to the server, log in under our new user, and continue working comfortably.
Step 2. Installing Apache.
For a Django project we’ll need the Apache HTTP Server. We’ll use the build from Apache Lounge, as it’s optimized for Windows.
Downloading and unpacking Apache
- Go to apachelounge.com/download.
- Download the ZIP archive of the latest stable Apache version (e.g., httpd-2.4.x-win64-VS17.zip).
- Unpack the archive to the root of drive C:\ so that there is only one folder — C:\Apache24.
- The digits (24) indicate the major server version (Apache 2.4.x).
Apache folder structure
Inside C:\Apache24 you’ll find key folders and files:
- bin — executables (httpd.exe, ab.exe) and Apache utilities.
- conf — configuration files (httpd.conf, extra\*.conf). This is where server modules, virtual hosts, SSL, etc. are configured.
- htdocs — default web root (HTML, PHP, static assets). We’ll store our Django project here.
- logs — error and access logs (error.log, access.log).
- modules — Apache module files (.so), including mod_wsgi.so.
- licenses — component licenses.
First run
Before starting, we must specify one important parameter in httpd.conf. Open it and set the parameter without which startup will throw an error:
ServerName example.com
Now you can start:
- Open cmd as Administrator.
- Go to C:\Apache24\bin
- Install Apache with
httpd.exe -k install
- Run
httpd.exe -t
(You should get Syntax OK) - Start Apache with
httpd.exe -k start
- Open the browser and go to localhost — you should see an HTML page saying “It works!”
Apache is running and ready for configuration.
Step 3. Setting up the development environment.
For deploying a Django project on Windows Server we’ll need:
- Python
- Django and project libraries
- Apache HTTP Server (already installed)
- mod_wsgi (a module to run Django via Apache)
- PostgreSQL
Installing Python
- Download the latest Python from www.python.org.
- During installation, be sure to check "Add Python to PATH" — this allows calling python and pip from the command line.
- Prefer installing for all users.
- After installation, open cmd and check:
python --version
pip --version
Creating a virtual environment
Our project will live in C:\Apache24\htdocs\. You’ll already see a created HTML file there that shows “It works!” when Apache starts.
Delete this file and create a virtual environment to isolate our project and its libraries we’ll install later.
Open cmd and run:
cd C:\Apache24\htdocs\
pip install virtualenv
python -m venv venv
venv\Scripts\activate
Moving the project
At this point you can transfer the existing project folder from the main machine to the server. I personally had trouble copying via Hyper-V, so I used OpenSSH. The project will live in the same root alongside the venv folder.
C:\Apache24\htdocs\
├──venv
├──our_project
Installing libraries
Ideally, you already have a requirements.txt for quick installation. If not, create one and add the list of libraries, which you can obtain on the main machine with pip freeze
.
cd our_project
pip install -r requirements.txt
Installing PostgreSQL
For production we’ll use PostgreSQL — a reliable and high-performance database.
- Download
- Go to the official site: https://www.postgresql.org/download/windows/
- Download the installer from EnterpriseDB.
- Installation
- Run the installer.
- During setup, select components:
- PostgreSQL Server
- pgAdmin 4 (for convenient DB management)
- Command Line Tools (psql)
- Specify the installation directory (default C:\Program Files\PostgreSQL\16\).
- Set the postgres superuser password — save it, you’ll need it for Django.
- Leave the port as default — 5432.
- Wait for the installation to finish.
- Verification
- Open cmd and enter:
psql -U postgres
If you see the prompt postgres=#, PostgreSQL is installed and running.
In pgAdmin 4 you can create a user, database, etc., as you did on your main machine earlier.
Django settings before deployment
Open settings.py and make the changes:
DEBUG = False
ALLOWED_HOSTS = [
'localhost',
'127.0.0.1',
'192.168.6.66’, # internal IP
'93.184.216.34', # external IP
'example.com',
'www.example.com'
]
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.postgresql_psycopg2’,
'NAME': 'myprojectdb',
'USER': 'myprojectuser',
'PASSWORD': 'password',
'HOST': 'localhost',
'PORT': '5432',
}
}
STATIC_ROOT = os.path.join(BASE_DIR, 'staticfiles')
Apply migrations:
python manage.py migrate
Django sanity check
Before configuring mod_wsgi and hooking up Apache, let’s make sure the project works correctly with PostgreSQL. Run the project without Apache.
In cmd go to the project root and run python manage.py runserver
Check:
- Homepage opens.
- Database connection works (if there are pages with data — they render).
- No errors in the console.
If you see errors at this stage, set DEBUG = True
and fix the project.
So:
✅ Server ready
✅ Virtual environment ready
✅ Project present
✅ Dependencies installed
✅ Database ready
Step 4. Installing and configuring mod_wsgi
mod_wsgi is a module that lets Apache run Python apps (in our case, Django).
Install mod_wsgi
- Activate the project’s virtual environment:
cd C:\Apache24\htdocs\venv\Scripts
activate
- Install:
pip install mod_wsgi
or
pip install mod-wsgi
Attention! If during installation you see error: Microsoft Visual C++ 14.0 or greater is required
proceed to the next step to fix it. If there was no error, you’re good.
Fixing “Microsoft Visual C++ 14.0 or greater is required”
- Go to the official site:
https://visualstudio.microsoft.com/visual-cpp-build-tools/ - Download the Build Tools for Visual Studio installer.
- During setup, select only the first checkbox:
Desktop development with C++.
(Main thing is to include MSVC v143 - VS 2022 C++ x64/x86 build tools and Windows 10 SDK)
- Wait for installation to complete and reboot the server.
- Repeat the installation:
pip install mod_wsgi
Getting the configuration for Apache
After a successful install, run:
mod_wsgi-express module-config
This command outputs ready-made connection lines, for example:
LoadFile "C:/Program Files/Python313/python313.dll"
LoadModule wsgi_module "C:/Program Files/Python313/Lib/site-packages/mod_wsgi/server/mod_wsgi.cp313-win_amd64.pyd"
WSGIPythonHome "C:/Apache24/htdocs/venv"
Important:
- The paths to python313.dll and mod_wsgi.cp***.pyd depend on your Python version.
- In WSGIPythonHome, specify the path to the project’s virtual environment.
Apache configuration (httpd.conf)
Open C:\Apache24\conf\httpd.conf in Notepad++.
Append the following to the end of the file (with your own paths and values):
LoadFile "C:/Program Files/Python313/python313.dll"
LoadModule wsgi_module "C:/Program Files/Python313/Lib/site-packages/mod_wsgi/server/mod_wsgi.cp313-win_amd64.pyd"
WSGIPythonHome "C:/Apache24/htdocs/venv"
WSGIScriptAlias / "C:/Apache24/htdocs/our_project/our_project/wsgi.py"
WSGIPythonPath "C:/Apache24/htdocs/our_project"
<Directory "C:/Apache24/htdocs/our_project/our_project/">
<Files wsgi.py>
Require all granted
Options -Indexes
</Files>
</Directory>
Alias /static "C:/Apache24/htdocs/our_project/staticfiles/"
<Directory "C:/Apache24/htdocs/our_project/staticfiles/">
Require all granted
Options -Indexes
</Directory>
Starting Apache
In Windows, open the search and type Services. Find Apache in the list of services, click it, and click restart.
If it doesn’t work or starts incorrectly, in cmd at C:\Apache24\bin run the tuning command:
httpd.exe -X -e debug
If successful, you should see your Django project.
Port forwarding 80
To make the site accessible from other devices on the network or the Internet, you need to forward the port:
Go to your router settings and create a rule in IP → Firewall → NAT:
- Chain: dstnat
- Dst. Port: 80
- Protocol: tcp
- Action: dst-nat → To Address: 192.168.6.66 (server IP)
Also, open port 80 in Windows Firewall:
- Open Control Panel → System and Security → Windows Defender Firewall.
- On the left, select Advanced settings (the “Advanced Security” window opens).
- In the left pane, go to Inbound Rules.
- On the right, click New Rule….
- In the wizard choose:
- Rule type: Port
- Protocol: TCP
- Port: 80 (for HTTP)
- In the next window select Allow the connection.
- Apply to all profiles (Domain, Private, Public).
- Name the rule, e.g., Apache HTTP 80.
- Click Finish.
Step 5. Adding SSL and configuring HTTPS.
To have the site open over the secure HTTPS protocol, you need to connect the SSL certificates we downloaded earlier from the registrar (see Step 0).
Preparing Apache for SSL
- Open C:\Apache24\conf\httpd.conf.
- Find the lines:
#LoadModule ssl_module modules/mod_ssl.so
#Include conf/extra/httpd-ssl.conf
and uncomment them (remove #).
- The line
Include conf/extra/httpd-ssl.conf
is better moved to the very end of the file so it’s applied after all other configs.
Placing the keys
- Create an ssl directory in C:\Apache24\conf\.
- Put the files downloaded from Porkbun (or another registrar) there. They usually have names like:
- private.key.pem — private key
- domain.cert.pem — main certificate
- domain.ca_bundle.crt — CA bundle
If extensions differ (.crt, .key, .pem) — that’s fine. What matters is:
- each file contains only one key/certificate;
- encoding is UTF-8 (without BOM) — you can check/change in Notepad++.
If one file contains two keys, split them into separate .pem or .crt files.
Configuring httpd-ssl.conf
Open C:\Apache24\conf\extra\httpd-ssl.conf and paste the following configuration:
Listen 443
<VirtualHost _default_:443>
ServerAdmin admin@example.com
ServerName example.com
DocumentRoot "C:/Apache24/htdocs"
SSLEngine on
SSLCertificateFile "C:/Apache24/conf/ssl/domain.cert.pem"
SSLCertificateKeyFile "C:/Apache24/conf/ssl/private.key.pem"
SSLCertificateChainFile "C:/Apache24/conf/ssl/domain.ca_bundle.crt"
WSGIScriptAlias / "C:/Apache24/htdocs/our_project/our_project/wsgi.py"
<Directory "C:/Apache24/htdocs/our_porject/our_project/«>
<Files wsgi.py>
Require all granted
Options -Indexes
</Files>
</Directory>
Alias /static "C:/Apache24/htdocs/our_project/staticfiles/"
<Directory "C:/Apache24/htdocs/our_project/staticfiles/">
Require all granted
Options -Indexes
</Directory>
ErrorLog "logs/ssl_error.log"
CustomLog "logs/ssl_access.log" combined
</VirtualHost>
Redirect HTTP to HTTPS (recommended)
To avoid duplicate content and force everyone onto HTTPS, add this to httpd.conf:
<VirtualHost *:80>
ServerName example.com
ServerAlias www.example.com
Redirect permanent / https://example.com/
</VirtualHost>
External network access (HTTPS)
In Step 4, port 80 was already forwarded. Here we’ll add what’s needed for 443/HTTPS and proper access from both the Internet and your LAN.
- Create dstnat for tcp/443 to your server (192.168.6.66).
- Set up hairpin NAT (loopback) so the domain opens from your LAN as well:
- dstnat: when dest-address = your external IP and in-interface = LAN → to-address = 192.168.6.66
- srcnat/masquerade: for traffic from LAN to the external IP.
- Result: https://example.com will open the same inside and outside.
- Add an inbound rule for TCP/443 in Windows Firewall (port 80 was done earlier).
Now the site opens over HTTPS without browser warnings. Everything is correct and secure!
Step 6. Final check and production checklist
Verify functionality. Go to https://example.com/
If issues arise during setup, check the logs folder to see the errors and paste them into ChatGPT. The main thing is to understand how it works so you can guide AI to fix unplanned errors — you can get hundreds even if everything looks logically correct and clean. It’s better to learn Apache than dive into the weeds like Linux with Gunicorn and Nginx.
Don’t use shady certificates; don’t be tempted to do everything for free (only Let’s Encrypt!). It’s not safe and not good for SEO.
Most errors are due to incorrect folder and file paths in configs. I also ran into version conflicts. It’s the second week of writing this article and I’m too lazy to check whether I mentioned it, but psycopg2-binary==2.9.10
threw an error for me, I replaced it with psycopg-binary==3.2.9
and it worked — keep that in mind.
If you run into errors that ChatGPT can’t solve, send your config and log screenshots to me on Telegram — I’ll try to help!