Analytics Azure

Plotly Dash on Ubuntu 24.04 on Azure User Guide

| Product: Plotly Dash on Ubuntu 24.04 LTS on Azure

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 its interactive behaviour 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 — and Dash serves it as a browsable analytics application that updates live in the browser.

The cloudimg image ships Dash as a finished, ready-to-run dashboard server, not a bare framework. It installs Dash 4.4.0 with Plotly 6.9.0 and pandas 2.2.3 in a Python virtual environment at /opt/plotly-dash/venv on Python 3.12, run by an unprivileged plotlydash system account. A substantive sample dashboard — the Global Development Explorer — is bundled and live on the first boot of every VM: 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. It is served in production by gunicorn (three workers, the WSGI app.server) on the loopback address 127.0.0.1:5000 — not the Flask development server — and fronted by nginx on TCP 80 with HTTP Basic Authentication. A unique admin password is generated on the first boot of every VM. Backed by 24/7 cloudimg support.

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 is included:

  • Dash 4.4.0 + Plotly 6.9.0 + pandas 2.2.3 in a Python 3.12 venv at /opt/plotly-dash, run by an unprivileged plotlydash account
  • A bundled, genuinely interactive sample dashboard at /opt/plotly-dash/app/dashboard.py (the Global Development Explorer)
  • gunicorn serving the Dash WSGI app in production on loopback :5000, managed by plotly-dash.service
  • nginx reverse proxy on :80 with HTTP Basic Auth in front of the dashboard; open /health probe
  • Per-VM admin password generated at first boot, in a root-only file
  • plotly-dash.service + nginx.service as systemd units, enabled and active
  • 24/7 cloudimg support

Prerequisites

An active Azure subscription, an SSH key pair, and a VNet + 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: allow 22/tcp from your management network and 80/tcp from the browsers that reach the dashboard (front port 80 with TLS for public exposure — 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 cloudimg, and select Create. On Basics 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 Review + createCreate.

Step 2 — Deploy from the Azure CLI

az vm create \
  --resource-group <your-rg> \
  --name plotly-dash \
  --image <marketplace-image-urn> \
  --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

ssh azureuser@<vm-public-ip>

Step 4 — Confirm the services are running

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. The dashboard is served by gunicorn on loopback 127.0.0.1:5000 and reached only through nginx on port 80.

Terminal showing plotly-dash and nginx services active, the open health endpoint, and nginx on port 80 in front of gunicorn bound to loopback 5000

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:

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.

Terminal showing the per-VM admin credentials file and the HTTP Basic Auth round-trip returning 401 without credentials and 200 with them

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: a Plotly bubble chart of life expectancy versus GDP per capita, with summary tiles above it.

Global Development Explorer dashboard: the default bubble chart of life expectancy versus GDP per capita for 2007, with summary tiles and the metric, region and year controls

Step 7 — Explore interactively

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

The bubble chart after selecting Asia in the Region dropdown, filtered to 33 Asian countries with the chart title updated to 2007 (Asia)

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

The bubble chart after moving the Year slider to 1952, redrawn with 1952 data showing much lower life expectancy and GDP per capita

Step 8 — The ranked view

Scroll down for the ranked bar chart and the top-10 data table, both driven by the same Metric, Region and Year controls:

The ranked bar chart of the top 15 countries by GDP per capita alongside a top-10 data table of country and value

Step 9 — Confirm the runtime and interactivity

Confirm the pinned versions and that the app is served by gunicorn 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 exercise the interactive callback endpoint directly with the admin credentials — two different inputs return two different figures, which is the proof 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

Terminal showing three gunicorn workers serving the Dash WSGI app and two POST requests to the callback endpoint returning different figures, proving the dashboard is interactive

Ship your own dashboard

The image is a production Dash host — 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), keeping a module-level server = app.server so gunicorn can serve it, then 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; adjust the worker count or module name in /etc/systemd/system/plotly-dash.service to match your app, then sudo systemctl daemon-reload && sudo systemctl restart plotly-dash.service. Pass environment variables to your app via /etc/plotly-dash/plotly-dash.env.

Terminal showing the installed Dash, Plotly, pandas and gunicorn versions and the venv layout under /opt/plotly-dash

Enabling HTTPS

For production, terminate TLS at nginx with a real domain pointed at the VM's public IP. Install certbot and request a certificate (replace the domain):

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/cloudimg-plotly-dash to add the TLS listener and 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 up if you customise it. Keep the OS patched with sudo apt update && sudo apt upgrade (unattended security upgrades are enabled by default). The server restarts cleanly with sudo systemctl restart plotly-dash.service; logs: sudo journalctl -u plotly-dash.service.

Support

This image is backed by 24/7 cloudimg support. Contact us by email and 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. Use of them does not imply any affiliation with or endorsement by them.