2 Commits

11 changed files with 582 additions and 437 deletions

View File

@@ -1,5 +1,12 @@
# Changelog
## 2026-03-24 - 1.8.0 - feat(docs,web)
document cluster and erasure coding support and align UI storage provider naming
- expand the README with cluster mode, erasure coding, multi-drive configuration, and multi-node Docker Compose examples
- update web storage integration to use the renamed storage data provider interface and browser component
- bump runtime, UI, and tooling dependencies to newer compatible versions
## 2026-03-22 - 1.7.1 - fix(repo)
no changes to commit

View File

@@ -1,6 +1,6 @@
{
"name": "@lossless.zone/objectstorage",
"version": "1.7.1",
"version": "1.8.0",
"exports": "./mod.ts",
"nodeModulesDir": "auto",
"tasks": {
@@ -8,12 +8,12 @@
"dev": "pnpm run watch"
},
"imports": {
"@push.rocks/smartstorage": "npm:@push.rocks/smartstorage@^6.3.1",
"@push.rocks/smartbucket": "npm:@push.rocks/smartbucket@^4.3.0",
"@aws-sdk/client-s3": "npm:@aws-sdk/client-s3@^3.937.0",
"@push.rocks/smartstorage": "npm:@push.rocks/smartstorage@^6.3.2",
"@push.rocks/smartbucket": "npm:@push.rocks/smartbucket@^4.5.1",
"@aws-sdk/client-s3": "npm:@aws-sdk/client-s3@^3.1015.0",
"@api.global/typedrequest-interfaces": "npm:@api.global/typedrequest-interfaces@^3.0.19",
"@api.global/typedrequest": "npm:@api.global/typedrequest@^3.2.6",
"@api.global/typedserver": "npm:@api.global/typedserver@^8.3.1",
"@api.global/typedrequest": "npm:@api.global/typedrequest@^3.3.0",
"@api.global/typedserver": "npm:@api.global/typedserver@^8.4.6",
"@push.rocks/smartguard": "npm:@push.rocks/smartguard@^3.1.0",
"@push.rocks/smartjwt": "npm:@push.rocks/smartjwt@^2.2.1"
},

670
deno.lock generated

File diff suppressed because it is too large Load Diff

View File

@@ -1,6 +1,6 @@
{
"name": "@lossless.zone/objectstorage",
"version": "1.7.1",
"version": "1.8.0",
"description": "object storage server with management UI powered by smartstorage",
"main": "mod.ts",
"type": "module",
@@ -17,13 +17,13 @@
"license": "MIT",
"dependencies": {
"@api.global/typedrequest-interfaces": "^3.0.19",
"@design.estate/dees-catalog": "^3.48.0",
"@design.estate/dees-element": "^2.2.2"
"@design.estate/dees-catalog": "^3.49.0",
"@design.estate/dees-element": "^2.2.3"
},
"devDependencies": {
"@git.zone/tsbundle": "^2.9.0",
"@git.zone/tsdocker": "^2.0.0",
"@git.zone/tswatch": "^3.2.0"
"@git.zone/tsbundle": "^2.9.1",
"@git.zone/tsdocker": "^2.2.0",
"@git.zone/tswatch": "^3.3.0"
},
"pnpm": {
"onlyBuiltDependencies": [

67
pnpm-lock.yaml generated
View File

@@ -12,20 +12,20 @@ importers:
specifier: ^3.0.19
version: 3.0.19
'@design.estate/dees-catalog':
specifier: ^3.48.0
version: 3.48.0(@tiptap/pm@2.27.2)
specifier: ^3.49.0
version: 3.49.0(@tiptap/pm@2.27.2)
'@design.estate/dees-element':
specifier: ^2.2.2
version: 2.2.2
specifier: ^2.2.3
version: 2.2.3
devDependencies:
'@git.zone/tsbundle':
specifier: ^2.9.0
specifier: ^2.9.1
version: 2.9.1
'@git.zone/tsdocker':
specifier: ^2.0.0
version: 2.0.0
specifier: ^2.2.0
version: 2.2.0
'@git.zone/tswatch':
specifier: ^3.2.0
specifier: ^3.3.0
version: 3.3.0(@tiptap/pm@2.27.2)
packages:
@@ -66,8 +66,8 @@ packages:
'@configvault.io/interfaces@1.0.17':
resolution: {integrity: sha512-bEcCUR2VBDJsTin8HQh8Uw/mlYl2v8A3jMIaQ+MTB9Hrqd6CZL2dL7iJdWyFl/3EIX+LDxWFR+Oq7liIq7w+1Q==}
'@design.estate/dees-catalog@3.48.0':
resolution: {integrity: sha512-P+y8YkbxZyEwQOnDRjK5nU+CWamY9zCJpjVoydElwPMuz1P/jps/MOg2aKKbqzeghET+ZjjXUrOPYOSJ3YFwbQ==}
'@design.estate/dees-catalog@3.49.0':
resolution: {integrity: sha512-ZtHroyBZekv+jVSDmtGOzoGVI+EA55kd5EcSsNmUByxN3UMcFFeg62QRNzm3RHpz01u1Zfynm0bN9E44pk6FDQ==}
'@design.estate/dees-comms@1.0.30':
resolution: {integrity: sha512-KchMlklJfKAjQiJiR0xmofXtQ27VgZtBIxcMwPE9d+h3jJRv+lPZxzBQVOM0eyM0uS44S5vJMZ11IeV4uDXSHg==}
@@ -75,8 +75,8 @@ packages:
'@design.estate/dees-domtools@2.5.1':
resolution: {integrity: sha512-ojzRSkOpQvxpd4drCNF1wadvPwthI6xIJpYjBbOwlgxkFCrlgxlOxHzRKEVnj5wWeUPqykKhddKp33LKW9mydw==}
'@design.estate/dees-element@2.2.2':
resolution: {integrity: sha512-sfA01ClHpTQSDgxFqZlfWOF0OlWvx59S8rjPir3UERF+LgYTvxGlGofMkx1fUo1TE32/MR+LzejWnB6RA+16HQ==}
'@design.estate/dees-element@2.2.3':
resolution: {integrity: sha512-MpAvJPrJDTDad8hUtdOzMgMFRE7n84O7INhvSlkTTLB3b84j8EKjwfUCMErGAo7Bq5zfw4LG7NnKhLYXXXjkXA==}
'@design.estate/dees-wcctools@3.8.0':
resolution: {integrity: sha512-CC14iVKUrguzD9jIrdPBd9fZ4egVJEZMxl5y8iy0l7WLumeoYvGsoXj5INVkRPLRVLqziIdi4Je1hXqHt2NU+g==}
@@ -270,8 +270,8 @@ packages:
resolution: {integrity: sha512-JW1xjSv7UjAm2lwAQPxhCWs14wqs+UIq5FqIGUPuI6rrDBWIMT2d0gpP6iP6TqXqgm6XpBlfU4rHcHheUXzXbQ==}
hasBin: true
'@git.zone/tsdocker@2.0.0':
resolution: {integrity: sha512-tYmmo54NNl6G/HR4PFUn4QtpgEC66C6w4bXE2DIbpBFP3HHIlhjeRNrFPQY1TT+R52x3fYwK2Qx+4uO1cA+oXQ==}
'@git.zone/tsdocker@2.2.0':
resolution: {integrity: sha512-9/0aoojZG5rLS06eTiqCCY2lN2F21AKiBS7xLKsq/riKeclwoX/2j6HAoogv529qGNQ3XEKwKCcu28gOM8E52A==}
hasBin: true
'@git.zone/tsrun@2.0.1':
@@ -1040,6 +1040,9 @@ packages:
'@tsclass/tsclass@9.3.0':
resolution: {integrity: sha512-KD3oTUN3RGu67tgjNHgWWZGsdYipr1RUDxQ9MMKSgIJ6oNZ4q5m2rg0ibrgyHWkAjTPlHVa6kHP3uVOY+8bnHw==}
'@tsclass/tsclass@9.5.0':
resolution: {integrity: sha512-HwMVwkrBnEFMjwOsMkGwWN/q+XEczSpf4a/PBAXgkDdV6sXdxAMFXUH1tW8Y5ecuvXFYMvFry4X57MCCT7Dm8A==}
'@tybys/wasm-util@0.10.1':
resolution: {integrity: sha512-9tTaPJLSiejZKx+Bmog4uSubteqTvFrVrURwkmHixBo0G4seD0zUxp98E1DzUBJxLQ3NPwXrGKDiVjwx/DpPsg==}
@@ -2311,6 +2314,10 @@ packages:
symbol-tree@3.2.4:
resolution: {integrity: sha512-9QNk5KwDF+Bvz+PyObkmSYjI5ksVUYtjW7AU22r2NKcfLJcXp96hkDWU3+XndOsUb+AQ9QhfzfCT2O+CNWT5Tw==}
tagged-tag@1.0.0:
resolution: {integrity: sha512-yEFYrVhod+hdNyx7g5Bnkkb0G6si8HJurOoOEgC8B/O0uXLHlaey/65KRv6cuWBNhBgHKAROVpc7QyYqE5gFng==}
engines: {node: '>=20'}
threads@1.7.0:
resolution: {integrity: sha512-Mx5NBSHX3sQYR6iI9VYbgHKBLisyB+xROCBGjjWm1O9wb9vfLxdaGtmT/KCjUqMsSNW6nERzCW3T6H43LqjDZQ==}
@@ -2360,6 +2367,10 @@ packages:
resolution: {integrity: sha512-TeTSQ6H5YHvpqVwBRcnLDCBnDOHWYu7IvGbHT6N8AOymcr9PJGjc1GTtiWZTYg0NCgYwvnYWEkVChQAr9bjfwA==}
engines: {node: '>=16'}
type-fest@5.5.0:
resolution: {integrity: sha512-PlBfpQwiUvGViBNX84Yxwjsdhd1TUlXr6zjX7eoirtCPIr08NAmxwa+fcYBTeRQxHo9YC9wwF3m9i700sHma8g==}
engines: {node: '>=20'}
typescript@5.9.3:
resolution: {integrity: sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw==}
engines: {node: '>=14.17'}
@@ -2527,7 +2538,7 @@ snapshots:
'@api.global/typedrequest-interfaces': 3.0.19
'@api.global/typedsocket': 4.1.2(@push.rocks/smartserve@2.0.1)
'@cloudflare/workers-types': 4.20260312.1
'@design.estate/dees-catalog': 3.48.0(@tiptap/pm@2.27.2)
'@design.estate/dees-catalog': 3.49.0(@tiptap/pm@2.27.2)
'@design.estate/dees-comms': 1.0.30
'@push.rocks/lik': 6.3.1
'@push.rocks/smartdelay': 3.0.5
@@ -2594,10 +2605,10 @@ snapshots:
dependencies:
'@api.global/typedrequest-interfaces': 3.0.19
'@design.estate/dees-catalog@3.48.0(@tiptap/pm@2.27.2)':
'@design.estate/dees-catalog@3.49.0(@tiptap/pm@2.27.2)':
dependencies:
'@design.estate/dees-domtools': 2.5.1
'@design.estate/dees-element': 2.2.2
'@design.estate/dees-element': 2.2.3
'@design.estate/dees-wcctools': 3.8.0
'@fortawesome/fontawesome-svg-core': 7.2.0
'@fortawesome/free-brands-svg-icons': 7.2.0
@@ -2613,7 +2624,7 @@ snapshots:
'@tiptap/extension-typography': 2.27.2(@tiptap/core@2.27.2(@tiptap/pm@2.27.2))
'@tiptap/extension-underline': 2.27.2(@tiptap/core@2.27.2(@tiptap/pm@2.27.2))
'@tiptap/starter-kit': 2.27.2
'@tsclass/tsclass': 9.3.0
'@tsclass/tsclass': 9.5.0
apexcharts: 5.10.3
highlight.js: 11.11.1
ibantools: 4.5.1
@@ -2662,7 +2673,7 @@ snapshots:
- supports-color
- vue
'@design.estate/dees-element@2.2.2':
'@design.estate/dees-element@2.2.3':
dependencies:
'@design.estate/dees-domtools': 2.5.1
'@push.rocks/isounique': 1.0.5
@@ -2677,7 +2688,7 @@ snapshots:
'@design.estate/dees-wcctools@3.8.0':
dependencies:
'@design.estate/dees-domtools': 2.5.1
'@design.estate/dees-element': 2.2.2
'@design.estate/dees-element': 2.2.3
'@push.rocks/smartdelay': 3.0.5
lit: 3.3.2
transitivePeerDependencies:
@@ -2824,7 +2835,7 @@ snapshots:
- supports-color
- vue
'@git.zone/tsdocker@2.0.0':
'@git.zone/tsdocker@2.2.0':
dependencies:
'@push.rocks/lik': 6.3.1
'@push.rocks/npmextra': 5.3.3
@@ -3366,7 +3377,7 @@ snapshots:
'@push.rocks/smartntml@2.0.8':
dependencies:
'@design.estate/dees-element': 2.2.2
'@design.estate/dees-element': 2.2.3
'@happy-dom/global-registrator': 15.11.7
'@push.rocks/smartpromise': 4.2.3
fake-indexeddb: 6.2.5
@@ -3541,7 +3552,7 @@ snapshots:
'@push.rocks/taskbuffer@3.5.0':
dependencies:
'@design.estate/dees-element': 2.2.2
'@design.estate/dees-element': 2.2.3
'@push.rocks/lik': 6.3.1
'@push.rocks/smartdelay': 3.0.5
'@push.rocks/smartlog': 3.2.1
@@ -3897,6 +3908,10 @@ snapshots:
dependencies:
type-fest: 4.41.0
'@tsclass/tsclass@9.5.0':
dependencies:
type-fest: 5.5.0
'@tybys/wasm-util@0.10.1':
dependencies:
tslib: 2.8.1
@@ -5459,6 +5474,8 @@ snapshots:
symbol-tree@3.2.4: {}
tagged-tag@1.0.0: {}
threads@1.7.0:
dependencies:
callsites: 3.1.0
@@ -5513,6 +5530,10 @@ snapshots:
type-fest@4.41.0: {}
type-fest@5.5.0:
dependencies:
tagged-tag: 1.0.0
typescript@5.9.3: {}
uc.micro@2.1.0: {}

231
readme.md
View File

@@ -1,10 +1,10 @@
# @lossless.zone/objectstorage
> 🚀 S3-compatible object storage server with a slick management UI — powered by [`smartstorage`](https://code.foss.global/push.rocks/smartstorage).
> 🚀 S3-compatible object storage server with clustering, erasure coding, and a slick management UI — powered by [`smartstorage`](https://code.foss.global/push.rocks/smartstorage).
**objectstorage** gives you a fully featured, self-hosted S3-compatible storage server with a beautiful web-based management interface — all in a single Docker image. No Java, no bloat, no fuss.
Built on Deno for the backend and [`@design.estate/dees-catalog`](https://code.foss.global/design.estate/dees-catalog) for a polished UI, it speaks the S3 protocol out of the box while adding powerful management features on top.
Built on Deno for the backend and [`@design.estate/dees-catalog`](https://code.foss.global/design.estate/dees-catalog) for a polished UI, it speaks the S3 protocol out of the box while adding powerful management features on top. Scale from a single node to a distributed cluster with erasure coding and multi-drive support.
## Issue Reporting and Security
@@ -13,14 +13,18 @@ For reporting bugs, issues, or security vulnerabilities, please visit [community
## ✨ Features
- **Full S3 API compatibility** — Works with any S3 client, SDK, or tool (AWS CLI, boto3, etc.)
- **Management UI** — Web dashboard for buckets, objects, policies, credentials, and server config
- **🔗 Cluster mode** — Distribute storage across multiple nodes with QUIC transport, automatic discovery, and quorum writes/reads
- **🛡️ Erasure coding** — Reed-Solomon erasure coding (default 4+2) for data durability with minimal overhead
- **💾 Multi-drive support** — Stripe data across multiple disks per node with per-drive health monitoring
- **🔄 Self-healing** — Background scanner detects and reconstructs missing or corrupt shards automatically
- **Management UI** — Web dashboard for buckets, objects, policies, credentials, cluster config, and storage drives
- **Finder-style object browser** — Column view with file preview, drag-and-drop upload, move/rename, context menus
- **Inline code editing** — Built-in Monaco editor with syntax highlighting and save-back-to-storage
- **PDF viewer** — Render PDFs inline with page navigation, zoom, and thumbnails
- **Named policy management** — Create reusable IAM-style policies, attach them to multiple buckets
- **Credential management** — Add/remove access keys through the UI with live-reload
- **Single Docker image** — Multi-arch (`amd64` + `arm64`), tiny Alpine-based image
- **Fast** — Rust-powered storage engine via `smartstorage`, Deno runtime for management layer
- **Fast** — Rust-powered storage engine via `smartstorage`, streaming I/O with zero-copy and backpressure
- **Secure by default** — JWT-based admin auth, S3 SigV4 authentication, bucket policies
- **🌙 Dark theme** — Automatic dark mode following your system preference
@@ -59,7 +63,7 @@ deno run --allow-all mod.ts server --ephemeral
objectstorage is configured through environment variables, CLI flags, or programmatic config. **Environment variables take precedence** over CLI flags.
### Environment Variables
### Server Environment Variables
| Variable | Description | Default |
|---|---|---|
@@ -71,18 +75,86 @@ objectstorage is configured through environment variables, CLI flags, or program
| `OBJST_ADMIN_PASSWORD` | Admin UI password | `admin` |
| `OBJST_REGION` | Storage region identifier | `us-east-1` |
### Cluster Environment Variables
| Variable | Description | Default |
|---|---|---|
| `OBJST_CLUSTER_ENABLED` | Enable cluster mode (`true`/`false`) | `false` |
| `OBJST_CLUSTER_NODE_ID` | Unique node identifier | auto-generated |
| `OBJST_CLUSTER_QUIC_PORT` | QUIC transport port | `4433` |
| `OBJST_CLUSTER_SEED_NODES` | Comma-separated seed node addresses | _(empty)_ |
| `OBJST_DRIVE_PATHS` | Comma-separated drive mount paths | storage dir |
| `OBJST_ERASURE_DATA_SHARDS` | Erasure coding data shards | `4` |
| `OBJST_ERASURE_PARITY_SHARDS` | Erasure coding parity shards | `2` |
| `OBJST_ERASURE_CHUNK_SIZE` | Erasure chunk size in bytes | `4194304` (4 MB) |
| `OBJST_HEARTBEAT_INTERVAL_MS` | Cluster heartbeat interval | `5000` |
| `OBJST_HEARTBEAT_TIMEOUT_MS` | Cluster heartbeat timeout | `30000` |
### CLI Flags
```bash
deno run --allow-all mod.ts server [options]
Options:
--storage-port <port> Storage API port (default: 9000)
--ui-port <port> Management UI port (default: 3000)
--storage-dir <path> Storage directory (default: /data)
--ephemeral Use ./.nogit/objstdata for storage (dev mode)
Server Options:
--storage-port <port> Storage API port (default: 9000)
--ui-port <port> Management UI port (default: 3000)
--storage-dir <path> Storage directory (default: /data)
--ephemeral Use ./.nogit/objstdata for storage (dev mode)
Clustering Options:
--cluster-enabled Enable cluster mode
--cluster-node-id <id> Unique node identifier
--cluster-quic-port <port> QUIC transport port (default: 4433)
--cluster-seed-nodes <list> Comma-separated seed node addresses
--drive-paths <list> Comma-separated drive mount paths
--erasure-data-shards <n> Erasure coding data shards (default: 4)
--erasure-parity-shards <n> Erasure coding parity shards (default: 2)
```
## 🔗 Cluster Mode
objectstorage supports distributed storage across multiple nodes with automatic failover and data redundancy.
### How it works
1. **Enable clustering** on each node with `OBJST_CLUSTER_ENABLED=true`
2. **Point nodes at each other** using `OBJST_CLUSTER_SEED_NODES` — nodes discover the full cluster from any seed
3. **Configure drives** per node with `OBJST_DRIVE_PATHS` — each drive is independently managed
4. **Erasure coding** splits objects into data + parity shards across drives and nodes
### Example: 3-node cluster
```bash
# Node 1
docker run -d --name objst-node1 \
-p 9000:9000 -p 3000:3000 -p 4433:4433/udp \
-v /mnt/disk1:/drive1 -v /mnt/disk2:/drive2 \
-e OBJST_CLUSTER_ENABLED=true \
-e OBJST_CLUSTER_NODE_ID=node-1 \
-e OBJST_CLUSTER_SEED_NODES=node2:4433,node3:4433 \
-e OBJST_DRIVE_PATHS=/drive1,/drive2 \
-e OBJST_ACCESS_KEY=myadminkey \
-e OBJST_SECRET_KEY=mysupersecret \
code.foss.global/lossless.zone/objectstorage:latest
# Node 2 and Node 3 — same pattern, different node IDs and seed nodes
```
### Erasure coding presets
| Config | Data Shards | Parity Shards | Overhead | Fault Tolerance |
|---|---|---|---|---|
| Default | 4 | 2 | 50% | 2 failures |
| High durability | 6 | 3 | 50% | 3 failures |
| Minimal | 2 | 1 | 50% | 1 failure |
### Inter-node transport
Cluster communication uses **QUIC** (UDP port 4433 by default) with:
- Auto-generated TLS certificates
- Multiplexed streams with flow-control backpressure
- Heartbeat-based failure detection (default: 5s interval, 30s timeout)
## 🖥️ Management UI
The web-based management UI is served on the UI port (default: `3000`). Log in with username `admin` and the configured admin password.
@@ -147,7 +219,7 @@ Click "Add Key" to create new access credentials. They're immediately available
### Configuration
View your server's current configuration at a glance — ports, region, storage directory, and auth/CORS status.
View your server's current configuration at a glance — ports, region, storage directory, auth/CORS status, cluster configuration, erasure coding settings, and storage drive paths. The config view also includes an environment variable reference guide for cluster setup.
![Configuration](./docs/06-config.png)
@@ -279,7 +351,7 @@ pnpm run build:docker
pnpm run start:docker
```
### Docker Compose
### Docker Compose (standalone)
```yaml
services:
@@ -299,45 +371,117 @@ volumes:
objstdata:
```
### Docker Compose (3-node cluster)
```yaml
services:
node1:
image: code.foss.global/lossless.zone/objectstorage:latest
ports:
- "9001:9000"
- "3001:3000"
- "4433:4433/udp"
volumes:
- node1-drive1:/drive1
- node1-drive2:/drive2
environment:
OBJST_CLUSTER_ENABLED: "true"
OBJST_CLUSTER_NODE_ID: node-1
OBJST_CLUSTER_QUIC_PORT: "4433"
OBJST_CLUSTER_SEED_NODES: node2:4433,node3:4433
OBJST_DRIVE_PATHS: /drive1,/drive2
OBJST_ACCESS_KEY: myadminkey
OBJST_SECRET_KEY: mysupersecret
node2:
image: code.foss.global/lossless.zone/objectstorage:latest
ports:
- "9002:9000"
- "3002:3000"
- "4434:4433/udp"
volumes:
- node2-drive1:/drive1
- node2-drive2:/drive2
environment:
OBJST_CLUSTER_ENABLED: "true"
OBJST_CLUSTER_NODE_ID: node-2
OBJST_CLUSTER_QUIC_PORT: "4433"
OBJST_CLUSTER_SEED_NODES: node1:4433,node3:4433
OBJST_DRIVE_PATHS: /drive1,/drive2
OBJST_ACCESS_KEY: myadminkey
OBJST_SECRET_KEY: mysupersecret
node3:
image: code.foss.global/lossless.zone/objectstorage:latest
ports:
- "9003:9000"
- "3003:3000"
- "4435:4433/udp"
volumes:
- node3-drive1:/drive1
- node3-drive2:/drive2
environment:
OBJST_CLUSTER_ENABLED: "true"
OBJST_CLUSTER_NODE_ID: node-3
OBJST_CLUSTER_QUIC_PORT: "4433"
OBJST_CLUSTER_SEED_NODES: node1:4433,node2:4433
OBJST_DRIVE_PATHS: /drive1,/drive2
OBJST_ACCESS_KEY: myadminkey
OBJST_SECRET_KEY: mysupersecret
volumes:
node1-drive1:
node1-drive2:
node2-drive1:
node2-drive2:
node3-drive1:
node3-drive2:
```
### Image Details
- **Base**: `alpine:edge` with Deno runtime
- **Architectures**: `linux/amd64`, `linux/arm64`
- **Size**: ~150 MB compressed
- **Init system**: `tini` for proper signal handling
- **Exposed ports**: `9000` (S3), `3000` (UI)
- **Exposed ports**: `9000` (S3), `3000` (UI), `4433` (QUIC cluster transport)
- **Volume**: `/data` — all bucket data and config persisted here
## 🏗️ Architecture
```
┌─────────────────────────────────────────────────┐
│ objectstorage │
│ │
│ ┌──────────────┐ ┌───────────────────────┐ │
│ │ Management │ │ Storage Engine │ │
│ │ UI (port │ │ (smartstorage/ │ │
│ │ 3000) │ │ ruststorage) │ │
│ │ │ │ (port 9000) │ │
│ │ dees-catalog │ │ • S3 API compat │ │
│ │ SPA bundle │ │ • SigV4 auth │ │
│ └──────┬───────┘ │ • Bucket policies │ │
│ │ │ • Rust binary engine │ │
│ ┌──────▼───────┐ └───────────────────────┘
│ │ OpsServer │
│ │ (TypedReq │──── AWS SDK S3 Client ────────
│ │ handlers) │ (manages own storage)
│ │ │ │
│ │ • Admin auth │
│ │ • CRUD APIs │
│ │ • Policy mgr │ │
│ └──────────────┘
┌──────────────────────────────────────────────┐
/data (persistent volume) ││
│ buckets/ .policies/ .objectstorage/ ││
│ └──────────────────────────────────────────────┘│
└─────────────────────────────────────────────────┘
┌──────────────────────────────────────────────────────────────
objectstorage
│ ┌──────────────┐ ┌────────────────────────────────────┐ │
│ │ Management │ │ Storage Engine (smartstorage) │ │
│ │ UI (port │ │ Rust binary via ruststorage │ │
│ │ 3000) │ │ (port 9000) │ │
│ │ │ │ │ │
│ │ dees-catalog │ │ • S3 API (path-style routing) │ │
│ │ SPA bundle │ │ • SigV4 authentication │ │
│ └──────┬───────┘ │ • Bucket policies │ │
│ │ │ • Streaming I/O (zero-copy) │ │
│ ┌──────▼───────┐ │ • Multipart upload support │
│ │ OpsServer │ └─────────────┬──────────────────────┘
│ │ (TypedReq │
│ │ handlers) │── S3 Client ──────┘
│ │ │
│ │ • Admin auth │ ┌────────────────────────────────────┐
│ │ • CRUD APIs │ Cluster Layer (optional) │
│ │ • Policy mgr │
│ └──────────────┘ • QUIC transport (port 4433) │
• Reed-Solomon erasure coding
│ • Quorum writes / reads │
│ • Heartbeat failure detection
│ • Self-healing shard repair
└────────────────────────────────────┘
│ │
│ ┌──────────────────────────────────────────────────────────┐ │
│ │ Storage Drives │ │
│ │ /drive1 /drive2 /drive3 ... (or single /data) │ │
│ └──────────────────────────────────────────────────────────┘ │
└──────────────────────────────────────────────────────────────┘
```
### Tech Stack
@@ -345,6 +489,8 @@ volumes:
| Layer | Technology |
|---|---|
| **Storage Engine** | [`@push.rocks/smartstorage`](https://code.foss.global/push.rocks/smartstorage) (Rust binary via `ruststorage`) |
| **Cluster Transport** | QUIC via `quinn` (auto-TLS, multiplexed streams, backpressure) |
| **Erasure Coding** | Reed-Solomon (configurable data + parity shards) |
| **Runtime** | Deno |
| **Management API** | [`@api.global/typedrequest`](https://code.foss.global/api.global/typedrequest) + [`@api.global/typedserver`](https://code.foss.global/api.global/typedserver) |
| **Auth** | JWT via [`@push.rocks/smartjwt`](https://code.foss.global/push.rocks/smartjwt), S3 SigV4 |
@@ -367,13 +513,16 @@ pnpm run build
# Type check backend
deno check mod.ts
# Run tests
pnpm test
# Run in development mode
deno run --allow-all mod.ts server --ephemeral
```
## License and Legal Information
This repository contains open-source code licensed under the MIT License. A copy of the license can be found in the [LICENSE](./LICENSE) file.
This repository contains open-source code licensed under the MIT License. A copy of the license can be found in the [license](./license) file.
**Please note:** The MIT License does not grant permission to use the trade names, trademarks, service marks, or product names of the project, except as required for reasonable and customary use in describing the origin of the work and reproducing the content of the NOTICE file.

View File

@@ -3,6 +3,6 @@
*/
export const commitinfo = {
name: '@lossless.zone/objectstorage',
version: '1.7.1',
version: '1.8.0',
description: 'object storage server with management UI powered by smartstorage'
}

File diff suppressed because one or more lines are too long

View File

@@ -3,6 +3,6 @@
*/
export const commitinfo = {
name: '@lossless.zone/objectstorage',
version: '1.7.1',
version: '1.8.0',
description: 'object storage server with management UI powered by smartstorage'
}

View File

@@ -1,13 +1,13 @@
import * as plugins from './plugins.js';
import * as appstate from './appstate.js';
import * as interfaces from '../ts_interfaces/index.js';
import type { IS3DataProvider } from '@design.estate/dees-catalog';
import * as plugins from './plugins.ts';
import * as appstate from './appstate.ts';
import * as interfaces from '../ts_interfaces/index.ts';
import type { IStorageDataProvider } from '@design.estate/dees-catalog';
const getIdentity = (): interfaces.data.IIdentity => {
return appstate.loginStatePart.getState().identity!;
};
export const createDataProvider = (): IS3DataProvider => ({
export const createDataProvider = (): IStorageDataProvider => ({
async listObjects(bucket: string, prefix?: string, delimiter?: string) {
const typedRequest = new plugins.domtools.plugins.typedrequest.TypedRequest<
interfaces.requests.IReq_ListObjects

View File

@@ -123,10 +123,10 @@ export class ObjstViewObjects extends DeesElement {
${this.selectedBucket
? html`
<div class="browser-container">
<dees-s3-browser
<dees-storage-browser
.dataProvider=${this.dataProvider}
.bucketName=${this.selectedBucket}
></dees-s3-browser>
></dees-storage-browser>
</div>
`
: html`