Deployment guide

Plotly Dash

Overview

Plotly Dash is the popular open source Python framework for building interactive, data-driven web applications and analytical dashboards without writing any JavaScript. You describe a dashboard's layout and interactive behavior entirely in Python: Plotly charts, controls such as dropdowns, sliders and date pickers, and callbacks that recompute the charts and tables whenever a user changes an input. Dash serves the result as a browsable analytics application that updates live in the browser.

This SecureAnyCloud image ships Dash as a finished, ready-to-run dashboard server, not a bare framework. A sample dashboard, the Global Development Explorer, is bundled and live on the first boot of every VM. It combines a Plotly bubble chart, a ranked bar chart and a data table, driven by a metric dropdown, a region dropdown and a year slider over the Gapminder development-indicators dataset.

The dashboard listens only on loopback and is never exposed directly. nginx fronts it on port 80. The unauthenticated /health probe stays open for load balancers, and everything else requires the admin password.

What you get:

  • Dash 4.4.0, Plotly 6.9.0 and pandas 2.2.3 in a Python 3.12 virtual environment at /opt/plotly-dash/venv, under /opt/plotly-dash, run by an unprivileged plotlydash system account
  • A bundled, interactive sample dashboard at /opt/plotly-dash/app/dashboard.py (the Global Development Explorer)
  • gunicorn (three workers, the WSGI app.server), not the Flask development server, serving the Dash app in production on loopback :5000 (127.0.0.1:5000) and managed by plotly-dash.service
  • An nginx reverse proxy on :80 (TCP 80) with HTTP Basic Authentication in front of the dashboard, and an open /health probe
  • A unique per-VM admin password, generated at first boot and stored in a root-only file
  • plotly-dash.service and nginx.service as enabled, active systemd units
  • 24/7 SecureAnyCloud support

Prerequisites

  • An active Azure subscription, an SSH key pair, and a VNet plus subnet in the target region
  • Standard_B2s (2 vCPU / 4 GiB RAM) is a good starting point. Scale up for heavier dashboards or more concurrent users.
  • NSG inbound rules: allow 22/tcp from your management network and 80/tcp from the browsers that reach the dashboard. For public exposure, front port 80 with TLS (see Enabling HTTPS).

Step 1 - Deploy from the Azure Marketplace

Sign in to the Azure Portal, choose Create a resource, search the Marketplace for Plotly Dash by SecureAnyCloud, and select Create.

On the Basics tab, pick your subscription, resource group, region and size. Under Administrator account, choose SSH public key and paste your key. Under Inbound port rules, allow SSH (22) and HTTP (80).

Then select Review + create and Create.

Step 2 - Deploy from the Azure CLI

Accept the Marketplace terms once per subscription, then create the VM and open port 80:

# Accept the Marketplace terms once per subscription (required before the first CLI deploy)
az vm image terms accept --urn sac1647283583153:plotly-dash-ubuntu-24-04:default:latest
az vm create \
  --resource-group <your-rg> \
  --name plotly-dash \
  --image sac1647283583153:plotly-dash-ubuntu-24-04:default:latest \
  --size Standard_B2s \
  --admin-username azureuser \
  --ssh-key-values ~/.ssh/id_ed25519.pub \
  --vnet-name <your-vnet> --subnet <your-subnet> \
  --public-ip-sku Standard
az vm open-port --resource-group <your-rg> --name plotly-dash --port 80 --priority 1010

Step 3 - Connect to your VM

Connect to the VM over SSH:

ssh azureuser@<vm-public-ip>

Step 4 - Confirm the services are running

Check both services and the health endpoint:

systemctl is-active plotly-dash.service nginx.service curl -s http://127.0.0.1/health

Both services report active, and the /health endpoint returns ok. gunicorn serves the dashboard on loopback 127.0.0.1:5000, and it is reachable only through nginx on port 80.

Step 5 - Retrieve your admin password

The password is generated uniquely on the first boot of your VM and written to a root-only file. Read it:

sudo cat /root/plotly-dash-credentials.txt

