Deploy Flask on Windows Server (Azure VM) using Apache & Wsgi
1. Pre-Preparation
- Open ports 80, 443, 5000 (Windows Logo > Windows Defender Firewall with Advanced Security > Inbound Rules > New Rules ...
- Install Microsoft C++ Build Tools, Please refer to https://github.com/bycloudai/InstallVSBuildToolsWindows for detail. Windows 11 SDK is pretty large yet is still needed.
- Install Microsoft Visual C++ Redistributable (Maybe not needed if the above step has already finished doing so)
2. Install & Test Run Apache
- Dowload Apache from Apache 2.4 VS17 Windows Binaries and Modules, Unzip the file you will find a ReadMe.txt, on it will be the instructions about how to install it.
- After copying files over to C:/Apache24, open a CMD terminal as Administrator.
cd C:\Apache24\bin
httpd.exe
# Test your installation open address http://localhost at local and open address http://[ip address] at remote. You can shut down Apache by pressing Ctrl+C (It may take a few seconds).
httpd.exe -k install
httpd.exe -k start
httpd.exe -k stop
httpd.exe -k restart
- Restart the computer and test the server local and remote again. Make sure it's
http://[ip address] not https://[ip_address].
E: (OS 10048)Only one usage of each socket address (protocol/network address/port) is normally permitted. : AH00072: make_sock: could not bind to address [::]:80
(OS 10048)Only one usage of each socket address (protocol/network address/port) is normally permitted. :
AH00072: make_sock: could not bind to address 0.0.0.0:80
AH00451: no listening sockets available, shutting down
AH00015: Unable to open logs
netstat -aon | findstr :80
TCP 0.0.0.0:80 0.0.0.0:0 LISTENING 2660
TCP [::]:80 [::]:0 LISTENING 2660
taskkill /PID 2660 /F
SUCCESS: The process with PID 2660 has been terminated.
3. Install Python, MySQL, etc
python -m venv venv
venv\Scripts\activate
pip install -r requirements.txt
# Test flask test server local and remote on port 5000
pip install mod_wsgi
mod_wsgi-express module-config
LoadFile "C:/Users/Developer/AppData/Local/Programs/Python/Python312/python312.dll"
LoadModule wsgi_module "C:/flask_blog/venv/Lib/site-packages/mod_wsgi/server/mod_wsgi.cp312-win_amd64.pyd"
WSGIPythonHome "C:/flask_blog/venv"
4. Copy the flask application into server and here is the project structure
C:\flask_blog\
+-- flaskblog
| +-- __init__.py
+-- deploy
| +-- flaskblog.wsgi
+-- logs
+-- venv
+-- requirements.txt
+-- run.py
+-- flaskblog.conf
flaskblog.wsgi
import sys
sys.path.insert(0, 'C:\\flask_blog')
from flaskblog import create_app
application = create_app()
flaskblog.conf
<VirtualHost *:80>
ServerName 104.208.86.219
WSGIScriptAlias / C:/flask_blog/deploy/flaskblog.wsgi
<Directory C:/flask_blog>
Require all granted
</Directory>
Alias /static C:/flask_blog/flaskblog/static
ErrorLog C:/flask_blog/logs/error.log
CustomLog C:/flask_blog/logs/access.log combined
</VirtualHost>
5. Configure Apache httpd.conf
......
LoadFile "C:/Users/Developer/AppData/Local/Programs/Python/Python312/python312.dll"
LoadModule wsgi_module "C:/flask_blog/venv/Lib/site-packages/mod_wsgi/server/mod_wsgi.cp312-win_amd64.pyd"
WSGIPythonHome "C:/flask_blog/venv"
Include C:/flask_blog/flaskblog.conf
6. Restart Apache server and test open the webpage on a remote browser
E: In the error.log: ModuleNotFoundError: No module named '_socket'\r
S: Add WSGIPythonPath in httpd.conf file under WSGIPythonHome
WSGIPythonHome "C:/Users/12506/AppData/Local/Programs/Python/Python311"
WSGIPythonPath "C:/Users/12506/AppData/Local/Programs/Python/Python311\DLLs"
E: httpd.exe: Syntax error on line 538 of C:/Apache24/conf/httpd.conf: Cannot load C:/flask_blog/venv/Lib/site-packages/mod_wsgi/server/mod_wsgi.cp312-win_amd64.pyd into server: The specified module could not be found.
S: Get rid of virtual environment
7. Enable HTTPS after adding a domain name
- Get a free SSL certificate from ZeroSSL
Troubleshooting - DNS (CNAME) Verification
Please check if you have added the correct Name record:
For example, your Name record in ZeroSSL is _D5856C5EEC87E5505EF3F53E95B414EB.domain.com, please enter only_D5856C5EEC87E5505EF3F53E95B414EB without the domain part as most DNS providers filter this part out automatically.
- Download the certificate files and paste it into C:\Apache24\conf directory
- Edit C:\Apache24\conf\httpd.conf by un-commenting these 3 lines
LoadModule socache_shmcb_module modules/mod_socache_shmcb.so
LoadModule ssl_module modules/mod_ssl.so
Include conf/extra/httpd-ssl.conf
- Comment out the original "Include" (We will stop using flaskblog.conf config setups from now on)
LoadFile "C:/Users/Developer/AppData/Local/Programs/Python/Python312/python312.dll"
LoadModule wsgi_module "C:/Users/Developer/AppData/Local/Programs/Python/Python312/Lib/site-packages/mod_wsgi/server/mod_wsgi.cp312-win_amd64.pyd"
WSGIPythonHome "C:/Users/Developer/AppData/Local/Programs/Python/Python312"
# Include C:/flask_blog/flaskblog.conf
- Edit C:\Apache24\conf\extra\httpd-ssl.con\
<VirtualHost *:80>
ServerName www.peng.codes
Redirect / https://www.peng.codes/
</VirtualHost>
<VirtualHost _default_:443>
ServerName www.peng.codes:443
WSGIScriptAlias / C:/flask_blog/deploy/flaskblog.wsgi
<Directory C:/flask_blog>
Require all granted
</Directory>
Alias /static C:/flask_blog/flaskblog/static
ErrorLog C:/flask_blog/logs/error.log
CustomLog C:/flask_blog/logs/access.log combined
SSLEngine on
SSLCertificateFile "${SRVROOT}/conf/certificate.crt"
SSLCertificateKeyFile "${SRVROOT}/conf/private.key"
SSLCertificateChainFile "${SRVROOT}/conf/ca_bundle.crt"
# Since I don't know what below lines mean, I will keep them for safety.
<FilesMatch "\.(cgi|shtml|phtml|php)$">
SSLOptions +StdEnvVars
</FilesMatch>
<Directory "${SRVROOT}/cgi-bin">
SSLOptions +StdEnvVars
</Directory>
BrowserMatch "MSIE [2-5]" \
nokeepalive ssl-unclean-shutdown \
downgrade-1.0 force-response-1.0
CustomLog "${SRVROOT}/logs/ssl_request.log" \
"%t %h %{SSL_PROTOCOL}x %{SSL_CIPHER}x \"%r\" %b"
</VirtualHost>
- Restart the apache service and it should work instantly.
8. References
Share this post
Related Posts
Basic tmux Commands for Terminal Sessions
Learn the basic tmux commands to create, list, detach, reattach, rename, and remove terminal sessions.
Xesim Guide for Chinese iPhones
Using Xesim to Manage Multiple Numbers or Data Plans from Different Countries on the Second SIM Card of a Chinese iPhone 17
The Evolution of Infrastructure Management
The evolution of infrastructure management goes from clicking in the cloud console to AI-assisted operations.
Linux Commands Cheat Sheet
Linux commands cheat sheet: comprehensive reference covering basic commands, man pages, and help options.