In this categoryDify ยท 9
DifyAdvanced

How to Self-Host Dify in Production with Docker Compose

Clone Dify, bring it up with Docker Compose, set the production env values, put it behind a reverse proxy with HTTPS, and set up backups and upgrades.

20 minAdvanced

Self-hosting Dify gives you full data control and lets you use local models. The official Docker Compose bundle brings up every service Dify needs: the API, the worker, the web UI, a database, Redis, and a vector store. This guide takes you from a clone to a hardened production instance behind HTTPS, with backups and a clean upgrade path.

What you need

  • A Linux server with Docker and the Docker Compose plugin installed
  • At least a few gigabytes of RAM; more if you run local models
  • A domain name pointed at the server for HTTPS
  • About 20 minutes

Step 1: Clone the repo and start the stack

Dify ships a ready docker directory. Clone the repository, copy the example environment file, and bring the stack up in the background. The first start pulls several images, so give it a minute.

bash
$git clone https://github.com/langgenius/dify.git
$cd dify/docker
$cp .env.example .env
$docker compose up -d
Creating dify-api, dify-worker, dify-web, db, redis ... done
$
First-run setup
Once the containers are healthy, open the server in a browser and finish the install wizard, which creates the first admin account. By default the web UI is served on port 80 through the bundled nginx container, so http://your-server should show the setup screen.

Step 2: Set the production env values

The defaults are fine for a local trial but not for production. Edit .env before you expose the instance. The values below are the ones that matter most for security and correct links.

docker/.env
# Set to your real HTTPS URLs so links and API callbacks are correct
APP_WEB_URL=https://dify.example.com
CONSOLE_WEB_URL=https://dify.example.com
SERVICE_API_URL=https://dify.example.com/v1

# Rotate every default secret and password
SECRET_KEY=replace-with-a-long-random-string
DB_PASSWORD=replace-with-a-strong-password
REDIS_PASSWORD=replace-with-a-strong-password

# Cap uploads to something sensible for your use
UPLOAD_FILE_SIZE_LIMIT=15
Rotate every secret before exposing it
Generate a fresh SECRET_KEY and change every default database and Redis password. Shipping the example values to a public server is the single most common self-host mistake. After editing .env, apply the changes with docker compose down and docker compose up -d.

Step 3: Put it behind a reverse proxy with HTTPS

Do not expose Dify's HTTP port to the internet directly. Run a reverse proxy such as Caddy or nginx in front of it, terminate TLS there, and forward to the Dify web container. Caddy is the quickest because it gets and renews certificates automatically.

Caddyfile
dify.example.com {
    # Forward to the Dify web container's published port on localhost.
    reverse_proxy localhost:80
}

With DNS pointed at the server, Caddy fetches a certificate on first request, so your instance is reachable over HTTPS with no manual certificate steps. If you prefer nginx, add a server block that proxies to the same port and use certbot for the certificate.

Step 4: Back up the data

Two things hold your state: the database (apps, accounts, logs) and the volumes that store uploaded files and vector data. Back both up on a schedule. The command below dumps the Postgres database from its container; pair it with an archive of the docker volumes directory.

bash
dump the Dify database
$docker compose exec db pg_dump -U postgres dify > dify-backup.sql
archive the persisted files and vectors
$tar czf dify-volumes.tar.gz ./volumes
copy both off the server on a schedule
$

Step 5: Upgrade cleanly

Dify releases often. To upgrade, pull the latest repo, read the release notes for any migration steps, then pull new images and recreate the containers. Because your data lives in named volumes and the database, a normal upgrade keeps everything. Always take a backup first.

bash
back up first, then from the dify/docker directory:
$git pull
$docker compose pull
$docker compose up -d
Recreating dify-api, dify-worker, dify-web ... done
$
Check release notes for migrations
Most upgrades are a plain pull and recreate, but some versions add database migrations or new env keys. Skim the release notes before upgrading, and compare your .env against the latest .env.example so you do not miss a required new value.

Result: a production Dify instance you fully control, served over HTTPS behind a reverse proxy, with rotated secrets, scheduled backups, and a repeatable upgrade routine.

Watch related tutorials

Free weekly email

New guides in your inbox

Fresh step-by-step how-to guides as we publish them. One email a week, no more.

Tags
#self host dify#dify docker production#dify#docker compose#self-hosted#deployment