I'm trying to deploy a very simple Flask app that appears in this tutorial for testing login capabilities in a flask app: https://www.digitalocean.com/community/tutorials/how-to-add-authentication-to-your-app-with-flask-login. I only changed a few things but it is mostly the same. The app structure is this one:
When I run it locally and externally through the flask server it works great but when I try to serve it through Apache it fails with a "Internal Server Error" message and the following errors in the error.log from Apache:
> [Tue May 09 19:48:18.108969 2023] [wsgi:error] [pid 31601] [client 185.216.73.35:9480] mod_wsgi (pid=31601): Failed to exec Python script file '/var/www/bdl/portal/app.wsgi'.
[Tue May 09 19:48:18.109123 2023] [wsgi:error] [pid 31601] [client 185.216.73.35:9480] mod_wsgi (pid=31601): Exception occurred processing WSGI script '/var/www/bdl/portal/app.wsgi'.
[Tue May 09 19:48:18.116248 2023] [wsgi:error] [pid 31601] [client 185.216.73.35:9480] Traceback (most recent call last):
[Tue May 09 19:48:18.116298 2023] [wsgi:error] [pid 31601] [client 185.216.73.35:9480] File "/var/www/bdl/portal/app.wsgi", line 4, in <module>
[Tue May 09 19:48:18.116305 2023] [wsgi:error] [pid 31601] [client 185.216.73.35:9480] from app import main as application
[Tue May 09 19:48:18.116322 2023] [wsgi:error] [pid 31601] [client 185.216.73.35:9480] ModuleNotFoundError: No module named 'app'
This is the content from the app.wsgi file:
import sys
sys.path.insert(0, "/var/www/bdl/portal")
from app import main as application
This is the __init__.py
:
activate_this_file = "/var/www/bdl/auth/bin/activate_this.py"
with open(activate_this_file) as _file:
exec(_file.read(), dict(__file__=activate_this_file))
from flask import Flask
from flask_sqlalchemy import SQLAlchemy
from flask_login import LoginManager
# init SQLAlchemy so we can use it later in our models
db = SQLAlchemy()
def create_app():
app = Flask(__name__)
app.config['SECRET_KEY'] = 'xxxxxxxxxxxxxxxxx'
app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///db.sqlite'
db.init_app(app)
login_manager = LoginManager()
login_manager.login_view = 'auth.login'
login_manager.init_app(app)
from .models import User
@login_manager.user_loader
def load_user(user_id):
# since the user_id is just the primary key of our user table, use it in the query for the user
return User.query.get(int(user_id))
# blueprint for auth routes in our app
from .auth import auth as auth_blueprint
app.register_blueprint(auth_blueprint)
# blueprint for non-auth parts of app
from .main import main as main_blueprint
app.register_blueprint(main_blueprint)
from . import models
with app.app_context():
db.create_all()
return app
This is the main.py
file:
from flask import Blueprint, render_template
from flask_login import login_required, current_user
from . import db
main = Blueprint('main', __name__)
@main.route('/')
def index():
return render_template('index.html')
@main.route('/profile')
@login_required
def profile():
return render_template('profile.html', name=current_user.name)
And this is the Apache .conf
file:
<VirtualHost *:80>
ServerName balldatalab.com
ServerAlias www.balldatalab.com
ServerAdmin webmaster@localhost
DocumentRoot /var/www/bdl/portal
RewriteEngine on
RewriteCond %{HTTPS} !=on
RewriteRule ^/?(.*) https://%{SERVER_NAME}/$1 [R=301,L]
WSGIScriptAlias / /var/www/bdl/portal/app.wsgi
<Directory /var/www/bdl/portal>
Order allow,deny
Allow from all
</Directory>
ErrorLog /var/www/bdl/portal/logs/error.log CustomLog /var/www/bdl/portal/logs/access.log combined </VirtualHost>
<VirtualHost *:443>
ServerName balldatalab.com
ServerAlias www.balldatalab.com
ServerAdmin webmaster@localhost
DocumentRoot /var/www/bdl/portal
SSLEngine on
SSLCertificateFile /etc/ssl/certs/bdl9.cer
SSLCertificateKeyFile /etc/ssl/private/bdl9.key
SSLCertificateChainFile /etc/ssl/certs/bdl9-inter.cer
WSGIScriptAlias / /var/www/bdl/portal/app.wsgi
<Directory /var/www/bdl/portal>
Order allow,deny
Allow from all
</Directory>
ErrorLog /var/www/bdl/portal/logs/error.log CustomLog /var/www/bdl/portal/logs/access.log combined
</VirtualHost>
I really don't know what's wrong here, can you help me? Thanks in advance!
It's complaining because--as the error says--there's no Python module named app
in the portal
directory. app.wsgi
isn't a Python module. You need to either have an app.py
file or an /app/
directory which contains an __init__.py
file in it. So the quickest way to fix the issue would be to rename /portal/__init__.py
to app.py
.
However, beyond that:
__init__.py
file doesn't actually create a Flask app object named main
(which is what you're trying to import in your app.wsgi
file). It has a create_app()
function that returns a Flask app object, but no code that actually calls that function and assigns it to a variable named main
.create_app()
function also references an auth
module that I don't see in your list of files/directories; I recommend you comment out that code until you get a 'hello world' app running.I would recommend you try to change __init__.py
(which you should rename to app.py
) to something like this for now:
from flask import Flask
from flask_sqlalchemy import SQLAlchemy
from flask_login import LoginManager
# init SQLAlchemy so we can use it later in our models
db = SQLAlchemy()
app = Flask(__name__)
app.config['SECRET_KEY'] = 'xxxxxxxxxxxxxxxxx'
app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///db.sqlite'
db.init_app(app)
login_manager = LoginManager()
login_manager.login_view = 'auth.login'
login_manager.init_app(app)
from .models import User
@login_manager.user_loader
def load_user(user_id):
# since the user_id is just the primary key of our user table, use it in the query for the user
return User.query.get(int(user_id))
# From Nathan: Comment this stuff out if you don't have an auth module set up yet.
# blueprint for auth routes in our app
# from .auth import auth as auth_blueprint
# app.register_blueprint(auth_blueprint)
# blueprint for non-auth parts of app
from .main import main as main_blueprint
app.register_blueprint(main_blueprint)
from . import models
with app.app_context():
db.create_all()