Skip to main content

Overview

Dify is an open-source builder for LLM applications: chatbots, agents and visual workflows with RAG knowledge bases. You build an app in the browser, then publish it as a web page, call it through the REST service API or expose it as an MCP server. This template runs Dify on a bundled PostgreSQL with pgvector and a bundled Redis. A login is always required.
This template does not create a GVC. It deploys into an existing GVC that you already have, and that GVC should have exactly one location, because the database, Redis, both volumes and the plugin daemon run in one location.

What Gets Created

The template creates no credentials. The public *.cpln.app URL is on by default and every page needs a Dify login. Each Dify tier accepts connections only from the tiers that call it.

Prerequisites

1

Create the Dify keys secret

A dictionary secret holding Dify’s own keys. Use only letters and digits in every value, and keep initPassword to at most 30 characters:
Set dify.secretName to this name.
2

Create the code sandbox key secret

An opaque secret holding the key that Dify and the code sandbox share:
Set codeExecution.apiKeySecretName to this name.
3

Create the database credentials secret

A dictionary secret with exactly username, password and database, letters and digits only:
Set postgres.config.credentialsSecretName to this name (or postgresHA.config.credentialsSecretName with the HA database).
4

Create the Redis password secret

A dictionary secret with a password key, letters and digits only. A password is required because user code runs inside this GVC:
Set redis.redis.auth.fromSecret.name to this name.
Secret names are org-wide, so give each release its own secrets. A value with other characters stops the API, worker and scheduler at start with a log line naming the key. Backups and a custom domain are optional, see Backing Up and Connecting.
Every secret your release names must exist before you install. If one does not, the deployment waits silently: cpln logs returns nothing, and the only place the missing secret is named is status.versions[].message in cpln workload get-deployments RELEASE_NAME-dify-api --gvc GVC_NAME -o yaml. Create the secret and the deployment recovers on its own after several minutes, or run cpln workload force-redeployment WORKLOAD_NAME --gvc GVC_NAME on each Dify workload to skip the wait.

Installation

The required values are the names of the four secrets from Prerequisites:
To install with the highly available database, add --set postgres.enabled=false --set postgresHA.enabled=true --set postgresHA.config.credentialsSecretName=DB_CREDENTIALS_SECRET_NAME. To install with the CLI, UI, Terraform or Pulumi, follow the instructions for your preferred method:

UI

Browse, install, and manage templates visually

CLI

Manage templates from your terminal

Terraform

Declare templates in your Terraform configurations

Pulumi

Declare templates in your Pulumi programs

Configuration

Dify

The gateway, web and beat tiers take the same resources shape under dify.resources.
Each API and worker process holds up to 8 database connections (SQLALCHEMY_POOL_SIZE 5 plus SQLALCHEMY_MAX_OVERFLOW 3), which allows about 8 concurrent runs per API replica. To allow more, set both in dify.extraEnv, staying within PostgreSQL’s 100 connections:

Code Execution and Network

Database

Redis

Connecting

Dify builds every link, cookie and webhook from the public URL, and the login works only on that exact address. With dify.publicUrl empty it is the gateway’s *.cpln.app endpoint. Behind a custom domain, route the domain to the RELEASE_NAME-dify workload and set dify.publicUrl to it. With publicAccess.enabled: false, set dify.publicUrl to the address users open, such as http://localhost:8080 for port-forward. To check the gateway, forward the port and read its health:
Streaming responses and long runs pass through the gateway unbuffered. The public endpoint cuts a request after dify.requestTimeoutSeconds; calls from inside the GVC over cpln.local are not subject to it.

First Run

Open the public URL. Dify asks for the initPassword from the Dify keys secret, then lets you create the admin account on the /install page. Read the password with cpln secret reveal DIFY_SECRET_NAME -o yaml. Self sign-up and creating more workspaces are turned off; invite members from Settings → Members, which shows an invite link to copy because the template sends no email.

Operations

Backing Up

