1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
|
# ychat / yhttpd / ycurses
This repository collects three small, legacy C++ projects by Paul C. Buetow
(originally ~2003–2007). They share a common socket/event/template engine and
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, builds in Docker with a mandatory embedded-SQLite backend** (real, persistent registered accounts) — see [`ychat/DOCKER.md`](ychat/DOCKER.md). **Deployed to f3s** (`https://ychat.f3s.lan.buetow.org/`) with a persistent volume backing `/app/data`, image tag `67babb2`. |
| [`./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). 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).
> See `git log` under `./ychat` and `./ychat/DOCKER.md` for the full list.
---
## Quickstart: run ychat locally in Docker
You need a container runtime (`podman` or `docker`). The build is a
multi-stage `Dockerfile` (Rocky Linux 9 builder + slim Rocky 9 runtime) that
compiles ychat **entirely inside the container** — no host toolchain required.
### 1. Build the image
From the **repository root**:
```sh
cd ychat
podman build -t ychat:dev .
# or: docker build -t ychat:dev .
```
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
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:
```
yChat 0.9.0-CURRENT Build ...
Sock: Created socket on localhost:2000
Sock: Server socket is ready
Initializing sock events (1)
```
### 3. Access it
Open http://localhost:2000/ in a browser.
- 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
an input box. Type a message and hit **Send** — it appears in the stream.
- Open a second browser/window with a different nick in the same room to see
messages delivered to both clients in real time.
Quick CLI checks:
```sh
# the login page (HTTP/1.1, 200):
curl -sS http://localhost:2000/ -o /dev/null -w '%{http_code}\n'
# log in and grab a session tmpid:
curl -sS -X POST -d 'event=login&nick=alice&room=Lounge&end=end' \
http://localhost:2000/frameset.html
```
### 4. Stop it
```sh
podman rm -f ychat
# (Ctrl-C also stops the foreground `run` above)
```
---
## Notes on the local run
- **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 `chat.database.dbname=data/ychat.db`).
Example: `podman run --rm -p 2000:2000 ychat:dev /app/bin/ychat -o chat.idle.timeout 300`.
- **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
Deploying ychat to a homelab k3s cluster (image build/push, Helm chart,
ArgoCD Application, PVC requirements) is homelab-specific and **not**
documented in this public repo. **The DB-backed build described in this README is now
deployed** — the live LAN URL (**https://ychat.f3s.lan.buetow.org/**) serves
image tag `67babb2` with a persistent volume (`ychat-data-pvc`, hostPath-backed
NFS share) mounted at `/app/data`, so registered accounts survive pod
restarts. Chart/manifests live in the `conf` repo under
`f3s/ychat/helm-chart/`.
---
## License
GPL-2.0 (see [`./ychat/COPYING`](ychat/COPYING)). Source:
https://codeberg.org/snonux/ychat
|