No description
  • Rust 45.8%
  • JavaScript 26.8%
  • HTML 10.5%
  • Python 9.8%
  • CSS 5.2%
  • Other 1.9%
Find a file
2026-10-10 13:18:12 +02:00
apps feat(app-platform): installable app platform with SDK and bundled apps 2026-09-21 18:16:08 +02:00
assets/collabora feat(files): drive storage, revisions, sharing, WebDAV, archives, Collabora editing 2026-09-21 18:16:03 +02:00
clients feat: expand workspace apps and administration 2026-10-10 13:18:12 +02:00
docs feat: expand workspace apps and administration 2026-10-10 13:18:12 +02:00
migrations feat: expand workspace apps and administration 2026-10-10 13:18:12 +02:00
scripts feat: expand workspace apps and administration 2026-10-10 13:18:12 +02:00
sdk feat(app-platform): installable app platform with SDK and bundled apps 2026-09-21 18:16:08 +02:00
src feat: expand workspace apps and administration 2026-10-10 13:18:12 +02:00
static feat: expand workspace apps and administration 2026-10-10 13:18:12 +02:00
templates feat: expand workspace apps and administration 2026-10-10 13:18:12 +02:00
tests feat: expand workspace apps and administration 2026-10-10 13:18:12 +02:00
.dockerignore feat: expand workspace apps and administration 2026-10-10 13:18:12 +02:00
.gitignore feat: expand workspace apps and administration 2026-10-10 13:18:12 +02:00
ai-design.html docs: README, design mockups, product docs, and design reviews 2026-09-21 18:16:15 +02:00
Cargo.lock feat: expand workspace apps and administration 2026-10-10 13:18:12 +02:00
Cargo.toml feat: expand workspace apps and administration 2026-10-10 13:18:12 +02:00
compose.yaml feat: expand workspace apps and administration 2026-10-10 13:18:12 +02:00
design.html docs: README, design mockups, product docs, and design reviews 2026-09-21 18:16:15 +02:00
Dockerfile feat: expand workspace apps and administration 2026-10-10 13:18:12 +02:00
index.html docs: README, design mockups, product docs, and design reviews 2026-09-21 18:16:15 +02:00
package-lock.json feat: expand workspace apps and administration 2026-10-10 13:18:12 +02:00
package.json feat: expand workspace apps and administration 2026-10-10 13:18:12 +02:00
README.md feat: expand workspace apps and administration 2026-10-10 13:18:12 +02:00

Cloudy

A Rust/Axum files hub for personal use and small teams, using the latest design.html: a compact dark app rail, neutral sidebar, blue accents, and file details only when opened.

Working development alpha. An OpenAI-powered assistant, personal Mail/Calendar/Tasks/Contacts, web files, team access, resumable uploads, versions, sharing, a Linux drive proof, and an installable app platform with managed PostgreSQL storage are implemented. This is not yet a business-ready Nextcloud replacement. See tested features and remaining release gates.

AI and productivity apps

Open Assistant from the app rail or Ask Cloudy from any app. Configure OPENAI_API_KEY and OPENAI_MODEL on the server, then enable the assistant and select sources. It searches authorized data and prepares changes for review. Mail connects to existing IMAP/SMTP accounts; sending requires a separate confirmation. See configuration and limits and the reviewed interactive design.

Calendar provides shared calendars, recurring events and two-way CalDAV sync; shared task lists expose VTODO collections. Open Calendar settings & sync for account/calendar links and revocable calendar-only app passwords. See setup, supported clients and limits.

Collaboration and connected services

File comments, mentions, tags, approvals, albums, automation, document/OCR search, shared calendars/tasks/address books, booking links, room reservations, richer mail, external storage and Cloudy-to-Cloudy shares are available. See setup, supported behavior and limits. These additions do not include desktop/mobile synchronization or organization identity management.

Administration, sign-in and security

After setup, a Welcome checklist walks administrators through email, account protection, inviting people, groups, sign-in, file protection and backups, and helps everyone get started. Settings (gear in the app rail) holds personal settings and, for administrators, a console for users, groups, quotas, storage, email, sign-in, file protection, retention, the audit log and background jobs; cloudy admin covers the same tasks from the command line. Groups can receive files, team folders, calendars, task lists and address books. Outgoing email adds invitations, password reset, emailed share links, notification digests and calendar invitations for people without an account. Sign-in supports OpenID Connect, LDAP/Active Directory, passkeys and authenticator apps. ClamAV scanning, encryption at rest, file access rules and retention policies protect stored files. The interface is available in English, German, French, Spanish and Dutch. See Administration, Email, Sign-in, Security controls and Languages.

Run with Docker Compose

Requires Docker with Compose. The application needs only PostgreSQL and a persistent data volume; no Redis or external object store.

