Redash on Ubuntu 24.04 on Azure User Guide
Overview
Redash is an open-source platform for querying your data with SQL, visualising the results and assembling them into shareable dashboards. It connects to dozens of databases and APIs, runs and schedules queries, turns result sets into charts, and lets a team build and share dashboards from a browser. The cloudimg image deploys Redash 10.1.0.b50633 as the official production Docker Compose stack (the server, a scheduler, two Celery workers, PostgreSQL and Redis), fronts it with an nginx reverse proxy on port 80, persists all state on a dedicated Azure data disk, rotates every secret, and creates a unique admin account on the first boot of every VM. Backed by 24/7 cloudimg support.
What is included:
- Redash 10.1.0.b50633 deployed from the official Docker Compose stack, pinned to
redash/redash:10.1.0.b50633 - The full multi-container stack:
server(gunicorn),scheduler,scheduled_worker,adhoc_worker, PostgreSQL and Redis - nginx on
:80as a reverse proxy to the loopback Redash server, plus a static unauthenticated/healthprobe - PostgreSQL and Redis bound to the private Docker network only (never published on the host)
- A per-VM admin account (email + password + API key) generated on first boot and recorded in a root-only file
- A dedicated Azure data disk at
/var/lib/redashholding the PostgreSQL metadata database and Redis data (Docker data-root relocated there) redash.service,redash-firstboot.service,nginx.serviceanddocker.serviceas 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_B4ms (4 vCPU / 16 GiB RAM) is the recommended size - the multi-container Redash stack needs the memory. NSG inbound: allow 22/tcp from your management network and 80/tcp. Redash serves plain HTTP on port 80; for production, terminate TLS in front of it with your own domain.
Step 1 - Deploy from the Azure Marketplace
Sign in to the Azure Portal, choose Create a resource, search the Marketplace for Redash by cloudimg, and select Create. On Basics pick your subscription, resource group, region and size (Standard_B4ms or larger); under Administrator account choose SSH public key and paste your key; under Inbound port rules allow SSH (22) and HTTP (80). Review the dedicated data disk on the Disks tab, then Review + create -> Create.
Step 2 - Deploy from the Azure CLI
az vm create \
--resource-group <your-rg> \
--name redash \
--image <marketplace-image-urn> \
--size Standard_B4ms \
--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 redash --port 80 --priority 1010
Step 3 - Connect to your VM
ssh azureuser@<vm-public-ip>
Step 4 - Confirm the services are running
Redash runs as a Docker Compose stack managed by redash.service, behind nginx. Confirm the units are active:
systemctl is-active redash.service nginx.service docker.service
Each reports active. On first boot the image rotates every secret and creates a per-VM admin account.

Step 5 - Confirm the container stack
The stack is six containers - the web server, the scheduler, two Celery workers, PostgreSQL and Redis:
docker compose -f /opt/redash/docker-compose.yml ps
All six report Up. PostgreSQL and Redis are attached to the private Docker network only and are never published on the host; only nginx on port 80 is reachable from outside.

Step 6 - Confirm the health and ping endpoints
nginx serves a static, unauthenticated /health file for load balancers and probes, and proxies Redash's own /ping liveness endpoint:
curl -s -o /dev/null -w 'health=%{http_code}\n' http://localhost/health
It returns health=200. Redash's application ping returns PONG:
curl -s http://localhost/ping; echo
Step 7 - Retrieve your admin credentials
The admin email, password and API key are generated uniquely on the first boot of your VM and written to a root-only file:
cat /root/redash-credentials.txt
This file contains REDASH_ADMIN_EMAIL (admin@cloudimg.local), REDASH_ADMIN_PASSWORD and REDASH_ADMIN_API_KEY. Store them somewhere safe.
Step 8 - Sign in to the Redash web UI
Browse to http://<vm-public-ip>/ and sign in as admin@cloudimg.local with the password from Step 7.

After signing in you land on the Dashboards home, with the left navigation for Dashboards, Queries, Alerts and Create.

Open Create -> New Query to reach the query editor, where you write SQL against a connected data source, run it, and turn the result into a visualisation.

Under Settings -> Data Sources you connect Redash to your databases and APIs - PostgreSQL, MySQL, BigQuery, Redshift, Elasticsearch and many more.

Step 9 - Verify the REST API with your API key
Every Redash user has an API key that authenticates REST calls without a session. Read the per-VM admin key from the credentials file and call the dashboards endpoint:
API=$(grep '^REDASH_ADMIN_API_KEY=' /root/redash-credentials.txt | cut -d= -f2-)
curl -s -o /dev/null -w 'api=%{http_code}\n' -H "Authorization: Key $API" http://localhost/api/dashboards
It returns api=200. A request with a wrong key is rejected. To authenticate as a browser session instead, POST your admin email and password to the login form - for example curl -i -c cookies.txt -d 'email=admin@cloudimg.local' -d 'password=<REDASH_ADMIN_PASSWORD>' http://<vm-public-ip>/login returns a 302 redirect on success.
Step 10 - Confirm data lives on the dedicated disk
The PostgreSQL metadata database (users, queries, dashboards, cached results) and the Redis data live on the dedicated Azure data disk, so they survive OS changes and can be resized independently:
findmnt /var/lib/redash
The mount is backed by a separate Azure data disk captured into the image and re-provisioned on every VM. Docker's data-root is relocated under it, so every Redash named volume lands on the resizable disk.

