apacheflaskmod-wsgiflask-restx

Deploy Flask API on Apache, with mod_wsgi


I've followed several tutorials at this point and know this has to be some minor issue. PLEASE help me find it!

I have a Flask API, using Flask-Restx, ready to go and a remote Debian VPS with Apache. I'm not using a virtual environment.
My project is located at /var/www/ProvisioningApi/ and contains..

- __init__.py (blank)
- setup.py
- setup.wsgi
- ProvisioningApi/
--- __pycache__
--- api/
------ __init__.py  # not blank
------ auth/   # this holds the file with the auth endpoints
------ provision/  # more endpoints

setup.wsgi

#!/usr/bin/python
import sys
import logging
logging.basicConfig(stream=sys.stderr)
sys.path.insert(0, "/var/www/ProvisioningApp/")

from setup import app as application
application.secret_key = "nosecretshere"

setup.py

from ProvisioningApi.api import create_app

app = create_app()

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

/api/__init__.py

# root init file
from flask import Flask
from flask_restx import Api
from flask_jwt_extended import JWTManager

from werkzeug.middleware.proxy_fix import ProxyFix 

# Import the API views
from .auth.auth import auth
from .provision.provision import prov

# Import configuration settings
from .config.config import config_dict

def create_app(config=config_dict['prod']):
    app=Flask(__name__)

    app.config.from_object(config)

    # Instantiate RestX and add the Namespaces
    api = Api(app, 
              version='1.0', 
              title='Provisioning API', 
              description='My provisioning endpoints')

    api.add_namespace(auth, path='/auth')
    api.add_namespace(prov, path='/provision')
    
    jwt = JWTManager(app)

    app.wsgi_app = ProxyFix(app.wsgi_app)

    return app

Virtual Host at /etc/apache2/sites-available/ProvisioningApi.conf

/etc/apache2/sites-available/ProvisioningApi.conf

    <VirtualHost *:80> 
      ServerName          <the IP address for the server> 
      ServerAdmin         <my email address>
      WSGIScriptAlias    /  /var/www/ProvisioningApi/setup.wsgi 

  <Directory   /var/www/ProvisioningApi/ProvisioningApi/> 
    Order allow,deny 
    Allow from all 
  </Directory> 

  Alias     /api    /var/www/ProvisioningApi/ProvisioningApi/api 
 
 <Directory /var/www/ProvisioningApi/ProvisioningApi/api/> 
    Order allow,deny 
    Allow from all 
  </Directory> 

  ErrorLog ${APACHE_LOG_DIR}/error.log 
  LogLevel warn 
  CustomLog ${APACHE_LOG_DIR}/access.log combined 
</VirtualHost>

The error logs read:

File "/var/www/ProvisioningApi/setup.wsgi", line 7, in <module>
from setup import app as application
ModuleNotFoundError: No module named 'setup'

Going to the IP address, I see Internal Server Error. If I go to IP_address/api I see my index of files.
I've tweaked the nesting of files, added/removed init files, restarted Apache again and again, and the error is always about the imports in the setup.py file.

Thanks in advance!


Solution

  • Past self, you're gonna get this!

    I tried a hundred different things (including fixing the typo pointed out by Razenstein), and ultimately it was a matter of adjusting my files. I removed the /api/ folder and shifted the contents up a level. No edits to the imports inside the __init__.py.

    setup.wsgi

    import sys
    import logging
    logging.basicConfig(stream=sys.stderr)
    sys.path.insert(0, "/var/www/ProvisioningApi")
    
    from ProvisioningApi import create_app
    
    application = create_app()
    

    Unrelated, but important: if you are passing Access Tokens in the header for protected endpoints, you need to add WSGIPassAuthorization On into the VirtualHost file.