{"id":45219562,"url":"https://github.com/purpleneutral/chatalot","last_synced_at":"2026-02-23T03:26:44.213Z","repository":{"id":338145527,"uuid":"1156694700","full_name":"purpleneutral/chatalot","owner":"purpleneutral","description":"Self-hosted encrypted chat platform with voice/video, communities, and a desktop app. Built with Rust + Svelte.","archived":false,"fork":false,"pushed_at":"2026-02-20T17:43:24.000Z","size":3217,"stargazers_count":0,"open_issues_count":5,"forks_count":0,"subscribers_count":0,"default_branch":"master","last_synced_at":"2026-02-20T20:58:31.017Z","etag":null,"topics":["chat","docker","encrypted-messaging","end-to-end-encryption","open-source","privacy","real-time","rust","self-hosted","signal-protocol","svelte","tauri","webrtc"],"latest_commit_sha":null,"homepage":null,"language":"Svelte","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"gpl-3.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/purpleneutral.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2026-02-13T00:08:06.000Z","updated_at":"2026-02-20T17:43:28.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/purpleneutral/chatalot","commit_stats":null,"previous_names":["purpleneutral/chatalot"],"tags_count":4,"template":false,"template_full_name":null,"purl":"pkg:github/purpleneutral/chatalot","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/purpleneutral%2Fchatalot","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/purpleneutral%2Fchatalot/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/purpleneutral%2Fchatalot/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/purpleneutral%2Fchatalot/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/purpleneutral","download_url":"https://codeload.github.com/purpleneutral/chatalot/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/purpleneutral%2Fchatalot/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":29736257,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-02-23T02:24:00.660Z","status":"ssl_error","status_checked_at":"2026-02-23T02:22:56.087Z","response_time":90,"last_error":"SSL_connect returned=1 errno=0 peeraddr=140.82.121.6:443 state=error: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["chat","docker","encrypted-messaging","end-to-end-encryption","open-source","privacy","real-time","rust","self-hosted","signal-protocol","svelte","tauri","webrtc"],"created_at":"2026-02-20T18:11:06.216Z","updated_at":"2026-02-23T03:26:44.207Z","avatar_url":"https://github.com/purpleneutral.png","language":"Svelte","funding_links":["https://buymeacoffee.com/uniqueuserg"],"categories":[],"sub_categories":[],"readme":"# Chatalot\n\n**Your chat. Your server. Your rules.**\n\nChatalot is a self-hosted chat platform for friends, teams, and communities who refuse to hand their conversations to corporations. Real-time messaging, voice and video calls, end-to-end encryption, and a desktop app — all running on hardware you control.\n\nNo data harvesting. No algorithmic feeds. No subscription tiers to unlock basic features. Just a fast, modern chat experience that belongs entirely to you.\n\n\u003e **Our mission:** Chatalot was born from a simple belief — your conversations are yours. Not a corporation's asset, not a data point, not a product. This is an independent, passion-driven project built for the long haul, with no corporate ties, no investors, and no exit strategy. Just software that respects its users. [Read the full mission statement \u0026rarr;](MISSION.md)\n\n\u003cp align=\"center\"\u003e\n  \u003cimg src=\"screenshots/01-chat-conversation.png\" alt=\"Chatalot chat interface — light mode\" width=\"800\"\u003e\n\u003c/p\u003e\n\n\u003cdetails\u003e\n\u003csummary\u003eDark mode \u0026 customization\u003c/summary\u003e\n\n\u003cp align=\"center\"\u003e\n  \u003cimg src=\"screenshots/07-chat-dark.png\" alt=\"Chatalot chat interface — dark mode\" width=\"800\"\u003e\n  \u003cbr\u003e\u003cbr\u003e\n  \u003cimg src=\"screenshots/05-settings.png\" alt=\"Chatalot appearance settings — themes, palettes, accent colors\" width=\"800\"\u003e\n\u003c/p\u003e\n\n\u003c/details\u003e\n\n\u003cdetails\u003e\n\u003csummary\u003eMore screenshots\u003c/summary\u003e\n\n\u003cp align=\"center\"\u003e\n  \u003cimg src=\"screenshots/00-login-page.png\" alt=\"Login page\" width=\"400\"\u003e\n  \u003cimg src=\"screenshots/09-register-page.png\" alt=\"Registration page\" width=\"400\"\u003e\n  \u003cbr\u003e\u003cbr\u003e\n  \u003cimg src=\"screenshots/02-community-picker.png\" alt=\"Community picker\" width=\"800\"\u003e\n  \u003cbr\u003e\u003cbr\u003e\n  \u003cimg src=\"screenshots/04-members-panel.png\" alt=\"Members panel\" width=\"800\"\u003e\n  \u003cbr\u003e\u003cbr\u003e\n  \u003cimg src=\"screenshots/08-admin-panel.png\" alt=\"Admin panel\" width=\"800\"\u003e\n  \u003cbr\u003e\u003cbr\u003e\n  \u003cimg src=\"screenshots/10-mobile-login.png\" alt=\"Mobile login\" width=\"300\"\u003e\n  \u003cimg src=\"screenshots/11-mobile-chat.png\" alt=\"Mobile chat\" width=\"300\"\u003e\n\u003c/p\u003e\n\n\u003c/details\u003e\n\n## Why Chatalot?\n\nMost chat platforms make you choose: convenience or privacy. Centralized services own your data and can change the rules whenever they want. Federated alternatives promise freedom but deliver complexity — running a node shouldn't require a systems engineering degree.\n\nChatalot takes a different approach: **one Docker command, and you're live.** A single binary serves the API, WebSocket connections, and the web UI. Add the desktop app for native performance. Invite your people with access codes. Done.\n\n### What you get\n\n- **Communities, groups, and channels** — organize your server with roles, permissions, and invite links\n- **Personal groups** — moderators assign isolated spaces to members with full channel control; privacy and invite permissions managed by moderators\n- **Voice and video calls** — peer-to-peer WebRTC with video grid (up to 25 participants)\n- **End-to-end encryption** — Signal protocol (X3DH + Double Ratchet for DMs, Sender Keys for groups), compiled to WASM and running client-side, with per-message lock icons, fingerprint verification, and TOFU key change warnings\n- **Rich messaging** — markdown, syntax-highlighted code blocks, inline media previews, GIF search, emoji autocomplete, reactions, replies, and forwarding\n- **Polls** — create polls with 2-10 options, multi-select, anonymous voting, optional expiry, and real-time vote broadcasting\n- **Custom emoji** — upload per-community emoji (PNG/GIF/WebP), use with `:shortcode:` syntax, autocomplete in composer\n- **File sharing** — drag-and-drop, clipboard paste, inline image/video/audio previews with lightbox viewer\n- **Desktop notifications** — configurable per-channel with sound controls\n- **Web push notifications** — receive DM notifications even when the tab is closed (metadata only, never message content)\n- **Customization** — themes, 8 accent colors, message density, sidebar layout (expanded panel or compact dropdown), font size, time format, profile banners, community theming with custom CSS, group icons/banners/accent colors, voice call backgrounds (6 presets + custom), and more\n- **Webhooks** — create incoming webhooks for channels, post messages from external services\n- **Desktop app** — native Linux and Windows clients via Tauri 2.0, with auto-update and OS keychain integration\n- **Security** — Argon2id passwords, Ed25519-signed JWTs, TOTP 2FA with backup codes, rate limiting, invite-only registration, self-service account recovery\n- **Moderation** — 5-tier role hierarchy (instance owner/admin, community owner/admin, moderator, member), message reports, user warnings, blocking, bans, timeouts, slow mode\n- **Admin panel** — user management, invite codes, announcements, report review, webhooks overview, instance settings, and system feedback\n- **Legal framework** — built-in privacy policy and terms of service, customizable per instance\n\nFor a complete feature list, see [Feature Status](docs/appendix/feature-status.md). For full documentation, see the [Chatalot Documentation](docs/README.md).\n\n\u003e All messages are end-to-end encrypted. DMs use the Signal protocol (X3DH + Double Ratchet), group channels use Sender Keys — both compiled to WASM and running in the browser. Keys are generated at registration, sessions are persisted in IndexedDB, and the server acts as an untrusted relay.\n\n## Privacy by Design\n\nChatalot is built for people who take privacy seriously. Here's what that means in practice:\n\n### Your admin cannot read your messages\n\nAll messages are end-to-end encrypted before leaving your device. The server stores only encrypted ciphertext — even someone with full database access sees nothing but random bytes.\n\n### Your password is never stored\n\nPasswords are hashed with Argon2id (64 MiB memory cost, 3 iterations, 4 parallel lanes). The original password cannot be recovered from the hash — not by admins, not by attackers, not by anyone.\n\n### No telemetry, no analytics, no tracking\n\nChatalot collects zero telemetry. There are no analytics scripts, no usage tracking, no crash reporting, and no phone-home behavior. The software communicates only with its own database.\n\n### Account recovery without email\n\nForgot your password? Use your recovery code — generated at registration, no email infrastructure needed. No admin intervention required. Your recovery code resets your password and generates a fresh code in one step.\n\n### What the server can vs. cannot see\n\n| The server can see | The server cannot see |\n|---|---|\n| Who sent a message and when | Message content (encrypted) |\n| File metadata (size, type) | File contents (encrypted) |\n| Your username and email | Your password (hashed) |\n| When you're online | What you're typing |\n| Channel membership | Private DM conversations |\n| Login timestamps and IPs | 2FA secrets (encrypted at rest) |\n\n## Quick Start\n\n### Prerequisites\n\n- Docker and Docker Compose v2\n- OpenSSL (for generating keys on first run)\n- **ARM64 supported** — runs natively on Raspberry Pi 4/5, Apple Silicon, and other ARM64 devices\n\n### 1. Clone and generate secrets\n\n```bash\ngit clone https://github.com/purpleneutral/chatalot.git\ncd chatalot\n./scripts/generate-secrets.sh\n```\n\nThis creates JWT signing keys (`secrets/`) and a `.env` file with a random database password and encryption key.\n\n### 2. Start everything\n\n```bash\ndocker compose up -d\n```\n\nTwo containers come up:\n- **chatalot** — the Rust server + web UI on port 8080\n- **postgres** — PostgreSQL 17 (internal only, not exposed to the host)\n\n### 3. Open and register\n\nNavigate to `http://localhost:8080`. Since registration defaults to **invite-only**, the first user must set `REGISTRATION_MODE=open` in `.env` (or use the deploy script which handles this). After creating the admin account, switch back to `invite_only` and generate invite codes from the admin panel.\n\nTo allow open registration:\n```bash\n# In .env, set:\nREGISTRATION_MODE=open\n\n# Then restart:\ndocker compose up -d\n```\n\n### Registration Modes\n\n| Mode | Behavior |\n|------|----------|\n| `invite_only` (default) | Users need a valid invite code to register |\n| `open` | Anyone can register |\n| `closed` | Registration is completely disabled |\n\nAdmins generate invite codes from the admin panel. Codes can have usage limits and expiration dates.\n\n### Pre-built Images (recommended for ARM/Raspberry Pi)\n\nBuilding from source on ARM devices takes 20+ minutes (Rust compilation). Pre-built multi-arch images are available on GHCR:\n\n```bash\n# Use the pre-built image instead of building locally\n# In docker-compose.override.yml:\nservices:\n  chatalot:\n    image: ghcr.io/purpleneutral/chatalot:latest\n    build: !reset null\n```\n\nThen run `docker compose up -d` as normal. The correct architecture (amd64 or arm64) is selected automatically.\n\n## Expose to the Internet\n\n### Option A: Cloudflare Quick Tunnel (free, no domain needed)\n\n```bash\ndocker compose --profile quick-tunnel up -d\n```\n\nThis spins up a `cloudflared` container that creates a temporary public URL. Check the logs for your URL:\n\n```bash\ndocker compose logs cloudflared-quick | grep trycloudflare\n```\n\nShare that URL with your friends — it works immediately, no DNS or certificates to configure.\n\n### Option B: Cloudflare Named Tunnel (persistent domain)\n\n```bash\n# Add your tunnel token to .env\necho \"CLOUDFLARE_TUNNEL_TOKEN=your_token\" \u003e\u003e .env\n\n# Start with the production profile\ndocker compose --profile production up -d\n```\n\n### Option C: Reverse Proxy (Traefik, nginx, Caddy, etc.)\n\nThe server listens on port 8080. Create a `docker-compose.override.yml` (gitignored):\n\n```yaml\nservices:\n  chatalot:\n    labels:\n      - \"traefik.enable=true\"\n      - \"traefik.http.routers.chatalot.rule=Host(`chat.example.com`)\"\n      - \"traefik.http.routers.chatalot.entrypoints=websecure\"\n      - \"traefik.http.routers.chatalot.tls=true\"\n      - \"traefik.http.services.chatalot.loadbalancer.server.port=8080\"\n    networks:\n      - proxy-network\n\nnetworks:\n  proxy-network:\n    external: true\n```\n\nWebSocket connections at `/ws` are proxied automatically.\n\n## Desktop App\n\nNative desktop clients are built with Tauri 2.0. They connect to any Chatalot server — just enter the URL on first launch.\n\n### Download\n\nCheck the [Releases](../../releases) page for:\n- **Linux**: AppImage (run anywhere), `.deb`, `.rpm`\n- **Windows**: NSIS installer (`.exe`)\n\n### Build from source\n\n```bash\n# Install Tauri CLI\ncargo install tauri-cli\n\n# Install web dependencies\ncd clients/web \u0026\u0026 npm install \u0026\u0026 cd ../..\n\n# Build (this also builds the web frontend automatically)\ncd clients/desktop/src-tauri \u0026\u0026 cargo tauri build\n```\n\nRequires Rust 1.84+, Node.js 22+, and platform-specific dependencies (WebKitGTK on Linux, WebView2 on Windows).\n\n## Tech Stack\n\n| Layer | Technology |\n|-------|-----------|\n| Server | Rust (axum + tokio) |\n| Database | PostgreSQL 17 |\n| Web Client | Svelte 5 + Tailwind CSS |\n| Desktop Client | Tauri 2.0 |\n| E2E Encryption | X3DH + Double Ratchet, ChaCha20-Poly1305 (Rust → WASM) |\n| Auth | Argon2id passwords, Ed25519-signed JWTs, refresh token rotation |\n| Voice/Video | WebRTC mesh (up to 25 participants) |\n| Deployment | Docker Compose, Cloudflare Tunnel |\n\n## Security\n\n### Encryption\n\nThe server is designed as an **untrusted relay** — it stores and routes messages but is architecturally separated from plaintext content.\n\n- **DMs**: X3DH key agreement + Double Ratchet — forward secrecy and break-in recovery, compiled to WASM and running client-side\n- **Groups**: Sender Keys — each member distributes a symmetric chain key; key rotation on member removal\n- **Cipher**: ChaCha20-Poly1305 (AEAD)\n- **Key exchange**: X25519\n- **Signatures**: Ed25519\n- **Key storage**: IndexedDB (web), OS keychain (desktop, planned)\n- **Session persistence**: Double Ratchet sessions and decrypted message cache stored in IndexedDB\n- **Prekey management**: Automatic replenishment when one-time prekeys run low\n\n### Authentication\n\n- Passwords hashed with **Argon2id** (64 MiB memory, 3 iterations, 4 lanes)\n- **JWT access tokens**: 15-minute expiry, Ed25519-signed\n- **Refresh tokens**: 30-day expiry, stored as SHA-256 hash, rotated on each use\n- **TOTP 2FA**: RFC 6238, optional per-user, with 8 single-use backup codes\n- **Recovery codes**: self-service password reset without email, generated at registration\n- **Account lockout**: 10 failed attempts triggers 15-minute lockout\n\n### Server Hardening\n\n- Rate limiting: token-bucket per IP (20 req/s general, 5 req/s auth)\n- Security headers: HSTS, CSP, X-Frame-Options, Permissions-Policy\n- SSRF protection on link previews (blocks private/internal IPs)\n- Channel authorization on all message, file, and typing operations\n- Audit logging of all auth events with IP and user agent\n\n## Project Structure\n\n```\nchatalot/\n├── crates/\n│   ├── chatalot-server/       # axum HTTP/WS server\n│   │   └── src/\n│   │       ├── routes/        # REST API endpoints\n│   │       ├── ws/            # WebSocket handler + connection manager\n│   │       ├── middleware/     # JWT auth, rate limiting, security headers\n│   │       └── services/      # Auth service, business logic\n│   ├── chatalot-db/           # Database layer (repository pattern)\n│   │   └── src/\n│   │       ├── models/        # Rust structs matching DB tables\n│   │       └── repos/         # Query functions per entity\n│   ├── chatalot-crypto/       # E2E encryption library\n│   │   └── src/\n│   │       ├── x3dh.rs        # X3DH key agreement\n│   │       ├── double_ratchet.rs\n│   │       ├── sender_keys.rs\n│   │       └── aead.rs        # ChaCha20-Poly1305\n│   ├── chatalot-crypto-wasm/  # WASM bindings for browser crypto\n│   └── chatalot-common/       # Shared types (API DTOs, WS messages)\n├── clients/\n│   ├── web/                   # Svelte 5 SPA\n│   │   └── src/\n│   │       ├── lib/api/       # REST client\n│   │       ├── lib/crypto/    # E2E crypto (WASM loader, IndexedDB, session manager)\n│   │       ├── lib/ws/        # WebSocket client\n│   │       ├── lib/stores/    # Svelte 5 rune-based state (17 stores)\n│   │       ├── lib/components/# Reusable UI components\n│   │       ├── lib/utils/     # Emoji data, helpers\n│   │       ├── lib/webrtc/    # WebRTC call manager\n│   │       └── routes/        # Pages\n│   └── desktop/               # Tauri 2.0 wrapper\n├── docs/                      # Detailed documentation\n├── migrations/                # PostgreSQL migrations (48 files)\n├── scripts/\n│   ├── install.sh             # Interactive setup wizard\n│   ├── deploy.sh              # Automated deploy (commit, push, pull, rebuild)\n│   ├── generate-secrets.sh    # Generate JWT keys + .env\n│   ├── generate-keys.sh       # Generate JWT keys only\n│   └── build-wasm.sh          # Build WASM crypto module for web client\n├── .github/workflows/         # CI: multi-arch Docker image builds (amd64 + arm64)\n├── Dockerfile                 # Multi-stage build\n└── docker-compose.yml\n```\n\n## Environment Variables\n\n| Variable | Default | Description |\n|----------|---------|-------------|\n| `DATABASE_URL` | *required* | PostgreSQL connection string |\n| `JWT_PRIVATE_KEY_PATH` | `./secrets/jwt_private.pem` | Ed25519 private key |\n| `JWT_PUBLIC_KEY_PATH` | `./secrets/jwt_public.pem` | Ed25519 public key |\n| `TOTP_ENCRYPTION_KEY` | *optional* | Hex key for encrypting TOTP secrets at rest |\n| `REGISTRATION_MODE` | `invite_only` | `open`, `invite_only`, or `closed` |\n| `ADMIN_USERNAME` | *optional* | Username that gets admin privileges |\n| `LISTEN_ADDR` | `0.0.0.0:8080` | Server bind address |\n| `FILE_STORAGE_PATH` | `./data/files` | Encrypted file storage directory |\n| `MAX_FILE_SIZE_MB` | `100` | Max upload size in MB (1–10,000) |\n| `UPLOAD_QUOTA_MB` | `500` | Per-user upload quota in MB (0 = unlimited) |\n| `COMMUNITY_CREATION_MODE` | `admin_only` | `open` or `admin_only` |\n| `ICE_SERVERS` | *optional* | JSON array of STUN/TURN servers for WebRTC |\n| `RUST_LOG` | `info` | Log level |\n| `VAPID_PRIVATE_KEY` | *optional* | Base64-encoded ECDSA P-256 private key for web push notifications |\n| `VAPID_PUBLIC_KEY` | *optional* | Base64-encoded ECDSA P-256 public key for web push notifications |\n| `CLOUDFLARE_TUNNEL_TOKEN` | *optional* | For production Cloudflare Tunnel profile |\n| `GIPHY_API_KEY` | *optional* | Giphy API key for GIF search ([get one free](https://developers.giphy.com/dashboard/)) |\n\n## Development\n\n### Prerequisites\n\n- Rust 1.84+ (edition 2024)\n- Node.js 22+\n- PostgreSQL 17 (or use Docker)\n- [wasm-pack](https://rustwasm.github.io/wasm-pack/) (for building the crypto WASM module)\n\n### Running locally\n\n```bash\n# Database\ndocker compose up postgres -d\n\n# Server\ncp .env.example .env\n./scripts/generate-secrets.sh\ncargo run\n\n# Build WASM crypto module (required before web client)\n./scripts/build-wasm.sh\n\n# Web client (separate terminal)\ncd clients/web\nnpm install\nnpm run dev\n```\n\n### Tests\n\n```bash\ncargo test          # 59 unit tests (crypto, auth, security, CSS sanitizer)\ncargo clippy        # Lint checks\ncd clients/web \u0026\u0026 npm run check   # Svelte type checking\n```\n\n\u003e **Note**: The Docker build handles the WASM compilation automatically — `build-wasm.sh` is only needed for local development.\n\n## Deployment\n\n### Automated\n\n```bash\n# Full deploy: commit, push, pull on server, rebuild containers\n./scripts/deploy.sh \"your commit message\"\n\n# Just pull and restart on server\n./scripts/deploy.sh --pull-only\n```\n\nConfigure with environment variables: `DEPLOY_HOST`, `DEPLOY_DIR`, `DEPLOY_GIT_URL`. See `scripts/deploy.sh` for all options.\n\n### Manual\n\n```bash\ngit clone \u003crepo-url\u003e chatalot \u0026\u0026 cd chatalot\n./scripts/generate-secrets.sh\ndocker compose up -d --build\n```\n\n## For Hosts\n\nRunning a Chatalot instance means you're responsible for the people who use it. Here's what that looks like:\n\n- **You control registration** — use invite-only mode (default) to decide who joins. Generate codes from the admin panel with usage limits and expiration.\n- **You moderate content** — use the reports queue, user warnings, bans, timeouts, and slow mode. You can suspend accounts and purge content.\n- **You handle data** — back up your PostgreSQL database and `data/` directory regularly. Messages are encrypted, but metadata (users, channels, memberships) is not.\n- **You're the authority** — the built-in Terms of Service and Privacy Policy are customizable defaults. Drop your own `data/terms-of-service.md` and `data/privacy-policy.md` to override them.\n- **You're not the developer** — the Chatalot developers built the software but don't operate your instance. You're responsible for security, uptime, and compliance in your jurisdiction.\n\n## For Users\n\nJoining a Chatalot instance means trusting the person who runs it. Here's what you should know:\n\n- **Verify your host** — E2E encryption protects message content, but the server admin controls the infrastructure. Only join instances run by people you trust.\n- **Save your recovery code** — it's shown once at registration. It's the only way to reset your password without admin help. You can regenerate it from Settings \u003e Security.\n- **Enable 2FA** — TOTP-based two-factor authentication adds a second layer of protection. Save your 8 backup codes in case you lose your authenticator.\n- **E2E encryption protects content, not metadata** — the server can see who you message and when, but not what you say. Channel names, usernames, and membership are visible to admins.\n- **Your data stays on this instance** — there's no federation, no cloud sync, and no third-party analytics. When you delete your account, your data is removed.\n\n## Support\n\nIf Chatalot is useful to you, consider buying me a coffee:\n\n[![Buy Me A Coffee](https://img.shields.io/badge/Buy%20Me%20A%20Coffee-support-yellow?style=flat\u0026logo=buy-me-a-coffee)](https://buymeacoffee.com/uniqueuserg)\n\n## License\n\nGPL-3.0 — see [LICENSE](LICENSE) for details.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fpurpleneutral%2Fchatalot","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fpurpleneutral%2Fchatalot","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fpurpleneutral%2Fchatalot/lists"}