diff options
Diffstat (limited to 'docs/CHAT-PRODUCTION.txt')
| -rw-r--r-- | docs/CHAT-PRODUCTION.txt | 247 |
1 files changed, 247 insertions, 0 deletions
diff --git a/docs/CHAT-PRODUCTION.txt b/docs/CHAT-PRODUCTION.txt new file mode 100644 index 0000000..7e0e315 --- /dev/null +++ b/docs/CHAT-PRODUCTION.txt @@ -0,0 +1,247 @@ +Copyright (C) 2026 Doan Luu Duc Tai <doan@luuduct.ai> + +This program is free software: you can redistribute it and/or modify +it under the terms of the GNU Affero General Public License as +published by the Free Software Foundation, either version 3 of the +License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU Affero General Public License for more details. + +You should have received a copy of the GNU Affero General Public License +along with this program. If not, see <https://www.gnu.org/licenses/>. + + +PRODUCTION CHAT INTEGRATION + + Implemented on feature/private-chat. Building and testing a release does not + merge main or activate the VPS. This is experimental software without an + independent cryptographic or application security audit. Read the limitations + in CHAT-APPLICATION.txt before using it for private conversations. + + Four services run through rootless Podman: Caddy, cgit, SearXNG, and chat. + The release contains statically linked x86_64 GNU/Linux management and chat + binaries, the WASM browser module, exact corresponding sources, and saved + native container images. The chat image starts FROM scratch: no compiler, + shell, package manager, or first-party Python. Its root filesystem is read + only, capabilities are dropped, and only its private data directory is writable. + + Caddy terminates HTTPS at CHAT_HOST and redirects www.CHAT_HOST while keeping + the requested path. CHAT_UPSTREAM defaults to chat:8080 on the private + container network. Chat publishes no host ports. Production publishes only + the gateway HTTP and TCP/UDP HTTPS ports. Existing host SSH policy is separate. + + The gateway supplies an explicit external origin selected from root .env. + The server accepts that exact HTTPS origin or the dedicated local gateway + origin. Forwarded client headers never select the trusted origin. Origin + checks supplement cryptographic authentication; they are not authentication. + +BUILD ON THE WORKSTATION + + Current releases require an x86_64 GNU/Linux build host and matching target. + Use the pinned Rust toolchain, Podman, Git, GnuPG, a GCC-compatible C compiler, + Linux UAPI headers, libclang, pkg-config, make, Perl, curl, and tar. Native + workspace checks need OpenSSL 3.5+ development libraries. Browser testing + additionally needs Node, Playwright, Chromium, and Firefox. These tools remain + on the workstation; production does not need Cargo or a compiler. + + cargo stack release + + This runs formatting, strict Clippy, all workspace tests, rustdoc, cargo-deny, + and cargo-about. It then builds static native binaries, the WASI module, + corresponding sources, the chat/cgit images, and the complete image export. + THIRD-PARTY-LICENSES.html is regenerated from the full workspace before + packaging. Check the archive checksum and test recovery before deployment. + + infra/chat/build-native.sh verifies OpenSSL 3.6.5's original source archive: + a2157c2830efdec3788939b00c9b0638306d3f0bbb76dc4832ee503bb397df98 + It verifies Alpine musl-dev 1.2.6-r3 headers: + 310b51cff12e1d5ce5f135c558a82e2550427da5465bbd16c9ff9b05e63ee3d9 + Sources come from the official OpenSSL GitHub release and Alpine CDN. The + compiler uses isolated musl/GCC built-in headers plus host Linux UAPI headers; + glibc headers are excluded. OpenSSL is static, has no dynamic providers, and + seeds its RNG through getrandom. The native cryptographic compatibility probe + must pass after the build. WASI uses its separately verified SDK and OpenSSL + build recorded in CHAT-OPENSSL-MIGRATION.txt. No crypto algorithm was changed. + + Cached inputs live only under .tools/. Rebuild OpenSSL when its version, + source, or build flags change. An OpenSSL update requires reviewing upstream + security notices, updating every affected URL/hash, native and WASI rebuilds, + rerunning both browsers and cargo-deny, regenerating notices and exact source, + and repeating release recovery. Never approve a dependency advisory merely + to make the build pass. cargo-deny does not audit C/OpenSSL advisories. + + The source download includes first-party code, Cargo-vendored dependencies, + and unmodified OpenSSL source. Toolchain/sysroot development inputs are not + bundled as application sources. Saved images preserve the tested runtime. + An ARM host needs a separately supported native release; do not copy these + x86_64 binaries there and assume they will work. + +LOCAL MODES AND ORIGIN BINDING + + Direct Rust development: + cargo stack chat + http://127.0.0.1:9080/ + var/data/chat + + Container preview: + cargo stack dev + http://chat.localhost:8080/ + var/data/chat-local + + Production: + ./bin/stack up --production + https://CHAT_HOST/ with the configured HTTPS_PORT + var/data/chat + + These are distinct browser origins and require separate identity files. The + direct process and production deliberately use the same relative database + name on their respective machines. Do not switch an installation containing + valuable identities between direct development and production. Use a fresh + restored release directory for integration tests. Rebuild the release after + edits to refresh the packaged browser, server, sources, notices, and image. + + The single root .env holds public hostnames, ports, upstreams, backup settings, + SEARXNG_SECRET, and CHAT_SETUP_TOKEN. The example is public; actual .env is + ignored and never included in public releases or source downloads. Caddy keys + and chat databases are generated private runtime state under var/data. + Initialization preserves configured values and generates missing secrets. + +DEPLOY AND CREATE THE REAL OWNER FILE + + Use the release upload/activation instructions in OPERATIONS.txt. Extract + the new prebuilt management binary into var/incoming/bootstrap and invoke + it with --root pointing at the current installation. The older three-service + management binary cannot parse the new chat service schema; do not use that + older binary to activate this release. The new binary verifies the archive + and installs packaged chat artifacts before starting services. + The host needs rootless Podman prerequisites, user linger, low-port permission, + DNS A/AAAA records for CHAT_HOST and www.CHAT_HOST, and the normal 80/443 + firewall rules. Caddy obtains and renews public certificates automatically. + Public certificate validation requires standard reachable ACME ports. + + The systemd user service runs ./bin/stack up --production at boot and + ./bin/stack down on stop. Podman restart policies restart failed containers. + Neither mechanism compiles code or requests a registry pull for a complete + release on the matching architecture. Check all four services after activation: + + ./bin/stack status + + Check HTTPS, HTTP-to-HTTPS and www redirects, the homepage Services entry, + /LIMITATIONS.txt, /javascript.html, and /SOURCE.tar.gz on the chat origin. + The displayed limitations are CHAT-APPLICATION.txt. Chat has its own origin; + the main website remains JavaScript-free. Its Message Me links lead to chat. + + In the browser on the production HTTPS origin, choose OWNER SETUP. Read the + setup token from the production root .env locally; never publish it or send it + through chat. Choose a unique owner-file password, save the downloaded file, + reopen it, and unlock it. Store that file and password in KeePassXC and keep + a protected backup of the database. The setup token cannot replace this file. + Never copy a development owner file and silently change its pinned origin. + +BACKUP, RESTORE, AND KEY LOSS + + A complete encrypted application export: + ./bin/stack backup --include-images + + Download the .gpg and .sha256 files off the VPS. A backup on the same VPS is + vulnerable to loss of that VPS. Existing configured backup recipients apply. + This export includes the single .env, consistent SQLite snapshots for chat + and chat-local, Caddy certificate state, repositories, static binaries, WASM, + sources, and exact container images. SQLite uses its online backup API; chat + is left unpaused so a pending writer cannot block snapshot completion. + The database contains ciphertext and public keys, plus the metadata described + in CHAT-APPLICATION.txt. The owner private file and GnuPG secret key are not + server data; back them up separately. + + Restore to a new directory, verify, then explicitly start production mode: + ./bin/stack restore /path/export.tar.gz.gpg /path/stack-restored + cd /path/stack-restored + ./bin/stack up --production + + Restore defaults to local mode and changes container project names to avoid + accidentally replacing another installation. up --production selects the + production database and HTTPS origin again. Keep the same hostname/origin, + point DNS at the replacement host, and use unchanged owner/visitor files and + passwords. A new IP does not change an origin. A changed hostname or HTTPS + port does. Do not expose two restored copies simultaneously under one origin. + Server restart invalidates sessions; reopening identity files authenticates + again. Historical ciphertext and counters persist across restart and recovery. + + Losing the owner private file cannot be repaired by CHAT_SETUP_TOKEN. If its + backups are also lost, reset deliberately deletes every stored conversation + and message. It does not decrypt or recover anything. This backend operation + has no HTTP endpoint and requires filesystem/Podman access: + + ./bin/stack chat --owner-fingerprint + ./bin/stack down + ./bin/stack chat --reset-owner PASTE_CURRENT_OWNER_FINGERPRINT_HERE + ./bin/stack up --production + + A running server holds a filesystem lock; reset refuses until it stops. The + full fingerprint must match. Root .env and previous exports are preserved. + Create a new production owner file afterward. Old visitor files reject its + changed pinned owner key and need a new chat identity. A reset does not erase + copies already present in exports or external snapshots. + +VERIFICATION + + The browser harness supports packaged HTTPS installations without Rust or + target/ inside them. It creates disposable identities and a separate temporary + GnuPG key, takes a complete encrypted export with images during live chat, + restores into a new directory, starts the saved images, and reopens the same + files to decrypt history. It also exercises wrong passwords, safe text, + counters, 0-to-N history, 50-row batches, retry deduplication, origin rejection, + browser storage checks, and backend reset guards. It never resets real data. + + Example after restoring a release to a disposable staging directory and + configuring fixture .localhost hostnames, WEB_BIND=127.0.0.1, HTTP_PORT=8181, + HTTPS_PORT=8443, and LOCAL_HTTP_PORT=8180: + + ./bin/stack up --production + CHAT_TEST_ROOT=/absolute/disposable/stack CHAT_TEST_ORIGIN=https://chat.fixture.localhost:8443 PLAYWRIGHT_BROWSERS_PATH=.tools/browsers node crates/chat-server/tests/browser.mjs + + Run from the source checkout for the harness and Playwright installation. + Add CHAT_LIBREJS=1 for Firefox with the actual GNU LibreJS add-on. That test + verifies the add-on is active and blocks an unlicensed control script. + Disposable staging needs a fresh database for each complete run. + + Browser automation permits the fixture's private CA only for functional tests. + Separately verify its chain and hostname with curl --cacert and --resolve; + test the canonical route and www redirect without disabling verification. + Production uses ordinary trusted public certificates with no TLS bypass. + Passing these checks demonstrates recovery and functional compatibility; it + does not establish absence of attacks or constitute an independent audit. + +RECORDED RESULTS, 2026-10-31 + + The complete native workspace check passed: formatting, strict Clippy, + 14 tests, private rustdoc, cargo-deny with no ignored advisories, and + cargo-about generation. Static musl and WASI OpenSSL 3.6.5 probes passed + without changing the required RFC 9980 algorithms. + + Direct development passed in Chromium. Packaged HTTPS passed independently + in Chromium and Firefox with GNU LibreJS 7.21.1 active; its unlicensed-script + control was rejected. Both packaged tests recovered a complete encrypted + application export, including saved images, into a new directory, then + reopened the unchanged owner/visitor files and decrypted the history. + Export and checksum permissions were verified as 0600. + + Runtime inspection verified read-only root filesystem, zero effective + capabilities, no chat host ports, and unless-stopped restart policy. Killing + the disposable chat process with SIGKILL caused an automatic restart, and + its owner fingerprint persisted. The supplied systemd user unit passed + systemd-analyze verification; this did not reboot the real VPS. + + curl independently verified the fixture CA chain and hostname for canonical + chat, www redirect, and homepage. The homepage Services limitations link + resolved correctly. The source download matched the packaged source archive + byte-for-byte and contained only .env.example, without actual .env. + + Upgrade testing started the 2026-10-30 three-service release, then activated + the chat-enabled release through its new prebuilt management binary. All + four services started, existing data and SearXNG secret persisted, and the + new owner setup token was generated in the same root .env. These tests used + disposable local data; they did not register a real production owner. |
