DEV Community

William Sousa
William Sousa

Posted on • Updated on

Flask on Windows using Apache

Flask is a Python based micro-framework, which can be used to create dynamic websites, APIs, and many other applications.

Despite all Linux cloud options you might have a customer with a Windows environment, that would rather use their existing system than setting a Linux one. No problem, right? But how do we deploy a Flask app to production Windows?

As I faced many issues when I had this challenge, I thought listing the steps and some of the problems would be a good topic for my first post on Dev.to.

The official deployment documentation states "Flask’s built-in server is not suitable for production as it doesn’t scale well", so you need a WSGI server to deploy your Flask application to production.

I will start using Apache + mod_wsgi, and later add more posts to the series covering other options.

Flask deployment on Windows using Apache and mod_wsgi

1. Install Apache

Go with the recommended distribution from Apache Lounge. I downloaded version 2.4.43 Win64 as a zip file. There was a warning saying "Be sure you installed latest 14.xx Visual C++ Redistributable for Visual Studio 2015-2019", and they provide direct download links for it. Make sure to download the appropriate vc_redist x64 or x86, matching the Apache version you got, in my case x64.

Install the vc_redist and then unzip Apache to the default location C:\Apache24. If you select a different location take note as we'll need it later.

To test Apache, open a command prompt, cd C:\Apache24\bin. Then issue this command to start Apache:
httpd.exe

After you press Enter, it will tell you if there are any errors. Open a browser and go to http://localhost. You should see a page saying "It works!". You can shut down Apache by pressing Ctrl+C (it may take a few seconds).
The ReadMe.txt file on Apache's zip file has more information and examples, including how to run it as a Windows service.

2. Install mod_wsgi

You need the mod_wsgi Python package as the middle man to show Apache how to handle Python applications.

Assuming you already have Python installed, mod_wsgi can be installed using pip install mod_wsgi on the command prompt. However, some of its dependencies might make it tricky.

2.1 Apache location

If you didn't install Apache on the default location, you might get this error after the pip install mod_wsgi:

RuntimeError: No Apache installation can be found. Set the MOD_WSGI_APACHE_ROOTDIR environment to its location.

If that's the case, use the set command. For example:

set "MOD_WSGI_APACHE_ROOTDIR=F:/Apache24"

Ensure you specify the path with a forward slash, like the example. This is only needed when doing the install.

2.2 Microsoft Visual C++ Build Tools

After that, if you try the pip install mod_wsgi again, you might receive a long error, but the most important part is this one:

    building 'mod_wsgi.server.mod_wsgi' extension
    error: Microsoft Visual C++ 14.0 is required. Get it with "Microsoft Visual
C++ Build Tools": https://visualstudio.microsoft.com/downloads/

mod_wsgi will be compiled on your Windows host, so it has a dependency on Microsoft Visual C++ Build Tools. Note the Build Tools are different than the Redistributable that you installed on step 1.

Go to the Visual Studio download page, expand Tools for Visual Studio, and click the download link for the Build Tools (currently 2019). Execute the installer, select C++ build tools, on the right side you can un-check some optional features, but you need at least MSVC v142 and Windows 10 SDK.
Microsoft Visual C++ Build Tools installer
After the install is complete you will have to reboot Windows.

Finally, try the pip install mod_wsgi again and it should work.
If you still face errors, on the Start menu look for "Developer Command Prompt for VS 2019", and use it to issue the pip install mod_wsgi. It will have the correct PATH with the VC++ Build Tools and should avoid setup issues.

3. Flask app setup

Assuming you already know Flask, and installed it on your Windows using pip install flask, there a few considerations for structuring your app:

  • The general recommendation is to set your app to act like a Python package, so create a folder containing at least a __init__.py with the main code.
  • Another option, is to use an empty __init__.py and the main code on another .py file on the same folder.
  • As a Python package, avoid using '-' on your folder name, otherwise you might face syntax errors when importing your app later. This StackOverflow question gives more details about it.

3.1 Sample app and structure

Here is the __init__.py sample I used for this article:

from flask import Flask
app = Flask(__name__)

@app.route('/')
def hello_world():
    return 'Hello Flask under Apache!'

