diff --git a/README.md b/README.md index 4e0ad5f..dd9e4d8 100644 --- a/README.md +++ b/README.md @@ -4,12 +4,53 @@ A secure, self-hostable "burn after reading" paste service with ephemeral storag ## Features -- **Ephemeral pastes** — Content is deleted immediately after first view -- **No persistence** — All data stored in-memory only (restarts clear everything) -- **No accounts** — Zero-friction sharing without registration -- **Self-hosted** — Run your own instance with full control -- **Fast & lightweight** — Built on the BEAM VM for reliability and performance -- **Type-safe** — Written in Gleam, a type-safe functional language +- Deletes pastes after they are viewed +- Data is stored only in memory +- No user accounts needed +- Easy to run yourself +- Fast and reliable +- Written in Gleam (type-safe) + +## Flowchart + +```mermaid +graph TD + A[User creates paste] --> B[Paste is stored in memory] + B --> C[Paste is deleted after first view] + C --> D[User shares paste URL] + D --> E[User views paste] + E --> F[Paste is deleted] +``` + +Note: the creator can now see their post - it will be burned immediately. + +## Configuration + +### SECRET_KEY_BASE (Required for Production) + +The application uses a secret key base for signing cookies and security tokens. + +You **must** set this for production deployments to ensure security and session persistence across restarts. + +```bash +# Generate a secure key (48 bytes of random data) +export SECRET_KEY_BASE=$(openssl rand -base64 48) + +# Or set it manually +export SECRET_KEY_BASE="your-secret-key-here" +``` + +**⚠️ Warning**: If not set, a temporary key will be generated on each startup. This: + +- Invalidates all existing user sessions/cookies after restart +- Reduces security (new key generated each time) +- Generates a warning in the logs + +For development, you can use: + +```bash +SECRET_KEY_BASE=dev gleam run +``` ## Quick Start @@ -32,17 +73,23 @@ The server starts on `http://localhost:3000`. ## Architecture -- **Web framework**: Wisp (Gleam's web framework) -- **HTTP server**: Mist (HTTP/1.1 & HTTP/2) -- **HTML rendering**: Lustre (type-safe, declarative HTML generation) -- **Storage**: In-memory OTP actor (no disk persistence) -- **Key generation**: Cryptographically random 16-character keys +- **Gleam**: Type-safe language built upon the BEAM +- **Web**: Wisp framework + Mist HTTP server +- **Frontend**: Lustre for HTML rendering +- **Storage**: In-memory only (no persistence) +- **Security**: AES-256-GCM client-side encryption, CSRF tokens, rate limiting, security headers ## Security Notes -- Pastes are stored **unencrypted** in server memory +- Pastes are client-side encrypted (AES-256-GCM) before being sent to server +- Server never sees the decryption key (stored in URL fragment after `#`) +- Data is stored **encrypted** in server memory only - Data is **never written to disk** - All data is lost on server restart +- CSRF protection via double-submit cookie pattern +- Rate limiting: 10 requests per minute per IP +- Security headers: CSP, X-Frame-Options, X-Content-Type-Options, Referrer-Policy +- 10MB maximum paste size limit - Intended for ephemeral sharing only — do not store sensitive data ## License