Oh ho, this is your lucky day! I solved this about a month ago and haven’t checked back here since, mainly because I was disheartened by the lack of help here. I didn’t get a notification of your message, I just happened to visit here. Have I already said that Dash/Plotly hardly seems ready for real work? Anyway, I was feeling guilty that I have ignored others who also needed help. I didn’t want to be one of those jerks who replies, “never mind, I solved it” and then doesn’t tell you how. Rant mode off now.
For me the problem boiled down to needing help with Apache Proxy configuration. A secondary problem was getting mod_wsgi installed on a cPanel host; we have a VPS (virtual private server) from Bluehost. Our domain is mira3.org. The long guide that follows will show you how I got a dash app deployed with WSGI on Apache in a cPanel host.
Advice is to put your python web apps not in Apache cgi-bin, but rather in directories not under Apache control. In a VPS system there is a primary administrative user (not root); let’s suppose the username is admin. I put python webapps in /home/admin/pyapps.
First make sure you can run a dash development server and connect by Apache proxy. Dash dev server typically runs on localhost:8050. This is not how dash apps should be run in production, but if you can’t get this to work, you probably won’t get WSGI deployment to work. In pyapps do mkdir proxy_test.
Program dash_test_app.py is put in /home/admin/pyapps/dash_test.
# -*- coding: utf-8 -*-
# test using localhost:8050
import dash
import dash_core_components as dcc
import dash_html_components as html
app = dash.Dash(__name__)
app.config.update({
'url_base_pathname':'/dtest/',
'routes_pathname_prefix':'/dtest/',
'requests_pathname_prefix':'/dtest/',
})
server = app.server
app.scripts.config.serve_locally = True
app.css.config.serve_locally = True
app.layout = html.Div(children=[
html.H1('Hello Dash: test by proxy'),
])
if __name__ == '__main__':
app.run_server(debug=True, port=8050)
Now you have to configure Apache. On a VPS cPanel system, you need to create a conf file that will be included when Apache boots. Look in /etc/apache2/conf/httpd.conf for specific instructions. On our system we create a file named vhost.conf (any .conf name is OK) and put it in /etc/apache2/conf.d/userdata/std/2_4/admin/mira3.org. Note that username admin and domain name mira3.org are required (but you will use whatever names you have). Here is the config:
# proxy for dash_test on localhost
ProxyPass /dtest http://127.0.0.1:8050
ProxyPassReverse /dtest http://127.0.0.1:8050
Restart Apache. The first command is required on cPanel systems in order to get your custom conf files.
/usr/local/cpanel/scripts/rebuildhttpdconf
/usr/local/cpanel/scripts/restartsrv httpd
Run you dash_test_app.py, assuming you have activated the virtualenv that has dash and plotly.
python dash_test_app.py
Web browser to http://mydomain/dtest/
If that doesn’t work, I probably can’t help you further!
Now on to the favored deployment, WSGI.
With the dev server approach above, the dash app will run with whatever Python version you choose. With mod_wsgi in Apache you are apparently stuck with the system default Python; on our Centos7 host, this happens to be Python 2.7 - yikes! Nevertheless, you will still need to create a virtualenv, but it will have to be whatever Python version your system runs; if you don’t match the system python, you’re likely to fail.
Our Apache server didn’t have mod_wsgi installed and I couldn’t install it with yum.
Evidently there are problems due to cPanel. I found that I needed to install using ea4 (Easy Apache 4) experimental resources: https://forums.cpanel.net/threads/configure-easyapache-experimental-for-python-with-mod_wsgi.647561/
yum install ea4-experimental
yum install ea-apache24-mod_wsgi
If you cannot get mod_wsgi installed, you will probably have to run as CGI.
When running with dev server (localhost) and proxy, it did not matter where the app code is located, but now it does. Create dir for this app: mkdir -p pyapps/dash_wsgi. Each app will get it’s own subdir in pyapps. This is not required, it’s just how I ended up doing it after many false steps.
I slightly modified the dash_test_app:
# -*- coding: utf-8 -*-
# test using WSGI
import sys
import dash
import dash_core_components as dcc
import dash_html_components as html
app = dash.Dash(__name__)
app.config.update({
'url_base_pathname':'/dash_wsgi/',
'routes_pathname_prefix':'/dash_wsgi/',
'requests_pathname_prefix':'/dash_wsgi/',
})
server = app.server
app.scripts.config.serve_locally = True
app.css.config.serve_locally = True
app.layout = html.Div(children=[
html.H1('Hello Dash'),
html.H2('Magic: from HOME /pyapps/dash_wsgi'),
html.H2(sys.version),
])
if __name__ == '__main__':
app.run_server(debug=True, port=8050)
You have to create a WSGI file to run the dash app. In the same directory, file dash_test.wsgi:
#!/home/admin/venv27/bin/python
# dash_test.wsgi - WSGI script
# Python virtualenv must be activated
activate_this = '/home/admin/venv27/bin/activate_this.py'
with open(activate_this) as f:
code = compile(f.read(), activate_this, 'exec')
exec(code, dict(__file__=activate_this))
import sys
# Add to Python search path so that the app itself can be found
sys.path.insert(0,'/home/admin/pyapps/dash_wsgi')
# standard way to run python wsgi program
from dash_test_app import server as application
Finally go back to Apache config. On our host it is:
/etc/apache2/conf.d/userdata/std/2_4/jkhyrsmy/mira3.org/vhost.conf
Add WSGI config:
WSGIDaemonProcess dash_test user=admin group=admin threads=5
WSGIScriptAlias /dash_wsgi /home/admin/pyapps/dash_wsgi/dash_test.wsgi
<Directory /home/admin/pyapps/dash_wsgi>
WSGIProcessGroup dash_test
WSGIApplicationGroup %{GLOBAL}
Require all granted
</Directory>
And again rebuild Apache config:
/usr/local/cpanel/scripts/rebuildhttpdconf
/usr/local/cpanel/scripts/restartsrv httpd
Web browser to http://mydomain/dash_wsgi
And there you have it!