Self-host
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 composecommand, on the machine that serves Dezfil. - A folder: the
dezfilfolder from Install, or a new one. It holds the Compose file and its keys. - For the key:
openssl, which makes a random encryption key.
1. Note what your instance runs with
Section titled “1. Note what your instance runs with”On a new machine, go on with step 2. If Dezfil already runs here, note its key and its variables before you replace anything:
- Sign in as an admin, open Settings > System, and find the Encryption key row in Server settings.
- List the container’s image and variables:
docker inspect --format '{{println .Config.Image}}{{range .Config.Env}}{{println .}}{{end}}' dezfilThe 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_KEYvalue in the list. - Not created yet: a new one, as step 3 makes it.
2. Write the Compose file
Section titled “2. Write the Compose file”In the dezfil folder, save this file as 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-dataimage: ghcr.io/dezfil/dezfilruns the latest release. To stay on one version, add its tag, as inghcr.io/dezfil/dezfil:<VERSION>, and change it when you upgrade.127.0.0.1:3000:3000serves Dezfil on port 3000 of this machine only. To serve it under your domain, see Reverse proxy and HTTPS.dezfil-data:/datakeeps everything Dezfil stores in thedezfil-datavolume.name: dezfil-datakeeps that exact name; without it, Compose adds the folder’s name, as indezfil_dezfil-data.env_file: .envpasses the variables you write in step 3 to Dezfil.restart: unless-stoppedstarts Dezfil again after a crash and whenever Docker starts, unless you stopped it withdocker compose stop.healthcheckasks/api/healthfrom 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.loggingcaps 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.
3. Make the keys file
Section titled “3. Make the keys file”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:
printf 'DEZFIL_SECRET_KEY=%s\n' "$(openssl rand -hex 32)" > .envchmod 600 .envDEZFIL_SECRET_KEYencrypts the passwords of saved database connections and the service addresses an admin saves in Settings. It takes 64 hex characters.openssl rand -hex 32makes a random key of that length.chmod 600 .envlets 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:
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.
4. Start Dezfil
Section titled “4. Start Dezfil”docker compose up -dThe 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:
docker inspect --format '{{.State.Health.Status}}' dezfilhealthystarting 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.
5. Check the keys
Section titled “5. Check the keys”- Sign in as an admin and open Settings > System.
- In Server settings, find the Encryption key row. You should see Set, with the source Environment.
- 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.
6. Check the restart policy
Section titled “6. Check the restart policy”docker inspect --format '{{.HostConfig.RestartPolicy.Name}}' dezfilunless-stoppedDocker restarts Dezfil only while Docker itself runs. On Linux with systemd, make Docker start when the machine boots:
sudo systemctl enable docker.service containerd.serviceA 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.
Keep the key you have
Section titled “Keep the key you have”A volume that holds data may hold a key Dezfil made, as secret.key. Everything it encrypted needs that same key. Print it:
docker run --rm -v dezfil-data:/data:ro --entrypoint cat ghcr.io/dezfil/dezfil /data/secret.key<64_HEX_CHARACTERS>-v dezfil-data:/data:romounts the volume read-only.--entrypoint cat ghcr.io/dezfil/dezfil /data/secret.keyprints 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.
Troubleshooting
Section titled “Troubleshooting”Compose says “env file … not found”
Section titled “Compose says “env file … not found””Make the keys file of step 3 in the folder that holds compose.yaml, then start again.
The health status reads unhealthy
Section titled “The health status reads unhealthy”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.
Next steps
Section titled “Next steps”- Back up and restore: copy the
dezfil-datavolume, and keep.envapart from it. - Upgrade: move to a new version and keep your data.
- Reverse proxy and HTTPS: serve Dezfil under your domain.
- Everyday commands: stop, start and read the logs.
- Configuration: add other settings to
.envorcompose.yaml.
7439201b