Environment configuration
Basedash is configured with environment variables. With Docker Compose, set them in the environment template in the Distr portal (or your.env file). With Kubernetes, set the equivalent Helm values instead; run helm show values oci://registry.distr.sh/basedash/basedash-charts to list them.
Quick start: generate secrets
LICENSE_KEY, POSTGRES_PASSWORD, CRYPTO_KEY, and PRISMA_FIELD_ENCRYPTION_KEY as customer secrets in the Distr portal before the first deploy. The environment template reads them from there.
Store CRYPTO_KEY and PRISMA_FIELD_ENCRYPTION_KEY somewhere safe. They encrypt data in the database, and changing them after you’ve saved data makes that data unreadable.
Required variables
Public URL:BASE_URL must be a full URL including http:// or https://. The app refuses to start with a bare hostname like basedash.example.com.
BASE_URL is used for login redirects, email links, OAuth and SSO callbacks, share links, and webhooks, so it must be the address your users actually open.
License:
The server won’t start without a valid key. Contact support@basedash.com if you don’t have one.
POSTGRES_PASSWORD. Compose derives DATABASE_URL from POSTGRES_USER, POSTGRES_PASSWORD, and POSTGRES_DB, using host postgres (the service name), not localhost. Inside the app container, localhost is the app itself.
APP_IMAGE, set it to a release, never latest:
Optional application settings
TLS and reverse proxy
HTTPS isn’t automatic. The app listens on port 3000 over plain HTTP. Direct access (default): open inbound TCP 3000 and useBASE_URL=http://<host>:3000.
Reverse proxy (recommended for production): terminate TLS on 443 with your existing proxy or load balancer (nginx, Cloudflare, AWS ALB, Kubernetes ingress) and forward to port 3000. Then set:
TRUST_PROXY to the number of proxies in front of the app (usually 1; 2 for a load balancer in front of another proxy). This applies to Docker Compose; the Helm chart doesn’t expose it yet. Without it, Google sign-in redirects break and rate limiting sees every request as coming from the proxy. Don’t use TRUST_PROXY=true, because it lets any client forge its IP address.
Cloudflare doesn’t proxy port 3000, so put Cloudflare in front of a proxy on 443, or connect to the server directly.
Bundled Caddy: the Compose file includes an optional Caddy service for existing deployments that already use it. It’s off by default and the Distr agent doesn’t start it. For new deployments, use your own proxy.
PostgreSQL database
PostgreSQL is the only service Basedash depends on.Bundled PostgreSQL
Docker Compose deployments (agent and manual) include a PostgreSQL 16 container:- Migrations run automatically every time the app starts
- Health checks hold the app until the database is ready
- Persistent storage in a Docker volume
POSTGRES_PASSWORD the first time it initializes the data volume. Changing the variable later doesn’t change the database password. Reset it inside the container (ALTER USER basedash WITH PASSWORD '...') or recreate the volume.
External PostgreSQL
For production above 500 users, use a managed PostgreSQL instance (Amazon RDS, Cloud SQL, Azure Database for PostgreSQL). See Sizing.- Use PostgreSQL 16 or later.
-
Create the database:
-
Set
max_connectionsto at least 60 per app replica, plus 20. -
Point
DATABASE_URLat it (with Helm, setpostgres.enabled: falseandpostgres.external.url). This overrides the derived Compose URL:Percent-encode reserved URL characters in the password (+,/,=,@).
Database backups
Back up the database regularly, and always before upgrading. For managed databases, use your provider’s automated backups. For the bundled Compose database:AI configuration
AI is optional on first boot. The app starts without a key and shows a banner until you add one. Chat, chart generation, and insights need a provider key. Supported providers: OpenAI, Anthropic, Azure OpenAI, Amazon Bedrock, xAI, and OpenRouter. Choose models withAI_MODEL (main agent) and AI_FAST_MODEL (lightweight tasks), using a provider prefix such as openai/ or anthropic/. If you leave them unset, Basedash picks defaults from the keys you’ve configured.
OpenAI
Anthropic
Azure OpenAI
Point the OpenAI provider at your Azure OpenAI v1 endpoint. This supports every AI feature, including web search, chat attachments, and voice input.gpt-6.1-sol, gpt-6-luna, and gpt-transcribe for the defaults, or whatever you set in AI_MODEL and AI_FAST_MODEL.
Existing deployments using AI_MODEL=azure/<deployment-name> with AI_AZURE_OPENAI_* variables keep working, but that setup doesn’t support web search, uploads, or voice input.
Amazon Bedrock
xAI
OpenRouter
OpenAI-compatible APIs
Any OpenAI-compatible endpoint (such as an internal LLM gateway) works through the OpenAI provider:Model considerations
- We test and benchmark against the default models. Other models may produce lower-quality SQL and charts.
- Some features need specific model capabilities, such as tool calling and structured output.
- Older variable names (
OPENAI_API_KEY,OPENAI_MODEL,ANTHROPIC_API_KEY,AI_PROVIDER) still work, but theAI_*variables above take precedence.
Email configuration
Email delivers login codes, invitations, alerts, automation deliveries, and dashboard subscriptions.First boot: log provider
The Distr templates setEMAIL_PROVIDER=log. Login codes are written to the app logs instead of being emailed, so you can sign in before email is set up. Switch to SMTP or SES before inviting users: anyone who can read the logs can read login codes.
docker compose logs app (or kubectl logs on Kubernetes).
SMTP
SMTP_SECURE=false (STARTTLS), or port 465 with SMTP_SECURE=true. Compose defaults SMTP_SECURE to true, so set it explicitly when you use port 587.
Common SMTP providers:
- Resend: smtp.resend.com:587
- SendGrid: smtp.sendgrid.net:587
- Mailgun: smtp.mailgun.org:587
- AWS SES: email-smtp.us-east-1.amazonaws.com:587
- Microsoft 365: smtp.office365.com:587
Amazon SES
SES_FROM_EMAIL is a verified identity.
Authentication and access control
Self-hosted Basedash has the same access controls as the cloud product:- SSO: SAML and OIDC with your identity provider. See SSO.
- SCIM provisioning: provision and deactivate members and sync groups from Okta, Microsoft Entra ID, and other identity providers. Generate a SCIM token under Settings → Security.
- Permissions: groups and per-dashboard, chart, and data source access.
- Audit logs: available to Enterprise organizations.
License key
Self-hosted Basedash requires a license key from Basedash. Contact support@basedash.com to get one.License behavior
At startup:- The server validates the key against
https://charts.basedash.combefore it accepts requests. - If the key is missing, invalid, expired, or inactive, or the license server can’t be reached, the server refuses to start.
- The server sends a heartbeat every 6 hours with the app version and organization and user counts, for billing.
- If a heartbeat fails, it retries with exponential backoff, starting at 5 minutes and capped at 6 hours.
- If the license expires or is deactivated, an error banner appears and new organizations can’t be created.
- If the license server can’t be reached, a warning banner appears and new organizations can’t be created until the next successful heartbeat. Existing users keep working.
Sandbox licenses
Sandbox licenses are for QA and CI environments. They show a “Sandbox environment” banner, and their usage isn’t billed.Troubleshooting license issues
Server won’t start: check the app logs for the license error.- Missing key: set
LICENSE_KEYand restart. - Can’t reach the license server: allow outbound HTTPS to
charts.basedash.com(check firewalls, proxies, and egress rules). - Invalid, expired, or inactive: contact support@basedash.com.
charts.basedash.com during a heartbeat. Check outbound HTTPS access. The server retries automatically.
“License has expired” or “License has been deactivated” banner: contact support@basedash.com.
Update management
Basedash never updates your deployment automatically. You choose when to move to a new version:- Distr agent (Compose or Kubernetes): select a new version in the Distr portal.
- Manual Compose: download the new version’s Compose file from the Distr portal, then run
docker compose pull && docker compose up -d. - Manual Helm: set
app.image.tagto the new release and runhelm upgradewith the matching chart version.
Advanced configuration
Object storage (recommended)
Configure S3-compatible storage to enable:- Avatar and organization icon uploads
- Chart images in Slack and email notifications and in the public API (without storage, images are rendered on demand and some notifications omit them)
- CSV downloads generated by the AI
https://{S3_BUCKET_NAME}.{endpoint host}.
Bucket access:
- Basedash marks avatars, icons, and chart images
public-readitself. Don’t make the whole bucket public. - Keep the
ai-csv-artifacts/prefix private, including through any CDN. It holds query results. - Grant the credentials get, put, delete, and list access, plus multipart upload listing and abort.
- Add a lifecycle rule on
ai-csv-artifacts/only that expires objects after 30 days and aborts incomplete multipart uploads after 1 day.
Google Cloud Storage setup
Google Cloud Storage setup
Follow these steps to use Google Cloud Storage (GCS) through its S3-compatible API.Apply it:
Step 1: Create a bucket
- Go to the Google Cloud Console
- Navigate to Cloud Storage → Buckets
- Click Create bucket
- Configure the bucket:
- Name: choose a globally unique name (e.g.,
basedash-uploads-yourcompany) - Location type: Regional is typically fine
- Region: close to your Basedash deployment
- Storage class: Standard
- Access control: Fine-grained (required, because Basedash sets per-object ACLs)
- Public access prevention: uncheck “Enforce public access prevention on this bucket”, so per-object
public-readACLs work
- Name: choose a globally unique name (e.g.,
- Click Create
allUsers access on the bucket. That makes every object public, including AI-generated CSV files.Step 2: Create HMAC keys
- Go to Cloud Storage → Settings
- Open the Interoperability tab
- Under “Access keys for service accounts,” click Create a key for a service account
- Select or create a service account with the Storage Object Admin role on the bucket
- Click Create key and save both values:
- Access key: your
S3_BUCKET_ACCESS_KEY_ID - Secret: your
S3_BUCKET_SECRET_ACCESS_KEY
- Access key: your
Step 3: Configure CORS
Browsers upload files directly with pre-signed URLs, so the bucket needs a CORS rule for your Basedash URL. Createcors.json:Step 4: Set environment variables
Step 5: Verify
- Upload a user avatar or organization icon
- Check that the file appears in your bucket
- Open the file’s public URL directly
Slack app (optional)
Enable Slack notifications, automations, and chatting with Basedash from Slack. Set all five values:Support and troubleshooting
Getting help
- Distr customer portal: deployment status, versions, and release notes
- Email: support@basedash.com
Health checks
kubectl logs -l app.kubernetes.io/component=app.
Common configuration issues
Application won’t start:- Check that all required variables are set:
LICENSE_KEY,CRYPTO_KEY,PRISMA_FIELD_ENCRYPTION_KEY,POSTGRES_PASSWORD, andBASE_URL - With bundled PostgreSQL, leave
DATABASE_URLderived (hostpostgres, notlocalhost). Override it only for an external database - Make sure
BASE_URLincludeshttp://orhttps:// - Make sure
CRYPTO_KEYis exactly 32 bytes (openssl rand -hex 16) - Make sure the server can reach
charts.basedash.comover HTTPS - Read the logs:
docker compose logs app
POSTGRES_PASSWORD when the data volume is first created. Reset it inside the container (ALTER USER basedash WITH PASSWORD '...') so it matches POSTGRES_PASSWORD, or recreate the volume (this deletes all data). If you overrode DATABASE_URL, its password must match too.
Browser never loads, but Distr shows healthy:
Distr’s health check calls /health inside the container, so it can pass while the app is unreachable from outside. Check:
curl http://127.0.0.1:3000/healthon the host- Inbound TCP 3000 is open in your security group or firewall
- You’re using
http://<host>:3000, nothttps:// - If the hostname is on Cloudflare, port 3000 isn’t proxied. Try the server IP, or turn off proxying for the record
BASE_URL without http:// or https://.
Google sign-in redirects to http:// or fails behind a proxy:
With Docker Compose, set TRUST_PROXY to the number of proxies in front of the app (usually 1).
AI features not working:
- Set a provider key (for example
AI_OPENAI_API_KEY) and, if you override models, a matching provider-prefixedAI_MODEL - Check the provider account’s credits and rate limits
- Check that the server can reach the provider’s API endpoint
- If
EMAIL_PROVIDER=log, codes are in the app logs, not in email - For SMTP, check the host, port, and credentials
- Match
SMTP_SECUREto the port:falsefor 587,truefor 465 - Make sure the firewall allows outbound SMTP
CRYPTO_KEY must be exactly 32 bytes. Generate one with openssl rand -hex 16, restart the app, and connect again. You can safely replace the key only if no database connection has been saved yet.