The DASH_ADMIN_PASSWORD value is the password. Sign in as admin with it. Without credentials, the dashboard returns 401. With them, it returns 200.

Step 6 - Open the dashboard

Browse to http://<vm-public-ip>/ and sign in as admin with the password from Step 5. The bundled Global Development Explorer loads immediately. It shows a Plotly bubble chart of life expectancy versus GDP per capita, with summary tiles above it.

Step 7 - Explore interactively

Every control on the dashboard fires a Dash callback that recomputes the charts server-side and updates them live. Change the Region dropdown to a single continent. The bubble chart filters to that region, and its title updates:

Drag the Year slider back to 1952. The same chart redraws with the historical data, where life expectancy and GDP per capita were far lower:

Step 8 - The ranked view

Scroll down to the ranked bar chart and the top-10 data table. Both are driven by the same Metric, Region and Year controls:

Step 9 - Confirm the runtime and interactivity

Confirm the pinned versions and that gunicorn serves the app in production:

for p in dash plotly pandas gunicorn; do printf '%-10s %s\n' "$p" "$(/opt/plotly-dash/venv/bin/pip show $p | awk '/^Version:/{print $2}')"; done

This prints dash 4.4.0, plotly 6.9.0, pandas 2.2.3 and gunicorn 23.0.0.

You can also call the interactive callback endpoint directly with the admin credentials. Two different inputs return two different figures, which shows that the dashboard reacts to input:

PASS=$(sudo grep '^DASH_ADMIN_PASSWORD=' /root/plotly-dash-credentials.txt | cut -d= -f2-)
curl -s -o /dev/null -w 'authenticated dashboard: HTTP %{http_code}\n' -u "admin:$PASS" http://127.0.0.1/
curl -s -u "admin:$PASS" http://127.0.0.1/_dash-layout | head -c 80; echo

Ship your own dashboard

The image is a production Dash host, so you can replace the bundled sample with your own application. Edit /opt/plotly-dash/app/dashboard.py, or drop in your own module and point gunicorn at it. Keep a module-level server = app.server so gunicorn can serve the app. Then install any extra packages and restart:

sudo -u plotlydash /opt/plotly-dash/venv/bin/pip install <your-extra-packages>
sudo systemctl restart plotly-dash.service

The systemd unit runs gunicorn --workers 3 --bind 127.0.0.1:5000 dashboard:server from /opt/plotly-dash/app. To match your app, adjust the worker count or module name in /etc/systemd/system/plotly-dash.service, then run sudo systemctl daemon-reload && sudo systemctl restart plotly-dash.service.

Pass environment variables to your app through /etc/plotly-dash/plotly-dash.env.

Enabling HTTPS

For production, terminate TLS at nginx with a real domain that points at the VM's public IP. Install certbot and request a certificate, replacing the domain with your own:

sudo apt-get update && sudo apt-get install -y certbot python3-certbot-nginx
sudo certbot --nginx -d your-domain.example.com

certbot edits the nginx site at /etc/nginx/sites-available/sac-plotly-dash to add the TLS listener, and it arranges automatic renewal.

Backup and maintenance

The admin password lives in the nginx htpasswd file /etc/nginx/.plotly-dash.htpasswd. Rotate it with sudo htpasswd /etc/nginx/.plotly-dash.htpasswd admin.

Your dashboard code and any data live under /opt/plotly-dash/app. Back that directory up if you customize it.

Keep the OS patched with sudo apt update && sudo apt upgrade. Unattended security upgrades are enabled by default. Restart the server cleanly with sudo systemctl restart plotly-dash.service, and read its logs with sudo journalctl -u plotly-dash.service.

Support

24/7 SecureAnyCloud support backs this image. Contact us by email or chat for help with building and serving Dash dashboards, production tuning, authentication, TLS and maintenance.

All product and company names are trademarks or registered trademarks of their respective holders. Their use does not imply any affiliation with or endorsement by them.

Deploy on Azure

Launch Plotly Dash on Ubuntu 24.04 LTS on Azure with 24/7 support from SecureAnyCloud.

View this image

Need Help?

Our support team is available 24/7.

sales@secureanycloud.com

Deploy on Azure