Deploy Dash with Apache2

Ever wondered how you can deploy Dash(Plotly) on an Apache2 Server? With this article i want to guide you through this journey. As many others, Apache2 is a Webserver where you can publish your own websites and so your dash-app. Dash is a framework to create beautiful dashboards in python. By following the link below you can see a bunch of projects where dash has been used.

https://dash-gallery.plotly.host/Portal/

Dash is coming with a tiny webserver itself. This webserver is for development only. Due to security i cannot recommend using it for production and so does the dash developer. During development i use virtualenv to isolate the environment and use different dash and python version apart from the regular server. Once i have finished development and started deploying my app, i copied that folder to /var/www/html/ and with it the virtual environment.

cp -p /<path>/Dash /var/www/html/Dash

For apache2 you need to install some requirements to make dash proper working. This differs from your python version. For python3 install libapache2-mod-wsgi-py3

sudo apt-get install libapache2-mod-wsgi-py3

See this link, if you don’t know what wsgi exactly is: http://wsgi.tutorial.codepoint.net/
In short wsgi is an interface specification by which server and application communicate. I put my wsgi file in /var/www/html/Dash/wsgi.py.

#cat wsgi.py
import sys
sys.path.insert(0,"/var/www/html/Dash/")
from app import server as application

Please note that app in “from app import server as application” is my file name. You might have a different name with your dash-code.

Configure Apache2

Further we need to modify our Apache2 configuration. There are several ways to deploy dash with Apache2. I like to use a different Port for my app. For now Apache2 is listening on Port 80/443 only. We need to add another Port like 8050. Amend ports.conf in /etc/apache2/ and add a second “Listen” line like below.

#cat ports.conf
# If you just change the port or add more ports here, you will likely also
# have to change the VirtualHost statement in
# /etc/apache2/sites-enabled/000-default.conf

Listen 80
Listen 8050

[...]

Once done we can create a new site on Apache2. Create a new file within /etc/apache/sites-available/. I named mine dash.conf but this is up to you.

#user@server:/etc/apache2/sites-available# cat dash.conf
<VirtualHost *:8050>
        ServerAdmin webmaster@localhost
        DocumentRoot /var/www/html/Dash

        ErrorLog ${APACHE_LOG_DIR}/error.log
        CustomLog ${APACHE_LOG_DIR}/access.log combined

        WSGIDaemonProcess Dash threads=5 user=www-data group=www-data python-path=/var/www/html/Dash python-home=/var/www/html/Dash/bin
        WSGIScriptAlias / /var/www/html/Dash/wsgi.py

        <Directory /var/www/html/Dash>
                <Files wsgi.py>
                        #Require all granted 
                        AuthType Basic #required for Authentication
                        AuthName <name> #required for Authentication
                        AuthUserFile "/<path>/.htusers" #required for Authentication
                        Require valid-user #required for Authentication
                </Files>
                WSGIProcessGroup Dash
                WSGIApplicationGroup %{GLOBAL}
                Order deny,allow
                Allow from all
        </Directory>

</VirtualHost>

*Please take into account that this file already contains the code for the Authentication in the next section.

WSGIDaemonProcess is running with user/group www-data, which usually is the group apache2 does work with. This is required to isolate apache2, mainly for security purpose.
Additionally we need to enable that site, so it gets recognized by Apache2

a2ensite dash

a2ensite will create a symlink in sites-enable to our configuration in sites-available.

As our WSGIProcess does run with www-data rights we have to give that group permission to access our dash folder with the correct privileges. Owner(root) does have full access while group(www-data) can read and execute. Others don’t have any permission for security reasons.

ls -ltr /var/www/html/
drwxr-x--- 9 root www-data  4096 Sep 28 15:28 Dash

You have to use command chmod respective chown to grant access to a folder/file. I had to do it as defined below, but it might differ in your case. “-R” stands for recursive execution.

chown -R :www-data Dash/
chmod -R o-rw Dash/

If you are not familiar with chown/chmod command read this post: https://www.unixtutorial.org/difference-between-chmod-and-chown/#:~:text=The%20chmod%20command%20stands%20for,a%20user%20and%20a%20group.

Dash Configuration

If you have come thus far, adapt your code and add “server = app.server”.

server = app.server
if __name__ == '__main__':
    app.run_server(debug=True,host='0.0.0.0',port='8050')

Last but not least you have to release the port in your firewall. Iptables and ufw are the most common ones. In case you use Iptables execute following command in your shell.

iptables -I INPUT 3 -p tcp --dport 8050 -j ACCEPT

Everyone should be allowed to access your page now. Of course you can restrict it way more with IPtables-rules, I leave it to you. This is the simplest way publishing your site.

Secure your app with Basic Authentication

By default dash provides Basic authentication within the python code, but for some reason it does not work for me. The authentication screen prompts and i can enter my username/password but apache/dash won’t let me in. So i decided to create my own authentication by using htpasswd.

