Skip to content

docs(docker): document the bind-mount permission fix for fresh deploys - #1252

Open
Saraswat123 wants to merge 1 commit into
moltis-org:mainfrom
Saraswat123:fix/293-docker-compose-db-permissions
Open

docs(docker): document the bind-mount permission fix for fresh deploys#1252
Saraswat123 wants to merge 1 commit into
moltis-org:mainfrom
Saraswat123:fix/293-docker-compose-db-permissions

Conversation

@Saraswat123

Copy link
Copy Markdown
Contributor

Summary

Closes #293.

On a fresh checkout, docker compose up (or docker run with bind mounts, per the docs' own example) can fail with:

moltis | I thread 'main' (1) panicked at /build/crates/gateway/src/server.rs:1475:14:
moltis | I failed to open moltis. db: Database(SqliteError { code: 14, message: "unable to open database file" })

Root cause

Dockerfile:

RUN ... chown -R moltis:moltis /home/moltis/.config /home/moltis/.moltis /home/moltis/.npm
USER moltis
...
ENTRYPOINT ["moltis"]

The image is chowned to the non-root moltis user at build time. But examples/docker-compose.yml (and the docker run example in docs/src/docker.md) bind-mount ./config and ./data over those exact paths at container start — replacing the image's directories entirely. Docker auto-creates the host-side source directories as root:root the first time they're bind-mounted (standard Docker Engine behavior on Linux), which shadows the image's chown. The non-root moltis user then has no write access to its own runtime data directory, and the SQLite open panics.

Named volumes (the docker run example in the README/Quick Start) don't hit this — Docker leaves an existing named volume's ownership alone. Only bind-mount source directories get created as root:root on first use, so this specifically affects the bind-mount path that both examples/docker-compose.yml and docs/src/docker.md's "Volume Mounts" section recommend for editing config files directly on the host.

The fix

Documented a one-time fix at both affected examples (examples/docker-compose.yml's header comment, and docs/src/docker.md's "Volume Mounts" section, right where the bind-mount example is):

mkdir -p ./config ./data
docker run --rm --user root --entrypoint chown \
  -v ./config:/home/moltis/.config/moltis \
  -v ./data:/home/moltis/.moltis \
  ghcr.io/moltis-org/moltis:latest \
  -R moltis:moltis /home/moltis/.config /home/moltis/.moltis

Uses the image's own moltis username rather than a hardcoded UID (the Dockerfile's useradd --create-home --user-group moltis doesn't pin a numeric UID, so it isn't guaranteed stable across image rebuilds).

Considered but not done here

A code-level fix — an entrypoint script that starts as root, chowns the mounted volumes, then drops to moltis via gosu/su-exec before exec'ing (the pattern official images like postgres/grafana use for exactly this) — would fix this without requiring users to run anything manually. I didn't do that in this PR: moltis ships 4 Dockerfile variants (Dockerfile, Dockerfile.alpine, Dockerfile.slim, Dockerfile.openshift), and the OpenShift one is explicitly designed to never run as root at all (arbitrary-UID restricted clusters per the README's own description), so a blanket root-then-drop-privileges entrypoint change needs per-variant design care I didn't want to bundle into a docs fix. Happy to scope that as a follow-up if you'd rather have the code-level fix instead of/in addition to this.

Validation

Completed

  • Root cause traced precisely against the current Dockerfile's chown/USER/ENTRYPOINT ordering and examples/docker-compose.yml's bind-mount paths — confirmed the shadowing mechanism, not guessed
  • Confirmed no prior fix or discussion exists (searched all open/closed PRs and issues for "database file", "unable to open", DB-permission-related terms — nothing)
  • Docs-only change: no Rust code touched, taplo/biome/cargo fmt not applicable

Remaining

  • I could not verify the exact docker run/docker compose run chown command end-to-end against a live container in this environment (see Manual QA below) — would appreciate a maintainer or the original reporter (@temobard) confirming the exact command works as written before merge, in case there's a subtlety in --entrypoint chown argument ordering I got wrong

Manual QA

I attempted to reproduce the bug live and verify the fix against the real published image (ghcr.io/moltis-org/moltis:latest) — pulled it, ran with bind mounts, intended to confirm the panic, then confirm the documented fix resolves it. Partway through, Docker Desktop's local VM state got corrupted (unrelated: this session hit local disk exhaustion from an unrelated cargo build earlier, which appears to have corrupted containerd's metadata DB mid-write during the image pull). A plain app restart didn't recover it, and a full Docker Desktop reset would wipe my other local images/containers, so I didn't do that unilaterally.

The fix as documented is derived directly from reading the Dockerfile and compose file, not from a live repro. Flagging this honestly rather than claiming a verification I didn't complete — if the docker run --user root --entrypoint chown ... invocation has an argument-ordering issue I couldn't catch by inspection alone, that's exactly what I'd want a live-tested confirmation to catch before merge.

On a fresh checkout, `docker compose up` (or `docker run` with bind
mounts) can fail with:

  failed to open moltis.db: Database(SqliteError { code: 14, message:
  "unable to open database file" })

Root cause: the Dockerfile chowns /home/moltis/.config and
/home/moltis/.moltis to the non-root moltis user at *image build time*,
before USER moltis, ENTRYPOINT ["moltis"]. But a bind mount replaces
those directories entirely at container start. Docker auto-creates the
host-side ./config and ./data directories as root:root the first time
they're bind-mounted, which shadows the image's chown and leaves the
non-root moltis user unable to write to its own data directory.

Document a one-time fix using the image's own `moltis` username (rather
than a hardcoded UID, which isn't guaranteed stable across image
rebuilds) in both examples/docker-compose.yml and docs/src/docker.md,
at the exact bind-mount example this affects.

Closes moltis-org#293.

Note: I could not verify this end-to-end against a live container in
this environment — Docker Desktop's local VM state got corrupted mid-session
(unrelated disk exhaustion while testing something else) and a plain
app restart didn't recover it; a full reset would wipe other local
images/containers, so I didn't do that unilaterally. The fix is derived
from reading the Dockerfile's chown/USER/ENTRYPOINT ordering and the
compose file's bind-mount paths directly, not from a live repro.
@greptile-apps

greptile-apps Bot commented Sep 1, 2026

Copy link
Copy Markdown
Contributor

Greptile Summary

This PR documents a one-time ownership repair for fresh Docker bind mounts so the non-root Moltis process can create its database and runtime files.

  • Adds an executable docker run ownership-fix example to the Docker volume documentation.
  • Adds equivalent first-run guidance to the example Compose file.
  • Explains why named volumes and image-internal ownership do not encounter the same bind-mount initialization issue.

Confidence Score: 5/5

The PR appears safe to merge because the documented commands match the image user, target paths, and Compose bind mounts.

The ownership repair runs as root inside the current image, resolves the existing moltis:moltis account, and recursively updates both bind-mounted configuration and data directories before startup.

Important Files Changed

Filename Overview
docs/src/docker.md Adds accurate, locally consistent bind-mount ownership guidance using the image’s own user and group names.
examples/docker-compose.yml Adds a compatible first-run Compose command that repairs ownership of both configured host directories.

Reviews (1): Last reviewed commit: "docs(docker): document the bind-mount pe..." | Re-trigger Greptile

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Bug]: No db file on fresh Docker Compose deployment

1 participant