Topic
lossless.zone
@lossless.zone/objectstorage is a self-hosted, S3-compatible object storage server packaged as a single Docker image. It gives you an S3 endpoint for applications, a browser-based management UI for humans, and a Rust-powered storage engine underneath.
The short version: it is the storage box you can run yourself when you want S3 semantics without signing up for a cloud bucket, wiring together MinIO, or building an admin console from scratch.
Why Another Object Storage Server?
Object storage is one of those pieces of infrastructure that looks simple until you operate it. The protocol is familiar: buckets, keys, objects, credentials, policies, multipart uploads. The hard part is everything around it.
You need a process that starts predictably in Docker. You need credentials that can be managed without rebuilding an image. You need a UI for buckets, policies, object browsing, and quick inspection. You need an S3-compatible API so existing SDKs and tools keep working. If the storage grows beyond one disk, you need clustering, erasure coding, drive awareness, and repair behavior that does not require a separate product.
@lossless.zone/objectstorage wraps those requirements into one product layer. The storage protocol and data path are handled by @push.rocks/smartstorage, a Rust-backed S3-compatible engine. The objectstorage package adds the Docker runtime, Deno-based control process, admin authentication, management APIs, and a dees-catalog web UI.
┌───────────────────────────────────────────────────────────────┐
│ objectstorage │
│ │
│ Management UI Storage Engine │
│ port 3000 port 9000 │
│ │
│ dees-catalog SPA smartstorage │
│ typed ops API ───────▶ Rust S3 server │
│ admin auth SigV4, policies, streaming I/O │
│ │
│ optional cluster layer: QUIC, erasure coding, drive paths │
└───────────────────────────────────────────────────────────────┘
Ecosystem note. lossless.zone is the storage-facing product line in the foss.global stack. objectstorage is the runnable service layer; @push.rocks/smartstorage is the lower-level S3 engine underneath it.
A Docker Container, Not a Framework Exercise
The recommended start path is intentionally boring:
docker run -d \
--name objectstorage \
-p 9000:9000 \
-p 3000:3000 \
-v objstdata:/data \
-e OBJST_ACCESS_KEY=myadminkey \
-e OBJST_SECRET_KEY=mysupersecret \
-e OBJST_ADMIN_PASSWORD=myuipassword \
code.foss.global/lossless.zone/objectstorage:latest
Port 9000 is the S3-compatible API. Port 3000 is the management UI. /data is the persistent volume for bucket data and product metadata.
The image is Alpine-based, runs Deno in production, uses tini for signal handling, and exposes the cluster transport port 4433 for distributed deployments. The build is multi-stage: a Node/pnpm stage bundles the frontend with @git.zone/tsbundle, and the final image contains the Deno runtime, backend code, shared interfaces, and bundled web assets.
That split matters. This is not just a library that happens to start a server. It is meant to be deployed as a service.
S3 Compatibility Where Applications Need It
Applications talk to objectstorage through the normal S3 model. Any S3-compatible client can point at http://localhost:9000, use path-style addressing, and authenticate with the configured access key and secret.
import { S3Client, PutObjectCommand, ListObjectsV2Command } from '@aws-sdk/client-s3';
const s3 = new S3Client({
endpoint: 'http://localhost:9000',
region: 'us-east-1',
credentials: {
accessKeyId: 'admin',
secretAccessKey: 'admin',
},
forcePathStyle: true,
});
await s3.send(new PutObjectCommand({
Bucket: 'my-bucket',
Key: 'hello.txt',
Body: 'Hello, object storage!',
}));
const result = await s3.send(new ListObjectsV2Command({
Bucket: 'my-bucket',
}));
console.log(result.Contents);
The underlying smartstorage engine handles the protocol details: AWS SigV4 authentication, IAM-style bucket policies, multipart uploads, byte-range requests, and streaming I/O. For large files, that distinction is important. The engine is Rust-based and designed around streaming and backpressure rather than loading whole objects into a JavaScript process.
The Management UI Is Part of the Product
Raw S3 compatibility is useful for applications. It is not enough for operators.
The management UI is served from the same container on port 3000. After logging in as admin with OBJST_ADMIN_PASSWORD, you get views for server status, buckets, objects, policies, access keys, and configuration.
The object browser is the part users notice first. It behaves more like a file manager than a cloud API explorer: column-style browsing, folder prefixes, upload, download, preview, move, rename, delete, and context menus. Text objects can be opened in a Monaco-powered code editor and saved back to storage. PDFs render inline with page navigation, zoom, thumbnails, print, and download controls.
That is a practical difference from a minimal S3 server. Operators do not need to keep switching between aws s3 ls, a bucket policy JSON file, and a separate dashboard. The common workflows are in the product.
Named Policies Instead of Copy-Pasted JSON
S3 bucket policies are powerful, but raw policy JSON is awkward to manage by hand. objectstorage adds a named policy layer on top.
You create a reusable policy once, then attach it to one or more buckets. The PolicyManager persists named policies under the storage directory, tracks bucket attachments, merges attached statements, replaces the ${bucket} placeholder with the concrete bucket name, and applies the resulting S3 policy to the bucket.
[
{
"Sid": "PublicRead",
"Effect": "Allow",
"Principal": "*",
"Action": "s3:GetObject",
"Resource": "arn:aws:s3:::${bucket}/*"
}
]
Attach that policy to assets, downloads, and public-site, and each bucket receives the correct concrete resource ARN. Updating the named policy recomputes the attached bucket policies. Deleting a policy detaches it and reapplies the affected buckets.
This is a small abstraction, but it removes one of the most common sources of S3 admin drift: nearly identical policy documents copied across buckets and edited manually.
Runtime Credentials and Admin State
objectstorage has two authentication surfaces.
The S3 API uses access-key credentials and SigV4 verification. The admin UI uses a JWT-backed login flow with the fixed username admin and the configured admin password.
The default standalone configuration is deliberately simple:
OBJST_ACCESS_KEY=admin
OBJST_SECRET_KEY=admin
OBJST_ADMIN_PASSWORD=admin
OBJST_REGION=us-east-1
Production deployments should override those values. Credentials can also be managed from the UI. The container persists runtime-managed access credentials in /data/.objectstorage/admin-config.json, so credential changes survive restart when /data is backed by a persistent volume.
The product boundary here is clear: objectstorage owns admin UX, product metadata, and startup configuration. smartstorage owns the S3 auth and policy enforcement path.