From c07aaa77fc46e9c0214397153cfd276c7de0c80a Mon Sep 17 00:00:00 2001 From: Dries Peeters Date: Fri, 28 Nov 2025 22:47:55 +0100 Subject: [PATCH] Fix data directory permission errors in Docker container - Change CONFIG_DIR from relative 'data' to absolute '/data' path in installation.py This fixes PermissionError when trying to create /app/data instead of using the mounted volume at /data - Update telemetry marker file paths to use absolute /data path for consistency - Add ensure_data_directory() function to entrypoint_fixed.sh to: - Create /data directory if it doesn't exist - Set proper permissions (755) on /data - Attempt to set ownership to current user - Create /data/uploads subdirectory This resolves the 'Permission denied: data' errors when accessing /admin/settings and ensures the data volume is properly initialized at container startup. --- app/utils/installation.py | 2 +- app/utils/telemetry.py | 6 +++--- docker/entrypoint_fixed.sh | 43 ++++++++++++++++++++++++++++++++++++++ 3 files changed, 47 insertions(+), 4 deletions(-) diff --git a/app/utils/installation.py b/app/utils/installation.py index 375c791..59a2fcd 100644 --- a/app/utils/installation.py +++ b/app/utils/installation.py @@ -16,7 +16,7 @@ from typing import Dict, Optional class InstallationConfig: """Manages installation-specific configuration""" - CONFIG_DIR = "data" + CONFIG_DIR = "/data" CONFIG_FILE = "installation.json" def __init__(self): diff --git a/app/utils/telemetry.py b/app/utils/telemetry.py index 86c4256..6332c29 100644 --- a/app/utils/telemetry.py +++ b/app/utils/telemetry.py @@ -302,7 +302,7 @@ def send_health_ping() -> bool: return send_telemetry_ping(event_type="health") -def should_send_telemetry(marker_file: str = "data/telemetry_sent") -> bool: +def should_send_telemetry(marker_file: str = "/data/telemetry_sent") -> bool: """ Check if telemetry should be sent based on marker file. @@ -318,7 +318,7 @@ def should_send_telemetry(marker_file: str = "data/telemetry_sent") -> bool: return not os.path.exists(marker_file) -def mark_telemetry_sent(marker_file: str = "data/telemetry_sent") -> None: +def mark_telemetry_sent(marker_file: str = "/data/telemetry_sent") -> None: """ Create a marker file indicating telemetry has been sent. @@ -360,7 +360,7 @@ def check_and_send_telemetry() -> bool: if not is_telemetry_enabled(): return False - marker_file = os.getenv("TELEMETRY_MARKER_FILE", "data/telemetry_sent") + marker_file = os.getenv("TELEMETRY_MARKER_FILE", "/data/telemetry_sent") if should_send_telemetry(marker_file): success = send_install_ping() diff --git a/docker/entrypoint_fixed.sh b/docker/entrypoint_fixed.sh index c770bef..3953177 100644 --- a/docker/entrypoint_fixed.sh +++ b/docker/entrypoint_fixed.sh @@ -663,6 +663,46 @@ except Exception as e: return 0 } +# Function to ensure data directory permissions +ensure_data_directory() { + log "Ensuring /data directory exists and has proper permissions..." + + # Create /data directory if it doesn't exist + if [ ! -d "/data" ]; then + log "Creating /data directory..." + mkdir -p /data + fi + + # Try to set permissions (best effort - may fail if we don't have permission) + # This is useful when the volume is mounted with different ownership + if [ -w "/data" ]; then + log "Setting permissions on /data directory..." + chmod 755 /data 2>/dev/null || true + + # Get current user info + CURRENT_UID=$(id -u 2>/dev/null || echo "1000") + CURRENT_GID=$(id -g 2>/dev/null || echo "1000") + + # Try to change ownership if we have permission (requires root or matching ownership) + if [ "$CURRENT_UID" = "0" ] || [ -O "/data" ]; then + log "Setting ownership of /data to current user (UID: $CURRENT_UID, GID: $CURRENT_GID)..." + chown "$CURRENT_UID:$CURRENT_GID" /data 2>/dev/null || true + else + log "Cannot change ownership of /data (not root and not owner), but directory is writable" + fi + + # Ensure subdirectories exist + mkdir -p /data/uploads 2>/dev/null || true + chmod 755 /data/uploads 2>/dev/null || true + + log "✓ /data directory setup complete" + else + log "⚠ /data directory is not writable - this may cause issues" + log "Current user: $(whoami) (UID: $(id -u 2>/dev/null || echo 'unknown'))" + log "Directory permissions: $(ls -ld /data 2>/dev/null || echo 'cannot read')" + fi +} + # Function to verify database integrity verify_database_integrity() { local db_url="$1" @@ -851,6 +891,9 @@ main() { log "Database URL: $db_url" + # Ensure data directory has proper permissions + ensure_data_directory + # Wait for database to be available if ! wait_for_database "$db_url"; then log "✗ Failed to connect to database"