Skip to content
DezfilDocsv0.1.0

Docker Compose

Run Dezfil as a lasting instance with Docker Compose: the data in a named volume, the keys in a file, a restart policy and a health check.

Turn the quick start into an instance that lasts: its keys in a file of their own, a health check Docker reads, logs that stay small, and a start after every reboot.

  • You need: Docker with the docker compose command, on the machine that serves Dezfil.
  • A folder: the dezfil folder from Install, or a new one. It holds the Compose file and its keys.
  • For the key: openssl, which makes a random encryption key.

On a new machine, go on with step 2. If Dezfil already runs here, note its key and its variables before you replace anything:

  1. Sign in as an admin, open Settings > System, and find the Encryption key row in Server settings.
  2. List the container’s image and variables:
Terminal
docker inspect --format '{{println .Config.Image}}{{range .Config.Env}}{{println .}}{{end}}' dezfil

The first line is the image. If it names a version, as in ghcr.io/dezfil/dezfil:0.1.0, give image: that name in step 2, so Dezfil keeps its version. The other lines hold the image’s own variables too, such as PATH and DEZFIL_DATA_DIR, and the ones you set, with -e or under environment:.

The Encryption key row says which key to use in step 3:

  • secret.key in the data folder: the volume’s key, which Keep the key you have prints.
  • Set, with the source Environment: the DEZFIL_SECRET_KEY value in the list.
  • Not created yet: a new one, as step 3 makes it.

In the dezfil folder, save this file as compose.yaml:

compose.yaml
services:
dezfil:
image: ghcr.io/dezfil/dezfil
container_name: dezfil
ports:
- "127.0.0.1:3000:3000"
volumes:
- dezfil-data:/data
env_file: .env
restart: unless-stopped
healthcheck:
test: ["CMD", "node", "-e", "fetch('http://127.0.0.1:3000/api/health').then(r=>process.exit(r.ok?0:1)).catch(()=>process.exit(1))"]
interval: 30s
timeout: 5s
retries: 3
start_period: 30s
logging:
driver: json-file
options:
max-size: "10m"
max-file: "3"
volumes:
dezfil-data:
name: dezfil-data
  • image: ghcr.io/dezfil/dezfil runs the latest release. To stay on one version, add its tag, as in ghcr.io/dezfil/dezfil:<VERSION>, and change it when you upgrade.
  • 127.0.0.1:3000:3000 serves Dezfil on port 3000 of this machine only. To serve it under your domain, see Reverse proxy and HTTPS.
  • dezfil-data:/data keeps everything Dezfil stores in the dezfil-data volume. name: dezfil-data keeps that exact name; without it, Compose adds the folder’s name, as in dezfil_dezfil-data.
  • env_file: .env passes the variables you write in step 3 to Dezfil.
  • restart: unless-stopped starts Dezfil again after a crash and whenever Docker starts, unless you stopped it with docker compose stop.
  • healthcheck asks /api/health from inside the container every 30 seconds. After three failures in a row, Docker marks the container unhealthy, but it does not restart it for that.
  • logging caps the container’s logs at three files of 10 MB each, so a long-running instance does not fill the disk.

If you used the Compose tab of Install, replace its compose.yaml with this one. Both use the dezfil-data volume, so your data stays.

If step 1 gave you a key, write it into .env as the line DEZFIL_SECRET_KEY=<64_HEX_CHARACTERS> and run chmod 600 .env, in place of the commands below. Otherwise make a new key:

Terminal
printf 'DEZFIL_SECRET_KEY=%s\n' "$(openssl rand -hex 32)" > .env
chmod 600 .env
  • DEZFIL_SECRET_KEY encrypts the passwords of saved database connections and the service addresses an admin saves in Settings. It takes 64 hex characters.
  • openssl rand -hex 32 makes a random key of that length.
  • chmod 600 .env lets only your user read the file.

