-
Notifications
You must be signed in to change notification settings - Fork 0
Storage Layout
github-actions[bot] edited this page Jun 19, 2026
·
1 revision
FileHarbor organises all files on disk under a configurable root directory (STORAGE_PATH, default ./storage).
storage/
├── defaults.fileharbor/ ← Built-in fallback images (shipped with repo)
│ ├── fileharbor_not_found.webp
│ ├── fileharbor_permission_denided.webp
│ ├── fileharbor_blocked.webp
│ ├── fileharbor_logo.webp
│ └── fileharbor_name_banner.webp
│
└── {client.domain | clientId}/ ← One directory per tenant
├── images/
│ └── {imageId}/
│ ├── original.webp ← Full-quality image
│ └── thumb.webp ← Thumbnail
└── avatars/
└── {externalUserId}/
├── original.webp ← Full-quality avatar
└── thumb.webp ← Thumbnail
The tenant directory name is:
-
client.domainif the client has a domain configured (e.g.example.com) -
client.id(UUID) as fallback
This allows human-readable paths when a domain is set.
StorageService enforces path safety on all operations:
-
validatePath()– Ensures the resolved path is insideSTORAGE_PATH. Blocks directory traversal attacks. -
sanitizePathComponent()– Strips..,/,\, and null bytes from path components. Dots (.) are allowed to support domain names likeexample.com.
Never construct storage paths manually — always use
StorageServicehelpers.
The storage/defaults.fileharbor/ directory contains images that are returned when an image cannot be served:
| File | When Served |
|---|---|
fileharbor_not_found.webp |
Image ID does not exist |
fileharbor_permission_denided.webp |
Image is private and requester lacks access |
These files are included in the repository and must be present at startup.
In production, mount the storage directory as a persistent volume:
volumes:
- fileharbor_storage:/data/storage
environment:
STORAGE_PATH: /data/storageThe container runs as UID/GID 1001. Ensure host directory permissions match:
sudo chown -R 1001:1001 /host/storage/path