htpasswd -c -B <filename(ie. .htusers)> <username>

While executing it will ask for a password for this user. As soon as it has finished you can see your file. Link that one to your dash.conf, which was mentioned above.

That’s it. You finally set your apache2 up to run dash-apps. In my next article i am going to write about my dash-app and what it does.

Happy Coding so far 🙂

12 thoughts on “Deploy Dash with Apache2

  1. Great blog post, Stefan. Very clear explanations and instructions. Thank you for your contribution to the data science world :).

  2. Dear Stevie,
    I would like to execute in apache2 web server in ubuntu an script showing a simple graphic. I have followed your steps but when I try to execute the .py script I only get the code. Any idea what I’m missing? It is like it’s no been executed.

    Thanks a lot for your guide and your help

    1. Hi Xavier,

      You may find an error code in /var/log/apache2/error.log if apache2 is trying to execute your python script. What python module is serving your graph? wsgi links your python code with apache, take this into account. You doesn`t need to execute your python script if apache was properly set up, curious why you mentioned you did so.

      Might be helpful if you send me your shell history of your executions so far.

      Best Regards
      stevie

  3. Dear Stevie,
    I’m sorry I haven’t seen your answer before and thought you didn’t answer… I think I said “execute” the script when I should say “run”.
    I’m still trying to run my dash/plotly script in apache2 webserver, but after following all your steps I can’t manage to make it work. I think I have all the needed libraries installed but I must have a misconfiguration error because I’m just getting the script code in plain text when I try to view the result of the script in the browser.
    Is it possible to run the scripts in the 80 port as the other web applications? And without Authentication?
    Thanks a lot for your help!

  4. Hi Xavier,

    you can skip the part with the authentication it is just optional.
    If you want to run Dash on Port 80, you have to change the configuration a little. Either you change 000-default.conf or create a new site and disable your Virtualhost 80 in 000-default.conf.
    Can you check if apache just prints the files content or if apache is serving your script as html? Did you use a virtual environment? If not you have to change python-home path.
    what is the URI you are gonna use?

    Bear in mind you have to consider your filename in your wsgi.py file. My dash-code is inside app.py so i used “from app import server as application” in my wsgi.py file.
    I suspect wsgi to be the pain, as it links python with apache and it seems it doesnt for now.

    Did you check your apache error.log?
    Can you check if wsgi is enabled:

    apache2ctl -M | grep -i wsgi

    this command should result in “wsgi_module (shared)” or somewhat similar.

    Best Regards
    stevie

  5. Hello,
    I followed your tutorial but when I fill in the ip address of the server with the port (ip_adress:8050) I get the php page.
    I tried to modify the content of dash.conf but in vain.
    Would you have a solution?

    1. Hi,

      sounds like the virtual host doesn’t work properly, is the site enabled?

      apache2ctl -S

      Further check if that port is open by using a portscanner like Nmap

      Have you had a look at your .htaccess? This file might contain a redirection to the main page.

      Disable the default page with a2dissite and see if that might solve your problem.

      Best regards
      stevie

      1. Hi, Thank you for your answer.
        I managed to display something, an index of the files that are in the Dash folder.
        I specify that I use a virtual environment. So I put : python-home=/var/www/html/Dash/venv/bin
        I didn’t touch the rest.
        I modify the .wsgi document to see, but without improvement.
        If you have a lead?

        1. Hi Legrand,

          Have you set the required permissions on file and directories?
          Please check your error.log file in /var/log/apache2. That file might contain the point you are doing wrong.

          Try to use the root of your virtual Environments path for your python-home. \var\www\html\Dash
          or
          \var\www\html\Dash\venv

          Not quite sure what your root folder of your virtual env is.

          Best Regards
          stevie

  6. Hello Stevie,

    thank you very much for the post!

    I tried following this but was only able to attain an invalid command “WSGIDaemonProcess” error.

    I’ve used pip install mod_wsgi, made sure to load it into the apache httpd.conf file as well so it should be installed and loaded – however I am unable to get it to work. Any suggestions?

    1. Hi Jonas,

      if you are using python3 pip3 is worth a shot and so is “sudo a2enmod wsgi” to check if wsgi is active.

      As soon as wsgi is installed you must have these files:

      /etc/apache2/mods-available# ll wsgi.*
      -rw-r–r– 1 root root 5055 Feb 18 2020 wsgi.conf
      -rw-r–r– 1 root root 60 Feb 18 2020 wsgi.load

      and when it is activated:

      /etc/apache2/mods-enabled# ll wsgi.*
      lrwxrwxrwx 1 root root 27 Apr 1 2021 wsgi.conf -> ../mods-available/wsgi.conf
      lrwxrwxrwx 1 root root 27 Apr 1 2021 wsgi.load -> ../mods-available/wsgi.load

      dont forget to restart apache 🙂

      Regards
      stevie

Leave a Reply

Your email address will not be published. Required fields are marked *