How to move Dify to a new server or host without losing users, files or plugin credentials
A Compose-based Dify can be moved to new hardware or another cloud account by stopping the stack cleanly, copying its state, and carrying the same SECRET_KEY to the new host. The move itself is mostly a copy of the entire dify/docker/volumes directory plus the configuration in .env, so the real effort is verification: confirming that users can sign in, that knowledge bases still answer, and that plugins and their stored credentials still work. The Docker Compose stack has defined minimums of 2 CPU cores, 4 GB of RAM and Docker Compose 2.24.0 or later, so confirm the target host meets them before you copy anything. Effort depends mainly on how much data sits in volumes, and on how many services you have already moved out of the bundled stack, such as PostgreSQL, Redis, file storage or Weaviate, because each externalized service has its own data to transfer and check.
The most important decision is the `SECRET_KEY`. Dify uses it to sign session cookies and JWTs and to encrypt OAuth credentials, and changing it after deployment logs out all users, invalidates file URLs and makes OAuth-encrypted plugin credentials unrecoverable. Copy the value exactly from the source .env to the target and keep the same key for the lifetime of the data. Also plan the public address: if the hostname or scheme changes, update the URL settings in the configuration so that links, redirects and file URLs point to the new location, and check the Dify environment variables reference for every URL-related key your version uses.
Stop the source stack before the final copy so that the database and volumes are not written during transfer, and preserve file ownership and permissions when you copy so that services in the new containers can read them. After the stack starts, test in order: administrator sign-in, a workflow run that calls a model, a retrieval query against an existing knowledge base, a file upload and download, and each installed plugin, including one that uses stored credentials. Ask your team to confirm the exact copy procedure for your Dify version in the Dify storage and migration documentation before the cutover window, and keep the source host intact until every check passes.
Which parts of a Dify deployment move as-is and which need rework
This table compares each part of a Docker Compose Dify deployment against what the target host needs, marking items that copy cleanly, items that need a new value, and items that must be re-entered. Read it before the cutover window to decide what the move plan has to rebuild rather than restore.
| Component | What carries over | What the target host needs |
|---|---|---|
| dify/docker/volumes directory | Copies cleanly as a whole when services are stopped, including PostgreSQL data, Redis data, Weaviate data and uploaded files, per Dify's backup list | Same directory layout and ownership restored, so container users can read and write the copied files |
| SECRET_KEY in .env | Must be kept identical, because changing it logs out all users and invalidates file URLs | Copy the exact value into the target .env before first start; do not generate a new one |
| Public URL settings (such as the console and app domain values) | Not portable, since they describe the old host name | Set new values to the target DNS name and TLS endpoint, then confirm the URLs served to users |
| Bundled PostgreSQL and Redis | Data copies with the volumes directory when services are cleanly stopped | Same major version and matching image tags; verify the database starts and migrations report no errors |
| Bundled Weaviate vector data | Copies with the volumes directory, so knowledge base indexes do not need rebuilding | Same Weaviate image version and writable data path; confirm collections load before users return |
| Plugin daemon state and OAuth-encrypted plugin credentials | Plugin files copy, but credentials depend on the unchanged SECRET_KEY | Confirm plugins load; re-enter any credential that cannot be decrypted |
| Apps as DSL exports | Configuration, workflow nodes, model parameters, prompts and knowledge base connections | Import into the new instance and reconnect each knowledge base and model provider |
| Third-party API keys and knowledge base content | Not included in DSL exports | Re-enter keys in the target console; re-upload or sync source documents if the volume copy failed |
| Usage logs | Not included in DSL exports | Decide with your team whether to archive logs from the old host before decommissioning it |
Why the volumes directory and SECRET_KEY decide whether the move succeeds
The two items that decide whether a Compose move succeeds are the dify/docker/volumes directory and the SECRET_KEY value in .env. Dify's storage and migration documentation lists the entire dify/docker/volumes directory as what to back up for Docker Compose deployments, and the move has to treat it the same way. That directory holds the data written by the stateful services, including the PostgreSQL database, the Redis data, the vector store data and the uploaded files. Copying only the database dump, or copying the volumes but skipping one subdirectory, leaves the new host with a working interface and missing content. Before you copy anything, stop the stack cleanly so the databases are not written during the copy, then confirm that file ownership and permissions survive the transfer, because the containers run as specific users and will fail to read files they cannot access.
SECRET_KEY is the second item, and it is the one most often changed by accident. According to the Dify environment variable reference, the key signs session cookies and JWTs and encrypts OAuth credentials. Carry the exact value from the source .env to the target and keep it unchanged. If it changes, all users are logged out immediately, file URLs stop working, and OAuth-encrypted plugin credentials become unrecoverable, so you would need to re-enter them by hand. A fresh install on the new host generates its own environment file, so the copied .env must replace the default one before the first start. Also keep the workspace encryption setting and any other encryption-related variables identical, and confirm both values against your secure record of the original configuration rather than assuming the copy is correct.
Which documented tools and paths the move uses
The file-level path copies the entire dify/docker/volumes directory and the .env file from a stopped stack to the new host. Dify's storage and migration guidance lists the whole volumes directory as the item to back up for Docker Compose deployments, which means database files, uploaded documents, plugin data and other stateful content move together. This path preserves the exact on-disk state, but it depends on the stack being stopped so the data is consistent.
- Stop the stack first: Shut down the Compose services cleanly before copying, so databases are not written during the transfer.
- Preserve ownership and modes: Copy with tools that keep numeric user IDs, group IDs and permissions, because containers read these files under specific users.
- Carry the environment file: Move
.envwith the volumes soSECRET_KEYand the other settings match the data. - Check free space and transfer integrity: Compare sizes and checksums on the destination before starting services.
- Keep the source intact: Leave the original volumes untouched until the new host passes verification.
Confirm the exact copy commands and any service names against the Dify version you run, using the storage and migration guidance as the reference.
A logical backup exports PostgreSQL data and Redis data while the services are running, instead of copying raw files. It gives you a consistent database snapshot that can be restored into a fresh PostgreSQL instance on the new host, and it does not require downtime to take the dump. Teams often use it as a second copy alongside the volume copy, because it can be restored and inspected independently of the underlying file layout.
- Dump PostgreSQL while live: A logical dump captures a consistent view of the metadata database without stopping the stack.
- Capture Redis separately: Redis holds transient state, so decide whether it needs a persistence copy or can be rebuilt after the move.
- Restore into a matching version: Restore the dump into the PostgreSQL major version the target deployment expects.
- Record the dump time: Note when each dump ran, because data written after it will not be in the copy.
- Test the restore: Load the dump into a scratch instance before you rely on it for cutover.
Confirm the dump and restore commands, PostgreSQL version requirements and Redis handling against the storage and migration guidance for your release.
DSL export writes each app to a YAML file that holds its configuration, workflow nodes, model parameters, prompts and knowledge base connections. It does not carry third-party API keys, knowledge base content or usage logs, so it cannot replace a database or volume copy. Its value is as a readable, portable record of how each app is designed, which helps reviewers and rebuild work if a restore fails.
- Export every app: Use the app management export function to save each app as a DSL file.
- Store exports with the change record: Keep the files under version control or in your change system, separate from the server.
- Note what is missing: Record which provider credentials, API keys and knowledge bases must be re-entered or re-attached after import.
- Compare against the restored instance: Check app names, workflow structure and model settings on the new host against the exports.
- Treat exports as sensitive: Prompts and connection details can reveal business logic, so apply the same access controls as other configuration.
Confirm the export and import steps for your Dify version in the app management documentation before relying on them in a cutover plan.
The sequence for stopping, copying, switching and verifying Dify
This sequence moves a Docker Compose Dify deployment to new hardware or another cloud with a verified backup, intact data and a known rollback path. Each phase closes with a check, so the cutover happens only when the new host is proven.
Inventory the running version and configuration
Record the exact Dify version the running stack uses, the Compose file, the full .env file and the list of enabled services, including PostgreSQL, Redis, Weaviate, Nginx, the code sandbox, the SSRF proxy and the plugin daemon. Note the configured metadata database, file storage provider and vector store, because the target host must match them. Store the SECRET_KEY value in your secrets vault, not in the ticket. Done when someone outside the migration team can read the inventory and confirm which services and storage backends the move touches.
Take a verified backup before any change
Back up the entire dify/docker/volumes directory, which Dify lists as the material to back up for Compose deployments, and export the .env file alongside it. The Compose docs recommend a backup before every upgrade, and a move carries the same risk. Confirm the archive is readable and the file sizes match the source. Done when a restore test on a scratch machine returns the same files with the same checksums.
Prepare the target host to the documented minimums
Provision the new host or cloud instance with at least 2 CPU cores, 4 GB of RAM and Docker Compose 2.24.0 or later, as the self-hosting docs require. Confirm outbound access rules, DNS resolution and the same or a newer Docker engine that your team has tested. Install the same Dify release recorded in the inventory, not the latest one, so the first boot compares like with like. Done when the host passes a clean Compose config check and starts an empty Dify stack.
Stop services cleanly and copy volumes
Stop the source stack with a graceful Compose shutdown so PostgreSQL and Redis flush writes, then confirm no containers are still writing. Copy the volumes directory with an archive or sync tool that preserves ownership, numeric user IDs, permissions and timestamps, such as tar with preserved attributes or rsync in archive mode. Check that database files, uploaded documents and Weaviate data arrived with the same owners. Done when the copied tree matches the source manifest and the database containers initialize without permission errors.
Start on the target with the same SECRET_KEY
Copy the .env file to the target, keep SECRET_KEY byte-for-byte identical, and start the stack. Changing SECRET_KEY logs out all users, invalidates file URLs and makes OAuth-encrypted plugin credentials unrecoverable, so treat any mismatch as a stop condition. Review other environment values that name hosts or paths, such as the public URL and storage settings, but do not change the key. Done when all containers report healthy and the api logs show no decryption or key errors.
Update public URLs and reverse proxy settings
Set the public URL and reverse proxy configuration on the target to the address users will reach, including TLS certificates and forwarded headers that the web and api services expect. Confirm the SSRF proxy and outbound allowlists still match the new network, since they route and filter requests to internal and private ranges. Done when the web console loads over the final hostname with valid TLS and the API responds at the expected base URL.
Verify logins, files, retrieval, models and plugins
Run a checklist on the target: sign in with a test account, open an existing app, download an uploaded file, run a knowledge base query against a known document, call one configured model provider and one self-hosted endpoint, and confirm each installed plugin loads and executes. Record failures against the inventory. Done when every check passes, and any failed plugin is reconfigured or reinstalled before users are switched.
Run a parallel period, cut over and decommission the old host
Keep the source stack stopped or read-only while DNS or the load balancer points to the target, or run both briefly only if your team has a tested way to avoid writing to two databases. Monitor logs and user reports, then keep the source backup and volumes archived for a retention period your policy sets. Decommission the old host only after sign-off, revoke its credentials and remove its copies of SECRET_KEY and the .env file. Done when the new host serves all traffic, the archive is stored under access control, and the old host is documented as retired.
What makes a Dify server move quick or slow
A Dify move is mostly a data and dependency problem, not a container problem. The six drivers below decide how much data must be copied, how many services must be re-pointed and how many people must be told before the new host is trusted.
Volume size and local storage
For Docker Compose deployments, the entire dify/docker/volumes directory is the backup set, and it holds uploaded files, knowledge base vectors held by the bundled Weaviate and other local state. The larger and more local this data is, the longer the copy and the verification. Ask the team how large the directory is today, which files sit inside it and how long a full copy takes on the actual network path to the new host. This cost is one-time for the move, but a backup of the same data recurs.
Bundled or external services
Compose runs PostgreSQL, Redis, Weaviate and the sandbox as containers on the same host, so they move with the volumes. If any of them is external, such as a managed PostgreSQL instance or an object store, the move becomes a connection change plus a data sync, and the new host must reach those services over the right network path. Confirm which services are bundled, which are external and who owns credentials for each before scheduling the cutover.
Plugins and model connections to re-verify
Every installed plugin and every configured model provider connection is a point where a move can fail quietly. Plugin credentials are encrypted with keys derived from SECRET_KEY, so their state after a move must be checked one by one rather than assumed. Build a list of plugins, providers and tool credentials from the console before the move, then test each one on the new host. Verification effort grows with the size of this list.
Public URL and TLS termination
A new host usually means a new public address, a new certificate or a new reverse proxy in front of Nginx. Uploaded file URLs, OAuth callbacks, embedded web apps and API clients all reference the address they were created with. Decide whether the old hostname will be redirected, which systems hold the old URL and who renews the certificate on the new host. Changing the URL is a one-time task, but every external caller that keeps the old address creates recurring failures until it is updated.
Target platform storage and networking
The target may be different hardware, another cloud or a different volume type. Ownership, permissions and filesystem behavior can change between platforms, so volumes must be copied with their permissions intact and the container user must still be able to write to them. Outbound paths also matter, since the SSRF proxy and model endpoints must be reachable from the new network. Confirm the target's disk performance, firewall rules and egress policy with the platform team before the first copy.
Users affected by re-login
Keeping SECRET_KEY unchanged avoids a forced logout, but a new address still makes sessions, bookmarks and shared links behave differently. The number of users, the number of published web apps and the number of integrations that embed Dify determine how much communication is needed. Count these before the move and prepare a short notice that states the new address, the change window and whether users must sign in again. This is a one-time communication effort, but support requests continue for days after cutover.
Questions teams ask before moving Dify themselves or hiring help
How much effort does moving Dify to a new server take?
The effort depends mostly on how the current deployment is built, not on the move itself. A single Docker Compose host with local volumes is a different job from a stack that uses external PostgreSQL, object storage and a non-default vector store. The main drivers are the size of the volumes directory, the number of services and custom settings in .env, the number of public URLs and API clients that point at the old address, and how many plugins and model credentials must be checked afterward. Dify's storage and migration guidance lists the entire dify/docker/volumes directory as what to back up, so the copy alone can be large. Ask any partner for a written estimate that breaks the work into inventory, backup, cutover, and verification, and confirm the figures against your own environment before committing to a window.
Can our team move Dify without outside help?
Yes, if your engineers are comfortable with Docker Compose, Linux file permissions and reverse proxy configuration. The move follows a clear sequence: stop services cleanly, back up and copy the volumes with ownership and permissions intact, bring the same .env values to the new host, keep SECRET_KEY unchanged, update public URLs, and then test. The riskiest step is changing SECRET_KEY, because the Dify environment variable reference says doing so logs out all users, invalidates file URLs and makes OAuth-encrypted plugin credentials unrecoverable. Outside help is most useful when the deployment is business-critical, has external dependencies, or must meet change control and evidence requirements that your team has not handled before. DeployOpen plans, implements and verifies these moves inside your own infrastructure under a written scope.
What does the move need from our side?
Plan for four inputs before the work starts: access, a change window, a named owner and sign-off authority. Access means shell or sudo rights on the source and target hosts, read access to the .env file and secrets store, DNS or load balancer control for public URLs, and credentials for any external database, object storage or vector store. A change window must allow for a planned stop of the api, worker and web services, so users know when the platform is unavailable. Name one owner who makes decisions about cutover timing and rollback, and one person who can confirm that the business workflows, knowledge bases and API clients work after the move. Confirm these roles in writing so that verification does not stall on an unassigned decision.
Should we upgrade Dify during the same move?
Keep the move and the upgrade as separate steps. Moving changes where the platform runs, and an upgrade changes what it runs. If both happen together, a failure cannot be attributed to one change, and rollback becomes harder. Dify's Docker Compose docs say upgrades follow the upgrade guide for the target version on the GitHub Releases page, recommend a backup before every upgrade, and advise checking .env.example for new variables. Minor releases arrive roughly monthly, so the target version you move to should match the version you run today unless a planned upgrade is already scoped. Once the new host is stable and verified, plan the upgrade as its own change with its own backup and test plan.
What should we ask for in a written scope for a server move?
A useful written scope names the source and target environments, the Dify version before and after the move, and the list of volumes, configuration files and external services in scope. It should also state the backup method and where backups are kept, the cutover steps and expected service interruption, the URL and DNS changes, and the checks that confirm success. Ask whether plugins will be verified individually, how model provider credentials and OAuth-linked plugin credentials are handled, and what happens if verification fails. Clarify what is excluded, such as upgrades, new integrations or a change of vector store. Request a fixed price or fee in writing with the assumptions behind it, and check that deliverables and acceptance criteria are defined before work starts.
What costs should we expect for moving Dify to a new host?
Costs fall into three groups: the target infrastructure, the labor to plan and execute the move, and the ongoing platform costs that continue regardless of hosting. The move itself is usually one-time labor, while the new hosts, storage and any managed database or object storage recur monthly. The community edition is free to self-host and is limited to a single workspace, according to Dify's pricing page, so a move does not add a license fee for that edition. Enterprise is custom priced and includes licensing, SSO and professional support. Hardware or cloud sizing starts from the minimum of 2 CPU cores, 4 GB of RAM and Docker Compose 2.24.0 or later, but real sizing depends on your workload. Ask any partner to separate the one-time move fee from recurring infrastructure and support charges in the quote.
How do we check that plugins and model connections still work after the move?
Test each plugin and model connection against the new host, because a successful container start does not prove that credentials and endpoints work. Keep SECRET_KEY unchanged so that encrypted credentials can still be decrypted, then open each installed plugin, confirm its status, and run one representative call per model provider. Check that outbound requests still pass through the SSRF proxy settings, because a new network path can change what is reachable. Confirm that file URLs in apps and knowledge bases resolve under the new public address, and that API clients receive responses from the new endpoint. Record the results in a checklist so the owner can sign off against it.
What stays the same under the Dify license when you change hosts
Moving a self-hosted Dify deployment to new hardware or another cloud does not change the terms of the Dify Open Source License. The license is a modified Apache License 2.0 that lets you run the software yourself, but it forbids using the source code to operate a multi-tenant environment, where one tenant is one workspace, without written authorization from the licensor. It also forbids removing or modifying the logo or copyright information in the Dify console. These conditions attach to how you use the software, not to where it runs, so a new host inherits them in full. Before the cutover, confirm the current wording in the Dify LICENSE file, since your legal team should read the actual text rather than a summary. Check also that the new environment's branding, login pages and any white-labeling work in your migration plan still leave the console logo and copyright notices intact.
The workspace count matters more after a move than many teams expect. Community edition is free to self-host but limited to a single workspace, so a relocated instance that serves several business units, customers or tenants as separate workspaces needs a licensing decision before it goes live, not after. Enterprise adds multiple workspaces, SSO and a commercial license, and its pricing is set by quote. Ask the vendor in writing whether a planned workspace layout, including any staging and production split on the new host, fits your current entitlement. If you are unsure whether a test or disaster recovery copy counts as a separate tenant under the license, get that answer in writing before you restore data into it.
How DeployOpen works on this
DeployOpen plans and carries out Dify server moves inside your own infrastructure, whether the target is new hardware or another cloud account. Each move starts with a written scope that fixes what is moved, verified and handed over before any service is stopped.
How we scope
- Inventory the current Compose stack, its volumes, the
.envfile and every external storage or vector store the deployment depends on. - Confirm the target host meets the documented minimums of 2 CPU cores, 4 GB of RAM and Docker Compose 2.24.0 or later.
- Agree in writing whether the move keeps the same Dify version, the same public URL, and the same
SECRET_KEYvalue.
How we build
- Stop services in a planned order, take a full backup of the entire
dify/docker/volumesdirectory, and record checksums before copying. - Copy volumes with ownership and permissions preserved, then start the stack on the new host and check each core service's logs.
- Update public URLs and proxy settings, then test login, file upload, knowledge base retrieval and each installed plugin from a client network.
How we hand over
- Deliver a runbook covering the cutover sequence, rollback steps, the backup location and the verification checklist used during the move.
- Document every changed environment variable, DNS record and certificate, so your team can repeat the process for later moves.
- Walk your operators through the post-move checks and the upgrade guidance for the target version before the old host is decommissioned.
How we support
- Engagements are fixed-scope, with scope, deliverables and timelines agreed in writing before work starts.
- Ongoing support, upgrades and continuous testing are available as a retainer for teams that want help after the move.
- Ask for the written scope and a quote that separates planning, cutover work, verification and any follow-on retainer.