if __name__ == "__main__":
    app.run()

Here is the project structure for this sample:

C:\git\
+-- yourapp
|   +-- __init__.py          
+-- wsgi_scripts
|   +-- yourapp.wsgi

In this case my app 'package' is called yourapp.

3.2 Create your .wsgi file

To run your application you need a wsgi file. In my sample I have yourapp.wsgi. Note that I stored this file on a separate folder. Storing the wsgi file on the same folder as you Flask app works as well, but is not recommended.

A minimal wsgi file (which is Python code):

import sys
sys.path.insert(0, 'C:\\git')
from yourapp import app as application
  • The sys.path.insert should point to the location that contains the folder with your app.
  • Use double backslashes on your sys.path.insert.

4. Configure Apache httpd.conf

On the command prompt, issue: mod_wsgi-express module-config , the output should be similar to:

LoadFile "c:/program files/python37/python37.dll"
LoadModule wsgi_module "C:/Users/prod_deploy/AppData/Roaming/Python/Python37/site-packages/mod_wsgi/server/mod_wsgi.cp37-win_amd64.pyd"
WSGIPythonHome "c:/program files/python37"

Copy the output and paste it on your C:\Apache24\conf\httpd.conf. I suggest putting it after the existing LoadModule directives.

At the end of the same httpd.conf file, add:

# Include Flask file
Include conf/yourapp.conf

Replace yourapp with the name of the configuration file you want to use. With this, we will have the Flask VirtualHost configuration on a separate file, avoiding mistakes.

5. Create the yourapp.conf

On your Apache install folder, navigate to the conf subfolder, e.g. C:\Apache24\conf, and create the yourapp.conf file.

A minimal sample file:

<VirtualHost *:80>
    ServerName flaskwill.com
    WSGIScriptAlias / C:/git/wsgi_scripts/yourapp.wsgi
    <Directory C:/git/yourapp>
        Require all granted
    </Directory>
</VirtualHost>
  • On VirtualHost, change 80 to a different port if needed.
  • ServerName should list the server's IP address or a DNS name
  • WSGIScriptAlias has two arguments, the first is the website path which will be associated with the wsgi file, in this example / or the root. The second argument is the absolute path to the wsgi file. In this example, when I access flaskwill.com/ it will execute my yourapp.wsgi.
  • Directory should point to the folder with your Flask app files. Note the 'Require all granted' to give Apache (version 2.4 or later) access to the files and sub-folders. Older versions of Apache use a different syntax.

6. Start Apache and test your app

After covering all steps, start Apache (or restart it if already running), so it will read the conf files and load your app.
Open a browser and enter http://localhost and your Flask app should show up. If you set a DNS address like the flaskwill I used, you will have to update the real DNS to point to your server, or you could update your Windows hosts file to test it locally.

Closing

I hope this is useful for someone, but remember this is just one way of doing it, as I am sure there are other methods of deploying Flask.
I appreciate any feedback so I can improve this post and learn for the next ones.

Thank you for reading!

References:

https://flask.palletsprojects.com/en/1.1.x/deploying/mod_wsgi/
https://github.com/GrahamDumpleton/mod_wsgi
https://modwsgi.readthedocs.io/en/develop/index.html
http://httpd.apache.org/docs/2.4/

Top comments (16)

Collapse
 
shreyanse081 profile image
Shreyans Jain • Edited

Hi William, thank you for the amazing article. I was facing a small issue with VHost.conf file in tag.
Error:
AH01630: client denied by server configuration: C:/git/wsgi_scripts/yourapp.wsgi
Solution:
It worked for me with <Directory C:/git> instead of <Directory C:/git/yourapp>

Also deploying it with flask there was an issue with few other packages like Pandas and Scikit-Learn where the flask was hanging.
So to solve this I added one line WSGIApplicationGroup %{GLOBAL} in httpd.conf under - Reference

LoadFile "c:/program files/python37/python37.dll"
LoadModule wsgi_module "C:/Users/prod_deploy/AppData/Roaming/Python/Python37/site-packages/mod_wsgi/server/mod_wsgi.cp37-win_amd64.pyd"
WSGIPythonHome "c:/program files/python37"
WSGIApplicationGroup %{GLOBAL}
Enter fullscreen mode Exit fullscreen mode

