summaryrefslogtreecommitdiff
path: root/docs/CHAT-PRODUCTION.txt
diff options
context:
space:
mode:
Diffstat (limited to 'docs/CHAT-PRODUCTION.txt')
-rw-r--r--docs/CHAT-PRODUCTION.txt222
1 files changed, 222 insertions, 0 deletions
diff --git a/docs/CHAT-PRODUCTION.txt b/docs/CHAT-PRODUCTION.txt
new file mode 100644
index 0000000..fdb48a6
--- /dev/null
+++ b/docs/CHAT-PRODUCTION.txt
@@ -0,0 +1,222 @@
+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 main. Builds/tests do not activate the VPS. Experimental;
+ no independent cryptographic or application security audit. Read
+ CHAT-APPLICATION.txt limitations before private use.
+
+ Rootless Podman runs Caddy, cgit, SearXNG, and chat. Releases contain static
+ x86_64 GNU/Linux management/chat binaries, browser WASM, exact corresponding
+ sources, and native images. Chat starts FROM scratch: no compiler, shell,
+ package manager, or first-party Python. Root filesystem is read-only;
+ capabilities are dropped; only private data is writable.
+
+ Caddy serves HTTPS at CHAT_HOST and redirects www.CHAT_HOST, preserving paths.
+ CHAT_UPSTREAM defaults to private chat:8080. Chat publishes no host ports;
+ only gateway HTTP and TCP/UDP HTTPS are published. Host SSH policy is separate.
+
+ Root .env selects the explicit external origin. Chat accepts exactly that
+ HTTPS origin or the dedicated local gateway origin. Forwarded client headers
+ cannot select it. Origin checks supplement cryptographic authentication.
+
+BUILD ON THE WORKSTATION
+
+ Build host and target must be x86_64 GNU/Linux. Requires pinned Rust, Podman,
+ Git, GnuPG, GCC-compatible C compiler, Linux UAPI headers, libclang, pkg-config,
+ make, Perl, curl, tar, Node >=22.18.0, npm, and OpenSSL 3.5+ development libraries.
+ Browser tests also need pinned Playwright, Chromium, and Firefox. Workstation
+ tools stay local; production needs neither Cargo nor compiler.
+
+ cargo stack release
+
+ Runs TypeScript build/checks, formatting, strict Clippy, workspace tests,
+ rustdoc, cargo-deny, and cargo-about. Builds static binaries, WASI, exact
+ sources, chat/cgit images, and complete image export. Regenerates workspace
+ THIRD-PARTY-LICENSES.html. Verify archive checksum and 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: official OpenSSL GitHub release and Alpine CDN. Compilation uses
+ isolated musl/GCC built-in and host Linux UAPI headers, excluding glibc.
+ Static OpenSSL has no dynamic providers and seeds through getrandom. The
+ native compatibility probe must pass. WASI uses separately verified SDK/OpenSSL
+ inputs in CHAT-OPENSSL-MIGRATION.txt. Cryptographic algorithms stay fixed.
+
+ Inputs cache under .tools/. Version/source/flag changes require an OpenSSL
+ rebuild. Updates require upstream advisory review, every affected URL/hash,
+ native/WASI rebuilds, both browsers, cargo-deny, regenerated notices/sources,
+ and release recovery. Never waive advisories to pass. cargo-deny excludes C/OpenSSL.
+
+ Source downloads include first-party code, Cargo-vendored dependencies, and
+ unmodified OpenSSL, excluding development toolchain/sysroot inputs. Saved
+ images preserve tested runtime. ARM requires a separately supported native release.
+
+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
+
+ Distinct origins require separate identity files. Direct development and
+ production share a relative database path on separate machines; do not switch
+ valuable installations between them. Integration tests need a fresh restored
+ release. Rebuild after edits to refresh browser, server, sources, notices, and image.
+
+ One root .env holds hostnames, ports, upstreams, backups, SEARXNG_SECRET, and
+ CHAT_SETUP_TOKEN. Only the example is public; releases/source downloads exclude
+ actual .env. Caddy keys/chat databases stay under var/data. Initialization
+ preserves configured values and generates missing secrets.
+
+DEPLOY AND CREATE THE REAL OWNER FILE
+
+ Follow OPERATIONS.txt. Extract the verified release's new management binary
+ into var/incoming/bootstrap; invoke with --root set to the current installation.
+ The new binary understands its release schema, verifies the archive, and
+ installs chat artifacts before startup.
+ 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 restarts
+ failed containers. Complete matching-architecture releases need no compilation
+ or registry pull. 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.
+
+ At the production HTTPS origin, choose OWNER SETUP. Read the root .env token
+ locally; never publish or send it through chat. Choose a unique password;
+ save, reopen, and unlock the downloaded owner file. Keep file/password in
+ KeePassXC with a protected database backup. The token cannot replace the file.
+ Never silently change a development file's pinned origin.
+
+BACKUP, RESTORE, AND KEY LOSS
+
+ A complete encrypted application export:
+ ./bin/stack backup --include-images
+
+ Copy .gpg and .sha256 off the VPS; local backups cannot survive VPS loss.
+ Configured recipients apply. Export includes one .env, online SQLite snapshots
+ for chat/chat-local, Caddy certificates, repositories, static binaries, WASM,
+ sources, and exact images. Chat stays unpaused so pending writers can complete.
+ Database contents are ciphertext/public keys and CHAT-APPLICATION.txt metadata.
+ Owner private file and GnuPG secret key need separate backups.
+
+ 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 with fresh project names, avoiding replacement
+ of another installation. up --production reselects production database/origin.
+ Keep hostname/origin, repoint DNS, and use unchanged identity files/passwords.
+ IP changes preserve origin; hostname/HTTPS-port changes do not. Never expose
+ two restored copies under one origin. Restart invalidates sessions; reopening
+ files authenticates again. Historical ciphertext/counters persist.
+
+ CHAT_SETUP_TOKEN cannot recover a lost private file. If backups are also lost,
+ reset deletes every conversation/message; it decrypts and recovers nothing.
+ Reset 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
+
+ Reset requires a stopped server and matching full fingerprint. Root .env and
+ exports survive. Create a new production owner file; old visitor files reject
+ its changed key and need fresh identities. Exports/external snapshots are not erased.
+
+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 npm run test:chat
+
+ 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.