docker: comprehensive config template pass - #58
Draft
MrLenin wants to merge 9 commits into
Draft
Conversation
…docker) nickserv.c register gates ldap_do_add on ldap_enable && ldap_admin_dn && ldap_writeback. The LDAP-docker templatization (b38ab2e) set ldap_enable etc. but never ldap_writeback, so it defaulted off — registrations landed in saxdb only (credential-less) and LDAP-authoritative SASL failed. Add %X3_LDAP_WRITEBACK% placeholder + X3_LDAP_WRITEBACK:=0 default. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
MrLenin
force-pushed
the
docker-template-completions
branch
from
August 1, 2026 06:43
2de9699 to
4476eb0
Compare
untrusted_max was hardcoded to 6 in x3.conf-dist, so any deployment using the docker template inherits the stock clone-G-line: a host exceeding 6 connections is auto-G-lined for clone_gline_duration (2h). On a testbed where a harness opens many connections from a single host, this auto-G-lines that host and the network appears dead (SASL/oper/link attempts all rejected) until the G-line expires — recurring on every heavy test run. Make it env-templated like the other X3_* settings: x3.conf-dist uses %X3_UNTRUSTED_MAX%, dockerentrypoint.sh defaults it to 6 (stock behavior preserved for normal deployments). A testbed sets X3_UNTRUSTED_MAX=0 (0 disables the clone-G-line entirely, per opserv.c) in its env so harness connection volume from one host is no longer auto-G-lined. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
The substitution loop uses '|' as the sed s/// delimiter but only escaped '/' and '&' in replacement values. A value containing '|' (any non-trivial LDAP filter, e.g. "(|(a=b)(c=d))") terminated the replacement early and corrupted the generated conf silently; a backslash was mis-handled too. Escape backslash FIRST (so the escapes added next are not re-escaped), then '&' and the '|' delimiter. '/' needs no escaping under a '|' delimiter. The empty-value warning behavior is unchanged, and the script stays bash -n clean. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Templatize the remaining hardcoded server-block identity settings: type -> %X3_SERVER_TYPE% (default 8) hidden_host_type -> %X3_HIDDEN_HOST_TYPE% (default 1) key1/key2/key3 -> %X3_HIDDEN_HOST_KEY1/2/3% (defaults 45432/76934/98336) prefix -> %X3_HIDDEN_HOST_PREFIX% (default NETWORK) Defaults preserve the shipped literals, so generated output is unchanged apart from two new comments: the type line now notes 8 = Nefarious 1.3.x / 9 = Nefarious 2.0.x (must match your ircd), and the key lines warn that they MUST match the ircd's HOST_HIDING_KEY* F:lines and that stock keys make style-2 cloaks predictable. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Templatize the remaining hardcoded nickserv (AuthServ) settings:
nick -> %X3_NICKSERV_NICK% (AuthServ)
default_maxlogins -> %X3_DEFAULT_MAXLOGINS% (3)
hard_maxlogins -> %X3_HARD_MAXLOGINS% (10)
auto_oper -> %X3_AUTO_OPER% (+oxwgs)
auto_oper_privs -> %X3_AUTO_OPER_PRIVS% (current literal, verbatim)
password_min_length -> %X3_PASSWD_MIN_LENGTH% (4)
password_min_digits/_upper/_lower -> %X3_PASSWD_MIN_DIGITS/UPPER/LOWER% (0/0/0)
email_enabled -> %X3_EMAIL_ENABLED% (0)
email_required -> %X3_EMAIL_REQUIRED% (0)
cookie_timeout -> %X3_COOKIE_TIMEOUT% (2d)
accounts_per_email -> %X3_ACCOUNTS_PER_EMAIL% (1)
titlehost_suffix -> %X3_TITLEHOST_SUFFIX% (derives from X3_GENERAL_DOMAIN,
replacing the hardcoded AfterNET.Org branding)
ldap_autocreate -> %X3_LDAP_AUTOCREATE% (1)
ldap_timeout -> %X3_LDAP_TIMEOUT% (10)
Also ADD two LDAP keys that exist in x3.conf.example but were missing from
the dist, so their env vars actually take effect:
"ldap_field_oslevel" "%X3_LDAP_FIELD_OSLEVEL%"; (X3AccountLevel)
"ldap_filter" "%X3_LDAP_FILTER%"; ((objectClass=inetOrgPerson))
Deliberately NOT added: ldap_oper_group_dn / ldap_oper_group_level /
ldap_field_group_member — they are commented in the example and their
empty-default semantics are unclear; adding them with a bogus default
could enable oper-group writeback unintentionally.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Templatize the remaining service-identity settings and their companion
limits (defaults preserve the shipped literals; generated output is
byte-identical):
opserv nick -> %X3_OPSERV_NICK% (O3)
opserv hostname -> %X3_OPSERV_HOSTNAME% (X3.Services)
debug_channel -> %X3_DEBUG_CHANNEL% (#TheOps)
alert_channel -> %X3_ALERT_CHANNEL% (#TheOps)
staff_auth_channel -> %X3_STAFF_AUTH_CHANNEL% (#OperServ)
clone_gline_duration -> %X3_CLONE_GLINE_DURATION% (2h) — companion to the
already-templatized untrusted_max
chanserv nick -> %X3_CHANSERV_NICK% (X3)
off_channel -> %X3_OFF_CHANNEL% (no)
max_owned -> %X3_MAX_OWNED% (2)
max_chan_users -> %X3_MAX_CHAN_USERS% (512)
support_channel -> (%X3_SUPPORT_CHANNEL%) ("#Operations", "#Help" —
the value is the list body, channels stay quoted)
global nick -> %X3_GLOBAL_NICK% (Global)
The logs targets follow the channels they feed: irc:#TheOps ->
irc:%X3_DEBUG_CHANNEL% and irc:#MrSnoopy -> irc:%X3_SNOOP_CHANNEL%.
X3_SNOOP_CHANNEL's entrypoint default (#MrSnoopy) lands here so the logs
reference resolves at this commit; the snoop module itself is templatized
with the other modules.
Channel MODES stay hardcoded. valid_channel_regex stays hardcoded on
purpose: regex metacharacters through sed substitution are a foot-gun.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…ential Templatize the module settings (defaults preserve shipped literals unless noted): sockcheck max_sockets -> %X3_SOCKCHECK_MAX_SOCKETS% (0) sockcheck gline_duration -> %X3_SOCKCHECK_GLINE_DURATION% (1d) snoop channel -> %X3_SNOOP_CHANNEL% (#MrSnoopy) snoop bot -> %X3_OPSERV_NICK% (reused) track channel -> %X3_TRACK_CHANNEL% (#MrPeanuts) memoserv bot -> %X3_MEMOSERV_BOT% (MemoServ) memoserv message_expiry -> %X3_MEMO_EXPIRY% (30d) memoserv limit -> %X3_MEMO_LIMIT% (30) qserver password -> %X3_QSERVER_PASSWORD% blacklist gline_duration -> %X3_BLACKLIST_GLINE_DURATION% (1h) The qserver password shipped as the literal credential "hello"; the entrypoint now generates a random 16-char password when the deployment doesn't provide one, so no image ever runs with a known qserver secret. The bogus sockcheck "bind_address" "192.168.0.10" is commented out — set only if you need a specific source IP; the shipped default was garbage that broke proxy checks on any host not owning that address. The webtv module is left alone (niche, mark-gated, nothing worth parameterizing). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Templatize the mail block and the mondo DB save interval: enable -> %X3_MAIL_ENABLE% (0 — BEHAVIOR CHANGE, see below) mailer -> %X3_MAIL_MAILER% (/usr/sbin/sendmail) smtp_server -> %X3_MAIL_SMTP_SERVER% (localhost) smtp_service -> %X3_MAIL_SMTP_SERVICE% (smtp) dbs mondo frequency -> %X3_DB_SAVE_FREQUENCY% (30m) The enable default flips 1 -> 0 deliberately: the image ships no MTA at /usr/sbin/sendmail, so mail was enabled-but-dead — every cookie/verify mail silently failed at mailer exec time. Deployments with a real mailer or SMTP relay set X3_MAIL_ENABLE=1 explicitly. Branding coherence: the mail body strings mixed %X3_GENERAL_DOMAIN% with leftover literals — "NET Support" / "NET IRC Network" now derive from the domain, and the odd "Network-Services: x3" extra header becomes a neutral "X-Mailer: X3-Services". Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
The entrypoint skipped generation whenever /x3/data/x3.conf existed, which
freezes the config at first container start forever: with x3.conf on a
persistent volume, every later env-var change, template update, or image
rebuild was silently inert. (Deployments hit exactly this: a conf generated
once in June still driving the container in August.)
New policy, keyed on a marker comment stamped as the first line of every
conf this script generates:
- no x3.conf -> generate (with marker)
- x3.conf WITH the marker -> regenerate: env + template are the source
of truth, config changes land on restart
- x3.conf WITHOUT the marker -> user-managed (volume-mounted, hand-rolled)
-> never touched
This preserves both documented workflows (env-templated and bring-your-own
x3.conf) while making the env-templated one actually track its inputs.
Generation substitutes into a temp file and stamps the marker on the final
move, so a mid-generation crash can't leave a half-substituted marker-less
conf that would then be mistaken for user-managed.
Migration note: confs generated by the OLD entrypoint carry no marker and
are therefore treated as user-managed after upgrade; delete the stale
x3.conf once (the volume's x3.db is unaffected) to opt into regeneration.
Co-Authored-By: Claude Fable 5 <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.
Expands the Docker config template from 19 env placeholders to 63, so real deployments can configure X3 without shipping a hand-edited conf. Grew out of two stragglers from #52 (ldap_writeback was never templatized — the LDAP Docker support couldn't actually enable write-back from env) into a full audit of x3.conf-dist vs x3.conf.example.
Fixes (behavior-affecting):
server.typewas hardcoded8(Nefarious 1.3.x protocol mode) — nowX3_SERVER_TYPE, so Nefarious 2.0.x deployments can run type 9 as documented.qserver.password "hello"shipped a literal credential — now generated randomly at container start unless overridden.mail.enableclaimed1while the image ships no MTA at /usr/sbin/sendmail — defaults to0now; mailer/smtp_server/smtp_service are templatized for images that add one.bind_address 192.168.0.10commented out./and&while using|as delimiter — a value containing|(e.g. an LDAP filter) silently corrupted the conf. Backslash/delimiter escaping fixed; verified with(|(a=b)(c=d))-style adversarial values.Templatized (defaults = previous literals, zero behavior change): server host-hiding type/keys/prefix (with a change-in-production warning on the stock keys), all service nicks, nickserv limits + email settings + password policy + auto_oper(+privs), the rest of the LDAP block incl. the previously-missing ldap_field_oslevel/ldap_filter keys, opserv channels + hostname + clone_gline_duration, chanserv off_channel/limits/support_channel, modules (sockcheck, snoop, track, memoserv, blacklist), mail branding (now derives consistently from the domain instead of leftover "AfterNET.Org"/"NET" literals), db save frequency, log channel targets.
Every commit was gated by a harness that regenerates the conf with default env and asserts byte-identity to the pre-pass output except the intended changes above.
🤖 Generated with Claude Code