Why encrypt Dify's internal connections in a self-hosted deployment
Encrypting the connections between Dify's own services is a decision you have to make and record, because the default setup does not make it for you. Dify is an LLM application platform, according to the langgenius/dify repository, and its api, worker and plugin daemon all open connections to Redis, PostgreSQL and the code sandbox. The Docker Compose deployment starts these services together on one host network with plain internal defaults, so traffic between them is unencrypted unless you change the configuration. Treat each internal connection as a separate item with its own owner, setting and evidence, rather than assuming that a private Docker network is enough.
The decision matters most when a data store leaves the Compose host. That includes an external or managed Redis or PostgreSQL service, a database shared with other applications, and any multi-host layout in which traffic crosses a network segment your team does not fully control. Confirm which metadata database you run, since Dify supports PostgreSQL (the default), MySQL and OceanBase, and check the server versions your platform team plans to use. The Dify Enterprise resources checklist sets minimums of PostgreSQL 14 or later and Redis 6 or later, which is a useful baseline for confirming that the server side supports the TLS settings you need before you commit to a design.
A regulated team usually has to show that data in transit between internal services is protected, so each connection needs two answers: is encryption on, and how strictly is the server's certificate checked. Verification is the part teams skip. Encryption without certificate verification still lets a client connect to an impostor, so the verification level and the certificate authority trusted by each service belong in your design record. Outbound calls from HTTP nodes, tools and knowledge retrieval, which pass through the SSRF proxy, are out of scope for this section and are handled separately.
Which connection to encrypt and which verification level fits
This table compares the four connections from Dify to its data and internal services, showing what each one carries and where the TLS switch and verification setting are looked up. Read it to decide which connections need encryption and whether encryption alone is enough or the certificate authority and hostname must also be checked. Exact setting names and accepted values must be confirmed in the environment variable reference for your release.
| Connection | What the traffic carries | TLS switch and verification setting to confirm | When each verification level fits |
|---|---|---|---|
| Redis (cache, queue and broker) | Task queue messages for the worker, cached session and config data, and broker traffic that can include request context from the api and worker services | Look up the Redis TLS switch and certificate verification mode in the environment variable reference for your release | Encryption only fits a single-host lab. Verify the CA when Redis runs on a separate host or managed service. Verify the hostname when multiple hosts or a load balancer present the certificate |
| Plugin daemon PostgreSQL connection | Plugin metadata, installed plugin state and records the plugin daemon writes to its own database | Look up the sslmode setting for the plugin daemon's PostgreSQL connection in the environment variable reference | Use an encrypted mode when the database sits on another host. Add CA verification when the database uses an internal CA. Add hostname verification when the certificate is issued for a fixed database name |
| Main metadata database connection | Apps, workflows, accounts, workspace settings and encrypted credential records for the api and worker services | Confirm the metadata database SSL options in the environment variable reference, which lists PostgreSQL, MySQL and OceanBase as options | This is the highest-value connection to verify. Verify the CA and hostname whenever the database is outside the Compose network or on managed infrastructure |
| Sandbox connection | Code and Template node execution requests from the api and worker to the code sandbox, including the sandbox API key | Confirm in the environment variable reference which sandbox endpoint settings exist and whether the sandbox supports a TLS switch in your release | If the sandbox listens only on the internal Compose network, document that boundary and confirm the setting before assuming encryption. Verify the hostname when the sandbox runs as a separate service with its own certificate |
| Deployment note | Applies to all four connections | Check the release-specific reference and .env.example after each upgrade, since variable names can change between versions | Keep a written record of which connection uses which setting and which certificate authority it trusts, so an assessor can trace each control |
How TLS for Redis and PostgreSQL changes by deployment layout
The default Docker Compose stack runs PostgreSQL, Redis, the api, worker, plugin daemon and sandbox as containers on one Compose network, so the first step is to confirm whether each internal connection is encrypted at all. Check the Compose files and environment reference for your version before assuming TLS is enabled. Deploy with Docker Compose
- Certificate chain: The chain is whatever you mount into the bundled containers, so define a private CA for the internal services and keep it scoped to this stack.
- Issuance and rotation: You issue and rotate these certificates yourself, because the bundled containers do not manage a CA for you. Record expiry dates in your operations calendar.
- CA bundle mount: Mount the CA file into every container that opens a connection to Redis or PostgreSQL, including the plugin daemon and sandbox. Place the mounts in a Compose override file so the vendor file stays untouched.
- Certificate names: The host names that the containers use inside Compose, such as service names, must appear in the certificate subject or subject alternative names.
- After an upgrade: Upgrades can replace the Compose file and add variables, so check
.env.examplefor new settings and confirm your override still applies. Take a backup before upgrading.
After every upgrade, confirm that each container negotiates TLS, not only that the stack starts.
With external or managed Redis and PostgreSQL on a separate network, the certificate chain usually comes from the provider or your internal PKI, and the verification level is set in each client. Trust therefore has to be tested from every container that connects, not from one place. Review the Dify environment reference for the settings your version exposes. Environment variables
- Certificate chain: Include any intermediate certificates the provider presents, because a leaf certificate alone often fails verification.
- PostgreSQL verification: Set the plugin daemon's PostgreSQL
sslmodedeliberately. Stronger modes verify the server certificate and, at the strictest level, the host name. Confirm which modes your client and database support. - Redis verification: Confirm how Dify's Redis client handles certificate verification in your version, then test with a deliberately wrong CA to confirm that the connection fails.
- Issuance and rotation: The provider or your security team owns renewal. Tie rotation to a planned window, since a rotated CA can break connections without any change in Dify.
- After an upgrade: New images may use different mount paths or defaults, so rerun connection tests from each container.
Confirm the sslmode and Redis verification options for your version before you set them in production.
Dify Enterprise on Kubernetes runs each service in pods, so certificate trust is usually distributed through cluster objects, and the platform team typically owns issuance. The resources checklist calls for Kubernetes 1.24 or later, Helm 3.14 or later, PostgreSQL 14 or later and Redis 6 or later, so confirm the list for the Enterprise version you plan to deploy. Enterprise resources checklist
- Version floor: The checklist sets PostgreSQL 14 or later and Redis 6 or later as minimums. Recheck these values for each Enterprise release before you choose database versions.
- Certificate chain: The cluster CA or corporate PKI signs the Redis and PostgreSQL certificates, and the chain is published to pods as a Secret or ConfigMap.
- Issuance and rotation: A certificate manager or your PKI can automate renewal, but confirm how the Helm chart reloads pods when a secret changes.
- CA bundle mount: Mount the bundle into each workload that connects, including worker and plugin daemon pods. Keep these values in version-controlled Helm values files.
- After an upgrade: Helm upgrades can reset values you did not set explicitly, so diff the rendered manifests and confirm that TLS settings survive.
After upgrades, test TLS from inside each pod rather than relying only on the release status.
Setting PostgreSQL sslmode for the plugin daemon and verifying the sandbox connection
The plugin daemon opens its own PostgreSQL connection, and that connection does not automatically inherit the TLS settings you chose for the main metadata database. Treat its sslmode as a separate setting to set and check. Confirm the variables the daemon reads in your release against the environment variable reference, then inspect the running container's effective configuration rather than trusting the .env file alone. A common gap is a main database connection that enforces TLS while the daemon quietly connects in plaintext because its variable was never changed.
The sslmode options differ in what they prove. At the weaker levels, the connection is encrypted but the client does not check who is on the other end, so a machine positioned on the network path could present its own certificate and still receive the traffic. The stronger levels add verification: one checks that the certificate was issued by a trusted certificate authority, and the strictest also checks that the certificate matches the hostname the client dialed. For a database that holds plugin state and credentials, the practical target is verification against your internal CA with a hostname match, and the decision to accept anything less should be written down with an owner. Ask your PostgreSQL team which CA issued the server certificate and whether the certificate covers the exact service name Dify uses.
The code sandbox runs Code and Template nodes, so its connection to the API and its egress path matter more than a typical internal service. Confirm in the release you run how its service-to-service connection is verified: whether the sandbox validates a certificate at all, which CA bundle it trusts, and whether that path is covered by TLS or only by the internal network. Dify 1.16.1 added token-based API authentication between services and network isolation for the agent sandbox through a Squid proxy, according to its release notes. Treat those as related controls to test, not as a replacement for TLS, because a valid token sent over an unverified connection can still be intercepted. Record the result of each check as evidence for your review.
Enabling TLS on Dify's data store connections step by step
This sequence moves Dify's Redis and PostgreSQL connections onto verified TLS, one connection at a time, with a check at each stage. It ends with a tested failure path and a recorded configuration that the team can renew and audit.
Back up the stack before changing anything
The operator takes a backup of PostgreSQL, the file storage volumes and the current .env and Compose files, following the same discipline the Docker Compose docs recommend before every upgrade. A restore is tested in a separate environment so the team knows the backup works. Done when the backup files exist, the restore test succeeded, and the team can revert the environment file in one step.
Inventory every connection in the target release
The platform engineer lists each client that talks to Redis or PostgreSQL, including the api, worker, web, plugin daemon, code sandbox and SSRF proxy, with its target host, port and current TLS setting. The Compose file and .env.example for the target version are read directly, because a release may add or rename variables. Done when the table has one row per connection and each row names the setting that controls its TLS behavior, confirmed against that version's documentation.
Issue server certificates from the organization CA
The security or PKI team issues server certificates for Redis and PostgreSQL from the organization's internal CA. The subject alternative names must match the exact hostnames the Dify containers use. Private keys stay out of the source repository and are readable only by the account that runs each service. Done when
openssl verifyconfirms each certificate chains to the CA bundle andopenssl x509output shows the expected names.Mount the CA bundle into dependent containers
The operator adds the CA bundle as a read-only volume to every container that dials Redis or PostgreSQL, so each process trusts the same internal root. Certificate verification stays on, because disabling checks to make a connection succeed removes the protection this work is meant to add. Done when a TLS client run inside each container completes a handshake against the Redis and PostgreSQL endpoints using only the mounted bundle.
Enable Redis TLS and certificate verification
The operator sets the Redis TLS switch, the CA file path and the certificate verification level in the environment file, choosing the strictest level the client library supports in the target release. The exact key names are confirmed in .env.example before editing. The api, worker and plugin daemon are restarted in the test environment. Done when their logs show successful Redis connections with no certificate errors and a document indexing job completes.
Set the plugin daemon's PostgreSQL sslmode
The operator sets sslmode for the plugin daemon's PostgreSQL connection, using a verifying mode with the CA file where the target release supports it. The variable name is confirmed in the release's .env.example. Because the plugin daemon has its own database settings, it is checked separately from the api and worker. Done when the plugin daemon starts, logs a successful database connection, and the console lists installed plugins.
Test failure cases in a test environment
The team deliberately breaks each connection: a certificate issued for a different hostname, a certificate that has expired and a certificate from an untrusted CA. Each case is run against Redis and the plugin daemon's PostgreSQL connection. Done when every case fails with a logged TLS or verification error and no service silently falls back to plaintext or unverified connections. Any fallback means the configuration is not finished and this step is repeated.
Restore valid certificates and record the final state
The team reinstates valid certificates, restarts the stack and repeats the handshake checks from earlier steps. They record the final settings, the CA bundle location and each certificate's expiry date, then set up an alert or calendar entry for renewal before expiry. Any new variable found in .env.example for the target release is reviewed and added to the record. Done when the connection table matches live results and a named owner is responsible for renewal.
Security and operational risks when encrypting internal Dify traffic
Encrypting traffic between Dify and its data stores adds certificates, trust bundles and connection settings that must agree across several containers. The cards below cover the failure modes that most often turn a TLS change into an outage or a silent gap, with the control and the check for each.
Certificate expiry takes down several services
The api, worker and plugin daemon all open connections to PostgreSQL and Redis, so one expired server certificate can fail all three at the same moment. The control is an inventory of every certificate used on internal connections, with its expiry date and the services that depend on it. Check that expiry alerts fire well before the date, and that someone is named to act on them. Confirm the expiry of the certificates in your own environment rather than assuming a default.
Rotation needs a planned window
Replacing a certificate on Redis or PostgreSQL often means restarting the services that hold connections, and Dify runs several of them. Plan the rotation as a change with a named window, a rollback copy of the previous certificate and a check that each service reconnects. Ask your platform team whether the Dify services pick up new certificates on restart or need a full stack restart in your deployment.
CA bundle missing from some containers
A certificate authority bundle mounted into the api container but not into the worker or plugin daemon produces connections that work in one place and fail in another. The control is a single, versioned CA bundle mounted identically into every container that connects to an internal store. Check each container's view of the trust store after deployment, and record which bundle version each one uses.
Disabled verification left after testing
Teams often turn off certificate verification to get a first connection working, then forget to turn it back on. A connection that accepts any certificate can be intercepted by anyone who can reach the network path. The control is a written rule that verification stays on in every environment that holds real data. Check the configuration of each service for verification settings that were changed during testing, and review them as part of every release.
PostgreSQL sslmode differs by service
Setting sslmode on the main database connection does not change how the plugin daemon connects to the same PostgreSQL server. Each service has its own connection settings, so one can encrypt while another falls back to plaintext. The control is to set and document the sslmode for every service that connects to PostgreSQL, then test each one separately. Confirm the value each service actually uses in the environment file and in the running container.
Private keys stored in the .env file
Placing certificate private keys in the .env file puts them next to other secrets, copies them into every backup and makes them readable by anyone who can read the deployment directory. Dify's own SECRET_KEY already demands careful handling, so the private keys deserve at least the same protection. The control is a secrets store or a file mounted with restricted permissions and excluded from backups that are not encrypted. Check who can read the file system path and where the keys appear in backups.
Questions teams ask before encrypting Dify's data store connections
Do we need to encrypt Dify's internal connections on a single host?
Not always, but the answer depends on whether traffic leaves a trust boundary. In the Docker Compose layout, the bundled PostgreSQL, Redis and other services talk over a Docker network on the same machine, so the main exposure is other workloads or users with access to that host. Encryption becomes more important when PostgreSQL or Redis run on separate hosts, when they are external managed services, or when your policy requires encryption in transit for every data path. Record the decision, the threat model behind it and the owner who accepted the risk. Confirm the requirement with your security team before you schedule the work.
How much work is internal TLS for Dify, and what drives the effort?
Effort rises with the number of connections, whether each data store is self-run or managed, and how certificates are issued. Count every client-to-store path, including Redis, the plugin daemon's PostgreSQL connection, sandbox connection verification and any external metadata database, vector store or object storage you have moved out of the bundled stack. A managed service may limit which TLS settings you can change, while a self-run store needs server configuration, certificate installation and client changes. Certificate work depends on whether you use an internal CA, an existing PKI or a public issuer. One-time costs include design, configuration and testing. Recurring costs include certificate renewal, rotation and regression testing after upgrades. Internal staff time and a partner's fixed-scope fee both cover these, so ask who carries each item.
Can our team enable TLS for Dify using only the Docker Compose docs?
A team with container, PostgreSQL, Redis and PKI experience can make progress from the official docs, but the Compose documentation covers deployment, not a verified TLS design for every connection. Start with the Docker Compose deployment guide, then confirm the current configuration keys in the environment variable reference for your release. Verification matters as much as the first successful connection. Test the failure cases: an untrusted CA, a hostname that does not match the certificate, an expired certificate and a server that refuses plaintext. Your team needs to own those tests and the runbook that follows them. DeployOpen implements, hardens and documents self-hosted platforms in your infrastructure under a written scope, so you can keep this work in-house or scope it with us.
What changes to TLS settings after a Dify upgrade?
An upgrade can change service images, default values and the variables you rely on, so a working TLS setup can break or be silently bypassed. Dify minor releases arrive roughly monthly, based on the release history: 1.16.0 on July 17, 2026, 1.17.0 on August 25, 2026 and 1.17.1 on September 10, 2026. The Compose docs recommend a backup before every upgrade and a check of .env.example for new variables. Build an upgrade routine that diffs your environment file against the new template, re-applies your TLS settings, restarts services and tests every encrypted connection again. Keep certificates and CA material in controlled storage so a rebuild does not force reissue. Pin the version you test, and treat each upgrade as a change that needs its own verification.
Do TLS settings have to match across Dify's services?
Each client needs to trust the server certificate and use a mode the server accepts, but the settings do not have to be identical everywhere. What must align is the trust chain and the names in the certificate. For PostgreSQL, the sslmode setting controls how strict the client is: require encrypts the connection without verifying the server, verify-ca checks the issuing CA, and verify-full also checks the hostname. A client set to verify-full will fail if the certificate lacks the hostname it connects to, even when the server works for other clients. Redis clients need the TLS port, the CA bundle and any client certificate requirements configured separately. Document each connection's mode and certificate name in one table so an upgrade or certificate renewal does not create a mismatch that is only found in production.
What should we ask a partner for in a fixed-scope TLS quote?
Ask for a written scope that lists every connection in scope, the services and versions involved, and the certificate source and issuing authority. A useful quote also names the verification level for each path, the test cases and the acceptance criteria. Ask for:
- A connection inventory and the target verification level for each one
- The certificate issuance, distribution and renewal process, and who operates the CA
- Regression testing after each planned Dify upgrade
- Runbook and handover documentation for your operators
- Explicit exclusions, such as configuration owned by a managed database provider
DeployOpen works fixed-scope, with scope, deliverables and timelines agreed in writing before work starts. We do not publish a price list, so a quote follows from that written scope.
What to confirm in your environment before relying on these settings
The settings for encrypting Dify's internal connections depend on the release you run, the images you deploy and the storage you attach. The cards below list the points the supporting facts do not settle. Confirm each one with the vendor, the release notes and a test environment before you record the configuration as final.
Exact setting names and accepted values
Confirm the TLS-related variable names, their accepted values and their defaults for the exact release you deploy. Compare them against the .env.example file that ships with that release, because variables change between versions. Do not copy a setting from a blog post, an older guide or a forum thread. Record the release tag next to every value so an upgrade can be checked against it.
Bundled Redis and PostgreSQL TLS support
Confirm whether the Redis and PostgreSQL images in the Compose file accept the TLS mode you plan to use in your version. Check whether the server certificates can be mounted, whether the client libraries in each service support the verification level you want, and whether the bundled images need a custom build. If support is missing, decide whether to move those services to managed or external instances.
Sandbox connection verification level
Confirm whether the code sandbox connection can be verified, which certificate checks the release performs and whether the setting is exposed as configuration or only in code. Test a connection with verification turned off and on, and record what the api and worker services actually reject. Do not assume the sandbox behaves like the database connections.
External vector stores and object storage
Confirm how each external vector store and object storage backend you choose handles TLS, including certificate paths, custom certificate authorities and hostname checks. Dify supports several options for both, so the answer depends on your selected provider. Test uploads, retrieval and backups through the encrypted path, and do not treat a successful health check as proof that data traffic is encrypted.
Auditor acceptance of the configuration
Ask your internal audit or external assessor whether the chosen TLS configuration, including any verification level below full certificate validation, meets your control requirements. Agree the evidence you will keep, such as configuration files, test output and certificate inventories. DeployOpen prepares systems and evidence for assessments, but independent auditors decide whether the evidence is sufficient.
How DeployOpen scopes and delivers Dify TLS hardening
DeployOpen plans and implements Dify inside your own infrastructure, including encryption of the connections between Dify and its data stores. We start from a written scope that names each connection, its certificate authority and the verification level you need, then build and document the change in your environment.
How we scope
- We inventory every connection from the api, worker and plugin daemon to Redis, PostgreSQL and the sandbox.
- We record which connections already use TLS, which use plaintext and which verify certificates today.
- We agree the certificate authority, hostnames and verification level for each connection in the written scope.
- Engagements are fixed-scope, with deliverables and timelines agreed in writing before work starts.
How we build
- We configure Redis TLS settings and certificate verification in the Dify environment file for your deployment.
- We set the plugin daemon's PostgreSQL sslmode and confirm the chosen mode against your database server.
- We verify sandbox connection settings and test each connection in a staging copy before any production change.
- We confirm that a failed certificate check stops the connection rather than falling back to plaintext.
How we hand over
- You receive a record of each encrypted connection, its verification level and the certificate source used.
- We document the certificate renewal steps and the restart order for services that load new certificates.
- We provide a rollback procedure and a backup taken before the change, in line with Dify's upgrade guidance.
- Your team walks through the runbook with us so operators can repeat the checks after future upgrades.
How we support
- Ongoing support, upgrades and continuous testing are available as retainers after handover.
- We can review connection settings when you move to a new Dify minor release, which arrive roughly monthly.
- We can re-verify TLS settings after certificate rotation, database changes or changes to your internal CA.
- Ask us to confirm in the quote which renewal and re-test tasks are covered by the retainer.

