feat(certs): auto-generate TLS cert on first run (closes #62)#67
Merged
Conversation
Hub-side luadch generates a server cert on first boot - the
operator never has to think about it. The announcer used to require
`certs/make_cert.{bat,sh}` to be run manually before the first
connect, which is poor UX for a tool that is otherwise
fire-and-forget. Sopor specifically asked for parity.
Fix: new `core/cert_autogen.lua` module with a single function
`cert_autogen.ensure(cert_path, key_path)`:
- returns true immediately if both files exist (steady-state
cost: two file_exists checks)
- shells out to openssl to generate the pair if either is
missing; chain mirrors make_cert.{bat,sh} exactly (EC
prime256v1 + single-use CA, 10-year validity)
- cleans up the transient cakey.pem + cacert.pem post-signing
so the runtime certs/ holds only servercert.pem + serverkey.pem
- cross-platform: Windows vs POSIX detected via package.config,
null redirect + openssl probe (where/which) adapted per
platform; openssl flags are identical
- graceful failure when openssl is not on PATH: returns false +
a message that points at the manual make_cert script as
fallback
Hooked at two places so both CLI and GUI users get coverage
regardless of entry path:
1. core/net.lua module-load (before ssl.newcontext reads the
files) - catches the CLI frontend AND the GUI's spawned
worker. Failures print to stderr (drained into logfile.txt
by the #59 capture) AND log.event.
2. frontends/gui/Announcer.wx.lua validate.cert at GUI startup -
replaces the legacy "Please generate manually" error with a
silent successful generation; only when openssl is unavailable
do we fall through to the operator-action error.
Live test on rc2 install: moved existing certs/*.pem aside, ran
`lua.exe frontends/cli/main.lua`. Result: fresh servercert.pem
(602 B) + serverkey.pem (310 B) generated, no CA leftover, logfile
shows "Certificates verified at certs/servercert.pem", announcer
proceeded into normal directory scanning + announce loop.
Note: the Windows release zip already ships libssl-3 + libcrypto-3
DLLs for LuaSec but NOT the `openssl.exe` binary. Operators on
Windows without OpenSSL installed still see the legacy
"Run make_cert.bat manually" hint and can install OpenSSL OR run
the script with a PATH-resolved openssl from a different path.
Shipping openssl.exe is a deliberate non-decision; the Windows
binary footprint stays minimal.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
The original smoke test expected the announcer to die immediately at ssl.newcontext with "error loading private key" because CI installs have no cert pair. With #62 introducing cert_autogen.ensure() at net.lua module load, the announcer NOW generates a working cert pair on the fly (both CI runners have openssl available) so ssl.newcontext succeeds, the announcer enters its reconnect loop, and the smoke command never returns - the job hangs until the 60-minute GitHub Actions step timeout. Two changes per platform (linux + windows): 1. Wrap the announcer invocation in `timeout 5s` so the smoke step always returns within bounded time. The announcer's reconnect loop with cfg.sleeptime=10 would never exit on its own. 2. Switch the success sentinel from the stdout-side "error loading private key" string to the logfile-side "Certificates verified at" line emitted by cert_autogen on success. This actually exercises #62 end-to-end: the smoke verifies cert_autogen ran and reached the post-gen log point. 3. For the anchored-path run, `rm -f certs/*.pem` first so cert_autogen actually re-exercises its generate path on this second invocation (otherwise the first invocation's output is what the second test would observe). Tested mentally against the failing #67 CI runs which hung exactly at the smoke step "Frontend bootstrap smoke (relative arg[0], fallback path)" with all earlier steps green. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Make the cert_autogen grep airtight: previously the second (anchored-path) test would have falsely passed if its own cert_autogen step failed but the first (fallback-path) step's "Certificates verified at" line was still in the appended logfile. Wiping log/logfile.txt before each invocation ensures the grep reflects only the current run. Same cleanup added to both linux + windows smoke jobs. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Aybook
added a commit
that referenced
this pull request
Jun 12, 2026
_VERSION bumped 1.0.0-dev -> 1.0.0-rc3 (visible in About window, title bar, tray-icon tooltip, status bar, and the "ready" log line). Release body re-leads with the rc2 -> rc3 delta: - #65 / #63 - TLS RadioBox overflow + missing taskbar .exe icon + branded About refresh - #66 / #59 - GUI worker stderr capture into log/logfile.txt - #67 / #62 - first-run cert auto-generation - #64 / #61 - tray exit crash + restore-from-tray (already in main since rc2-tag; documented for completeness as the load-bearing GUI fix between rc2 and rc3) Tag will be pushed once this lands on main; release.yml auto-detects the `-rc3` suffix as a SemVer pre-release. Co-authored-by: Claude Opus 4.7 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Sopor asked for hub-style auto-generation of the TLS cert on first run. New `core/cert_autogen.lua` module shells out to openssl when `certs/servercert.pem` / `certs/serverkey.pem` are missing, mirroring `make_cert.{bat,sh}` exactly (EC prime256v1 + single-use CA + 10-year validity + cleanup of transient cakey.pem / cacert.pem).
Hooked in two places for coverage across entry paths:
Behaviour
Live test (rc2 Windows install)
```
$ ls certs/*.pem
servercert.pem
serverkey.pem
$ mv certs/servercert.pem certs/serverkey.pem /tmp/
$ ./lua.exe frontends/cli/main.lua
... announcer starts normally, no errors
$ ls -la certs/*.pem
-rw-r--r-- 1 ... 602 ... certs/servercert.pem
-rw-r--r-- 1 ... 310 ... certs/serverkey.pem
$ grep cert log/logfile.txt
[ 2026-06-12 / 15:01:08 ] Certificates verified at certs/servercert.pem
```
Auto-gen ran, fresh pair created, no `cakey.pem` / `cacert.pem` leftover, announcer proceeded into normal directory scanning + announce loop without operator intervention.
Out of scope
Test plan
🤖 Generated with Claude Code