Skip to content

Filesystem Layout

dockmesh treats the filesystem as the source of truth. Knowing where things live helps with backups, migrations, and debugging.

/opt/dockmesh/ # DATA_DIR root (configurable)
├── data/
│ ├── dockmesh.db # SQLite: users, roles, audit, CA
│ ├── dockmesh.db-wal # SQLite write-ahead log
│ ├── dockmesh.db-shm # SQLite shared memory
│ └── ca-passphrase # CA passphrase file (mode 600, optional)
├── stacks/ # STACKS_ROOT (configurable)
│ ├── <host-name>/
│ │ ├── <stack-name>/
│ │ │ ├── compose.yaml # Source of truth for the stack
│ │ │ ├── .env # Stack environment
│ │ │ └── .dockmesh/ # dockmesh-managed metadata
│ │ │ ├── state.json # Last-known deploy state
│ │ │ └── migration.lock # Present during stack migration
│ │ └── ...
│ └── ...
├── backups/ # Local backup target default
│ └── <job-name>/
│ ├── 2026-04-15T02-00.tar.age
│ ├── 2026-04-14T02-00.tar.age
│ └── ...
├── caddy/ # Embedded Caddy data (when enabled)
│ ├── config/
│ ├── data/ # Let's Encrypt certs live here
│ └── logs/
└── grype/ # Vulnerability database (when enabled)
└── db/
└── ...

Must back up:

  • data/dockmesh.db — entire dockmesh state (users, roles, CA key, audit log, config)
  • stacks/ — all compose files + env files

Should back up:

  • caddy/data/ — Let’s Encrypt certs (can be re-issued but saves rate limits)

Can skip:

  • grype/db/ — regenerates from the internet
  • backups/ — you don’t want backups of backups

Each stack lives at stacks/<host>/<stack>/. The host directory matches the dockmesh host name; for single-host setups, use local as a convention.

Inside a stack directory:

FilePurposeManaged by
compose.yamlCompose definitionYou (or Git)
.envEnvironment vars for ${VAR} interpolationYou or dockmesh
.dockmesh/state.jsonDeploy history, image digests, healthdockmesh (read-only for you)
Any other fileMounted configs, certsYou

You can also put any other file in the stack directory — dockmesh ignores files it doesn’t recognize, and they can be referenced from your compose.yaml as bind mounts:

services:
nginx:
volumes:
- ./nginx.conf:/etc/nginx/nginx.conf:ro

dockmesh doesn’t own these but interacts with them:

PathContents
/var/lib/docker/volumes/Docker named volumes (your data!)
/var/lib/docker/containers/Container runtime state
/var/lib/docker/overlay2/Image layers
/var/run/docker.sockDocker daemon socket

Don’t manually modify /var/lib/docker/. Use dockmesh’s UI or docker CLI.

WhatWhere
dockmesh server logssystemd journal (journalctl -u dockmesh)
Agent logssystemd journal (journalctl -u dockmesh-agent) on each agent host
Container logs/var/lib/docker/containers/<id>/<id>-json.log — but access via dockmesh UI
Caddy access logs/opt/dockmesh/caddy/logs/
Audit login dockmesh.db — use UI or API
PathOwnerModeWhy
/opt/dockmeshroot700Contains CA key + secrets
/opt/dockmesh/dataroot700DB protection
/opt/dockmesh/data/*.dbroot600DB files readable only by root
/opt/dockmesh/stacksroot755Compose files readable, writable by root only

Set env vars to use different paths:

/etc/systemd/system/dockmesh.service
Environment="DOCKMESH_DATA_DIR=/var/lib/dockmesh"
Environment="DOCKMESH_STACKS_ROOT=/srv/docker"

/srv/docker is a common alternative if you want stacks on a separate disk.

Inside Docker (when running dockmesh itself in a container)

Section titled “Inside Docker (when running dockmesh itself in a container)”

The paths move to container-local:

volumes:
- dockmesh-data:/opt/dockmesh/data
- /opt/dockmesh/stacks:/opt/dockmesh/stacks # host mount so you can edit from host
- /var/run/docker.sock:/var/run/docker.sock

Using a named volume for data means the DB stays on container restart. Using a bind mount for stacks means you can edit compose files from the host.