summaryrefslogtreecommitdiff
path: root/README.md
diff options
context:
space:
mode:
authorPaul Buetow <paul@buetow.org>2026-07-02 10:01:50 +0300
committerPaul Buetow <paul@buetow.org>2026-07-02 10:01:50 +0300
commit67babb244b8ab6fcdfe3748b1c52fcac60eb2ed4 (patch)
tree88c40aff603237cb5eacc9fbc76de8b56d7aaff1 /README.md
parent462e4ac6995760646b53e110f2662a6cd14fc882 (diff)
ychat: remove the no-database build option (task es0)
DATABASE/SQLite is no longer optional. src/configure.ac and the generated src/configure now check sqlite3.h/-lsqlite3 unconditionally, the same way pthread/libevent already were, right after those checks (matching order in both files) - there's no --enable-sqlite opt-in any more, and configure aborts via header_error/lib_error if SQLite isn't available rather than silently producing the old in-memory-only, no-account "Mode A" guest chat. --enable-mysql is left alone (pre-existing, separately broken, out of scope - this is about ychat always having *a* database, not about MySQL). With DATABASE guaranteed, the three recent no-DB-build UI special-cases (651f762, 0cdec77, 6c3a65b) are dead code, so they're reverted: deleted html/index_guest.html, reverted html/input.html + src/reqp.cpp to always render a static Options link (dropped the #ifdef DATABASE/%%OPTIONS_LINK%% templating), and the Dockerfile no longer strips register.html/options.html or their .so modules. Unregistered guest chatting itself is untouched - chat.enableguest is a runtime config toggle independent of the compile-time database requirement, and a guest's is_reg is still always false so a guest can never claim operator via chat.defaultop. Consolidated the two Dockerfiles into one (SQLite-backed; deleted Dockerfile.sqlite) and merged DOCKER.md/DOCKER-SQLITE.md into a single DOCKER.md. Updated root README.md and etc/ychat.conf's option descriptions to stop claiming the no-DB build is live/default. Verified in a Rocky Linux 9 podman container: index.html has the password field + Register link, register.html/options.html both resolve, POSTing to register.html creates a SQLite user row, wrong password is rejected and the correct one logs in, the same account's login still works identically after a full container restart with /app/data bind-mounted (persistence), and unregistered guest login still works. Independently reproduced by a fresh-context review agent, which also rebuilt + re-verified the whole flow itself and caught one real (if harmless) issue - the generated src/configure had the SQLite check in a different physical position than configure.ac's - now fixed so both files agree on ordering. Not deployed to f3s: the live cluster still runs the old no-DB image. Rolling this out needs a persistent volume for /app/data and an updated Helm chart - a deliberate follow-up, not done here. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Diffstat (limited to 'README.md')
-rw-r--r--README.md60
1 files changed, 34 insertions, 26 deletions
diff --git a/README.md b/README.md
index 8cbc53e..120f09c 100644
--- a/README.md
+++ b/README.md
@@ -6,15 +6,13 @@ are kept here as historical/revival code.
| Subproject | What it is | Status |
|------------|------------|--------|
-| [`./ychat`](ychat/) | An HTTP-based web chat server (browsers are the clients; CSS/HTML/JS only). | **Revived & deployed** — Mode A (in-memory guest chat) builds in Docker, runs on the f3s k3s cluster. Mode B (embedded SQLite, real persistent accounts) builds and works locally — see [`ychat/DOCKER-SQLITE.md`](ychat/DOCKER-SQLITE.md) — but isn't deployed. |
+| [`./ychat`](ychat/) | An HTTP-based web chat server (browsers are the clients; CSS/HTML/JS only). | **Revived, builds in Docker with a mandatory embedded-SQLite backend** (real, persistent registered accounts) — see [`ychat/DOCKER.md`](ychat/DOCKER.md). Builds and is verified locally; **not yet deployed** to f3s — the live cluster (`https://ychat.f3s.lan.buetow.org/`) still runs an older, in-memory-only, no-database image. |
| [`./yhttpd`](yhttpd/) | A tiny standalone http server derived from ychat's socket/threading engine. | Builds and serves reliably in Docker (verified under concurrent load) — not deployed. See [`./yhttpd/DOCKER.md`](yhttpd/DOCKER.md). |
| [`./ycurses`](ycurses/) | A curses front-end experiment. | Builds and runs in Docker (a demo, not a service, so nothing to deploy) — see [`./ycurses/BUILD.md`](ycurses/BUILD.md). |
The detailed, up-to-date build/deploy notes for the chat live in
-[`./ychat/DOCKER.md`](ychat/DOCKER.md) (Mode A) and
-[`./ychat/DOCKER-SQLITE.md`](ychat/DOCKER-SQLITE.md) (Mode B). The rest of
-this file is a quickstart for running **ychat** locally in Docker and
-accessing it.
+[`./ychat/DOCKER.md`](ychat/DOCKER.md). The rest of this file is a
+quickstart for running **ychat** locally in Docker and accessing it.
> The ychat tree has been substantially fixed during this revival (legacy-C++
> build fixes, a from-scratch streaming-chat layer, and a security/bug sweep).
@@ -38,15 +36,17 @@ podman build -t ychat:dev .
# or: docker build -t ychat:dev .
```
-The build configures ychat with all optional features off (no SSL, no MySQL,
-no readline) — this is "Mode A": an **in-memory guest chat with no account
-database**. The default chat port is **2000**.
+The build configures ychat with SSL and readline off, but a database is not
+optional: `./configure` always requires SQLite (`sqlite3.h`/`libsqlite3`),
+so registration/login persist in a SQLite file across container restarts.
+The default chat port is **2000**.
### 2. Run it
```sh
-podman run --rm -p 2000:2000 --name ychat ychat:dev
-# or: docker run --rm -p 2000:2000 --name ychat ychat:dev
+mkdir -p /tmp/ychat-data && chmod 777 /tmp/ychat-data # see DOCKER.md for why
+podman run --rm -p 2000:2000 --name ychat -v /tmp/ychat-data:/app/data:Z ychat:dev
+# or: docker run --rm -p 2000:2000 --name ychat -v /tmp/ychat-data:/app/data ychat:dev
```
The server logs to stdout. You should see something like:
@@ -62,8 +62,10 @@ Initializing sock events (1)
Open http://localhost:2000/ in a browser.
-- You'll get the **guest login page** (no password field, no "Register" link —
- there is no account database in this build).
+- You'll get the full login page (password field + "Register" link). You can
+ register a nick/password (persisted in the SQLite file under
+ `/app/data`), or leave the password blank and log in as an unregistered
+ guest — `chat.enableguest=true` allows that regardless of the database.
- Enter any alphanumeric nick (e.g. `alice`), leave the room as `Lounge`, and
click **login**.
- The chat frameset loads: a streaming message view, the online-user list, and
@@ -93,32 +95,38 @@ podman rm -f ychat
## Notes on the local run
-- **State is in-memory only.** With no database, all users/sessions/rooms live
- in RAM and are wiped on container restart. That's intentional for the
- revival; `chat.enableguest=true` lets anyone log in with just a nick.
+- **Registered accounts persist; guest sessions don't.** The SQLite file at
+ `/app/data/ychat.db` (bind-mount it, as above, to survive container
+ restarts) holds registered users. Sessions/rooms/online-state are still
+ in-memory, and unregistered `chat.enableguest=true` guest chatters are
+ wiped on restart same as before — only the accounts table persists.
- **Logs** go to `/app/log/` inside the container (`access_log`, `system_log`,
`rooms/<room>`). They're an `emptyDir` in k8s and a container-local dir
locally, so they don't persist after `rm`.
- **Configuration** is `ychat/etc/ychat.conf`, baked into the image at
`/app/etc/ychat.conf`. You can override any config key at runtime with
`-o <key> <value>` (the image already does this for
- `chat.session.md5hash=false` and `httpd.startsite=index_guest.html`).
+ `chat.session.md5hash=false` and `chat.database.dbname=data/ychat.db`).
Example: `podman run --rm -p 2000:2000 ychat:dev /app/bin/ychat -o chat.idle.timeout 300`.
-- **No operator commands for guests.** The default-operator escalation
- (`/exec` shell RCE) was removed for security; in this no-DB build there is no
- authenticated operator, so privileged commands (`/ko`, `/ban`, `/exec`, …)
- are unavailable by design.
+- **The `/exec` command module is removed from the image entirely**
+ (defense-in-depth against its shell-injection RCE), and operator status
+ via `chat.defaultop` now requires a database-authenticated registered
+ account — an unregistered guest can never claim it. Other privileged
+ commands (`/ko`, `/ban`, …) work normally for a registered operator.
---
## Deploying to the f3s k3s cluster
-This is covered in detail in [`./ychat/DOCKER.md`](ychat/DOCKER.md). In short:
-the image is pushed to the f3s private registry
-(`r0.lan.buetow.org:30001/ychat:<tag>`), and a Helm chart + ArgoCD Application
-in the [`conf` repo](https://codeberg.org/snonux/conf) (path
-`f3s/ychat/helm-chart`) deploy it. The LAN URL is
-**https://ychat.f3s.lan.buetow.org/**.
+This is covered in detail in [`./ychat/DOCKER.md`](ychat/DOCKER.md) (push
+steps, Helm chart, ArgoCD Application in the
+[`conf` repo](https://codeberg.org/snonux/conf), path
+`f3s/ychat/helm-chart`). **The DB-backed build described in this README is
+not deployed there yet** — the live LAN URL
+(**https://ychat.f3s.lan.buetow.org/**) currently still serves the older,
+in-memory-only, no-database image. Rolling out this build needs a persistent
+volume for `/app/data` (the existing Helm chart doesn't provision one) and
+is a deliberate follow-up, not automatic.
---