Dify: AI Workflow Platform
Dify is an open-source platform for developing generative AI and LLM applications. It supports agent creation, AI workflows, RAG retrieval, and model management. These features help users build and operate generative AI applications.
Pigsty supports self-hosted Dify with single-command deployment. Critical state resides in externally managed PostgreSQL. You can use pgvector in the same PostgreSQL instance as the vector database to simplify deployment.
The template uses Dify
v1.19.0with plugin daemonv0.6.14-localand sandboxv0.2.15. The previousv1.17.1template was validated on 2026-10-08 for login, an existing Code workflow, and service connections on Linux amd64 with PostgreSQL 18.6. Dify v1.16 and later handle PostgreSQL 18’s built-inuuidv7()without a local migration patch.
Quick Start
On a fresh Linux x86/ARM server running a compatible operating system:
Dify listens on port 5001 by default. Access http://<ip>:5001 in your browser and set up your initial user credentials to log in.
After Dify starts, install extensions and configure system models to begin using it.
Why Self-Host
Data security is a primary reason to self-host Dify. Dify’s Docker Compose template uses basic database images. It lacks enterprise features such as high availability, disaster recovery, monitoring, IaC, and PITR.
Pigsty provides declarative Dify deployment and image mirrors for access in China. The template places PostgreSQL and pgvector under Pigsty management. It deploys Compose Redis, VictoriaMetrics/Grafana monitoring, and an Nginx reverse proxy. After public DNS, ports, and Certbot are configured, it can request a Let’s Encrypt certificate. Files use DIFY_DATA (/data/dify) by default, with optional Silo/S3 object storage.
The template places PostgreSQL/pgvector in an externally managed Pigsty database. API files and plugin data use DIFY_DATA, which defaults to /data/dify. Compose Redis data remains in /data/dify/redis/data. Sandbox dependencies and Certbot data also use /opt/dify/volumes/. The Agent local sandbox also stores /home/dify and /workspace in separate named volumes. Backups must include these volumes as well as the database and host directories.
Installation
Start with a single-node Dify deployment. Production high-availability deployment is covered later.
First, use Pigsty’s standard installation process to install the PostgreSQL instance required by Dify:
The ./configure -c app/dify command generates configuration from conf/app/dify.yml and your current environment. Edit passwords, domains, and other required settings in pigsty.yml. Then run ./deploy.yml to perform the standard installation.
Next, run docker.yml to install Docker and Docker Compose, then use app.yml to complete Dify deployment:
You can access the Dify Web admin interface at http://<your_ip_address>:5001 on your local network.
The first login will prompt you to set up default username, email, and password.
You can also use the locally resolved placeholder domain dify.pigsty, or follow the configuration below to use a real domain with an HTTPS certificate.
Configuration
When you run ./configure -c app/dify, Pigsty generates a configuration file from the conf/app/dify.yml template and the current environment. The snapshot below matches the v4.5.0 source template:
Checklist
Check these configuration items:
- Hardware/Software: Prepare required machine resources: Linux
x86_64/arm64server, fresh installation of a mainstream Linux OS - Network/Permissions: SSH passwordless login access, user with sudo privileges without password
- Ensure the machine has a static IPv4 network address on the internal network and can access the internet
- If accessing via public network, ensure you have a domain pointing to the node’s public IP address
- Ensure you use the
app/difyconfiguration template and modify parameters as neededconfigure -c app/dify, enter the node’s internal primary IP address, or specify via-i <primary_ip>command line parameter
- In production, change every example password, application secret, and database credential. [Required]
grafana_admin_password:pigsty, Grafana admin passwordpg_admin_password:DBUser.DBA, PG superuser passwordpg_monitor_password:DBUser.Monitor, PG monitoring user passwordpg_replication_password:DBUser.Replicator, PG replication user passwordpatroni_password:Patroni.API, Patroni HA component passwordhaproxy_admin_password:pigsty, Load balancer admin password
- Change the PostgreSQL business user password and the application settings that use it.
- Default username
difyand passworddifyai123456are generated by Pigsty for Dify; modify according to your needs - In the Dify configuration block, modify
DB_USERNAME,DB_PASSWORD,PGVECTOR_USER,PGVECTOR_PASSWORDaccordingly
- Default username
- Change Dify’s default encryption key.
- You can randomly generate a password string with
openssl rand -base64 42and fill in theSECRET_KEYparameter - Also replace the three Agent development secrets:
DIFY_AGENT_API_TOKEN,DIFY_AGENT_SERVER_SECRET_KEY, andDIFY_AGENT_LOCAL_SANDBOX_AUTH_TOKEN. Generate independent random values; use the format produced bysecrets.token_urlsafe(32)for the server secret. - Since Dify 1.18, the local Agent sandbox refuses to start with a blank
DIFY_AGENT_LOCAL_SANDBOX_AUTH_TOKEN. Generate it withopenssl rand -hex 32and keep the same value across upgrades.
- You can randomly generate a password string with
- Change the domain used by Dify.
- Replace placeholder domain
dify.pigstywith your actual domain, e.g.,dify.pigsty.io - You can use
sed -ie 's/dify.pigsty/dify.pigsty.io/g' pigsty.ymlto modify Dify’s domain
- Replace placeholder domain
Domain and SSL
To use a real domain with HTTPS, update these settings in pigsty.yml:
- The
difydomain in theinfra_portalparameter - It’s best to specify an email address
certbot_emailfor certificate expiration notifications - Configure Dify’s
NGINX_SERVER_NAMEparameter to specify your actual domain
Use the following commands to request Nginx certificates:
Run the app.yml playbook to redeploy Dify service for the NGINX_SERVER_NAME configuration to take effect:
Upgrading
Before upgrading, verify the PostgreSQL backup and back up the files and named volumes listed below. With MIGRATION_ENABLED=true, the API container runs database migrations at startup. After updating configuration, pulling the new images, and recreating the API container, confirm that it runs the new version before invoking migrations explicitly:
Upgrading from 1.17.x to 1.19.0. Dify 1.19.0 includes the 1.18.0 changes. Read the upgrade guides in the 1.18.0 and 1.19.0 release notes. For this template:
- Upgrade the API, worker, Beat, web, Agent backend, and local sandbox to
1.19.0together, with plugin daemon0.6.14-local. The Agent backend uses a new run protocol, and older Agent runtimes cannot read session snapshots saved by 1.18 and later. Use a maintenance window: stop the old stack in/opt/difywithdocker compose stop -t -1, then rerun./app.yml -l dify. Keep overrides inapps.dify.conf, becauseapp.ymlrewrites/opt/dify/.envfrom the template. - Plugin daemon 0.6.12 and later run as the non-root
difyuser (uid 1001). The template’sinit_permissionsservice now also changes/data/dify/plugin_daemonto1001:1001once (recorded by a.init_permissionsflag file there) beforeplugin_daemonstarts; otherwise plugin installation fails withpermission denied. The first start after upgrading can take a while on large plugin directories. - The local sandbox now starts with
--require-auth-token. Compose passes the sameDIFY_AGENT_LOCAL_SANDBOX_AUTH_TOKENvalue from.envtoagent_backendandlocal_sandbox; it must not be blank. Keep an existing value unchanged. - The template does not set
PASSWORD_PEPPER. Leave it unset on existing installations: setting, changing, or removing it invalidates all stored password hashes. - The bundled Nginx now replaces
X-Forwarded-Forwith$remote_addr, andapi/api_websocketdefault toRESPECT_XFORWARD_HEADERS_ENABLED=true. Behind Pigsty’s portal Nginx, all visitors share the proxy’s address for rate limiting unless you add annginx/conf.d/real-ip.confthat trusts only that proxy withset_real_ip_from. Never trust0.0.0.0/0; setRESPECT_XFORWARD_HEADERS_ENABLED: falseto opt out. - New tracing tasks use the
ops_trace_v2queue (OPS_TRACE_QUEUEapplication default). API, worker, and Beat share the same.env, so they agree. CustomCELERY_QUEUESorCELERY_WORKER_QUEUESlists must includeops_trace_v2,human_input_delivery, andhuman_input_contact_sync. - Migrations run from 1.17.1 to
b9d3f7a5c102(1.18.0) and then to53c10126d551(1.19.0). Several PostgreSQL indexes are builtCONCURRENTLY, scanning large tables such asworkflow_runsandmessage_files. If an index build is interrupted, confirm that no build is still running, drop only the invalid index withDROP INDEX CONCURRENTLY, and rerunflask db upgrade; never drop a healthy index. Revision53c10126d551deletes duplicate tracing configurations; a downgrade does not restore them. - App exports now use
.ifpkgpackage format v2, which older Dify installations may reject. v1 imports and explicit YAML export remain available. - The Beta KnowledgeFS (Agent Knowledge Base) integration is not included. It requires a separate service and database and an amd64-only image. See the upstream KnowledgeFS guide to add it with a Compose override.
- Upstream Compose now splits settings into
envs/**/*.defaultsand requires Compose 2.35.0 or later for that layout. Pigsty keeps a single.envgenerated fromapps.dify.confand does not useenvs/.
Dify 1.17.1 includes the pre-1.15 legacy model type migration in this process. The separate flask data-migrate legacy-model-types command is no longer needed. Deployments upgrading from before 1.15 that have not completed the plugin auto-upgrade backfill must still run it once:
When upgrading from 1.16, rename EDITION to DEPLOYMENT_EDITION, DIFY_AGENT_SHELLCTL_AUTH_TOKEN to DIFY_AGENT_LOCAL_SANDBOX_AUTH_TOKEN, DIFY_AGENT_SHELLCTL_ENTRYPOINT to DIFY_AGENT_LOCAL_SANDBOX_ENDPOINT, and AGENT_BACKEND_RUN_TIMEOUT_SECONDS to DIFY_AGENT_RUN_TIMEOUT_SECONDS in deployment overrides. Use DIFY_AGENT_RUNTIME_BACKEND=local for the bundled self-hosted sandbox.
Version 1.17.1 fixes document extraction, Human Input workflows, collaboration, and Agent behavior. Re-import CSV, Notion, and XLS documents that were previously extracted incorrectly; replacing the image does not repair indexed text. See the 1.17.1 release notes.
The Agent feature remains Beta and should be exposed only to trusted users. SSRF_PROXY_ALLOW_PRIVATE_IPS and SSRF_PROXY_ALLOW_PRIVATE_DOMAINS apply to both workflow and Agent proxies. Leave them empty for the default private-network deny policy. Explicitly allowlisting api, agent_backend, or a network covering their addresses also allows their other ordinary paths; use precise targets. The Agent shellctl control network still permits direct access from the local sandbox to agent_backend.
File Backup
Use restic to back up Dify file state. Include at least /data/dify, /opt/dify/.env, and /opt/dify/volumes/. The last directory contains Compose Redis, Sandbox dependencies, and any Certbot data. Back up PostgreSQL separately with Pigsty/pgBackRest. Also back up the dify_agent_local_sandbox_home and dify_agent_local_sandbox_workspace named volumes, whose actual names include the Compose project prefix. The Restic commands below do not include these two volumes.
After creating the Restic backup repository, you can backup Dify with:
Another option is to place /data/dify on a shared filesystem managed by the JUICE module. File data can live in Silo/S3 or in a PostgreSQL jfs_blob table; the latter is not PostgreSQL large-object storage.
To store JuiceFS metadata and file data in PostgreSQL, declare a dedicated database and least-privilege user in pg_databases. Then declare the instance on the Dify node. The example passwords are placeholders. Do not use them in production.
Handle database creation and JUICE deployment separately. After confirming the exact targets, run the playbooks:
Database creation, initial filesystem formatting, and mounting change the target environment. Confirm the backup, database name, and host group before execution. Start Dify only after the mount is ready. See JUICE configuration and its PITR consistency boundary. Before mounting over a nonempty /data/dify, stop Dify and plan migration of existing files.