./scripts/configure.sh
# Edit .env: CLOUDY_PUBLIC_URL must match the URL users open.
docker compose up --build -d
docker compose exec app cat /app/data/bootstrap-token

Open http://localhost:5174. Enter the setup token and your details. Choose For myself (the default) or With other people. Naming your Cloudy is optional and defaults to "Home". Every account starts with a private Files home. Use the + New menu (Nextcloud-style) to upload files and folders, create folders or an empty text file directly in All files, and share individual items as needed. Incoming shares appear alongside your files in All files. Existing storage locations appear as folders there; new folders use ordinary per-folder sharing. Add accounts and groups in Settings → Users and Settings → Groups. Setup is available only before the first account exists. .env and the setup token contain secrets. Put a TLS reverse proxy in front of the application when making it available beyond your local machine; configure its actual external origin in CLOUDY_PUBLIC_URL.

With a Collabora-compatible office server configured (CLOUDY_COLLABORA_URL; the Compose file offers the free CODE image as an opt-in --profile office service for testing/home use), Files gains a New document button for .docx/.xlsx/.pptx and opens office files for collaborative editing, Nextcloud-style. See Collabora setup and limits.

The full Compose deployment has not been validated as part of this increment. The native server has been exercised against PostgreSQL 18.6. Pin image digests/toolchain versions as part of deployment hardening.

Native development

Requires Rust, PostgreSQL, and an ordinary non-superuser database owner. On an existing PostgreSQL instance, create a cloudy login and database owned by it; revoke public schema CREATE and database TEMP from PUBLIC. Set DATABASE_URL=postgresql://cloudy:…@localhost/cloudy.

export DATABASE_URL='postgresql://cloudy:YOUR_PASSWORD@localhost/cloudy'
cargo run --locked

In this workspace an isolated local PostgreSQL installation is already under .local/postgres; it does not modify system packages or another project's database. For this environment:

./scripts/run-dev.sh
cat data/bootstrap-token

The helper starts a cluster bound to 127.0.0.1:55434. Its private configuration is .local/dev.env. scripts/dev-db.sh requires that local installation; on another machine use your own PostgreSQL or Compose. Core schema migrations run at startup. Static assets are served from static, so start the binary at the repository root.

Optional variables: CLOUDY_BIND (default 127.0.0.1:5174), CLOUDY_PUBLIC_URL, CLOUDY_DATA_DIR (default data), CLOUDY_MAX_UPLOAD_BYTES (default 10 GiB), CLOUDY_COLLABORA_URL and CLOUDY_COLLABORA_PUBLIC_URL (collaborative office editing, see Collabora setup), RUST_LOG. The browser uses 4 MiB resumable chunks. Accounts/passwords and real files are never seeded into the working development database.

Linux drive prototype

This is a tested FUSE proof of the file protocol. It is not yet the planned production rclone backend or a cross-platform desktop product. In particular, rename-over-existing and office safe-save behavior remain release gates.

For a desktop app with a local synced folder, connection status, pause/resume and a tray icon, see Cloudy desktop. It uses the personal Files WebDAV endpoint and works separately from this online FUSE mount.

Create a device token under Connect a drive in the web app. Obtain the space UUID from GET /api/v1/spaces or the browser's [data-space] element.

CARGO_TARGET_DIR=target cargo build --locked --manifest-path clients/drive/Cargo.toml
mkdir -p "$HOME/Cloudy" "$HOME/.cache/cloudy-drive"
read -rs CLOUDY_DEVICE_TOKEN
export CLOUDY_DEVICE_TOKEN
export CLOUDY_DRIVE_CACHE="$HOME/.cache/cloudy-drive"
./target/debug/cloudy-drive http://localhost:5174 YOUR_SPACE_UUID "$HOME/Cloudy"

Open ~/Cloudy in your usual file manager. Keep the process running. Unmount with fusermount3 -u "$HOME/Cloudy". This requires /dev/fuse and fusermount3, usually provided by the distribution's FUSE package. Do not enable allow_other.

Writable files are staged in the private disk cache. A successful fsync/close waits for the server commit. An unavailable server or conflicting revision causes an error and leaves the local bytes plus a JSON description in that cache. Preserve that copy and upload it under a new name after comparing versions. A local write or sync failure blocks further changes and saves on that open handle. Close it and inspect the retained cache file before recovering it; a partial write may leave incomplete contents. Automatic replay is deliberately not implemented. This is a mounted online drive, not offline synchronization.

Built-in and installable apps

Mail, Calendar, Tasks, Contacts, Notes, Bookmarks and Forms live in the core: native modules rendered in the app rail on the same session, with no separate services, ports or launch tokens. Notes store Markdown up to 100 KB per note; Bookmarks store http(s) URLs up to 2 KB; both are private per account and version-checked like tasks and contacts.

