Skip to content

feat(mount): customizable uid/gid/mode for volume mounts#101

Open
AminDhouib wants to merge 5 commits into
canaryfrom
port/upr-2517
Open

feat(mount): customizable uid/gid/mode for volume mounts#101
AminDhouib wants to merge 5 commits into
canaryfrom
port/upr-2517

Conversation

@AminDhouib

Copy link
Copy Markdown
Member

Summary

Adds optional Unix ownership (uid/gid) and permission mode to volume / bind / file mounts, so containers running as a non-root user can own their mounted data. After a mount with ownership set is created or updated, dokploy applies chown/chmod to the target (bind path, file path, or a one-shot alpine container for named volumes) on the local or remote server.

  • packages/server/src/db/schema/mount.ts: add nullable uid (integer), gid (integer), mode (text) columns; expose them on apiCreateMount; mode validated as octal (/^[0-7]{3,4}$/).
  • packages/server/src/services/mount.ts: applyMountPermissions() (+ hasOwnership / buildChownArg helpers) runs chown/chmod for bind/file/volume mounts; invoked from createMount / updateMount when ownership is set.
  • apps/dokploy/components/dashboard/application/advanced/volumes/{add-volumes,update-volume,show-volumes}.tsx + new components/shared/permission-mode.tsx: UID/GID/mode inputs and labels in the volume UI.
  • apps/dokploy/drizzle/0182_sturdy_vision.sql (+ snapshot/journal): migration adding the three mount columns.

Ports Dokploy#2517 by @divaltor (feature) with migration + octal validation by @Siumauricio; authorship preserved via cherry-pick, migration regenerated locally and co-credited.
Addresses Dokploy#497.

Adaptations

  • Migration renumbered. Upstream's generated 0175_careless_marvex.sql / snapshot / journal were dropped; the migration was regenerated against the fork's canary chain and renumbered to slot 0182 (when=1784005000000) so it does not collide with sibling migration PRs. The SQL is identical (ALTER TABLE "mount" ADD COLUMN "uid"/"gid"/"mode").
  • Columns land on the mount table, not applications — no interaction with the 100-column ceiling, no relational-query changes.
  • services/mount.ts merged cleanly onto the fork's rewritten version (which already provides getServerId / getBaseFilesPath); the ported applyMountPermissions reuses them unchanged.

Merge-order note

Carries drizzle migration slot 0182. Merge after fork #11/#12 (slots 0175/0176) and after the sibling PR holding slot 0181; sibling migration PRs conflict only in apps/dokploy/drizzle/meta/_journal.json — keep both entries, idx-ordered.

Verification

  • pnpm --filter=dokploy run typecheck passes on this branch.

divaltor and others added 5 commits July 12, 2026 16:12
- Updated the `mode` field in the mount schema to require a regex validation for octal values, ensuring it matches formats like 755 or 0644.

(cherry picked from commit 99fed39)
Regenerated the drizzle migration locally against the fork's canary chain
(renumbered from generated 0175 to slot 0182, when=1784005000000) so it does
not collide with sibling migration PRs. Adds nullable uid/gid/mode columns to
the mount table backing the volume ownership/permissions feature.

Co-authored-by: Mauricio Siu <siumauricio@icloud.com>
The uid/gid/mode form fields use `z.preprocess`, whose `z.input` is `unknown`
in zod 4; `@hookform/resolvers` 5 then infers a resolver input type that does
not match `useForm<AddMount>` (the `z.output`), so the discriminated-union
form fails `tsc`. Cast the resolver to the form's value type in
add-volumes.tsx and update-volume.tsx. Runtime behaviour is unchanged.
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.

3 participants