Dify (https://dify.ai) is an open-source LLM application platform: a visual builder for RAG pipelines, agents, and chat assistants, with prompt management, dataset ingestion, and an API to call your finished app from anywhere. The hosted version is convenient, but self-hosting gives you data control, no per-seat pricing, and the ability to keep your knowledge base on infrastructure you own. This guide self-hosts Dify on PandaStack, leaning on managed PostgreSQL and Redis so you're not babysitting stateful containers.
What Dify needs to run
Dify is a multi-service application. The full stack includes:
- API server (the backend)
- Worker (async tasks: dataset indexing, etc.)
- Web (the Next.js frontend)
- PostgreSQL (application data)
- Redis (cache + Celery broker)
- A vector store (for RAG embeddings — Dify supports several)
The stateful pieces (Postgres, Redis) are where PandaStack's managed databases save you real operational pain. The stateless pieces (API, worker, web) run as container apps.
Step 1: Provision the managed data stores first
In the dashboard (https://dashboard.pandastack.io):
- 1Databases → New Database → PostgreSQL — Dify's primary store.
- 2Databases → New Database → Redis — cache and the Celery message broker for the worker.
Grab both connection strings. Using managed instances means backups, monitoring, and connection pooling are handled — you don't run Redis-in-a-container and hope it survives.
Step 2: The vector store
Dify supports multiple vector backends. Two pragmatic options on PandaStack:
- pgvector — enable the
pgvectorextension on the PostgreSQL instance you already created and let Dify use it. Fewest moving parts. - A dedicated vector DB (e.g. Qdrant or Weaviate) as its own container app if you expect a large knowledge base.
For most teams, pgvector on the existing Postgres is the right starting point — one fewer service to run.
Step 3: Deploy the API server
Dify publishes official images. Deploy the API image as a container app:
- 1New App → Container App, use the Dify API image, container port 5001.
- 2Environment variables (the important ones):
| Variable | Value |
|---|---|
SECRET_KEY | openssl rand -base64 42 |
DB_USERNAME / DB_PASSWORD / DB_HOST / DB_DATABASE | from your managed Postgres |
REDIS_HOST / REDIS_PASSWORD / REDIS_PORT | from your managed Redis |
CELERY_BROKER_URL | redis://:password@host:6379/1 |
VECTOR_STORE | pgvector (or your chosen store) |
- 1Deploy.
Step 4: Deploy the worker
The worker shares the API image but runs Celery instead of the web server. Create a second container app from the same image with the same database/Redis env vars, and set its command to start the Celery worker (Dify's docs specify the exact celery invocation). No public port needed — it processes background jobs like dataset indexing.
Skip this and your document uploads will appear to hang forever, because nothing is processing the indexing queue. (This is the Dify equivalent of the Dagster "forgot the daemon" trap.)
Step 5: Deploy the web frontend
- 1New App → Container App, use the Dify web image, container port 3000.
- 2Set
CONSOLE_API_URLandAPP_API_URLto your deployed API server's public URL (https://your-dify-api.pandastack.io). - 3Deploy. The web app is at
https://your-dify.pandastack.io.
Step 6: First-run setup
Open the web URL, create the admin account (the first account becomes the owner), and you're in. Add your LLM provider credentials (OpenAI, Anthropic, or a self-hosted model endpoint) under Settings → Model Provider. Those keys live in Dify's own encrypted settings, backed by the Postgres you provisioned.
Step 7: Build and expose an app
Now the fun part. In the Dify UI:
- 1Create an app — pick a chat assistant, agent, or workflow.
- 2Upload a dataset — PDFs, docs, or web pages. The worker chunks and embeds them into your vector store.
- 3Wire up RAG — attach the dataset to your app so it retrieves relevant context per query.
- 4Publish — Dify gives you an API endpoint and an embeddable web widget.
Call your published app from your own product:
curl -X POST https://your-dify-api.pandastack.io/v1/chat-messages \
-H "Authorization: Bearer YOUR_APP_API_KEY" \
-H "Content-Type: application/json" \
-d '{"inputs": {}, "query": "How do refunds work?", "user": "user-123", "response_mode": "blocking"}'Step 8: Operational notes
- Backups — your managed Postgres holds every app, dataset reference, and conversation. PandaStack's managed backups cover it; verify they're enabled.
- Scaling — the API and worker are independent apps, so scale the worker separately when indexing large datasets.
- Secrets — LLM provider keys and
SECRET_KEYare the crown jewels. Keep them in PandaStack env vars and rotate on any suspected leak. - Cost honesty — self-hosting Dify is several coordinated services. If you just need a single RAG endpoint, deploying a small LlamaIndex or LangChain app may be far less to operate. Choose Dify when you want the visual builder and multi-app management.
Wrap-up
Self-hosted Dify gives you a full LLM app platform on infrastructure you control: API + worker + web as container apps, with managed Postgres and Redis doing the stateful heavy lifting and pgvector handling embeddings. Just remember the worker, or indexing silently stalls. Docs: https://docs.pandastack.io. Start free at https://dashboard.pandastack.io.