fix(ergo): findings from reviewing the first live deploy
Seven confirmed findings from an observed-vs-expected review of a real deploy
transcript against the code (four other proposed findings were refuted and no
change was made for them).
- Caddyfile reformatted so `caddy fmt` is clean, removing the warning Caddy
printed on every validate and every start. Two causes, not one: `caddy fmt`
indents with TABS, and it deletes a blank line whose following line begins
with `{` -- which is why the warning pointed at line 17, the blank before the
global options block. The check is a whole-file byte comparison, so the line
number was only the first difference and the entire file had to be
reformatted. Verified whitespace-only outside the heredoc, whose body is left
byte-identical: Caddy strips padding derived from the closing marker's
indentation, so re-indenting it would change what the page serves.
- deploy.sh no longer upgrades Caddy behind the operator's back. A bare
`docker compose pull` refreshed the floating `caddy:2-alpine` on every re-run
and `up -d` then recreated it, doing exactly what CADDY_AUTOUPDATE=0 promises
not to, with none of update.sh's health check or rollback. Pulls are now
per service: the pinned Ergo tag always, Caddy only when absent or opted in.
- deploy.sh seeds the ACME_EMAIL and NETWORK_NAME prompts from .env, so pressing
Enter through a re-run no longer renames the network to the hostname in the
summary while .env keeps the real one.
- The Caddy restart guard compares the container's identity across `up -d`. A
container compose created or recreated has already read the new Caddyfile;
only one left running still holds the old config, and `svc_state` cannot tell
those apart.
- Container logs are now rotated (json-file, 10m x 3) on every service. Alpine's
docker package ships no daemon.json, so the default is unbounded, and the
60-second health probe alone writes a log line per run.
- ergoctl notes that LUSERS counts its own probe connection, which is why a
server with nobody on it reports one invisible user.
Verified: seven local suites pass, the embedded archive round-trips, line
endings are LF, and the reformatted Caddyfile is a verified fixed point of the
formatter (semantically identical token-for-token to the previous one).
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
+33
-34
@@ -14,42 +14,41 @@
|
||||
# Add your own site config (e.g. a Gamja web client, see README) as
|
||||
# conf.d/*.caddy -- deploy.sh installs this file but never touches conf.d/.
|
||||
# Apply changes with: docker compose restart caddy
|
||||
|
||||
{
|
||||
email {$ACME_EMAIL}
|
||||
email {$ACME_EMAIL}
|
||||
|
||||
# Host networking would put the admin API on the HOST's 127.0.0.1:2019,
|
||||
# reachable by every local process and container. The config is static, so
|
||||
# turn it off; changes are applied by restarting the container.
|
||||
admin off
|
||||
# Host networking would put the admin API on the HOST's 127.0.0.1:2019,
|
||||
# reachable by every local process and container. The config is static, so
|
||||
# turn it off; changes are applied by restarting the container.
|
||||
admin off
|
||||
|
||||
# No HTTP/3: it would bind udp/443 on the host (not in the firewall's port
|
||||
# list) and browsers do not run WebSockets over h3 anyway.
|
||||
servers {
|
||||
protocols h1 h2
|
||||
}
|
||||
# No HTTP/3: it would bind udp/443 on the host (not in the firewall's port
|
||||
# list) and browsers do not run WebSockets over h3 anyway.
|
||||
servers {
|
||||
protocols h1 h2
|
||||
}
|
||||
}
|
||||
|
||||
# Loopback-only health endpoint for the compose healthcheck (no admin API to ask).
|
||||
http://127.0.0.1 {
|
||||
respond "ok" 200
|
||||
respond "ok" 200
|
||||
}
|
||||
|
||||
{$ERGO_DOMAIN} {
|
||||
encode zstd gzip
|
||||
encode zstd gzip
|
||||
|
||||
# IRC over WebSocket. Ergo ignores the request path; Caddy proxies the
|
||||
# Upgrade transparently and supplies X-Forwarded-For/-Proto itself.
|
||||
handle_path /webirc* {
|
||||
reverse_proxy 127.0.0.1:8097
|
||||
}
|
||||
# IRC over WebSocket. Ergo ignores the request path; Caddy proxies the
|
||||
# Upgrade transparently and supplies X-Forwarded-For/-Proto itself.
|
||||
handle_path /webirc* {
|
||||
reverse_proxy 127.0.0.1:8097
|
||||
}
|
||||
|
||||
# Operator additions (web client, redirects, ...). See conf.d/00-readme.caddy.
|
||||
import conf.d/*.caddy
|
||||
# Operator additions (web client, redirects, ...). See conf.d/00-readme.caddy.
|
||||
import conf.d/*.caddy
|
||||
|
||||
handle {
|
||||
header Content-Type "text/plain; charset=utf-8"
|
||||
respond <<TXT
|
||||
handle {
|
||||
header Content-Type "text/plain; charset=utf-8"
|
||||
respond <<TXT
|
||||
{$NETWORK_NAME} -- IRC server
|
||||
|
||||
Connect with any IRC client:
|
||||
@@ -60,17 +59,17 @@ http://127.0.0.1 {
|
||||
Register a nickname: /msg NickServ REGISTER <password>
|
||||
Powered by Ergo (https://ergo.chat).
|
||||
TXT 200
|
||||
}
|
||||
}
|
||||
|
||||
header {
|
||||
Strict-Transport-Security "max-age=31536000; includeSubDomains"
|
||||
X-Content-Type-Options "nosniff"
|
||||
Referrer-Policy "strict-origin-when-cross-origin"
|
||||
-Server
|
||||
}
|
||||
header {
|
||||
Strict-Transport-Security "max-age=31536000; includeSubDomains"
|
||||
X-Content-Type-Options "nosniff"
|
||||
Referrer-Policy "strict-origin-when-cross-origin"
|
||||
-Server
|
||||
}
|
||||
|
||||
log {
|
||||
output stdout
|
||||
format console
|
||||
}
|
||||
log {
|
||||
output stdout
|
||||
format console
|
||||
}
|
||||
}
|
||||
|
||||
+686
-656
File diff suppressed because it is too large
Load Diff
@@ -45,6 +45,11 @@ services:
|
||||
- SETGID # the entrypoint drops from root to the postgres user
|
||||
- SETUID
|
||||
security_opt: [no-new-privileges:true]
|
||||
logging:
|
||||
driver: json-file
|
||||
options:
|
||||
max-size: "10m"
|
||||
max-file: "3"
|
||||
healthcheck:
|
||||
test: ["CMD-SHELL", "pg_isready -U \"${POSTGRES_USER:-ergo}\" -d \"${POSTGRES_DB:-ergo_history}\" -q"]
|
||||
interval: 15s
|
||||
|
||||
@@ -41,6 +41,11 @@ services:
|
||||
ERGO_DOMAIN: "${ERGO_DOMAIN}"
|
||||
ACME_EMAIL: "${ACME_EMAIL}"
|
||||
NETWORK_NAME: "${NETWORK_NAME}"
|
||||
logging:
|
||||
driver: json-file
|
||||
options:
|
||||
max-size: "10m"
|
||||
max-file: "3"
|
||||
healthcheck:
|
||||
# Loopback-only health site defined in the Caddyfile (the admin API is off).
|
||||
test: ["CMD-SHELL", "wget -qO- http://127.0.0.1/ | grep -q '^ok'"]
|
||||
@@ -69,6 +74,11 @@ services:
|
||||
tmpfs: [/tmp]
|
||||
volumes:
|
||||
- ./ircd:/ircd
|
||||
logging:
|
||||
driver: json-file
|
||||
options:
|
||||
max-size: "10m"
|
||||
max-file: "3"
|
||||
healthcheck:
|
||||
# IRC-level probe: Ergo answers a pre-registration QUIT with "ERROR :Quit"
|
||||
# and closes. A bare TCP connect would pass even with a wedged server.
|
||||
|
||||
@@ -226,6 +226,9 @@ cmd_users() {
|
||||
if (n=="265" || n=="266") sub(/^[^:]*:/, "")
|
||||
sub(/^:/, ""); sub(/ :/, " ")
|
||||
print " " $0 }'
|
||||
# LUSERS is answered while our own throwaway client is still registered, so
|
||||
# every count above includes it (and Ergo's default +i makes it "invisible").
|
||||
printf '%s\n' " (counts include ergoctl's own probe connection)"
|
||||
}
|
||||
|
||||
cmd_logs() {
|
||||
|
||||
Reference in New Issue
Block a user