Inviting your team by email (SMTP setup)
The image does not ship with an outbound email server, because sending mail needs credentials for your own provider (SendGrid, Microsoft 365, Google Workspace, Amazon SES, or your own SMTP). Until you add them, Redash cannot send user invitations or alert emails. Set them once and both start working.
- Edit the Redash environment file and add your provider's settings. There is already a
REDASH_MAIL_DEFAULT_SENDERline, so update it to a real address on your domain:
bash
sudo nano /opt/redash/.env
REDASH_MAIL_SERVER=smtp.sendgrid.net
REDASH_MAIL_PORT=587
REDASH_MAIL_USE_TLS=true
REDASH_MAIL_USERNAME=apikey
REDASH_MAIL_PASSWORD=<your-smtp-password-or-api-key>
REDASH_MAIL_DEFAULT_SENDER=redash@yourdomain.com
For Microsoft 365 use smtp.office365.com on port 587 with TLS. For SendGrid the username is the literal word apikey and the password is your API key. If your provider uses SSL on port 465, set REDASH_MAIL_USE_SSL=true instead of the TLS line. Make sure no line has a trailing space after its value, as Docker reads those literally and the login will fail.
- Recreate the stack so every container, including the background workers that actually send the mail, picks up the new settings. A plain restart does not always reload them:
bash
cd /opt/redash && sudo docker compose up -d --force-recreate
- Confirm it works. Invite a user from Settings -> Users, or send a quick test that prints the exact SMTP response (swap in an inbox you can check):
bash
cd /opt/redash && sudo docker compose run --rm --entrypoint python server -c "
import os, smtplib
s = smtplib.SMTP(os.environ['REDASH_MAIL_SERVER'].strip(), int(os.environ['REDASH_MAIL_PORT']))
s.set_debuglevel(1); s.starttls()
s.login(os.environ['REDASH_MAIL_USERNAME'].strip(), os.environ['REDASH_MAIL_PASSWORD'].strip())
s.sendmail(os.environ['REDASH_MAIL_DEFAULT_SENDER'].strip(), ['you@yourdomain.com'], 'Subject: Redash SMTP test\n\nWorks!')
s.quit(); print('OK')
"
Reaching external inboxes (Gmail, Outlook). Verifying a single sender is enough to send, but Gmail and Outlook often junk or reject mail from a domain that is not authenticated at your provider. If internal test mail arrives but invites to external addresses do not, set up domain authentication (in SendGrid: Settings -> Sender Authentication -> Authenticate Your Domain) and add the SPF and DKIM records it gives you to your DNS. Most providers show a per-message delivery log (SendGrid's is the Activity Feed) that tells you whether each invite was delivered, dropped or blocked, and why.
Invite links. The sign-in link in the invitation is built from REDASH_HOST in the same .env file. It is set to your VM's address on first boot; if you move Redash behind a custom domain or HTTPS, update REDASH_HOST to match so the links resolve.
If the test email works but invitations never arrive (and never appear in your provider's send logs). Redash sends the test email directly from the server container, but it sends invitation and alert emails through a background worker on its emails queue. Confirm a worker is assigned that queue. Open /opt/redash/docker-compose.yml, find the adhoc_worker service, and make sure its QUEUES line includes emails:
adhoc_worker:
...
environment:
QUEUES: 'queries,emails,default,periodic'
If emails is missing, add it as above, then recreate the stack so the worker picks it up:
cd /opt/redash && sudo docker compose up -d --force-recreate
Resend the invitation and it will now be sent (and show up in your provider's activity log). Any invites you queued before the change may all send at once when the worker starts.
Building with Redash
Connect a data source (Settings -> Data Sources), write a query in the editor, and save it. Add a visualisation to the query - a chart, counter, pivot or table - then pin one or more visualisations onto a dashboard and share it with your team. Queries can be scheduled to refresh on an interval (handled by the scheduler and workers), and alerts can notify you when a value crosses a threshold. See the Redash documentation for the query language, data source options and API reference.
Maintenance
- Admin users: add users and groups from Settings -> Users and Settings -> Groups in the web UI.
- Backups: snapshot the
/var/lib/redashdata disk, or back up the PostgreSQL metadata database inside thepostgrescontainer. - Data: the metadata database and Redis data live under
/var/lib/redash(Docker data-root). - Stack control: manage the stack with
sudo systemctl restart redash.service, or withdocker composein/opt/redash. - TLS: Redash serves plain HTTP on port 80; front it with TLS (e.g. certbot) and your own domain before production use.
- Upgrades: edit the pinned image tag in
/opt/redash/docker-compose.yml, thensudo systemctl restart redash.service. - Security patches: unattended-upgrades remains enabled so the OS continues to receive security updates automatically.
Support
cloudimg provides 24/7 expert support for this image. Contact support@cloudimg.co.uk.