* feat: add libSQL (Turso) platform adapter and Docker opt-in - server/platform/libsql.ts: createLibsqlPlatform() using @libsql/client + drizzle-orm/libsql; accepts plain env record; async migrate at boot; authToken optional for file:// URLs - server/entry-node.ts: select platform at startup — libsql when TURSO_DATABASE_URL is set, otherwise existing SQLite via createNodePlatform() - drizzle.config.ts: switch to turso dialect when TURSO_DATABASE_URL is set - vitest.libsql.config.ts + server/platform/libsql.libsql-test.ts: smoke suite covering connect, migrations, insert/select against users + storages tables - package.json: add @libsql/client dependency; add test:libsql script; externalize @libsql/client in build:node tsup command - vitest.config.ts: exclude *.libsql-test.ts from coverage - docs/deploy/docker.md: document Turso opt-in with copy-pasteable docker-compose snippet - CONTRIBUTING.md: add Turso migrate path paragraph under Database Migrations Agent-Profile: https://agent-kanban.dev/agents/a6bb038c4226a87f * refactor: turn bootstrap.ts into a Platform-accepting factory - server/bootstrap.ts: replace singleton module-scope script with exportable createBootstrap(platform) async factory; reads BETTER_AUTH_SECRET/BETTER_AUTH_URL/TRUSTED_ORIGINS from platform.getEnv so every future entry (Lambda, Vercel, Netlify, Azure) can reuse it - server/entry-node.ts: slim down to platform selection + createBootstrap call; no more duplicate auth/app wiring - server/dev.ts: thin vite-dev-server entry that creates NodePlatform and calls createBootstrap; replaces the former default export in bootstrap.ts - vite.config.ts: update node dev server entry to server/dev.ts - server/platform/libsql.ts: fix getEnv to check env record before falling back to process.env, matching the cloudflare.ts pattern Agent-Profile: https://agent-kanban.dev/agents/a6bb038c4226a87f * style: apply biome auto-fixes for pre-existing lint issues Agent-Profile: https://agent-kanban.dev/agents/a6bb038c4226a87f --------- Co-authored-by: Bob <aibob@mails.agent-kanban.dev>
ZPan
The open-source, S3-native file hosting platform.
Image bed, file sharing, and backup — powered by S3, deployed anywhere.
What is ZPan?
ZPan is a lightweight file hosting platform built on top of S3-compatible storage. Files upload directly from the client to S3, bypassing server bandwidth entirely.
Three scenarios, one platform:
- Image Bed — Upload via PicGo / ShareX / API, get a URL instantly
- File Sharing — Upload files, generate share links, distribute to anyone
- File Backup — CLI agent syncs local directories to S3/R2
Deploy
Cloudflare Workers (Recommended)
Deploy via GitHub Actions with zero server management. Free tier covers personal use.
- Fork this repository
- In your fork, go to Settings → Secrets and variables → Actions and add:
CLOUDFLARE_ACCOUNT_ID— found on the Cloudflare dashboard sidebarCLOUDFLARE_API_TOKEN— create one here with Workers Scripts:Edit and D1:Edit permissions
- Go to the Actions tab, select Deploy to Cloudflare Workers, and click Run workflow
After initial setup, the workflow runs automatically every time you sync your fork with the latest release.
Docker
Quick start — pull the pre-built image and bring your own S3 storage:
curl -O https://raw.githubusercontent.com/saltbo/zpan/master/deploy/docker-compose.yml
docker compose up -d
With RustFS (self-hosted S3-compatible storage, no external dependencies):
curl -O https://raw.githubusercontent.com/saltbo/zpan/master/deploy/docker-compose.rustfs.yml
docker compose -f docker-compose.rustfs.yml up -d
After startup:
- Open the RustFS console at
http://localhost:9001(admin / admin123) and create a bucket (e.g.zpan-bucket) - Open ZPan at
http://localhost:8222, register a user (first user gets admin role) - Go to Admin → Storage and add the RustFS storage:
- Endpoint:
http://localhost:9000(must be reachable from your browser, not the Docker internal hostname) - Bucket: the bucket name you created in step 1
- Region:
us-east-1 - Access Key / Secret Key:
admin/admin123
- Endpoint:
Important: The storage endpoint must be accessible from the client browser, since files upload directly to S3 via presigned URLs. Use
http://localhost:9000for local development, or your server's public URL for production.
Documentation
Why ZPan?
- Zero bandwidth bottleneck — files transfer directly between client and S3
- Zero ops option — deploy to Cloudflare Workers for free, no server needed
- Self-host friendly — Docker deployment with any S3-compatible storage
- Tool ecosystem — works with PicGo, ShareX, Flameshot out of the box
- Open source — free forever for self-hosted users
v1
Looking for ZPan v1 (Go version)? See the v1 branch.
Contributing
See CONTRIBUTING.md for details.
Thank you to all the people who contributed to ZPan!
License
ZPan is under the GPL 3.0 license. See the LICENSE file for details.