All state lives in PostgreSQL and the file storage volume. Enable postgres.backup.enabled (or postgresHA.backup.enabled with the HA database) and fill in the provider block; the keys and defaults are in the chart’s values.yaml. The bucket, cloud account and IAM policy are set up as described in the postgres or postgres-highly-available template, and a MinIO provider needs a dictionary secret with the keys accessKey and secretKey. Restore steps are in those templates’ pages. The backup covers the database only; uploaded files and the keys that decrypt saved provider credentials on the file storage volume are not included.

Scaling and Availability

Set dify.replicas from 1 to 3 for the gateway, web, API, code sandbox and SSRF proxy, and worker.replicas from 1 to 3 for the worker. The scheduler and the plugin daemon always run one replica. When several API replicas start together, one applies the database migrations and the others wait for it. For near-zero-downtime upgrades and failover, set dify.replicas: 2, worker.replicas: 2 and postgresHA.enabled: true. Redis stays a single node. After changing a secret a workload reads, redeploy the workloads that use it:

Clearing a Login Lockout

Dify locks an email address out for 24 hours after 6 failed logins, from any address. To clear it, delete the lock from Redis:

Troubleshooting

A secret named in the values does not exist. Read status.versions[].message with cpln workload get-deployments RELEASE_NAME-dify-api --gvc GVC_NAME -o yaml, create the secret, then run cpln workload force-redeployment WORKLOAD_NAME --gvc GVC_NAME on each Dify workload.
A database or Redis value contains characters other than letters and digits, secretKey is empty, or initPassword is longer than 30 characters. Fix the secret and redeploy the Dify workloads.
The login works only on the exact address in dify.publicUrl. For a private install or a custom domain, set dify.publicUrl to the address users open, without a trailing slash.
The SSRF proxy refuses private, link-local and in-GVC addresses (*.cpln.local) for HTTP Request nodes, tools and Python HTTP calls. Set ssrfProxy.enabled: false to lift it, knowing that flows can then call any service in the GVC. Model-provider plugins run in the plugin daemon, not through the proxy, so Ollama, vLLM and LiteLLM providers can use in-GVC URLs.
Concurrent runs exhausted the database connection pool. Raise SQLALCHEMY_POOL_SIZE and SQLALCHEMY_MAX_OVERFLOW in dify.extraEnv, as shown in Configuration.
The public endpoint cuts requests after dify.requestTimeoutSeconds (default 600, maximum 3600). Raise it for longer calls.
Clear the lock as shown in Clearing a Login Lockout.
The error names the offending value. The template rejects replica counts outside 1-3, enabling both or neither database, redis.mode other than dev, and extraEnv names that the chart sets itself.

Important Notes

  • The Dify licence allows one workspace per install, not a multi-tenant service, and forbids removing or changing the Dify logo and copyright in the console.
  • Never rotate secretKey (it signs every login and shared link) and never delete the file storage volume (it holds the keys that decrypt the model-provider credentials saved in Dify).
  • Anyone who can edit an app can run Python and JavaScript in the code sandbox, and that code can open direct connections to the internet. The Dify API, web and plugin daemon refuse the sandbox, but the other services in this GVC, including the bundled PostgreSQL and Redis, are guarded only by their passwords. Give accounts only to people you trust.
  • With the SSRF proxy on, HTTP Request nodes, tools and Python requests calls in Code nodes go through it. JavaScript code gets no proxy.
  • Plugins install from the Dify marketplace or an uploaded package, and only signed plugins are accepted.
  • Use a single-location GVC: the database, Redis, both volumes and the plugin daemon run in one location.
  • The first helm upgrade after an install can restart the bundled database, which briefly interrupts Dify.
  • Uninstalling deletes the database and both volumes, and with them every app, user, knowledge base and installed plugin.

External References

Dify documentation

Concepts, apps and deployment

Environment variables

Dify settings

Dify service API

Calling published apps over REST

Dify as an MCP server

Exposing apps as MCP tools

Dify on GitHub

Source, licence and issues