Redash remains one of the most approachable open-source tools for building dashboards, sharing SQL queries, and collaborating on data.
While the project is no longer actively maintained upstream, the community builds (10.x) are still widely used for internal analytics.
In this article, I’ll show how to bring up Redash quickly on Debian 12 using Docker Compose. We’ll focus on the two files that matter most: the .env
and the docker-compose.yaml
.
This assumes you already have Docker Engine and Docker Compose v2 installed.
1. Directory Layout
Create a workspace for your Redash stack:
0 1 2 3 4 |
sudo mkdir -p /var/app/docker/redash-example cd /var/app/docker/redash-example mkdir -p data/postgres data/redis logs |
This folder will hold:
data/postgres
→ PostgreSQL data filesdata/redis
→ Redis persistencelogs
→ container logs if needed.env
anddocker-compose.yaml
2. Environment File (.env
)
The .env
file holds all credentials and configuration. Redash services will consume these automatically.
0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 |
# ========================= # Redash on Docker (.env) # ========================= # ---- Postgres POSTGRES_USER=redash POSTGRES_PASSWORD=change_me_strong_pw POSTGRES_DB=redash # ---- Redis REDIS_PASSWORD=another_strong_pw # ---- Redash image REDASH_IMAGE=redash/redash:10.1.0.b50633 # ---- Core secrets REDASH_SECRET_KEY=REPLACE_WITH_64B_BASE64 REDASH_COOKIE_SECRET=REPLACE_WITH_32B_BASE64 # ---- App behavior REDASH_RATELIMIT_ENABLED=true REDASH_LOG_LEVEL=INFO REDASH_MULTI_ORG=false REDASH_WEB_WORKERS=4 REDASH_SCHEDULED_QUEUE_NAME=scheduled REDASH_ADHOC_QUERY_TIME_LIMIT=600 REDASH_QUERY_TIME_LIMIT=1800 REDASH_CORS_ACCESS_CONTROL_ALLOW_ORIGIN=* # ---- External URL REDASH_HOST=http://localhost:50001 # ---- SMTP / Email REDASH_MAIL_SERVER=smtp-relay.local REDASH_MAIL_PORT=587 REDASH_MAIL_USE_TLS=true REDASH_MAIL_USE_SSL=false REDASH_MAIL_USERNAME=no-reply@example.com REDASH_MAIL_PASSWORD=supersecret # ========================= # NOTE: # Do NOT put REDASH_DATABASE_URL or REDASH_REDIS_URL here. # They are built dynamically in docker-compose.yaml. # ========================= |
Tip, generate strong random secrets with:
0 1 2 3 |
openssl rand -base64 64 # for REDASH_SECRET_KEY openssl rand -base64 32 # for REDASH_COOKIE_SECRET |
3. Docker Compose File (docker-compose.yaml
)
This Compose file brings up five containers: PostgreSQL, Redis, the Redash server, a worker, and a scheduler.
Since the host already has Nginx, we don’t run Nginx inside the stack — instead we bind the server on localhost:50001.
0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 |
name: redash-example services: postgres: image: postgres:14-alpine restart: unless-stopped environment: POSTGRES_USER: ${POSTGRES_USER} POSTGRES_PASSWORD: ${POSTGRES_PASSWORD} POSTGRES_DB: ${POSTGRES_DB} volumes: - ./data/postgres:/var/lib/postgresql/data healthcheck: test: ["CMD-SHELL", "pg_isready -U ${POSTGRES_USER} -d ${POSTGRES_DB}"] interval: 10s timeout: 5s retries: 10 redis: image: redis:7-alpine command: ["redis-server", "--appendonly", "yes", "--requirepass", "${REDIS_PASSWORD}"] restart: unless-stopped volumes: - ./data/redis:/data healthcheck: test: ["CMD", "redis-cli", "-a", "${REDIS_PASSWORD}", "PING"] interval: 10s timeout: 5s retries: 10 server: image: ${REDASH_IMAGE} depends_on: postgres: condition: service_healthy redis: condition: service_healthy restart: unless-stopped env_file: .env environment: REDASH_DATABASE_URL: "postgresql://${POSTGRES_USER}:${POSTGRES_PASSWORD}@postgres:5432/${POSTGRES_DB}" REDASH_REDIS_URL: "redis://:${REDIS_PASSWORD}@redis:6379/0" REDASH_SECRET_KEY: ${REDASH_SECRET_KEY} REDASH_COOKIE_SECRET: ${REDASH_COOKIE_SECRET} REDASH_LOG_LEVEL: ${REDASH_LOG_LEVEL:-INFO} REDASH_HOST: ${REDASH_HOST} GUNICORN_CMD_ARGS: "--timeout 120 --graceful-timeout 120 --workers ${REDASH_WEB_WORKERS:-2}" command: server ports: - "127.0.0.1:50001:5000" healthcheck: test: ["CMD", "wget", "-q", "-O-", "http://localhost:5000/healthcheck"] interval: 10s timeout: 5s retries: 30 worker: image: ${REDASH_IMAGE} depends_on: server: condition: service_started restart: unless-stopped env_file: .env environment: REDASH_DATABASE_URL: "postgresql://${POSTGRES_USER}:${POSTGRES_PASSWORD}@postgres:5432/${POSTGRES_DB}" REDASH_REDIS_URL: "redis://:${REDIS_PASSWORD}@redis:6379/0" REDASH_SECRET_KEY: ${REDASH_SECRET_KEY} QUEUES: "queries,scheduled,celery,schemas,periodic,emails,default" WORKERS_COUNT: "2" command: worker scheduler: image: ${REDASH_IMAGE} depends_on: server: condition: service_started restart: unless-stopped env_file: .env environment: REDASH_DATABASE_URL: "postgresql://${POSTGRES_USER}:${POSTGRES_PASSWORD}@postgres:5432/${POSTGRES_DB}" REDASH_REDIS_URL: "redis://:${REDIS_PASSWORD}@redis:6379/0" REDASH_SECRET_KEY: ${REDASH_SECRET_KEY} QUEUES: "scheduled,celery" command: scheduler |
4. Initialize Redash
Bring the services up:
0 1 2 3 4 5 |
docker compose pull docker compose up -d postgres redis docker compose run --rm server create_db docker compose up -d |
Check logs:
0 1 2 |
docker compose logs -f server |
Visit: http://localhost:50001
5. Integrate with Host Nginx
If your Debian host already runs Nginx for other sites, just add a vhost:
0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
server { listen 443 ssl http2; server_name analytics.example.com; ssl_certificate /etc/letsencrypt/live/analytics.example.com/fullchain.pem; ssl_certificate_key /etc/letsencrypt/live/analytics.example.com/privkey.pem; location / { proxy_pass http://127.0.0.1:50001; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header X-Forwarded-Proto $scheme; } } |
Reload:
0 1 2 |
sudo nginx -t && sudo systemctl reload nginx |
Now Redash is available at https://analytics.example.com
.
6. Sending Email
Test SMTP from inside the container:
0 1 2 |
docker compose run --rm server manage send_test_mail |
If configured correctly, Redash will send a test message from the REDASH_MAIL_DEFAULT_SENDER
.
Closing Notes
That’s all it takes: a .env
for configuration, and a docker-compose.yaml
for orchestration.
This pattern keeps the stack self-contained while leaving room for scaling or migrating later (for example, moving Postgres to RDS, or Redis to a managed service).
If you already run Nginx on your host, exposing Redash only to 127.0.0.1:50001
is the cleanest way to avoid conflicts and keep your surface minimal.
Happy dashing!!