Storage and attachments
PostgreSQL stores Storage object metadata and application file references.
Separate object records from file bytes
PostgreSQL stores Storage object metadata and application file references. The Storage backend holds the actual bytes. Both belong to the same instance and backup point. The full filesystem profile persists bytes in the pinned upstream docker/volumes/storage directory; a configured S3-compatible backend needs a separate raw backend snapshot. Ephemeral container files are not durable Storage. Watch capacity for database, attachments and backup copies and keep backups off the active Storage disk.
Verify authorized access
Private page and issue files pass application authorization before the service generates an allowed download. Publishing a page exposes files only within its published set through signed URLs; it does not make the bucket public or open the private application route. A stored object existing on disk does not prove its metadata, policies, encryption key or application permissions are correct. With a demo account, upload and download a file and compare its SHA-256. Repeat after restoration for each bucket used by the instance.
Recover a missing or inaccessible file
Run the Supabase verifier, check the correct stack and service-role configuration, then compare object records with the raw backend bytes and preserved keys. Correct the Storage service, policy or configuration failure before retrying. Never delete a non-empty avatars bucket to clear a readiness warning. Restoring database records alone cannot restore bytes. For S3 restoration, restore the raw backend snapshot rather than reimporting through /storage/v1/s3, which can create conflicting metadata.
pnpm verify:supabase --db-url "$SUPABASE_DB_URL" \
--supabase-url "$MINDDY_PUBLIC_SUPABASE_URL" \
--service-role-key "$SUPABASE_SERVICE_ROLE_KEY"
Docker Desktop filesystem Storage
On the tested macOS Docker Desktop profile, a host bind mount returned ENOTSUP when Storage wrote extended attributes. A new Linux named volume avoided that failure. For a new installation with no object bytes, the following persistent override replaces only the Storage mount. Keep RESTORE_OVERRIDE in the installed Compose context. Do not switch an existing populated mount to an empty volume or overwrite an existing restore override: stop writes and preserve its bytes using the backup and restoration procedures first.
: "${RESTORE_OVERRIDE:=/etc/minddy/storage-volume.yml}"
export RESTORE_OVERRIDE
test ! -e "$RESTORE_OVERRIDE"
export STORAGE_VOLUME=minddy-filesystem-storage
if docker volume inspect "$STORAGE_VOLUME" >/dev/null 2>&1; then
echo "Refusing to replace an existing Storage volume." >&2
exit 1
fi
cat > "$RESTORE_OVERRIDE" <<EOF
services:
storage:
volumes:
- $STORAGE_VOLUME:/var/lib/storage
volumes:
$STORAGE_VOLUME:
EOF
# Apply this overlay with the installed Compose context before the first start.