Enclosed

Send end-to-end encrypted notes and files where the server never sees your content — true zero-knowledge sharing.

2Kstars
179forks
Apache License 2.0
TypeScript

Enclosed is a minimalist web application for sending private notes and files with end-to-end encryption. Every piece of content is encrypted in the browser before it ever reaches the server, using AES-256-GCM with keys derived via PBKDF2 — making the server genuinely unable to read what you share. The decryption key travels only as a URL hash fragment, which browsers never send to servers, completing the zero-knowledge guarantee.

Users can configure notes with optional password protection, a time-to-live expiration, and self-destruction after first read. Files can be attached alongside text and are encrypted as part of the same payload. A live instance is available at enclosed.cc, and the entire project is self-hostable via Docker with persistent volume support or deployable to Cloudflare Pages with Cloudflare KV storage.

The project ships as a pnpm monorepo with dedicated packages for the SolidJS frontend, the Hono-based backend, a shared crypto library, and a CLI tool that lets developers create and view notes straight from the terminal. Optional email-and-password authentication restricts who can create notes on a given instance, making Enclosed suitable for both personal and team deployments.

What You Get

  • Client-side AES-256-GCM encryption - Every note and file is encrypted in the browser using AES-256-GCM with a 256-bit key derived by PBKDF2 before anything is transmitted, so plaintext never leaves the client.
  • Zero-knowledge URL sharing - The encryption key is embedded in the URL hash fragment, which browsers never include in server requests, guaranteeing the server has no path to the decryption key.
  • Optional password protection - Users can add a password that is folded into PBKDF2 key derivation; the password is never transmitted or stored, adding a second factor the recipient must know.
  • Configurable TTL and self-destruction - Notes can be set to expire after a defined number of seconds or to delete themselves immediately after the first read, giving senders control over data lifetime.
  • File attachment support - Files are serialized, encrypted, and bundled with the note payload using CBOR serialization before upload, enabling secure multi-file sharing within a single link.
  • CLI for terminal workflows - The @enclosed/cli npm package lets developers pipe content, create notes, and view encrypted notes entirely from the command line, with support for file uploads and password prompts.
  • Docker self-hosting with volume persistence - A single Docker run command starts a production-ready instance; a volume flag maps local storage for persistence across container restarts.
  • Optional email/password authentication - Server operators can restrict note creation to authenticated users, defined as bcrypt-hashed credentials in an environment variable, with JWT-based session management.
  • i18n support across 15+ languages - The SolidJS UI includes locale files for English, French, German, Chinese (Simplified and Traditional), Vietnamese, Polish, Turkish, Italian, Indonesian, and more.
  • Cloudflare Workers and Node.js dual deployment - The same server codebase compiles to a Cloudflare Pages Worker or a standard Node.js process, giving operators a choice between serverless and VPS deployments.

Common Use Cases

  • Sharing temporary credentials securely - A developer sends a database password or API key to a teammate via a self-destructing, password-protected note, ensuring the secret vanishes after one view and was never stored in plaintext.
  • Transferring sensitive files between devices - A user encrypts and uploads a tax document or personal ID to a note, accesses it from another device using the link, then lets the note auto-delete so no copy lingers on any server.
  • Private team communication on self-hosted infrastructure - A small company deploys Enclosed internally with authentication enabled, using it to exchange one-time passwords, environment configs, or confidential internal communications without relying on a third-party pastebin.
  • Automated secret distribution in CI/CD pipelines - A DevOps engineer uses the CLI to pipe secrets from a secrets manager into Enclosed and distribute expiring links to deployment scripts, avoiding plaintext secrets in CI logs.
  • Journalist or researcher source communication - A journalist uses Enclosed to receive encrypted tips or documents from sources, knowing the hosting server has zero ability to read the content even if served with a legal demand.

Under The Hood

