🌀 OxiCloud v0.7.0 — "Slipstream"
Three weeks. 237 commits. One obsession: make OxiCloud not just complete, but fast — fast like it's not even there.
If 0.6.0 "Open Skies" was the release where OxiCloud became a real personal cloud — files, calendar, contacts, office, photos — then 0.7.0 "Slipstream" is the release where it learned to move. Uploads that only send the bytes that changed. Search that reads inside your documents. A storage path rewritten to stop copying, stop blocking, stop re-computing. Invites that reach people who don't even have an account yet.
This is the engine-room release. Less new furniture, more raw horsepower — and a few headline features that genuinely change how you use it.
Self-hosted. No vendor. No telemetry. Just your data, now moving at the speed it always should have.
✨ Headline features
⚡ Delta sync — upload only what changed
The marquee feature of this cycle. OxiCloud now does content-defined chunking (FastCDC) right in the browser, compiled to WebAssembly and pipelined across web workers:
- Instant upload — if the server already has your content (by hash), the upload completes with zero bytes on the wire. Re-upload a 2 GB file you already have? Instant.
- Delta upload — the client and server negotiate chunks by hash and transfer only the parts that actually changed. Edit one page of a huge document and you send a few kilobytes, not the whole file.
- Delta download — a file manifest + user-scoped chunk fetch lets sync clients pull only the chunks they're missing.
- Uploads stream directly into the CDC chunk store — no temp spool, a single write, one durability barrier per file instead of an fsync per chunk.
Combined with the existing BLAKE3 dedup, OxiCloud now stores and transfers the absolute minimum.
🔎 Search inside your files
Full-text search is no longer just filenames. OxiCloud now ships an embedded Tantivy content-search index — the actual text inside your documents is indexed and searchable, with relevance ranking, no external service required.
👥 External users & passwordless magic-link login
Sharing now reaches beyond your user list:
- Invite anyone by email — grant access to people who don't have an account. They're created as lightweight external users (no storage of their own) and log in via a magic link.
- Passwordless accounts — sign in with an emailed magic link, hardened with a low-TTL cookie challenge and rate limiting.
- Login by email or username, usernameless and passwordless accounts, email verification flags, and full anti-enumeration (you can't tell whether an account exists).
- SMTP support with templated, theme-matched emails and the
/magiclanding page, plus an admin-only SMTP test tool.
🧑🤝🧑 Groups & ReBAC grants
Permissions grew up. A first-class Groups implementation lets you grant files and folders to all users or to a defined group, built on the relationship-based access control (ReBAC) model. Legacy shares were merged into the unified grant system, with a normalized My Shares view, grant-expiration handling, and coalesced grant notifications.
📸 Photos that know when they were taken
A new photo/video capture-date pipeline extracts real capture dates from media metadata, paired with a premium UI/UX overhaul of the photos experience.
🌍 A frontend that flows
- Infinite scrolling everywhere — no more "load more" buttons; every section streams as you scroll.
- Normalized light / dark / follow-OS theming.
- Server-side i18n with templating, tooltips on users and groups, user vignettes with given/family-name preferences, and a pile of new translations.
- Native media streaming,
requestAnimationFramerubber-band scrolling,Map-based selection, delegated event handlers, and batched rendering across lists and search.
🏎️ Performance — the real story
This release landed dozens of measured backend and frontend optimizations. The greatest hits:
- Storage write path rewritten to consume
selfand stop cloning;O(1)incremental quota updates instead of a fullSUMon every upload; three per-upload DB round-trips collapsed into a single CTE. GET /api/auth/meno longer recomputes storage usage on every call.- WebDAV / NextCloud large uploads stream straight to disk — no more OOM on huge files; direct-PUT size caps for safety.
- CalDAV / CardDAV multiget stops loading entire collections into memory; indexed UID lookups for single-object ops.
- PROPFIND streams in batches with
Range+304support, and batchedoc:fileidresolution kills the NextCloud N+1. - Smart compression — one layer that stops wastefully compressing already-compressed media on
/apiand downloads. - Thumbnails / transcode — decode permits before reading blobs, stop re-transcoding JPEGs, cache negative verdicts.
- DB — statement-level tree-ETag triggers, batched trash purge, dropped two unused indexes, released the blob-cache index mutex before disk I/O.
- Docker — dropped
libpqruntime +postgresql-devbuild deps, trimmed the build context, and skip recursivechownwhen the volume is already owned.
The result: less memory, fewer round-trips, lower latency under load — across uploads, downloads, listings, search, and sync.
🔒 Reliability & security
- Per-IP + per-account login lockout — scoped the lockout key to (account, IP) to stop a login flood from locking everyone out (#326).
- External users are sandboxed — they can only query themselves and their granters; unnecessary routes are blocked.
- Magic links &
/magicareno-cache,no-referrer,noindex, and rate-limited. - Always-on audit logging for every denied or rejected resource access.
- Dedup ref-counting fix — count chunk
ref_countper distinct chunk, not per occurrence. - NFC filename normalization fixes duplicate-name bugs; centralized, mtime-aware ETags that cascade correctly up the folder tree.
- Orphan-share cleanup, refresh-token hardening carried forward, and a sweep of aborted-upload orphans from the periodic trash job.
⚙️ Upgrade notes
- Requires Rust 1.93+ (edition 2024) and PostgreSQL 13+ with
pg_trgmandltree. - Database migrations apply automatically on startup.
- Legacy blobs are re-chunked into CDC manifests at startup so existing data gets delta-sync and dedup benefits — first boot after upgrade may do extra one-time work.
- New env knobs for operators:
OXICLOUD_DIRECT_PUT_MAX_BYTES,OXICLOUD_CHUNK_DIR,OXICLOUD_SMTP_*,OXICLOUD_EXTERNAL_EMAIL_DOMAINS. See the storage fine-tuning and external-user docs. - The container can now run fully rootless (#393).
💛 Thank you — this one was built by the community
0.7.0 is, once again, a community triumph.
🏆 Edouard Vanbelle (@EdouardVanbelle) — still, simply, a crack 👑
131 commits this cycle. One hundred and thirty-one. Edouard didn't just contribute to "Slipstream" — in many ways he is "Slipstream." External users and the entire magic-link / passwordless / email pipeline. Groups and the ReBAC grant unification. Server-side i18n and email templating. The light/dark/like-OS theming. Streaming chunked uploads. Endless UX polish, test coverage, and the kind of relentless, caring craft that makes a project feel loved. Edouard — there aren't enough words. Thank you. 🙏
🙌 And huge thanks to:
- @SAY-5 — for the per-IP/per-account login-lockout hardening (#326).
- @Cilenco — for making the container run rootless (#393).
- @jonathansmith9485 — for the Helm chart fix (#409).
- @leofishman — for the admin-setup link fix after initialization (#432).
- Christian Dielitz and everyone who filed an issue, tested a build, or translated a string.
To every self-hoster, every star-gazer, every person running OxiCloud on a Raspberry Pi in a closet: this one moves a little faster, for you. ❤️
What's Changed
- chore(release): bump version to 0.7.0 — "Slipstream" by @DioCrafts in #463
- perf: six measured backend optimizations (downloads, CDC reads, content cache, write path) by @DioCrafts in #462
- Clean/front test by @EdouardVanbelle in #460
- chore(wasm): check, clippy, test, CI by @EdouardVanbelle in #459
- Delta-upload protocol: client-side chunk negotiation to skip unchanged bytes by @DioCrafts in #455
- Add embedded Tantivy full-text content search by @DioCrafts in #454
- Legacy whole-file blob re-chunk migration + DAV multiget optimizations by @DioCrafts in #453
- chore(test): improve API test coverage by @EdouardVanbelle in #452
- test(e2e): webdav + nextcloud full e2e test coverage by @EdouardVanbelle in #450
- Optimize folder tree ETag triggers and fix descendant path cascade by @DioCrafts in #448
- Optimize encryption, storage, and media streaming performance by @DioCrafts in #447
- Streaming PROPFIND, range requests, and batch ID resolution by @DioCrafts in #445
- Batch fsync for blob uploads: unsynced writes + parallel durability sweep by @DioCrafts in #444
- Optimize volume permission handling and reduce Docker build context by @DioCrafts in #443
- Reduce lock contention and improve query efficiency across multiple subsystems by @DioCrafts in #440
- feat: cap chunk size and maximize use of stream by @EdouardVanbelle in #438
- fix(nextcloud): PROPFIND on chunk upload (permit resume) by @EdouardVanbelle in #437
- fix(ui): ellipsis list view by @EdouardVanbelle in #436
- chore(docker): fix docker healthcheck by @EdouardVanbelle in #435
- feat(nextcloud): use user's image for avatar by @EdouardVanbelle in #434
- fix(db-migration): fix 2 changes with same ID by @EdouardVanbelle in #433
- fix(auth): hide admin setup link after language selection when system is initialized by @leofishman in #432
- perf(quota): stop recomputing storage usage on every GET /api/auth/me by @DioCrafts in #429
- fix(upload): stream WebDAV/NextCloud PUT to disk to prevent OOM on large files by @DioCrafts in #428
- refactor & normalize etag for Nextcloud + fix NFC string by @EdouardVanbelle in #426
- feat: grant notification with coalesce + UI bug fixes by @EdouardVanbelle in #423
- feat(templating+i18n): for mail and for /magic section by @EdouardVanbelle in #421
- feat(usernameless & passwordless): passwordless with magic link via email by @EdouardVanbelle in #416
- feat(user): add external user logged via magic link by @EdouardVanbelle in #414
- chore(user-lifecycle): normalize user life cycle by @EdouardVanbelle in #413
- fix(shares): remove orphan shares by @EdouardVanbelle in #412
- chore(vitepress): ignore non relevant docs, link ReBAC documentation by @EdouardVanbelle in #411
- fix(SharedWithMe): remove group by size by @EdouardVanbelle in #410
- FIX bug 397: helm chart changes by @jonathansmith9485 in #409
- feat(groups): add group, enabling ReBAC for all users or a defined group by @EdouardVanbelle in #408
- feat(trash): move trash API to normalized version by @EdouardVanbelle in #406
- feat(light-dark): normalize light/dark/like-os mode + groupBy UX by @EdouardVanbelle in #405
- feat(grants): finalize merge grants with shares, improve My Shares view by @EdouardVanbelle in #402
- Allow container to be started as non root user by @Cilenco in #393
- fix(auth): scope lockout key to (account, IP) to prevent DOS by login flood by @SAY-5 in #326
New Contributors
- @SAY-5 made their first contribution in #326
- @Cilenco made their first contribution in #393
- @jonathansmith9485 made their first contribution in #409
- @leofishman made their first contribution in #432
Full Changelog: v0.6.0...v0.7.0
Built with 🦀 and stubborn love for open source.
What's Changed
- feat(grants): finalize merge grants with shares, improve My Shares view by @EdouardVanbelle in #402
- Allow container to be started as non root user by @Cilenco in #393
- feat(trash): move trash API to normalized version by @EdouardVanbelle in #406
- feat(light-dark): normalize light/dark/like-os mode + improve UX groupBy selector by @EdouardVanbelle in #405
- FIX : bug 397 add: helm chart changes by @jonathansmith9485 in #409
- feat(groups): add group, will permit ReBAC to use All users, or a defined group with permission to files/folders by @EdouardVanbelle in #408
- fix(SharedWithMe): remove group by size, not relevant and not implemented on server side by @EdouardVanbelle in #410
- chore(vitepress): ignore non relevant docs, link ReBAC documentation by @EdouardVanbelle in #411
- fix(shares): remove orphan shares by @EdouardVanbelle in #412
- chore(user-lifecycle): normalize user life cycle to simplify implementation by @EdouardVanbelle in #413
- feat(templating+i18n): for mail and for /magic section by @EdouardVanbelle in #421
- feat(user): add external user logged via magic link by @EdouardVanbelle in #414
- feat(usernameless & passwordless): permit password less with magic link via email by @EdouardVanbelle in #416
- feat:grant notification with coalesce + UI bug fixes by @EdouardVanbelle in #423
- fix(upload): stream WebDAV/NextCloud PUT to disk to prevent OOM on large files by @DioCrafts in #428
- perf(quota): stop recomputing storage usage on every GET /api/auth/me by @DioCrafts in #429
- refactor & normalize etag for Nextcloud + fix NFC string (important fix) by @EdouardVanbelle in #426
- fix(auth): hide admin setup link after language selection when system… by @leofishman in #432
- fix(db-migration): fix 2 changes with same ID by @EdouardVanbelle in #433
- fix(ui): ellipsis list view by @EdouardVanbelle in #436
- fix(nextcloud): PRODFIND on chunk upload (permit resume) by @EdouardVanbelle in #437
- feat(nextcloud): use user's image for avatar by @EdouardVanbelle in #434
- chore(docker): fix docker healthcheck by @EdouardVanbelle in #435
- Reduce lock contention and improve query efficiency across multiple subsystems by @DioCrafts in #440
- feat: cap chunk size and maximize use of stream by @EdouardVanbelle in #438
- fix(auth): scope lockout key to (account, IP) to prevent DOS by login flood (#323) by @SAY-5 in #326
- Optimize volume permission handling and reduce Docker build context by @DioCrafts in #443
- Batch fsync for blob uploads: unsynced writes + parallel durability sweep by @DioCrafts in #444
- Streaming PROPFIND, range requests, and batch ID resolution by @DioCrafts in #445
- Optimize encryption, storage, and media streaming performance by @DioCrafts in #447
- Optimize folder tree ETag triggers and fix descendant path cascade by @DioCrafts in #448
- Legacy whole-file blob re-chunk migration + DAV multiget optimizations by @DioCrafts in #453
- Add embedded Tantivy full-text content search by @DioCrafts in #454
- Delta-upload protocol: client-side chunk negotiation to skip unchanged bytes by @DioCrafts in #455
- perf: six measured backend optimizations (downloads, CDC reads, content cache, write path) by @DioCrafts in #462
- chore(test): improve API test coverage by @EdouardVanbelle in #452
- test(e2e): webdav + nextcloud full e2e test coverage by @EdouardVanbelle in #450
- chore(release): bump version to 0.7.0 — "Slipstream" by @DioCrafts in #463
- Clean/front test by @EdouardVanbelle in #460
- chore(wasm): check, clippy, test, CI by @EdouardVanbelle in #459
New Contributors
- @Cilenco made their first contribution in #393
- @jonathansmith9485 made their first contribution in #409
- @leofishman made their first contribution in #432
- @SAY-5 made their first contribution in #326
Full Changelog: v0.6.0...v0.7.0