Forms supports public links, up to 20 pages, required questions, text, email, number, date, choice and file answers, response review, and CSV export. File questions can restrict extensions, MIME types, file count and size. Each form has an uploads folder in the owner's personal Files space; every submitted file is a normal Files node with a revision, included in the same quota and backup set. A file can be at most 50 MB, and one response can upload at most 100 MB. Deleting a form leaves its uploaded files in Files.

Administrators can install and update separate app packages under Apps, review requested access, and enable, disable or remove them. Apps render in the same workspace shell and can keep private and shared data, define custom interfaces/routes, use typed collections and migrations, work with files, schedule jobs, receive events, send notifications, and call approved HTTP integrations. Their JavaScript runs in bounded, short-lived workers with an explicit capability contract; no Node service or server rebuild is needed. WASM remains a possible future runtime rather than the only app format. See the architecture and trust boundary and app authoring guide.

Try the standalone Reading list and Task overview examples:

node sdk/pack.mjs apps/reading-list /tmp/reading-list.cloudy-app.json
node sdk/pack.mjs apps/task-overview /tmp/task-overview.cloudy-app.json

Choose the resulting file in Apps → Choose app package. API 2 supports full custom applications, including a collaborative project board with attachments and scheduled reminders. Pack it with node sdk/pack.mjs apps/project-board /tmp/project-board.cloudy-app.json. Administrator-configured catalogs support signed packages and reviewed updates. See the API 2 guide and limits. The platform remains alpha; it does not run Nextcloud PHP apps.

Backups and restore

For this alpha, use a cold recovery set on a dedicated PostgreSQL cluster. Stop Cloudy first; app workers are part of its process lifecycle. The script rejects active database clients, temporarily blocks the core login, verifies every referenced blob, and archives PostgreSQL metadata, global roles, and staged upload data.

python3 scripts/backup.py /safe/location/cloudy-recovery.tar.gz \
  --data /absolute/path/to/data --services-stopped

Requires psql, pg_dump, and pg_dumpall on PATH. The data directory includes mail-encryption-key (mail, connector and settings secrets) and, when file encryption is on, blob-encryption-key; if CLOUDY_ENCRYPTION_KEY_FILE keeps that key elsewhere, back it up separately — encrypted files cannot be restored without it. The archive contains credentials and is not encrypted by this script: encrypt it and copy it to a separate failure domain. Installed app packages, private/shared records, attachments, migrations, jobs, notifications and publisher registrations live in the database and are included in the database dump.

Restore into an empty dedicated cluster and a new data directory, with services stopped:

  1. Extract the private archive. Restore metadata/roles.sql using an administrator whose bootstrap role name does not conflict with restored roles.
  2. Create the target database owned by the restored cloudy role. Run pg_restore --exit-on-error --dbname=… metadata/database.dump as the administrator.
  3. Restore data and set ownership for the service account.
  4. Verify blob SHA-256 values against metadata/manifest.json; review account/space/share state. Restore LOGIN for the core role, then start the matching core version.
  5. Exercise login, downloads, permissions, app data, and mount reconnect before switching users over.

A binary rollback does not reverse schema migrations. Restore the matching recovery set when a migration is incompatible. The plan's recovery-time and recovery-point targets are not yet measured.

Validation

cargo test --locked
# Local isolated PostgreSQL helper required; creates a disposable database on port 5176.
./scripts/test.sh
npm ci
npx playwright install chromium
RUN_BROWSER=1 RUN_MOUNT=1 ./scripts/test.sh

tests/browser.mjs supports CHROMIUM_PATH; otherwise it uses Playwright's installed Chromium. tests/mount.py needs the drive binary and FUSE. Tests never initialize the normal cloudy workspace. The test harness stops its services and retains disposable DBs for inspection. Set KEEP_TEST_SERVER=1 to retain the core test server for manual inspection; stop that server before rerunning the port-5176 suite.

An earlier cold-backup restore test (tests/restore.sh) passed against a separate PostgreSQL cluster, validating database ownership and referenced blob checksums. The app-platform restore test (tests/app-platform-restore.py) additionally round-trips a package, shared records, binary attachments, migrations and pending reminders through pg_dump/pg_restore into a separate disposable database.

The passing suite covers API authorization and CSRF, quotas, conditional writes, upload resume/idempotence, byte ranges, share revocation, restore, browser persistence, actual FUSE operations, and app lifecycle, capability and private-state isolation. It does not replace host-crash injection, multi-OS office tests, load benchmarks or an independent security review.

The development HTTP contract, implementation status, architecture plan, and design reference describe the boundaries and next work.

Contact synchronization

Open Contacts → Contacts settings → Connect device to configure a CardDAV client with your email and a revocable device token. Web and device changes use the same personal and shared address books. See CardDAV setup, supported protocol features and limits.