With a new key in .env from the first start, a copy of the volume alone cannot read those passwords.

Add the other variables you noted in step 1, one NAME=value line each, or put them under environment: in compose.yaml as Configuration shows. To turn on the assistant, add its key to .env:

.env
DEZFIL_SECRET_KEY=<64_HEX_CHARACTERS>
ANTHROPIC_API_KEY=<YOUR_ANTHROPIC_KEY>

For OpenAI, the line is OPENAI_API_KEY=<YOUR_OPENAI_KEY>. Set up the assistant covers the models and how to check that it answers.

When you change .env later, run docker compose up -d. Compose replaces the container and keeps the volume.

Terminal
docker compose up -d

The first start downloads the image, which takes a few minutes.

If Dezfil runs from Install’s Docker command, Compose stops at The container name "/dezfil" is already in use. Remove that container with docker rm -f dezfil, which keeps the volume, and run the command again. Compose then says the dezfil-data volume “already exists but was not created by Docker Compose”, and uses it all the same.

About a minute after Dezfil starts, check its health:

Terminal
docker inspect --format '{{.State.Health.Status}}' dezfil
Output
healthy

starting means the first check has not passed yet. Ask again after 30 seconds.

Then open http://localhost:3000. On a new volume, Dezfil asks for the first account, which becomes the admin: see First run. Behind a reverse proxy, the proxy’s address changes with Compose: set DEZFIL_TRUSTED_PROXIES again as Trust the proxy shows.

  1. Sign in as an admin and open Settings > System.
  2. In Server settings, find the Encryption key row. You should see Set, with the source Environment.
  3. If you added an assistant key, the Anthropic credential or OpenAI credential row shows Set too.

Set shows that the variable reached Dezfil. A key of the wrong form also shows Set: Troubleshooting says how it shows itself.

Terminal
docker inspect --format '{{.HostConfig.RestartPolicy.Name}}' dezfil
Output
unless-stopped

Docker restarts Dezfil only while Docker itself runs. On Linux with systemd, make Docker start when the machine boots:

Terminal
sudo systemctl enable docker.service containerd.service

A restart ends the tool and workflow runs in progress. When Dezfil starts again, it records that the server stopped them and repeats nothing, so people run them again.

A volume that holds data may hold a key Dezfil made, as secret.key. Everything it encrypted needs that same key. Print it:

Terminal
docker run --rm -v dezfil-data:/data:ro --entrypoint cat ghcr.io/dezfil/dezfil /data/secret.key
Output
<64_HEX_CHARACTERS>
  • -v dezfil-data:/data:ro mounts the volume read-only.
  • --entrypoint cat ghcr.io/dezfil/dezfil /data/secret.key prints the key file with Dezfil’s image.

Use that value in step 3. The volume keeps its secret.key, so its backups still hold that key. If you see cat: /data/secret.key: No such file or directory instead, the volume holds no key: read the Encryption key row again, as step 1 says.

Make the keys file of step 3 in the folder that holds compose.yaml, then start again.

Run curl http://localhost:3000/api/health. Internal Server Error means Dezfil did not start: Start-up names the causes. An answer of {"status":"unready", ...} gives a reason, which Health answers “unready” explains.

Settings says “The instance’s encryption key cannot read the saved address. Save it again.”

Section titled “Settings says “The instance’s encryption key cannot read the saved address. Save it again.””

The key in .env is not the one that saved the address: it changed, or it has another form than 64 hex characters. With a key of another form, saving the address again fails with “An unexpected server error occurred.”, and the logs say “DEZFIL_SECRET_KEY must be 64 hex characters (32 bytes).”

Put the earlier key back in .env, the value you kept or the volume’s secret.key, then run docker compose up -d. A new key from openssl rand -hex 32 is right only when Dezfil never saved anything with a key. If the earlier key is lost, Back up and restore says what to save again.

Dezfil · Apache-2.0docs from 7439201b