I also hope this helps others.

Collapse
 
willmvs profile image
William Sousa

Thank you for the feedback and these other hints Shreyans!

Collapse
 
fabiolus profile image
fabiolus

Thanks Shreyans - I encountered an issue when just importing spacy in the flask app
adding WSGIApplicationGroup %{GLOBAL} fixed it

Also regarding the Error:
AH01630: client denied by server configuration:

Changing the directive from

to

worked for me.

Collapse
 
ganeshkp11 profile image
Ganesh • Edited

Hi William,

I followed steps as you said..I am trying to diploy dash application. When i run server, webpage keeps running without any results. Any specific things needs to be considered?? Please help me on this.

Regards
Ganesh

Collapse
 
aitahmed99 profile image
AitAhmed99

Hello Ganesh, I am trying to deloy a dash application as well under wampserver stack ( it's a Web server stack package including apache). the app is not rendered, I still get "it works!" in the web page when I test it. I would like your guidance if you've managed to succesfully deploy it. Thanks.

Collapse
 
willmvs profile image
William Sousa

Sorry Ganesh, I didn't get notified of your post. I'm not sure about "dash application", but I recommend that you check the Apache logs on C:\Apache24\logs , to see if any error was recorded.

Collapse
 
appleonly707 profile image
appleonly

Hi William, Thanks for the article. I am just having trouble booting up apache after adding the Config lines in httpd.conf file. Getting this in my error logs -

Fatal Python error: initfsencoding: unable to load the file system codec
ModuleNotFoundError: No module named 'encodings'

Already checked that Encodings module is present and python is correctly installed.

Can you please help?

Collapse
 
chandersheel profile image
chandersheel • Edited

Hi william,
Thanks for the great article. Although, I am stuck at a problem while executing command at step-4 i.e. "mod_wsgi-express module-config" in command prompt. It is throwing "failed to create process" error. I have also searched many articles on the internet but did not find the solution. Kindly guide me through this error, if you know this.
Thanks

Collapse
 
aitahmed99 profile image
AitAhmed99

Thank you William for this detailed article. I am a complete newbie trying to deploy a dash application (mainly a Flask app) in windows environment. I have apache server already set up under wampserver (in my understanding it's a Web server stack package including apache ). However, I followed the steps as if apache is not there yet. Now, after completion, the app test (localhost test) is still returning "it works!" instead of the actual app.
I am stuck at this point, I would appreciate any comment of suggestion.
PS1: the app was tested in localhost and it works perfectly
PS2: my team uses wampserver for integrating other tools and apps, so this choice is kinda out of my hand. However, I am open to any other suggestions to rectify this.

Collapse
 
quangyendn profile image
yennq • Edited

Thanks for the post.
Apache is robust but it doesn't support well socket communication on Windows.

Collapse
 
willmvs profile image
William Sousa

Thank you for the feedback. I still need to learn more about Apache, are you saying it might face issues once it needs to handle multiple connections?

Collapse
 
deepank2596 profile image
deepank2596

Hi William,

Can u plz tell how to update hosts file to test the app locally.

Collapse
 
willmvs profile image
William Sousa

Hi deepank2596,
On Windows the hosts file is usually on C:\Windows\System32\drivers\etc . I believe it's a good idea to make a backup in case you make a mistake, and depending on your settings you might need admin access to edit the file. Once you edit it, you can add entries like this one:
127.0.0.1 willtest.com

It points to a fake address that I can type on my browser to simulate going to a real address. Besides that you can always use localhost on your browser to test the app locally.

Collapse
 
stonawski profile image
stonawski

Hi William,

after starting Apache, localhost shows just Forbidden site with error 403. Any advice?

Collapse
 
aokiahishatsu profile image
xeno • Edited

I also get HTTP 403 Forbidden

EDIT: Change the <Directory C:/git/yourapp> to <Directory C:/git> as described in the comment above.

Collapse
 
fabiolus profile image
fabiolus

Thanks for sharing this William!