Architecture Enclosed follows a clean, modular monorepo structure where cryptographic concerns, shared business logic, frontend, backend, CLI, and deployment configuration are each isolated in their own package. The server is built with Hono as a thin HTTP layer, registering middleware and routes in a predictable order — logging, config injection, timeout, CORS, storage binding, security headers, and authentication — before delegating to discrete route modules for notes, auth, and config. Business logic lives one layer below in use cases and repositories that operate through abstracted storage interfaces, making it straightforward to swap the underlying storage driver without touching application logic. The frontend uses SolidJS’s fine-grained reactivity to bind encryption state directly to UI primitives, keeping the security context tightly scoped to the component that needs it.

Tech Stack The frontend is a SolidJS application bundled with Vite and styled with UnoCSS using atomic utility classes, with Kobalte providing accessible headless components and Tabler Icons for the iconography. The backend is a Hono-based TypeScript server that can run on Node.js 22 via @hono/node-server or compile to a Cloudflare Workers ESM bundle with wrangler. Storage is abstracted through unstorage, supporting in-process memory, local filesystem via fs-lite, or Cloudflare KV depending on the deployment target. Encryption is implemented using the native Web Crypto API for both browser and Node.js environments, with a thin platform adapter in the crypto package that bridges web and Node runtimes. CBOR serialization via the lib package is used to pack note content and file assets efficiently before encryption.

Code Quality The codebase is fully written in TypeScript with strict mode enabled, and the server additionally applies @total-typescript/ts-reset for stricter built-in type behavior. Tests are organized in layers: Vitest handles unit and integration tests across all packages, and Playwright drives end-to-end tests that exercise the full note creation and viewing flow in a real browser. Error handling is explicit throughout — custom error factory functions produce typed error objects, and route middleware catches and serializes them consistently. ESLint uses @antfu/eslint-config for a comprehensive rule set, and Renovate automates dependency updates. CI checks lint, typecheck, test, and build in each package on every pull request.

What Makes It Unique The cryptographic design is the defining characteristic: key derivation happens entirely in the browser using PBKDF2 with SHA-256, the resulting master key encrypts the note with AES-256-GCM, and only the base key (not the master key or password) is embedded in the URL hash fragment. Since hash fragments are never sent in HTTP requests, the server is structurally incapable of decrypting content — this is enforced by the protocol, not just by policy. The ability to deploy the exact same application to both Cloudflare Workers (zero-infrastructure, globally distributed) and a standard Node.js process means operators can choose the cost and latency profile that suits them. The CLI’s stdin support makes Enclosed composable with shell pipelines, enabling patterns like cat secret.txt | enclosed create that are difficult to replicate with web-only secure sharing tools.

Self-Hosting

Enclosed is released under the Apache License 2.0, which is a permissive open-source license. You are free to use it commercially, modify it, distribute modified versions, and integrate it into proprietary systems without any copyleft obligation that would force you to open-source your own code. The only requirements are attribution and preservation of license and NOTICE files. There are no dual-licensing restrictions, enterprise tiers, or feature flags gating functionality — every capability described in the repository is available to self-hosters.

Running Enclosed yourself is deliberately lightweight. A single Docker container starts the server on port 8787, and a volume mount is all you need for persistent storage. There is no database to manage — data is stored via the unstorage abstraction, either as files on disk or in Cloudflare KV depending on your target. For production deployments you will want to front the container with a reverse proxy such as Nginx or Caddy for TLS termination, and you are responsible for setting up automated backups of the data volume. The server is a stateless process (all state lives in the storage layer), so horizontal scaling is straightforward as long as the storage backend is shared. The task scheduler for purging expired notes runs inside the process via node-cron, so you do not need an external cron daemon.

There is no hosted managed tier, paid plan, or SaaS alternative offered by the maintainer — the live instance at enclosed.cc is simply the open-source application running on Cloudflare Pages. What you give up compared to commercial secret-sharing services is primarily support: there are no SLAs, no guaranteed response times for issues, and no managed upgrade path. Updates must be applied manually by pulling new Docker images. The tradeoff is full data sovereignty and the architectural guarantee that even the operator of the server cannot read your notes.

Join founders buildingwith open source

Opinionated takes, migration guides, cost-saving tips, and insights from the open source ecosystem.

Subscribe on Substack

No spam. Unsubscribe anytime.

Join 750+ subscribers
No spam. Unsubscribe anytime.

Search