Skip to content

[Bug]: /data/coolify parent-dir perms reset to 9999:root mode 2700 on container restart (v4.1.0) — breaks SSH deploy pipeline as non-root user #10401

Description

@leonvictorstaege

Bug Description

On Coolify container restart (v4.1.0, image ghcr.io/coollabsio/coolify:4.1.0 built 2026-05-18), the host directories /data/coolify and /data/coolify/applications get reset to 9999:root mode 2700.

This breaks the SSH-based deploy pipeline for users following Coolify's own Non-Root-User Setup (host user leon UID 1001, member of host group coolify GID 9999). The deploy command:

ssh leon@host.docker.internal "sudo echo '<base64>' | base64 -d | tee /data/coolify/applications/<uuid>/.env"

fails with Permission denied — not because the app dir itself is unreachable (it is owned by leon:leon mode 2700), but because leon cannot traverse the parent /data/coolify (mode 2700, group=root, owner=UID-9999-without-host-mapping).

Steps to Reproduce

  1. Configure Coolify host per documented Non-Root setup: host user leon (UID 1001), host group coolify (GID 9999), leon is member of coolify. /data/coolify set to 9999:coolify mode 2770 and dirs setgid.
  2. Confirm working SSH-deploy: tee /data/coolify/applications/<app-uuid>/.env from inside the Coolify container reaches the host as leon and succeeds.
  3. Restart the Coolify container: sudo docker restart coolify.
  4. Observe /data/coolify is now 9999:root mode 2700 (stat -c "%a %U:%G" /data/coolify).
  5. Trigger any deploy. It fails at the .env-write step with Permission denied.

Root Cause

The Coolify container init scripts appear to forcibly reset /data/coolify and /data/coolify/applications ownership/mode on startup. Previously these were 9999:coolify mode 2770 (setgid + group-rwx), allowing host group members to traverse. After v4.1.0 restart, mode collapses to 2700 (owner-only) and group resets to root, blocking the documented non-root SSH-deploy path.

The inner app dirs (/data/coolify/applications/<uuid>/) are not reset — they remain leon:leon. So the symptom looks like an app-dir bug but is actually parent-dir traversal blocking.

Environment

  • Coolify version: v4.0.0-beta.473 → v4.1.0 image (ghcr.io/coollabsio/coolify:4.1.0 2026-05-18)
  • Container restart that triggered onset: 2026-05-23 16:12 CEST. Last successful deploy: 2026-05-23 15:57 CEST.
  • Server OS: Ubuntu 24.04 LTS, systemd 255
  • Self-hosted on Hetzner

Temporary Fix

Restore the parent perms manually and add a watcher to re-apply on drift:

sudo chgrp coolify /data/coolify /data/coolify/applications
sudo chmod 2750 /data/coolify /data/coolify/applications

Defense-in-depth watcher (systemd timer 1min + cron 5min backup, both calling an idempotent repair script):

# /usr/local/sbin/coolify-perm-repair.sh
#!/bin/bash
set -e
TARGET_PERMS="2750"
TARGET_GROUP="coolify"
for dir in /data/coolify /data/coolify/applications; do
  [ -d "$dir" ] || continue
  current=$(stat -c "%a %G" "$dir")
  expected="$TARGET_PERMS $TARGET_GROUP"
  if [ "$current" != "$expected" ]; then
    chgrp "$TARGET_GROUP" "$dir"
    chmod "$TARGET_PERMS" "$dir"
    logger -t coolify-perm-repair "Repaired $dir: was [$current], now [$expected]"
  fi
done

Expected Behavior

  • Coolify container restart should NOT reset host-side /data/coolify ownership/mode.
  • If init scripts must enforce perms, they should match the documented Non-Root-User Setup: 9999:coolify mode 2770 (preserving setgid + group-traversal).

Related

Coolify Version

v4.0.0-beta.473 / image ghcr.io/coollabsio/coolify:4.1.0

Are you using Coolify Cloud?

No (self-hosted)

Operating System and Version (self-hosted)

Ubuntu 24.04 LTS

Additional Information

Diagnosis steps used:

  • sudo stat -c "%a %U:%G" /data/coolify — confirmed 2700 9999:root post-restart
  • sudo docker exec coolify sh -c "ssh -i ... leon@host.docker.internal 'touch /data/coolify/applications/<uuid>/.testwrite'" — reproduced Permission denied
  • Verified host has group coolify GID 9999 with leon as member (getent group coolify)
  • Independent confirmation: a different app on the same host (different UUID) recovered from the same Permission-denied loop within 30s of applying the chgrp+chmod fix — bug is global, not app-specific

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions