Skip to content

Bug: Satellite container fails to persist credentials due to volume permission mismatch #547

@bytefrostdev

Description

@bytefrostdev

Environment

  • DeployStack Version: Latest (as of Dec 6, 2025)
  • Deployment Method: Docker Compose (self-hosted)
  • Satellite Image: deploystack/satellite:latest

Description

When deploying DeployStack using Docker Compose following the official documentation, the satellite container fails to persist its credentials (backend.key.json) to the mounted volume. This causes the satellite to attempt re-registration on every container restart, which fails once the initial registration token has been used or expired.

Root Cause

The satellite container runs as user deploystack (uid=1001, gid=1001):

$ docker inspect deploystack/satellite:latest --format='{{.Config.User}}'
deploystack

However, when Docker creates the volume directory, it is owned by root:root:

$ docker run --rm -v deploystack_satellite_data:/data alpine ls -la /data/
total 8
drwxr-xr-x    2 root     root          4096 Dec  6 08:36 .
drwxr-xr-x    1 root     root          4096 Dec  6 10:43 ..

This results in a permission denied error when the satellite attempts to save its API key:

$ docker exec deploystack-satellite touch /app/persistent_data/test.txt
touch: cannot touch '/app/persistent_data/test.txt': Permission denied

Observed Behavior

  1. Satellite starts and successfully registers with backend
  2. Satellite receives API key: API key received and ready for authenticated communication
  3. Satellite fails to write backend.key.json to persistent storage (silently fails)
  4. On next restart, satellite finds no credentials and attempts re-registration
  5. Registration fails because token is already used/expired:
   ERROR: Satellite registration failed
   error_code: "invalid_registration_token"
   error_message: "Invalid registration token format..."
  1. Satellite enters restart loop

Expected Behavior

The satellite should be able to persist its credentials across container restarts without manual intervention.

Suggested Solutions

Option 1 (Recommended): Update docker-entrypoint.sh to fix permissions on startup:

#!/bin/sh
# Ensure persistent_data directory is writable
if [ -d "/app/persistent_data" ]; then
    # Check if we can write, if not and we're root, fix permissions
    if ! touch /app/persistent_data/.write_test 2>/dev/null; then
        echo "Warning: persistent_data not writable, this may cause issues"
    else
        rm -f /app/persistent_data/.write_test
    fi
fi
exec "$@"

Option 2: Document the workaround in self-hosted documentation and docker-compose.yml

Option 3: Add init container or volume configuration to docker-compose.yml examples

Current Workaround

Users must manually fix volume permissions before starting the satellite:

# Find the correct volume name
docker volume ls | grep satellite

# Fix permissions (adjust volume name as needed)
docker run --rm -v deploystack_deploystack_satellite_data:/data alpine chown -R 1001:1001 /data

# Restart satellite
docker compose restart satellite

Impact

This bug affects all self-hosted Docker Compose deployments. Users following the official documentation will encounter a broken satellite that cannot maintain persistent registration, requiring manual intervention and generation of new registration tokens.

Logs

[2025-12-06 10:49:25.705 +0000] INFO: No persistent satellite data found - will proceed with registration
    operation: "persistent_data_not_found"
    file_path: "/app/persistent_data/backend.key.json"
[2025-12-06 10:49:25.763 +0000] INFO: Satellite registered successfully: bytefrost-satellite-001
[2025-12-06 10:49:25.763 +0000] INFO: API key received and ready for authenticated communication

# After restart (credentials not persisted):
[2025-12-06 10:52:13.873 +0000] INFO: No persistent satellite data found - will proceed with registration
[2025-12-06 10:52:13.880 +0000] ERROR: Satellite registration failed
    error_code: "invalid_registration_token"

Additional Context

  • The backend.key.json file is successfully created once permissions are fixed
  • The satellite works correctly after the permission fix
  • This is a critical issue for self-hosted deployments as it breaks the core registration flow

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions